mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-15 09:05:25 +00:00
Use boxvec for frame.stack
This commit is contained in:
parent
596e338c51
commit
d567f967e8
2 changed files with 42 additions and 40 deletions
|
@ -178,10 +178,11 @@ impl Compiler {
|
||||||
posonlyarg_count: usize,
|
posonlyarg_count: usize,
|
||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
kwonlyarg_count: usize,
|
kwonlyarg_count: usize,
|
||||||
source_path: String,
|
|
||||||
first_line_number: usize,
|
|
||||||
obj_name: String,
|
obj_name: String,
|
||||||
) {
|
) {
|
||||||
|
let source_path = self.source_path.clone();
|
||||||
|
let first_line_number = self.get_source_line_number();
|
||||||
|
|
||||||
let table = self
|
let table = self
|
||||||
.symbol_table_stack
|
.symbol_table_stack
|
||||||
.last_mut()
|
.last_mut()
|
||||||
|
@ -824,14 +825,11 @@ impl Compiler {
|
||||||
funcflags |= bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS;
|
funcflags |= bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
let line_number = self.get_source_line_number();
|
|
||||||
self.push_output(
|
self.push_output(
|
||||||
bytecode::CodeFlags::NEW_LOCALS | bytecode::CodeFlags::IS_OPTIMIZED,
|
bytecode::CodeFlags::NEW_LOCALS | bytecode::CodeFlags::IS_OPTIMIZED,
|
||||||
args.posonlyargs_count,
|
args.posonlyargs_count,
|
||||||
args.args.len(),
|
args.args.len(),
|
||||||
args.kwonlyargs.len(),
|
args.kwonlyargs.len(),
|
||||||
self.source_path.clone(),
|
|
||||||
line_number,
|
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -900,8 +898,9 @@ impl Compiler {
|
||||||
// except handlers:
|
// except handlers:
|
||||||
self.switch_to_block(handler_block);
|
self.switch_to_block(handler_block);
|
||||||
// Exception is on top of stack now
|
// Exception is on top of stack now
|
||||||
let mut next_handler = self.new_block();
|
|
||||||
for handler in handlers {
|
for handler in handlers {
|
||||||
|
let next_handler = self.new_block();
|
||||||
|
|
||||||
// If we gave a typ,
|
// If we gave a typ,
|
||||||
// check if this handler can handle the exception:
|
// check if this handler can handle the exception:
|
||||||
if let Some(exc_type) = &handler.typ {
|
if let Some(exc_type) = &handler.typ {
|
||||||
|
@ -937,7 +936,7 @@ impl Compiler {
|
||||||
self.emit(Instruction::PopException);
|
self.emit(Instruction::PopException);
|
||||||
|
|
||||||
if finalbody.is_some() {
|
if finalbody.is_some() {
|
||||||
self.emit(Instruction::PopBlock); // pop finally block
|
self.emit(Instruction::PopBlock); // pop excepthandler block
|
||||||
// We enter the finally block, without exception.
|
// We enter the finally block, without exception.
|
||||||
self.emit(Instruction::EnterFinally);
|
self.emit(Instruction::EnterFinally);
|
||||||
}
|
}
|
||||||
|
@ -948,13 +947,8 @@ impl Compiler {
|
||||||
|
|
||||||
// Emit a new label for the next handler
|
// Emit a new label for the next handler
|
||||||
self.switch_to_block(next_handler);
|
self.switch_to_block(next_handler);
|
||||||
next_handler = self.new_block();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.emit(Instruction::Jump {
|
|
||||||
target: next_handler,
|
|
||||||
});
|
|
||||||
self.switch_to_block(next_handler);
|
|
||||||
// If code flows here, we have an unhandled exception,
|
// If code flows here, we have an unhandled exception,
|
||||||
// raise the exception again!
|
// raise the exception again!
|
||||||
self.emit(Instruction::Raise {
|
self.emit(Instruction::Raise {
|
||||||
|
@ -971,7 +965,7 @@ impl Compiler {
|
||||||
if finalbody.is_some() {
|
if finalbody.is_some() {
|
||||||
self.emit(Instruction::PopBlock); // pop finally block
|
self.emit(Instruction::PopBlock); // pop finally block
|
||||||
|
|
||||||
// We enter the finally block, without return / exception.
|
// We enter the finallyhandler block, without return / exception.
|
||||||
self.emit(Instruction::EnterFinally);
|
self.emit(Instruction::EnterFinally);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -998,6 +992,9 @@ impl Compiler {
|
||||||
|
|
||||||
self.prepare_decorators(decorator_list)?;
|
self.prepare_decorators(decorator_list)?;
|
||||||
let mut funcflags = self.enter_function(name, args)?;
|
let mut funcflags = self.enter_function(name, args)?;
|
||||||
|
self.current_codeinfo()
|
||||||
|
.flags
|
||||||
|
.set(bytecode::CodeFlags::IS_COROUTINE, is_async);
|
||||||
|
|
||||||
// remember to restore self.ctx.in_loop to the original after the function is compiled
|
// remember to restore self.ctx.in_loop to the original after the function is compiled
|
||||||
let prev_ctx = self.ctx;
|
let prev_ctx = self.ctx;
|
||||||
|
@ -1031,7 +1028,7 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut code = self.pop_code_object();
|
let code = self.pop_code_object();
|
||||||
self.current_qualified_path = old_qualified_path;
|
self.current_qualified_path = old_qualified_path;
|
||||||
self.ctx = prev_ctx;
|
self.ctx = prev_ctx;
|
||||||
|
|
||||||
|
@ -1081,10 +1078,6 @@ impl Compiler {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_async {
|
|
||||||
code.flags |= bytecode::CodeFlags::IS_COROUTINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.build_closure(&code) {
|
if self.build_closure(&code) {
|
||||||
funcflags |= bytecode::MakeFunctionFlags::CLOSURE;
|
funcflags |= bytecode::MakeFunctionFlags::CLOSURE;
|
||||||
}
|
}
|
||||||
|
@ -1221,16 +1214,7 @@ impl Compiler {
|
||||||
self.current_qualified_path = Some(qualified_name.clone());
|
self.current_qualified_path = Some(qualified_name.clone());
|
||||||
|
|
||||||
self.emit(Instruction::LoadBuildClass);
|
self.emit(Instruction::LoadBuildClass);
|
||||||
let line_number = self.get_source_line_number();
|
self.push_output(bytecode::CodeFlags::empty(), 0, 0, 0, name.to_owned());
|
||||||
self.push_output(
|
|
||||||
bytecode::CodeFlags::empty(),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
self.source_path.clone(),
|
|
||||||
line_number,
|
|
||||||
name.to_owned(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let (new_body, doc_str) = get_doc(body);
|
let (new_body, doc_str) = get_doc(body);
|
||||||
|
|
||||||
|
@ -2175,22 +2159,24 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let line_number = self.get_source_line_number();
|
|
||||||
// Create magnificent function <listcomp>:
|
// Create magnificent function <listcomp>:
|
||||||
self.push_output(
|
self.push_output(
|
||||||
bytecode::CodeFlags::NEW_LOCALS | bytecode::CodeFlags::IS_OPTIMIZED,
|
bytecode::CodeFlags::NEW_LOCALS | bytecode::CodeFlags::IS_OPTIMIZED,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
self.source_path.clone(),
|
|
||||||
line_number,
|
|
||||||
name.clone(),
|
name.clone(),
|
||||||
);
|
);
|
||||||
let arg0 = self.varname(".0");
|
let arg0 = self.varname(".0");
|
||||||
|
|
||||||
|
let is_genexpr = matches!(kind, ast::ComprehensionKind::GeneratorExpression { .. });
|
||||||
|
|
||||||
// Create empty object of proper type:
|
// Create empty object of proper type:
|
||||||
match kind {
|
match kind {
|
||||||
ast::ComprehensionKind::GeneratorExpression { .. } => {}
|
ast::ComprehensionKind::GeneratorExpression { .. } => {
|
||||||
|
// pop the None that was passed to kickstart the generator
|
||||||
|
self.emit(Instruction::Pop);
|
||||||
|
}
|
||||||
ast::ComprehensionKind::List { .. } => {
|
ast::ComprehensionKind::List { .. } => {
|
||||||
self.emit(Instruction::BuildList {
|
self.emit(Instruction::BuildList {
|
||||||
size: 0,
|
size: 0,
|
||||||
|
@ -2300,6 +2286,10 @@ impl Compiler {
|
||||||
self.emit(Instruction::PopBlock);
|
self.emit(Instruction::PopBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if is_genexpr {
|
||||||
|
self.emit_constant(ConstantData::None)
|
||||||
|
}
|
||||||
|
|
||||||
// Return freshly filled list:
|
// Return freshly filled list:
|
||||||
self.emit(Instruction::ReturnValue);
|
self.emit(Instruction::ReturnValue);
|
||||||
|
|
||||||
|
|
28
src/ir.rs
28
src/ir.rs
|
@ -161,16 +161,20 @@ impl CodeInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn max_stacksize(&self) -> u32 {
|
fn max_stacksize(&self) -> u32 {
|
||||||
let mut maxdepth = 0;
|
let mut maxdepth = 0u32;
|
||||||
let mut stack = Vec::with_capacity(self.blocks.len());
|
let mut stack = Vec::with_capacity(self.blocks.len());
|
||||||
let mut startdepths = vec![0; self.blocks.len()];
|
let mut startdepths = vec![u32::MAX; self.blocks.len()];
|
||||||
|
// if it's a generator or a coroutine, it starts with something already on the stack
|
||||||
|
startdepths[0] =
|
||||||
|
self.flags
|
||||||
|
.intersects(CodeFlags::IS_GENERATOR | CodeFlags::IS_COROUTINE) as u32;
|
||||||
stack.push((Label(0), 0));
|
stack.push((Label(0), 0));
|
||||||
'process_blocks: while let Some((block, blockorder)) = stack.pop() {
|
'process_blocks: while let Some((block, blockorder)) = stack.pop() {
|
||||||
let mut depth = startdepths[block.0 as usize];
|
let mut depth = startdepths[block.0 as usize];
|
||||||
for i in &self.blocks[block.0 as usize].instructions {
|
for i in &self.blocks[block.0 as usize].instructions {
|
||||||
let instr = &i.instr;
|
let instr = &i.instr;
|
||||||
let effect = instr.stack_effect(false);
|
let effect = instr.stack_effect(false);
|
||||||
let new_depth = depth + effect;
|
let new_depth = add_ui(depth, effect);
|
||||||
if new_depth > maxdepth {
|
if new_depth > maxdepth {
|
||||||
maxdepth = new_depth
|
maxdepth = new_depth
|
||||||
}
|
}
|
||||||
|
@ -182,7 +186,7 @@ impl CodeInfo {
|
||||||
);
|
);
|
||||||
if let Some(&target_block) = jump_label {
|
if let Some(&target_block) = jump_label {
|
||||||
let effect = instr.stack_effect(true);
|
let effect = instr.stack_effect(true);
|
||||||
let target_depth = depth + effect;
|
let target_depth = add_ui(depth, effect);
|
||||||
if target_depth > maxdepth {
|
if target_depth > maxdepth {
|
||||||
maxdepth = target_depth
|
maxdepth = target_depth
|
||||||
}
|
}
|
||||||
|
@ -206,19 +210,27 @@ impl CodeInfo {
|
||||||
let next = self.block_order[next_blockorder as usize];
|
let next = self.block_order[next_blockorder as usize];
|
||||||
stackdepth_push(&mut stack, &mut startdepths, (next, next_blockorder), depth);
|
stackdepth_push(&mut stack, &mut startdepths, (next, next_blockorder), depth);
|
||||||
}
|
}
|
||||||
maxdepth as u32
|
maxdepth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stackdepth_push(
|
fn stackdepth_push(
|
||||||
stack: &mut Vec<(Label, u32)>,
|
stack: &mut Vec<(Label, u32)>,
|
||||||
startdepths: &mut [i32],
|
startdepths: &mut [u32],
|
||||||
target: (Label, u32),
|
target: (Label, u32),
|
||||||
depth: i32,
|
depth: u32,
|
||||||
) {
|
) {
|
||||||
let block_depth = &mut startdepths[target.0 .0 as usize];
|
let block_depth = &mut startdepths[target.0 .0 as usize];
|
||||||
if depth > *block_depth {
|
if *block_depth == u32::MAX || depth > *block_depth {
|
||||||
*block_depth = depth;
|
*block_depth = depth;
|
||||||
stack.push(target);
|
stack.push(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_ui(a: u32, b: i32) -> u32 {
|
||||||
|
if b < 0 {
|
||||||
|
a - b.abs() as u32
|
||||||
|
} else {
|
||||||
|
a + b as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue