From d567f967e84d1666ec50f1fcfd3ff8da479ce6e4 Mon Sep 17 00:00:00 2001 From: Noah <33094578+coolreader18@users.noreply.github.com> Date: Fri, 18 Dec 2020 13:30:42 -0600 Subject: [PATCH] Use boxvec for frame.stack --- src/compile.rs | 54 ++++++++++++++++++++------------------------------ src/ir.rs | 28 ++++++++++++++++++-------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/compile.rs b/src/compile.rs index 739be8e..18b3eb9 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -178,10 +178,11 @@ impl Compiler { posonlyarg_count: usize, arg_count: usize, kwonlyarg_count: usize, - source_path: String, - first_line_number: usize, obj_name: String, ) { + let source_path = self.source_path.clone(); + let first_line_number = self.get_source_line_number(); + let table = self .symbol_table_stack .last_mut() @@ -824,14 +825,11 @@ impl Compiler { funcflags |= bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS; } - let line_number = self.get_source_line_number(); self.push_output( bytecode::CodeFlags::NEW_LOCALS | bytecode::CodeFlags::IS_OPTIMIZED, args.posonlyargs_count, args.args.len(), args.kwonlyargs.len(), - self.source_path.clone(), - line_number, name.to_owned(), ); @@ -900,8 +898,9 @@ impl Compiler { // except handlers: self.switch_to_block(handler_block); // Exception is on top of stack now - let mut next_handler = self.new_block(); for handler in handlers { + let next_handler = self.new_block(); + // If we gave a typ, // check if this handler can handle the exception: if let Some(exc_type) = &handler.typ { @@ -937,7 +936,7 @@ impl Compiler { self.emit(Instruction::PopException); 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. self.emit(Instruction::EnterFinally); } @@ -948,13 +947,8 @@ impl Compiler { // Emit a new label for the 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, // raise the exception again! self.emit(Instruction::Raise { @@ -971,7 +965,7 @@ impl Compiler { if finalbody.is_some() { 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); } @@ -998,6 +992,9 @@ impl Compiler { self.prepare_decorators(decorator_list)?; 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 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.ctx = prev_ctx; @@ -1081,10 +1078,6 @@ impl Compiler { }); } - if is_async { - code.flags |= bytecode::CodeFlags::IS_COROUTINE; - } - if self.build_closure(&code) { funcflags |= bytecode::MakeFunctionFlags::CLOSURE; } @@ -1221,16 +1214,7 @@ impl Compiler { self.current_qualified_path = Some(qualified_name.clone()); self.emit(Instruction::LoadBuildClass); - let line_number = self.get_source_line_number(); - self.push_output( - bytecode::CodeFlags::empty(), - 0, - 0, - 0, - self.source_path.clone(), - line_number, - name.to_owned(), - ); + self.push_output(bytecode::CodeFlags::empty(), 0, 0, 0, name.to_owned()); let (new_body, doc_str) = get_doc(body); @@ -2175,22 +2159,24 @@ impl Compiler { } .to_owned(); - let line_number = self.get_source_line_number(); // Create magnificent function : self.push_output( bytecode::CodeFlags::NEW_LOCALS | bytecode::CodeFlags::IS_OPTIMIZED, 1, 1, 0, - self.source_path.clone(), - line_number, name.clone(), ); let arg0 = self.varname(".0"); + let is_genexpr = matches!(kind, ast::ComprehensionKind::GeneratorExpression { .. }); + // Create empty object of proper type: 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 { .. } => { self.emit(Instruction::BuildList { size: 0, @@ -2300,6 +2286,10 @@ impl Compiler { self.emit(Instruction::PopBlock); } + if is_genexpr { + self.emit_constant(ConstantData::None) + } + // Return freshly filled list: self.emit(Instruction::ReturnValue); diff --git a/src/ir.rs b/src/ir.rs index ce4877a..6b564e0 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -161,16 +161,20 @@ impl CodeInfo { } fn max_stacksize(&self) -> u32 { - let mut maxdepth = 0; + let mut maxdepth = 0u32; 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)); 'process_blocks: while let Some((block, blockorder)) = stack.pop() { let mut depth = startdepths[block.0 as usize]; for i in &self.blocks[block.0 as usize].instructions { let instr = &i.instr; let effect = instr.stack_effect(false); - let new_depth = depth + effect; + let new_depth = add_ui(depth, effect); if new_depth > maxdepth { maxdepth = new_depth } @@ -182,7 +186,7 @@ impl CodeInfo { ); if let Some(&target_block) = jump_label { let effect = instr.stack_effect(true); - let target_depth = depth + effect; + let target_depth = add_ui(depth, effect); if target_depth > maxdepth { maxdepth = target_depth } @@ -206,19 +210,27 @@ impl CodeInfo { let next = self.block_order[next_blockorder as usize]; stackdepth_push(&mut stack, &mut startdepths, (next, next_blockorder), depth); } - maxdepth as u32 + maxdepth } } fn stackdepth_push( stack: &mut Vec<(Label, u32)>, - startdepths: &mut [i32], + startdepths: &mut [u32], target: (Label, u32), - depth: i32, + depth: u32, ) { 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; stack.push(target); } } + +fn add_ui(a: u32, b: i32) -> u32 { + if b < 0 { + a - b.abs() as u32 + } else { + a + b as u32 + } +}