Skip to content

Commit 322aba3

Browse files
committed
Impl Eq+Hash for ConstantData, make CodeInfo.constants an IndexSet
1 parent c63a429 commit 322aba3

4 files changed

Lines changed: 56 additions & 11 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bytecode/src/lib.rs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use num_bigint::BigInt;
1111
use num_complex::Complex64;
1212
use serde::{Deserialize, Serialize};
1313
use std::collections::BTreeSet;
14-
use std::fmt;
14+
use std::{fmt, hash};
1515

1616
/// Sourcecode location.
1717
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
@@ -103,7 +103,7 @@ impl ConstantBag for BasicBag {
103103

104104
/// Primary container of a single code object. Each python function has
105105
/// a codeobject. Also a module has a codeobject.
106-
#[derive(Clone, PartialEq, Serialize, Deserialize)]
106+
#[derive(Clone, Serialize, Deserialize)]
107107
pub struct CodeObject<C: Constant = ConstantData> {
108108
pub instructions: Box<[Instruction]>,
109109
pub locations: Box<[Location]>,
@@ -400,20 +400,66 @@ bitflags! {
400400
}
401401
}
402402

403-
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
403+
#[derive(Debug, Clone, Serialize, Deserialize)]
404404
pub enum ConstantData {
405+
Tuple { elements: Vec<ConstantData> },
405406
Integer { value: BigInt },
406407
Float { value: f64 },
407408
Complex { value: Complex64 },
408409
Boolean { value: bool },
409410
Str { value: String },
410411
Bytes { value: Vec<u8> },
411412
Code { code: Box<CodeObject> },
412-
Tuple { elements: Vec<ConstantData> },
413413
None,
414414
Ellipsis,
415415
}
416416

417+
impl PartialEq for ConstantData {
418+
fn eq(&self, other: &Self) -> bool {
419+
use ConstantData::*;
420+
match (self, other) {
421+
(Integer { value: a }, Integer { value: b }) => a == b,
422+
// we want to compare floats *by actual value* - if we have the *exact same* float
423+
// already in a constant cache, we want to use that
424+
(Float { value: a }, Float { value: b }) => a.to_bits() == b.to_bits(),
425+
(Complex { value: a }, Complex { value: b }) => {
426+
a.re.to_bits() == b.re.to_bits() && a.im.to_bits() == b.im.to_bits()
427+
}
428+
(Boolean { value: a }, Boolean { value: b }) => a == b,
429+
(Str { value: a }, Str { value: b }) => a == b,
430+
(Bytes { value: a }, Bytes { value: b }) => a == b,
431+
(Code { code: a }, Code { code: b }) => std::ptr::eq(a.as_ref(), b.as_ref()),
432+
(Tuple { elements: a }, Tuple { elements: b }) => a == b,
433+
(None, None) => true,
434+
(Ellipsis, Ellipsis) => true,
435+
_ => false,
436+
}
437+
}
438+
}
439+
impl Eq for ConstantData {}
440+
441+
impl hash::Hash for ConstantData {
442+
fn hash<H: hash::Hasher>(&self, state: &mut H) {
443+
use ConstantData::*;
444+
std::mem::discriminant(self).hash(state);
445+
match self {
446+
Integer { value } => value.hash(state),
447+
Float { value } => value.to_bits().hash(state),
448+
Complex { value } => {
449+
value.re.to_bits().hash(state);
450+
value.im.to_bits().hash(state);
451+
}
452+
Boolean { value } => value.hash(state),
453+
Str { value } => value.hash(state),
454+
Bytes { value } => value.hash(state),
455+
Code { code } => std::ptr::hash(code.as_ref(), state),
456+
Tuple { elements } => elements.hash(state),
457+
None => {}
458+
Ellipsis => {}
459+
}
460+
}
461+
}
462+
417463
pub enum BorrowedConstant<'a, C: Constant> {
418464
Integer { value: &'a BigInt },
419465
Float { value: f64 },

compiler/src/compile.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ impl Compiler {
157157

158158
blocks: vec![ir::Block::default()],
159159
current_block: bytecode::Label(0),
160-
constants: Vec::new(),
160+
constants: IndexSet::default(),
161161
name_cache: IndexSet::default(),
162162
varname_cache: IndexSet::default(),
163163
cellvar_cache: IndexSet::default(),
@@ -235,7 +235,7 @@ impl Compiler {
235235

236236
blocks: vec![ir::Block::default()],
237237
current_block: bytecode::Label(0),
238-
constants: Vec::new(),
238+
constants: IndexSet::default(),
239239
name_cache: IndexSet::default(),
240240
varname_cache: IndexSet::default(),
241241
cellvar_cache,
@@ -2377,8 +2377,7 @@ impl Compiler {
23772377

23782378
fn emit_constant(&mut self, constant: ConstantData) {
23792379
let info = self.current_codeinfo();
2380-
let idx = info.constants.len() as u32;
2381-
info.constants.push(constant);
2380+
let idx = info.constants.insert_full(constant).0 as u32;
23822381
self.emit(Instruction::LoadConst { idx })
23832382
}
23842383

compiler/src/ir.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub struct CodeInfo {
3737

3838
pub blocks: Vec<Block>,
3939
pub current_block: BlockIdx,
40-
pub constants: Vec<ConstantData>,
40+
pub constants: IndexSet<ConstantData>,
4141
pub name_cache: IndexSet<String>,
4242
pub varname_cache: IndexSet<String>,
4343
pub cellvar_cache: IndexSet<String>,
@@ -104,7 +104,7 @@ impl CodeInfo {
104104
max_stacksize,
105105
instructions: instructions.into_boxed_slice(),
106106
locations: locations.into_boxed_slice(),
107-
constants: constants.into(),
107+
constants: constants.into_iter().collect(),
108108
names: name_cache.into_iter().collect(),
109109
varnames: varname_cache.into_iter().collect(),
110110
cellvars: cellvar_cache.into_iter().collect(),

0 commit comments

Comments
 (0)