Use boxvec for frame.stack

This commit is contained in:
Noah 2020-12-18 13:30:42 -06:00
parent 596e338c51
commit d567f967e8
2 changed files with 42 additions and 40 deletions

View file

@ -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);

View file

@ -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
}
}