Skip to content

Commit 9271bfc

Browse files
committed
Moved from using BigInt in set hash to u64, which is guaranteed to be of constant size - u64 seems easier than usize as it's the same size across all platforms.
1 parent cca16ff commit 9271bfc

2 files changed

Lines changed: 17 additions & 14 deletions

File tree

vm/src/obj/objset.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ use super::objiter;
1111
use super::objstr;
1212
use super::objint;
1313
use super::objtype;
14-
use num_bigint::BigInt;
14+
use std::hash::{Hash, Hasher};
1515
use std::collections::HashMap;
16+
use std::collections::hash_map::DefaultHasher;
1617

17-
pub fn get_elements(obj: &PyObjectRef) -> HashMap<BigInt, PyObjectRef> {
18+
pub fn get_elements(obj: &PyObjectRef) -> HashMap<u64, PyObjectRef> {
1819
if let PyObjectPayload::Set { elements } = &obj.borrow().payload {
1920
elements.clone()
2021
} else {
@@ -24,31 +25,33 @@ pub fn get_elements(obj: &PyObjectRef) -> HashMap<BigInt, PyObjectRef> {
2425

2526
fn perform_action_with_hash(
2627
vm: &mut VirtualMachine,
27-
elements: &mut HashMap<BigInt, PyObjectRef>,
28+
elements: &mut HashMap<u64, PyObjectRef>,
2829
item: &PyObjectRef,
2930
f: &Fn(
3031
&mut VirtualMachine,
31-
&mut HashMap<BigInt, PyObjectRef>,
32-
BigInt,
32+
&mut HashMap<u64, PyObjectRef>,
33+
u64,
3334
&PyObjectRef,
3435
) -> PyResult,
3536
) -> PyResult {
3637
let hash: PyObjectRef = vm.call_method(item, "__hash__", vec![])?;
3738

3839
let hash_value = objint::get_value(&hash);
39-
let key = hash_value.clone();
40+
let mut hasher = DefaultHasher::new();
41+
hash_value.hash(&mut hasher);
42+
let key = hasher.finish();
4043
f(vm, elements, key, item)
4144
}
4245

4346
fn insert_into_set(
4447
vm: &mut VirtualMachine,
45-
elements: &mut HashMap<BigInt, PyObjectRef>,
48+
elements: &mut HashMap<u64, PyObjectRef>,
4649
item: &PyObjectRef,
4750
) -> PyResult {
4851
fn insert(
4952
vm: &mut VirtualMachine,
50-
elements: &mut HashMap<BigInt, PyObjectRef>,
51-
key: BigInt,
53+
elements: &mut HashMap<u64, PyObjectRef>,
54+
key: u64,
5255
value: &PyObjectRef,
5356
) -> PyResult {
5457
elements.insert(key, value.clone());
@@ -85,8 +88,8 @@ fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
8588
PyObjectPayload::Set { ref mut elements } => {
8689
fn remove(
8790
vm: &mut VirtualMachine,
88-
elements: &mut HashMap<BigInt, PyObjectRef>,
89-
key: BigInt,
91+
elements: &mut HashMap<u64, PyObjectRef>,
92+
key: u64,
9093
value: &PyObjectRef,
9194
) -> PyResult {
9295
match elements.remove(&key) {
@@ -116,7 +119,7 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
116119
return Err(vm.new_type_error(format!("{} is not a subtype of set", cls.borrow())));
117120
}
118121

119-
let elements: HashMap<BigInt, PyObjectRef> = match iterable {
122+
let elements: HashMap<u64, PyObjectRef> = match iterable {
120123
None => HashMap::new(),
121124
Some(iterable) => {
122125
let mut elements = HashMap::new();

vm/src/pyobject.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ impl PyContext {
491491
pub fn new_set(&self) -> PyObjectRef {
492492
// Initialized empty, as calling __hash__ is required for adding each object to the set
493493
// which requires a VM context - this is done in the objset code itself.
494-
let elements: HashMap<BigInt, PyObjectRef> = HashMap::new();
494+
let elements: HashMap<u64, PyObjectRef> = HashMap::new();
495495
PyObject::new(PyObjectPayload::Set { elements: elements }, self.set_type())
496496
}
497497

@@ -909,7 +909,7 @@ pub enum PyObjectPayload {
909909
elements: objdict::DictContentType,
910910
},
911911
Set {
912-
elements: HashMap<BigInt, PyObjectRef>,
912+
elements: HashMap<u64, PyObjectRef>,
913913
},
914914
Iterator {
915915
position: usize,

0 commit comments

Comments
 (0)