diff --git a/Cargo.lock b/Cargo.lock index 725e2ad50..ed6d2ebd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1101,7 +1101,7 @@ checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" [[package]] name = "lock_api" version = "0.4.2" -source = "git+https://github.com/coolreader18/parking_lot?branch=remutex-is_owned#391cf555e94c05450cea2e88b42c95c6631ab163" +source = "git+https://github.com/Amanieu/parking_lot#2b3032f95d4aa5b1ccdf41b937c60603f569763c" dependencies = [ "scopeguard", ] diff --git a/bytecode/src/lib.rs b/bytecode/src/lib.rs index 49b8b7d20..73e2e173d 100644 --- a/bytecode/src/lib.rs +++ b/bytecode/src/lib.rs @@ -11,7 +11,7 @@ use num_bigint::BigInt; use num_complex::Complex64; use serde::{Deserialize, Serialize}; use std::collections::BTreeSet; -use std::fmt; +use std::{fmt, hash}; /// Sourcecode location. #[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)] @@ -103,7 +103,7 @@ impl ConstantBag for BasicBag { /// Primary container of a single code object. Each python function has /// a codeobject. Also a module has a codeobject. -#[derive(Clone, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] pub struct CodeObject { pub instructions: Box<[Instruction]>, pub locations: Box<[Location]>, @@ -400,8 +400,9 @@ bitflags! { } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum ConstantData { + Tuple { elements: Vec }, Integer { value: BigInt }, Float { value: f64 }, Complex { value: Complex64 }, @@ -409,11 +410,56 @@ pub enum ConstantData { Str { value: String }, Bytes { value: Vec }, Code { code: Box }, - Tuple { elements: Vec }, None, Ellipsis, } +impl PartialEq for ConstantData { + fn eq(&self, other: &Self) -> bool { + use ConstantData::*; + match (self, other) { + (Integer { value: a }, Integer { value: b }) => a == b, + // we want to compare floats *by actual value* - if we have the *exact same* float + // already in a constant cache, we want to use that + (Float { value: a }, Float { value: b }) => a.to_bits() == b.to_bits(), + (Complex { value: a }, Complex { value: b }) => { + a.re.to_bits() == b.re.to_bits() && a.im.to_bits() == b.im.to_bits() + } + (Boolean { value: a }, Boolean { value: b }) => a == b, + (Str { value: a }, Str { value: b }) => a == b, + (Bytes { value: a }, Bytes { value: b }) => a == b, + (Code { code: a }, Code { code: b }) => std::ptr::eq(a.as_ref(), b.as_ref()), + (Tuple { elements: a }, Tuple { elements: b }) => a == b, + (None, None) => true, + (Ellipsis, Ellipsis) => true, + _ => false, + } + } +} +impl Eq for ConstantData {} + +impl hash::Hash for ConstantData { + fn hash(&self, state: &mut H) { + use ConstantData::*; + std::mem::discriminant(self).hash(state); + match self { + Integer { value } => value.hash(state), + Float { value } => value.to_bits().hash(state), + Complex { value } => { + value.re.to_bits().hash(state); + value.im.to_bits().hash(state); + } + Boolean { value } => value.hash(state), + Str { value } => value.hash(state), + Bytes { value } => value.hash(state), + Code { code } => std::ptr::hash(code.as_ref(), state), + Tuple { elements } => elements.hash(state), + None => {} + Ellipsis => {} + } + } +} + pub enum BorrowedConstant<'a, C: Constant> { Integer { value: &'a BigInt }, Float { value: f64 }, diff --git a/compiler/src/compile.rs b/compiler/src/compile.rs index e25bd7c01..3dfd7731a 100644 --- a/compiler/src/compile.rs +++ b/compiler/src/compile.rs @@ -157,7 +157,7 @@ impl Compiler { blocks: vec![ir::Block::default()], current_block: bytecode::Label(0), - constants: Vec::new(), + constants: IndexSet::default(), name_cache: IndexSet::default(), varname_cache: IndexSet::default(), cellvar_cache: IndexSet::default(), @@ -235,7 +235,7 @@ impl Compiler { blocks: vec![ir::Block::default()], current_block: bytecode::Label(0), - constants: Vec::new(), + constants: IndexSet::default(), name_cache: IndexSet::default(), varname_cache: IndexSet::default(), cellvar_cache, @@ -2377,8 +2377,7 @@ impl Compiler { fn emit_constant(&mut self, constant: ConstantData) { let info = self.current_codeinfo(); - let idx = info.constants.len() as u32; - info.constants.push(constant); + let idx = info.constants.insert_full(constant).0 as u32; self.emit(Instruction::LoadConst { idx }) } diff --git a/compiler/src/ir.rs b/compiler/src/ir.rs index 89cecc850..d2926bf6e 100644 --- a/compiler/src/ir.rs +++ b/compiler/src/ir.rs @@ -37,7 +37,7 @@ pub struct CodeInfo { pub blocks: Vec, pub current_block: BlockIdx, - pub constants: Vec, + pub constants: IndexSet, pub name_cache: IndexSet, pub varname_cache: IndexSet, pub cellvar_cache: IndexSet, @@ -104,7 +104,7 @@ impl CodeInfo { max_stacksize, instructions: instructions.into_boxed_slice(), locations: locations.into_boxed_slice(), - constants: constants.into(), + constants: constants.into_iter().collect(), names: name_cache.into_iter().collect(), varnames: varname_cache.into_iter().collect(), cellvars: cellvar_cache.into_iter().collect(),