diff --git a/bytecode/src/bytecode.rs b/bytecode/src/bytecode.rs index db759f3c9..8051fa73d 100644 --- a/bytecode/src/bytecode.rs +++ b/bytecode/src/bytecode.rs @@ -143,7 +143,7 @@ impl CodeFlags { #[repr(transparent)] // XXX: if you add a new instruction that stores a Label, make sure to add it in // Instruction::label_arg{,_mut} -pub struct Label(pub usize); +pub struct Label(pub u32); impl fmt::Display for Label { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) @@ -153,6 +153,8 @@ impl fmt::Display for Label { /// Transforms a value prior to formatting it. #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum ConversionFlag { + /// No conversion + None, /// Converts by calling `str()`. Str, /// Converts by calling `ascii()`. @@ -161,7 +163,14 @@ pub enum ConversionFlag { Repr, } -pub type NameIdx = usize; +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum RaiseKind { + Reraise, + Raise, + RaiseCause, +} + +pub type NameIdx = u32; /// A Single bytecode instruction. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -199,7 +208,7 @@ pub enum Instruction { }, LoadConst { /// index into constants vec - idx: usize, + idx: u32, }, UnaryOperation { op: UnaryOperator, @@ -218,7 +227,7 @@ pub enum Instruction { }, Pop, Rotate { - amount: usize, + amount: u32, }, Duplicate, GetIter, @@ -249,10 +258,10 @@ pub enum Instruction { }, MakeFunction(MakeFunctionFlags), CallFunctionPositional { - nargs: usize, + nargs: u32, }, CallFunctionKeyword { - nargs: usize, + nargs: u32, }, CallFunctionEx { has_kwargs: bool, @@ -297,56 +306,57 @@ pub enum Instruction { WithCleanupFinish, PopBlock, Raise { - argc: usize, + kind: RaiseKind, }, BuildString { - size: usize, + size: u32, }, BuildTuple { - size: usize, unpack: bool, + size: u32, }, BuildList { - size: usize, unpack: bool, + size: u32, }, BuildSet { - size: usize, unpack: bool, + size: u32, }, BuildMap { - size: usize, unpack: bool, for_call: bool, + size: u32, }, BuildSlice { - size: usize, + /// whether build a slice with a third step argument + step: bool, }, ListAppend { - i: usize, + i: u32, }, SetAdd { - i: usize, + i: u32, }, MapAdd { - i: usize, + i: u32, }, PrintExpr, LoadBuildClass, UnpackSequence { - size: usize, + size: u32, }, UnpackEx { before: u8, after: u8, }, FormatValue { - conversion: Option, + conversion: ConversionFlag, }, PopException, Reverse { - amount: usize, + amount: u32, }, GetAwaitable, BeforeAsyncWith, @@ -360,7 +370,7 @@ pub enum Instruction { /// required to support named expressions of Python 3.8 in dict comprehension /// today (including Py3.9) only required in dict comprehension. MapAddRev { - i: usize, + i: u32, }, } @@ -612,7 +622,7 @@ impl CodeObject { let label_targets = self.label_targets(); for (offset, instruction) in self.instructions.iter().enumerate() { - let arrow = if label_targets.contains(&Label(offset)) { + let arrow = if label_targets.contains(&Label(offset as u32)) { ">>" } else { " " @@ -819,39 +829,41 @@ impl Instruction { }; } - let cellname = |i: usize| { + let varname = |i: u32| varnames[i as usize].as_ref(); + let name = |i: u32| names[i as usize].as_ref(); + let cellname = |i: u32| { cellvars - .get(i) - .unwrap_or_else(|| &freevars[i - cellvars.len()]) + .get(i as usize) + .unwrap_or_else(|| &freevars[i as usize - cellvars.len()]) .as_ref() }; match self { - ImportName { idx } => w!(ImportName, names[*idx].as_ref()), + ImportName { idx } => w!(ImportName, name(*idx)), ImportNameless => w!(ImportNameless), ImportStar => w!(ImportStar), - ImportFrom { idx } => w!(ImportFrom, names[*idx].as_ref()), - LoadFast(idx) => w!(LoadFast, *idx, varnames[*idx].as_ref()), - LoadNameAny(idx) => w!(LoadNameAny, *idx, names[*idx].as_ref()), - LoadGlobal(idx) => w!(LoadGlobal, *idx, names[*idx].as_ref()), + ImportFrom { idx } => w!(ImportFrom, name(*idx)), + LoadFast(idx) => w!(LoadFast, *idx, varname(*idx)), + LoadNameAny(idx) => w!(LoadNameAny, *idx, name(*idx)), + LoadGlobal(idx) => w!(LoadGlobal, *idx, name(*idx)), LoadDeref(idx) => w!(LoadDeref, *idx, cellname(*idx)), LoadClassDeref(idx) => w!(LoadClassDeref, *idx, cellname(*idx)), - StoreFast(idx) => w!(StoreFast, *idx, varnames[*idx].as_ref()), - StoreLocal(idx) => w!(StoreLocal, *idx, names[*idx].as_ref()), - StoreGlobal(idx) => w!(StoreGlobal, *idx, names[*idx].as_ref()), + StoreFast(idx) => w!(StoreFast, *idx, varname(*idx)), + StoreLocal(idx) => w!(StoreLocal, *idx, name(*idx)), + StoreGlobal(idx) => w!(StoreGlobal, *idx, name(*idx)), StoreDeref(idx) => w!(StoreDeref, *idx, cellname(*idx)), - DeleteFast(idx) => w!(DeleteFast, *idx, varnames[*idx].as_ref()), - DeleteLocal(idx) => w!(DeleteLocal, *idx, names[*idx].as_ref()), - DeleteGlobal(idx) => w!(DeleteGlobal, *idx, names[*idx].as_ref()), + DeleteFast(idx) => w!(DeleteFast, *idx, varname(*idx)), + DeleteLocal(idx) => w!(DeleteLocal, *idx, name(*idx)), + DeleteGlobal(idx) => w!(DeleteGlobal, *idx, name(*idx)), DeleteDeref(idx) => w!(DeleteDeref, *idx, cellname(*idx)), LoadClosure(i) => w!(LoadClosure, *i, cellname(*i)), Subscript => w!(Subscript), StoreSubscript => w!(StoreSubscript), DeleteSubscript => w!(DeleteSubscript), - StoreAttr { idx } => w!(StoreAttr, names[*idx].as_ref()), - DeleteAttr { idx } => w!(DeleteAttr, names[*idx].as_ref()), + StoreAttr { idx } => w!(StoreAttr, name(*idx)), + DeleteAttr { idx } => w!(DeleteAttr, name(*idx)), LoadConst { idx } => { - let value = &constants[*idx]; + let value = &constants[*idx as usize]; match value.borrow_constant() { BorrowedConstant::Code { code } if expand_codeobjects => { writeln!(f, "{:20} ({:?}):", "LoadConst", code)?; @@ -865,13 +877,13 @@ impl Instruction { } } } - UnaryOperation { op } => w!(UnaryOperation, format!("{:?}", op)), - BinaryOperation { op } => w!(BinaryOperation, format!("{:?}", op)), + UnaryOperation { op } => w!(UnaryOperation, format_args!("{:?}", op)), + BinaryOperation { op } => w!(BinaryOperation, format_args!("{:?}", op)), BinaryOperationInplace { op } => { - w!(BinaryOperationInplace, format!("{:?}", op)) + w!(BinaryOperationInplace, format_args!("{:?}", op)) } - LoadAttr { idx } => w!(LoadAttr, names[*idx].as_ref()), - CompareOperation { op } => w!(CompareOperation, format!("{:?}", op)), + LoadAttr { idx } => w!(LoadAttr, name(*idx)), + CompareOperation { op } => w!(CompareOperation, format_args!("{:?}", op)), Pop => w!(Pop), Rotate { amount } => w!(Rotate, amount), Duplicate => w!(Duplicate), @@ -903,7 +915,7 @@ impl Instruction { BeforeAsyncWith => w!(BeforeAsyncWith), SetupAsyncWith { end } => w!(SetupAsyncWith, end), PopBlock => w!(PopBlock), - Raise { argc } => w!(Raise, argc), + Raise { kind } => w!(Raise, format_args!("{:?}", kind)), BuildString { size } => w!(BuildString, size), BuildTuple { size, unpack } => w!(BuildTuple, size, unpack), BuildList { size, unpack } => w!(BuildList, size, unpack), @@ -913,7 +925,7 @@ impl Instruction { unpack, for_call, } => w!(BuildMap, size, unpack, for_call), - BuildSlice { size } => w!(BuildSlice, size), + BuildSlice { step } => w!(BuildSlice, step), ListAppend { i } => w!(ListAppend, i), SetAdd { i } => w!(SetAdd, i), MapAddRev { i } => w!(MapAddRev, i), @@ -921,7 +933,7 @@ impl Instruction { LoadBuildClass => w!(LoadBuildClass), UnpackSequence { size } => w!(UnpackSequence, size), UnpackEx { before, after } => w!(UnpackEx, before, after), - FormatValue { .. } => w!(FormatValue), // TODO: write conversion + FormatValue { conversion } => w!(FormatValue, format_args!("{:?}", conversion)), PopException => w!(PopException), Reverse { amount } => w!(Reverse, amount), GetAwaitable => w!(GetAwaitable), diff --git a/compiler/src/compile.rs b/compiler/src/compile.rs index 270d0449b..0847cab4c 100644 --- a/compiler/src/compile.rs +++ b/compiler/src/compile.rs @@ -76,8 +76,8 @@ impl CodeInfo { // this is a little bit hacky, as until now the data stored inside Labels in // Instructions is just bookkeeping, but I think it's the best way to do this if let Some(l) = instruction.label_arg_mut() { - let real_label = label_map[l.0]; - debug_assert!(real_label.0 != usize::MAX, "label wasn't set"); + let real_label = label_map[l.0 as usize]; + debug_assert!(real_label.0 != u32::MAX, "label wasn't set"); *l = real_label; } } @@ -303,7 +303,7 @@ impl Compiler { let cache = cache(self.current_codeinfo()); cache .get_index_of(name) - .unwrap_or_else(|| cache.insert_full(name.to_owned()).0) + .unwrap_or_else(|| cache.insert_full(name.to_owned()).0) as u32 } fn compile_program( @@ -470,7 +470,7 @@ impl Compiler { NameUsage::Delete => Instruction::DeleteLocal, }, }; - self.emit(op(idx)); + self.emit(op(idx as u32)); } fn compile_statement(&mut self, statement: &ast::Statement) -> CompileResult<()> { @@ -665,23 +665,22 @@ impl Compiler { body, orelse, } => self.compile_for(target, iter, body, orelse, *is_async)?, - Raise { exception, cause } => match exception { - Some(value) => { - self.compile_expression(value)?; - match cause { - Some(cause) => { - self.compile_expression(cause)?; - self.emit(Instruction::Raise { argc: 2 }); - } - None => { - self.emit(Instruction::Raise { argc: 1 }); + Raise { exception, cause } => { + let kind = match exception { + Some(value) => { + self.compile_expression(value)?; + match cause { + Some(cause) => { + self.compile_expression(cause)?; + bytecode::RaiseKind::RaiseCause + } + None => bytecode::RaiseKind::Raise, } } - } - None => { - self.emit(Instruction::Raise { argc: 0 }); - } - }, + None => bytecode::RaiseKind::Reraise, + }; + self.emit(Instruction::Raise { kind }); + } Try { body, handlers, @@ -721,7 +720,9 @@ impl Compiler { self.emit(Instruction::CallFunctionPositional { nargs: 0 }); } } - self.emit(Instruction::Raise { argc: 1 }); + self.emit(Instruction::Raise { + kind: bytecode::RaiseKind::Raise, + }); self.set_label(end_label); } } @@ -835,7 +836,7 @@ impl Compiler { let have_defaults = !args.defaults.is_empty(); if have_defaults { // Construct a tuple: - let size = args.defaults.len(); + let size = args.defaults.len() as u32; for element in &args.defaults { self.compile_expression(element)?; } @@ -1003,7 +1004,9 @@ impl Compiler { self.set_label(handler_label); // If code flows here, we have an unhandled exception, // raise the exception again! - self.emit(Instruction::Raise { argc: 0 }); + self.emit(Instruction::Raise { + kind: bytecode::RaiseKind::Reraise, + }); // We successfully ran the try block: // else: @@ -1177,10 +1180,10 @@ impl Compiler { if let SymbolScope::Free = symbol.scope { idx += parent_code.cellvar_cache.len(); } - self.emit(Instruction::LoadClosure(idx)) + self.emit(Instruction::LoadClosure(idx as u32)) } self.emit(Instruction::BuildTuple { - size: code.freevars.len(), + size: code.freevars.len() as u32, unpack: false, }); true @@ -1305,7 +1308,7 @@ impl Compiler { .position(|var| *var == "__class__"); if let Some(classcell_idx) = classcell_idx { - self.emit(Instruction::LoadClosure(classcell_idx)); + self.emit(Instruction::LoadClosure(classcell_idx as u32)); self.emit(Instruction::Duplicate); let classcell = self.name("__classcell__"); self.emit(Instruction::StoreLocal(classcell)); @@ -1362,11 +1365,11 @@ impl Compiler { elements: kwarg_names, }); self.emit(Instruction::CallFunctionKeyword { - nargs: 2 + keywords.len() + bases.len(), + nargs: (2 + keywords.len() + bases.len()) as u32, }); } else { self.emit(Instruction::CallFunctionPositional { - nargs: 2 + bases.len(), + nargs: (2 + bases.len()) as u32, }); } @@ -1461,7 +1464,9 @@ impl Compiler { op: bytecode::ComparisonOperator::ExceptionMatch, }); self.emit(Instruction::JumpIfTrue { target: else_label }); - self.emit(Instruction::Raise { argc: 0 }); + self.emit(Instruction::Raise { + kind: bytecode::RaiseKind::Reraise, + }); let was_in_loop = self.ctx.loop_data; self.ctx.loop_data = Some((start_label, end_label)); @@ -1649,7 +1654,7 @@ impl Compiler { if !seen_star { self.emit(Instruction::UnpackSequence { - size: elements.len(), + size: elements.len() as u32, }); } @@ -1917,7 +1922,7 @@ impl Compiler { self.emit_constant(const_value); } List { elements } => { - let size = elements.len(); + let size = elements.len() as u32; let must_unpack = self.gather_elements(elements)?; self.emit(Instruction::BuildList { size, @@ -1925,7 +1930,7 @@ impl Compiler { }); } Tuple { elements } => { - let size = elements.len(); + let size = elements.len() as u32; let must_unpack = self.gather_elements(elements)?; self.emit(Instruction::BuildTuple { size, @@ -1933,7 +1938,7 @@ impl Compiler { }); } Set { elements } => { - let size = elements.len(); + let size = elements.len() as u32; let must_unpack = self.gather_elements(elements)?; self.emit(Instruction::BuildSet { size, @@ -1944,11 +1949,11 @@ impl Compiler { self.compile_dict(elements)?; } Slice { elements } => { - let size = elements.len(); + let step = elements.len() >= 3; for element in elements { self.compile_expression(element)?; } - self.emit(Instruction::BuildSlice { size }); + self.emit(Instruction::BuildSlice { step }); } Yield { value } => { if !self.ctx.in_func() { @@ -2107,7 +2112,7 @@ impl Compiler { keywords: &[ast::Keyword], ) -> CompileResult<()> { self.compile_expression(function)?; - let count = args.len() + keywords.len(); + let count = (args.len() + keywords.len()) as u32; // Normal arguments: let must_unpack = self.gather_elements(args)?; @@ -2116,7 +2121,7 @@ impl Compiler { if must_unpack || has_double_star { // Create a tuple with positional args: self.emit(Instruction::BuildTuple { - size: args.len(), + size: args.len() as u32, unpack: must_unpack, }); @@ -2295,13 +2300,13 @@ impl Compiler { ast::ComprehensionKind::List { element } => { compile_element(element)?; self.emit(Instruction::ListAppend { - i: 1 + generators.len(), + i: (1 + generators.len()) as u32, }); } ast::ComprehensionKind::Set { element } => { compile_element(element)?; self.emit(Instruction::SetAdd { - i: 1 + generators.len(), + i: (1 + generators.len()) as u32, }); } ast::ComprehensionKind::Dict { key, value } => { @@ -2310,7 +2315,7 @@ impl Compiler { self.compile_expression(value)?; self.emit(Instruction::MapAddRev { - i: 1 + generators.len(), + i: (1 + generators.len()) as u32, }); } } @@ -2370,7 +2375,9 @@ impl Compiler { for value in values { self.compile_string(value)?; } - self.emit(Instruction::BuildString { size: values.len() }) + self.emit(Instruction::BuildString { + size: values.len() as u32, + }) } ast::StringGroup::Constant { value } => { self.emit_constant(ConstantData::Str { @@ -2390,7 +2397,7 @@ impl Compiler { }; self.compile_expression(value)?; self.emit(Instruction::FormatValue { - conversion: conversion.map(compile_conversion_flag), + conversion: compile_conversion_flag(*conversion), }); } } @@ -2431,7 +2438,7 @@ impl Compiler { fn emit_constant(&mut self, constant: ConstantData) { let info = self.current_codeinfo(); - let idx = info.constants.len(); + let idx = info.constants.len() as u32; info.constants.push(constant); self.emit(Instruction::LoadConst { idx }) } @@ -2447,8 +2454,8 @@ impl Compiler { // Generate a new label fn new_label(&mut self) -> Label { let label_map = &mut self.current_codeinfo().label_map; - let label = Label(label_map.len()); - label_map.push(Label(usize::MAX)); + let label = Label(label_map.len() as u32); + label_map.push(Label(u32::MAX)); label } @@ -2459,10 +2466,10 @@ impl Compiler { label_map, .. } = self.current_codeinfo(); - let actual_label = Label(instructions.len()); - let prev_val = std::mem::replace(&mut label_map[label.0], actual_label); + let actual_label = Label(instructions.len() as u32); + let prev_val = std::mem::replace(&mut label_map[label.0 as usize], actual_label); debug_assert!( - prev_val.0 == usize::MAX || prev_val == actual_label, + prev_val.0 == u32::MAX || prev_val == actual_label, "double-set a label" ); } @@ -2526,11 +2533,14 @@ fn compile_location(location: &ast::Location) -> bytecode::Location { bytecode::Location::new(location.row(), location.column()) } -fn compile_conversion_flag(conversion_flag: ast::ConversionFlag) -> bytecode::ConversionFlag { +fn compile_conversion_flag( + conversion_flag: Option, +) -> bytecode::ConversionFlag { match conversion_flag { - ast::ConversionFlag::Ascii => bytecode::ConversionFlag::Ascii, - ast::ConversionFlag::Repr => bytecode::ConversionFlag::Repr, - ast::ConversionFlag::Str => bytecode::ConversionFlag::Str, + None => bytecode::ConversionFlag::None, + Some(ast::ConversionFlag::Ascii) => bytecode::ConversionFlag::Ascii, + Some(ast::ConversionFlag::Repr) => bytecode::ConversionFlag::Repr, + Some(ast::ConversionFlag::Str) => bytecode::ConversionFlag::Str, } } diff --git a/vm/src/builtins/frame.rs b/vm/src/builtins/frame.rs index 5248dac61..77bd5d843 100644 --- a/vm/src/builtins/frame.rs +++ b/vm/src/builtins/frame.rs @@ -73,7 +73,7 @@ impl FrameRef { } #[pyproperty] - fn f_lasti(self) -> usize { + fn f_lasti(self) -> u32 { self.lasti() } diff --git a/vm/src/builtins/traceback.rs b/vm/src/builtins/traceback.rs index 2155fe303..26f5455bc 100644 --- a/vm/src/builtins/traceback.rs +++ b/vm/src/builtins/traceback.rs @@ -8,7 +8,7 @@ use crate::vm::VirtualMachine; pub struct PyTraceback { pub next: Option, // TODO: Make mutable pub frame: FrameRef, - pub lasti: usize, + pub lasti: u32, pub lineno: usize, } @@ -22,7 +22,7 @@ impl PyValue for PyTraceback { #[pyimpl] impl PyTraceback { - pub fn new(next: Option>, frame: FrameRef, lasti: usize, lineno: usize) -> Self { + pub fn new(next: Option>, frame: FrameRef, lasti: u32, lineno: usize) -> Self { PyTraceback { next, frame, @@ -37,7 +37,7 @@ impl PyTraceback { } #[pyproperty(name = "tb_lasti")] - fn lasti(&self) -> usize { + fn lasti(&self) -> u32 { self.lasti } diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 3188d5517..335c7a5a1 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -1,5 +1,5 @@ use std::fmt; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::{AtomicU32, Ordering}; use indexmap::IndexMap; use itertools::Itertools; @@ -99,7 +99,7 @@ pub struct Frame { pub builtins: PyDictRef, /// index of last instruction ran - pub lasti: AtomicUsize, + pub lasti: AtomicU32, /// tracer function for this frame (usually is None) pub trace: PyMutex, state: PyMutex, @@ -186,7 +186,7 @@ impl Frame { globals: scope.globals, builtins, code, - lasti: AtomicUsize::new(0), + lasti: AtomicU32::new(0), state: PyMutex::new(FrameState { stack: Vec::new(), blocks: Vec::new(), @@ -283,14 +283,14 @@ impl FrameRef { } pub fn current_location(&self) -> bytecode::Location { - self.code.locations[self.lasti.load(Ordering::Relaxed) - 1] + self.code.locations[self.lasti.load(Ordering::Relaxed) as usize - 1] } pub fn yield_from_target(&self) -> Option { self.with_exec(|exec| exec.yield_from_target()) } - pub fn lasti(&self) -> usize { + pub fn lasti(&self) -> u32 { self.lasti.load(Ordering::Relaxed) } } @@ -305,7 +305,7 @@ struct ExecutingFrame<'a> { globals: &'a PyDictRef, builtins: &'a PyDictRef, object: &'a FrameRef, - lasti: &'a AtomicUsize, + lasti: &'a AtomicU32, state: &'a mut FrameState, } @@ -325,7 +325,7 @@ impl ExecutingFrame<'_> { flame_guard!(format!("Frame::run({})", self.code.obj_name)); // Execute until return or exception: loop { - let idx = self.lasti.fetch_add(1, Ordering::Relaxed); + let idx = self.lasti.fetch_add(1, Ordering::Relaxed) as usize; let instr = &self.code.instructions[idx]; let result = self.execute_instruction(instr, vm); match result { @@ -365,7 +365,9 @@ impl ExecutingFrame<'_> { } fn yield_from_target(&self) -> Option { - if let Some(bytecode::Instruction::YieldFrom) = self.code.instructions.get(self.lasti()) { + if let Some(bytecode::Instruction::YieldFrom) = + self.code.instructions.get(self.lasti() as usize) + { Some(self.last_value()) } else { None @@ -442,22 +444,23 @@ impl ExecutingFrame<'_> { match instruction { bytecode::Instruction::LoadConst { idx } => { - self.push_value(self.code.constants[*idx].0.clone()); + self.push_value(self.code.constants[*idx as usize].0.clone()); Ok(None) } bytecode::Instruction::ImportName { idx } => { - self.import(vm, Some(self.code.names[*idx].clone())) + self.import(vm, Some(self.code.names[*idx as usize].clone())) } bytecode::Instruction::ImportNameless => self.import(vm, None), bytecode::Instruction::ImportStar => self.import_star(vm), bytecode::Instruction::ImportFrom { idx } => self.import_from(vm, *idx), bytecode::Instruction::LoadFast(idx) => { - let x = self.fastlocals.lock()[*idx].clone().ok_or_else(|| { + let idx = *idx as usize; + let x = self.fastlocals.lock()[idx].clone().ok_or_else(|| { vm.new_exception_msg( vm.ctx.exceptions.unbound_local_error.clone(), format!( "local variable '{}' referenced before assignment", - self.code.varnames[*idx] + self.code.varnames[idx] ), ) })?; @@ -465,7 +468,7 @@ impl ExecutingFrame<'_> { Ok(None) } bytecode::Instruction::LoadNameAny(idx) => { - let name = &self.code.names[*idx]; + let name = &self.code.names[*idx as usize]; let x = self.locals.get_item_option(name.clone(), vm)?; let x = match x { Some(x) => x, @@ -475,13 +478,13 @@ impl ExecutingFrame<'_> { Ok(None) } bytecode::Instruction::LoadGlobal(idx) => { - let name = &self.code.names[*idx]; + let name = &self.code.names[*idx as usize]; let x = self.load_global_or_builtin(name, vm)?; self.push_value(x); Ok(None) } bytecode::Instruction::LoadDeref(i) => { - let i = *i; + let i = *i as usize; let x = self.cells_frees[i] .get() .ok_or_else(|| self.unbound_cell_exception(i, vm))?; @@ -489,7 +492,7 @@ impl ExecutingFrame<'_> { Ok(None) } bytecode::Instruction::LoadClassDeref(i) => { - let i = *i; + let i = *i as usize; let name = self.code.freevars[i - self.code.cellvars.len()].clone(); let value = if let Some(value) = self.locals.get_item_option(name, vm)? { value @@ -503,32 +506,32 @@ impl ExecutingFrame<'_> { } bytecode::Instruction::StoreFast(idx) => { let value = self.pop_value(); - self.fastlocals.lock()[*idx] = Some(value); + self.fastlocals.lock()[*idx as usize] = Some(value); Ok(None) } bytecode::Instruction::StoreLocal(idx) => { let value = self.pop_value(); self.locals - .set_item(self.code.names[*idx].clone(), value, vm)?; + .set_item(self.code.names[*idx as usize].clone(), value, vm)?; Ok(None) } bytecode::Instruction::StoreGlobal(idx) => { let value = self.pop_value(); self.globals - .set_item(self.code.names[*idx].clone(), value, vm)?; + .set_item(self.code.names[*idx as usize].clone(), value, vm)?; Ok(None) } bytecode::Instruction::StoreDeref(i) => { let value = self.pop_value(); - self.cells_frees[*i].set(Some(value)); + self.cells_frees[*i as usize].set(Some(value)); Ok(None) } bytecode::Instruction::DeleteFast(idx) => { - self.fastlocals.lock()[*idx] = None; + self.fastlocals.lock()[*idx as usize] = None; Ok(None) } bytecode::Instruction::DeleteLocal(idx) => { - let name = &self.code.names[*idx]; + let name = &self.code.names[*idx as usize]; match self.locals.del_item(name.clone(), vm) { Ok(()) => {} Err(e) if e.isinstance(&vm.ctx.exceptions.key_error) => { @@ -539,7 +542,7 @@ impl ExecutingFrame<'_> { Ok(None) } bytecode::Instruction::DeleteGlobal(idx) => { - let name = &self.code.names[*idx]; + let name = &self.code.names[*idx as usize]; match self.globals.del_item(name.clone(), vm) { Ok(()) => {} Err(e) if e.isinstance(&vm.ctx.exceptions.key_error) => { @@ -550,11 +553,11 @@ impl ExecutingFrame<'_> { Ok(None) } bytecode::Instruction::DeleteDeref(i) => { - self.cells_frees[*i].set(None); + self.cells_frees[*i as usize].set(None); Ok(None) } bytecode::Instruction::LoadClosure(i) => { - let value = self.cells_frees[*i].clone(); + let value = self.cells_frees[*i as usize].clone(); self.push_value(value.into_object()); Ok(None) } @@ -576,7 +579,7 @@ impl ExecutingFrame<'_> { bytecode::Instruction::Rotate { amount } => self.execute_rotate(*amount), bytecode::Instruction::BuildString { size } => { let s = self - .pop_multiple(*size) + .pop_multiple(*size as usize) .as_slice() .iter() .map(|pyobj| pystr::borrow_value(&pyobj)) @@ -586,7 +589,7 @@ impl ExecutingFrame<'_> { Ok(None) } bytecode::Instruction::BuildList { size, unpack } => { - let elements = self.get_elements(vm, *size, *unpack)?; + let elements = self.get_elements(vm, *size as usize, *unpack)?; let list_obj = vm.ctx.new_list(elements); self.push_value(list_obj); Ok(None) @@ -594,7 +597,7 @@ impl ExecutingFrame<'_> { bytecode::Instruction::BuildSet { size, unpack } => { let set = vm.ctx.new_set(); { - let elements = self.pop_multiple(*size); + let elements = self.pop_multiple(*size as usize); if *unpack { for element in elements { vm.map_iterable_object(&element, |x| set.add(x, vm))??; @@ -609,7 +612,7 @@ impl ExecutingFrame<'_> { Ok(None) } bytecode::Instruction::BuildTuple { size, unpack } => { - let elements = self.get_elements(vm, *size, *unpack)?; + let elements = self.get_elements(vm, *size as usize, *unpack)?; let list_obj = vm.ctx.new_tuple(elements); self.push_value(list_obj); Ok(None) @@ -619,7 +622,7 @@ impl ExecutingFrame<'_> { unpack, for_call, } => self.execute_build_map(vm, *size, *unpack, *for_call), - bytecode::Instruction::BuildSlice { size } => self.execute_build_slice(vm, *size), + bytecode::Instruction::BuildSlice { step } => self.execute_build_slice(vm, *step), bytecode::Instruction::ListAppend { i } => { let list_obj = self.nth_value(*i); let item = self.pop_value(); @@ -872,7 +875,7 @@ impl ExecutingFrame<'_> { Ok(None) } - bytecode::Instruction::Raise { argc } => self.execute_raise(vm, *argc), + bytecode::Instruction::Raise { kind } => self.execute_raise(vm, *kind), bytecode::Instruction::Break => self.unwind_blocks(vm, UnwindReason::Break), bytecode::Instruction::Continue { target } => { @@ -904,7 +907,7 @@ impl ExecutingFrame<'_> { e } })?; - let msg = match elements.len().cmp(size) { + let msg = match elements.len().cmp(&(*size as usize)) { std::cmp::Ordering::Equal => { for element in elements.into_iter().rev() { self.push_value(element); @@ -930,12 +933,13 @@ impl ExecutingFrame<'_> { self.execute_unpack_ex(vm, *before, *after) } bytecode::Instruction::FormatValue { conversion } => { - use bytecode::ConversionFlag::*; + use bytecode::ConversionFlag; + let value = self.pop_value(); let value = match conversion { - Some(Str) => vm.to_str(&self.pop_value())?.into_object(), - Some(Repr) => vm.to_repr(&self.pop_value())?.into_object(), - Some(Ascii) => vm.ctx.new_str(builtins::ascii(self.pop_value(), vm)?), - None => self.pop_value(), + ConversionFlag::Str => vm.to_str(&value)?.into_object(), + ConversionFlag::Repr => vm.to_repr(&value)?.into_object(), + ConversionFlag::Ascii => vm.ctx.new_str(builtins::ascii(value, vm)?), + ConversionFlag::None => value, }; let spec = self.pop_value(); @@ -954,7 +958,7 @@ impl ExecutingFrame<'_> { } bytecode::Instruction::Reverse { amount } => { let stack_len = self.state.stack.len(); - self.state.stack[stack_len - amount..stack_len].reverse(); + self.state.stack[stack_len - *amount as usize..stack_len].reverse(); Ok(None) } } @@ -1001,7 +1005,7 @@ impl ExecutingFrame<'_> { #[cfg_attr(feature = "flame-it", flame("Frame"))] fn import_from(&mut self, vm: &VirtualMachine, idx: bytecode::NameIdx) -> FrameResult { let module = self.last_value(); - let name = &self.code.names[idx]; + let name = &self.code.names[idx as usize]; // Load attribute, and transform any error into import error. let obj = vm.get_attribute(module, name.clone()).map_err(|_| { vm.new_import_error(format!("cannot import name '{}'", name), name.clone()) @@ -1106,7 +1110,7 @@ impl ExecutingFrame<'_> { } } - fn execute_rotate(&mut self, amount: usize) -> FrameResult { + fn execute_rotate(&mut self, amount: u32) -> FrameResult { // Shuffles top of stack amount down if amount < 2 { panic!("Can only rotate two or more values"); @@ -1156,10 +1160,11 @@ impl ExecutingFrame<'_> { fn execute_build_map( &mut self, vm: &VirtualMachine, - size: usize, + size: u32, unpack: bool, for_call: bool, ) -> FrameResult { + let size = size as usize; let map_obj = vm.ctx.new_dict(); if unpack { for obj in self.pop_multiple(size) { @@ -1191,14 +1196,8 @@ impl ExecutingFrame<'_> { Ok(None) } - fn execute_build_slice(&mut self, vm: &VirtualMachine, size: usize) -> FrameResult { - assert!(size == 2 || size == 3); - - let step = if size == 3 { - Some(self.pop_value()) - } else { - None - }; + fn execute_build_slice(&mut self, vm: &VirtualMachine, step: bool) -> FrameResult { + let step = if step { Some(self.pop_value()) } else { None }; let stop = self.pop_value(); let start = self.pop_value(); @@ -1212,13 +1211,9 @@ impl ExecutingFrame<'_> { Ok(None) } - fn execute_call_function_positional( - &mut self, - vm: &VirtualMachine, - nargs: usize, - ) -> FrameResult { + fn execute_call_function_positional(&mut self, vm: &VirtualMachine, nargs: u32) -> FrameResult { let args = FuncArgs { - args: self.pop_multiple(nargs).collect(), + args: self.pop_multiple(nargs as usize).collect(), kwargs: IndexMap::new(), }; @@ -1228,12 +1223,12 @@ impl ExecutingFrame<'_> { Ok(None) } - fn execute_call_function_keyword(&mut self, vm: &VirtualMachine, nargs: usize) -> FrameResult { + fn execute_call_function_keyword(&mut self, vm: &VirtualMachine, nargs: u32) -> FrameResult { let kwarg_names = self .pop_value() .downcast::() .expect("kwarg names should be tuple of strings"); - let args = self.pop_multiple(nargs); + let args = self.pop_multiple(nargs as usize); let kwarg_names = kwarg_names .borrow_value() @@ -1274,9 +1269,9 @@ impl ExecutingFrame<'_> { Ok(None) } - fn execute_raise(&mut self, vm: &VirtualMachine, argc: usize) -> FrameResult { - let cause = match argc { - 2 => { + fn execute_raise(&mut self, vm: &VirtualMachine, kind: bytecode::RaiseKind) -> FrameResult { + let cause = match kind { + bytecode::RaiseKind::RaiseCause => { let val = self.pop_value(); Some(if vm.is_none(&val) { // if the cause arg is none, we clear the cause @@ -1287,19 +1282,19 @@ impl ExecutingFrame<'_> { }) } // if there's no cause arg, we keep the cause as is - _ => None, + bytecode::RaiseKind::Raise | bytecode::RaiseKind::Reraise => None, }; - let exception = match argc { - 0 => vm + let exception = match kind { + bytecode::RaiseKind::RaiseCause | bytecode::RaiseKind::Raise => { + ExceptionCtor::try_from_object(vm, self.pop_value())?.instantiate(vm)? + } + bytecode::RaiseKind::Reraise => vm .current_exception() .ok_or_else(|| vm.new_runtime_error("No active exception to reraise".to_owned()))?, - 1 | 2 => ExceptionCtor::try_from_object(vm, self.pop_value())?.instantiate(vm)?, - 3 => panic!("Not implemented!"), - _ => panic!("Invalid parameter for RAISE_VARARGS, must be between 0 to 3"), }; - let context = match argc { - 0 => None, // We have already got the exception, - _ => vm.current_exception(), + let context = match kind { + bytecode::RaiseKind::RaiseCause | bytecode::RaiseKind::Raise => vm.current_exception(), + bytecode::RaiseKind::Reraise => None, // We have already got the current exception }; info!( "Exception raised: {:?} with cause: {:?} and context: {:?}", @@ -1620,7 +1615,7 @@ impl ExecutingFrame<'_> { } fn load_attr(&mut self, vm: &VirtualMachine, attr: bytecode::NameIdx) -> FrameResult { - let attr_name = self.code.names[attr].clone(); + let attr_name = self.code.names[attr as usize].clone(); let parent = self.pop_value(); let obj = vm.get_attribute(parent, attr_name)?; self.push_value(obj); @@ -1628,7 +1623,7 @@ impl ExecutingFrame<'_> { } fn store_attr(&mut self, vm: &VirtualMachine, attr: bytecode::NameIdx) -> FrameResult { - let attr_name = self.code.names[attr].clone(); + let attr_name = self.code.names[attr as usize].clone(); let parent = self.pop_value(); let value = self.pop_value(); vm.set_attr(&parent, attr_name, value)?; @@ -1636,13 +1631,13 @@ impl ExecutingFrame<'_> { } fn delete_attr(&mut self, vm: &VirtualMachine, attr: bytecode::NameIdx) -> FrameResult { - let attr_name = self.code.names[attr].clone().into_object(); + let attr_name = self.code.names[attr as usize].clone().into_object(); let parent = self.pop_value(); vm.del_attr(&parent, attr_name)?; Ok(None) } - fn lasti(&self) -> usize { + fn lasti(&self) -> u32 { // it's okay to make this Relaxed, because we know that we only // mutate lasti if the mutex is held, and any other thread that // wants to guarantee the value of this will use a Lock anyway @@ -1686,8 +1681,8 @@ impl ExecutingFrame<'_> { self.state.stack.last().unwrap().clone() } - fn nth_value(&self, depth: usize) -> PyObjectRef { - self.state.stack[self.state.stack.len() - depth - 1].clone() + fn nth_value(&self, depth: u32) -> PyObjectRef { + self.state.stack[self.state.stack.len() - depth as usize - 1].clone() } }