From 9271bfcb847f6e8e8ace1dbe4bd8bbed8eb34227 Mon Sep 17 00:00:00 2001 From: Matthew Constable Date: Sat, 9 Feb 2019 21:57:26 +0000 Subject: [PATCH] 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. --- vm/src/obj/objset.rs | 27 +++++++++++++++------------ vm/src/pyobject.rs | 4 ++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index 9e6166a91..88fde01c7 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -11,10 +11,11 @@ use super::objiter; use super::objstr; use super::objint; use super::objtype; -use num_bigint::BigInt; +use std::hash::{Hash, Hasher}; use std::collections::HashMap; +use std::collections::hash_map::DefaultHasher; -pub fn get_elements(obj: &PyObjectRef) -> HashMap { +pub fn get_elements(obj: &PyObjectRef) -> HashMap { if let PyObjectPayload::Set { elements } = &obj.borrow().payload { elements.clone() } else { @@ -24,31 +25,33 @@ pub fn get_elements(obj: &PyObjectRef) -> HashMap { fn perform_action_with_hash( vm: &mut VirtualMachine, - elements: &mut HashMap, + elements: &mut HashMap, item: &PyObjectRef, f: &Fn( &mut VirtualMachine, - &mut HashMap, - BigInt, + &mut HashMap, + u64, &PyObjectRef, ) -> PyResult, ) -> PyResult { let hash: PyObjectRef = vm.call_method(item, "__hash__", vec![])?; let hash_value = objint::get_value(&hash); - let key = hash_value.clone(); + let mut hasher = DefaultHasher::new(); + hash_value.hash(&mut hasher); + let key = hasher.finish(); f(vm, elements, key, item) } fn insert_into_set( vm: &mut VirtualMachine, - elements: &mut HashMap, + elements: &mut HashMap, item: &PyObjectRef, ) -> PyResult { fn insert( vm: &mut VirtualMachine, - elements: &mut HashMap, - key: BigInt, + elements: &mut HashMap, + key: u64, value: &PyObjectRef, ) -> PyResult { elements.insert(key, value.clone()); @@ -85,8 +88,8 @@ fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { PyObjectPayload::Set { ref mut elements } => { fn remove( vm: &mut VirtualMachine, - elements: &mut HashMap, - key: BigInt, + elements: &mut HashMap, + key: u64, value: &PyObjectRef, ) -> PyResult { match elements.remove(&key) { @@ -116,7 +119,7 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { return Err(vm.new_type_error(format!("{} is not a subtype of set", cls.borrow()))); } - let elements: HashMap = match iterable { + let elements: HashMap = match iterable { None => HashMap::new(), Some(iterable) => { let mut elements = HashMap::new(); diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index c97eb4cbb..1773d4896 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -491,7 +491,7 @@ impl PyContext { pub fn new_set(&self) -> PyObjectRef { // Initialized empty, as calling __hash__ is required for adding each object to the set // which requires a VM context - this is done in the objset code itself. - let elements: HashMap = HashMap::new(); + let elements: HashMap = HashMap::new(); PyObject::new(PyObjectPayload::Set { elements: elements }, self.set_type()) } @@ -909,7 +909,7 @@ pub enum PyObjectPayload { elements: objdict::DictContentType, }, Set { - elements: HashMap, + elements: HashMap, }, Iterator { position: usize,