Skip to content

Commit 4e9f9ff

Browse files
committed
change Dict Entries type Vec<DictEntry> to Vec<Option<DictEntry>>
1 parent b1207ab commit 4e9f9ff

File tree

1 file changed

+55
-31
lines changed

1 file changed

+55
-31
lines changed

vm/src/dictdatatype.rs

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type EntryIndex = usize;
2525
pub struct Dict<T = PyObjectRef> {
2626
inner: PyRwLock<DictInner<T>>,
2727
}
28+
2829
impl<T> fmt::Debug for Dict<T> {
2930
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3031
f.debug_struct("Debug").finish()
@@ -37,10 +38,12 @@ enum IndexEntry {
3738
Free,
3839
Index(usize),
3940
}
41+
4042
impl IndexEntry {
4143
const FREE: i64 = -1;
4244
const DUMMY: i64 = -2;
4345
}
46+
4447
impl From<i64> for IndexEntry {
4548
fn from(idx: i64) -> Self {
4649
match idx {
@@ -50,6 +53,7 @@ impl From<i64> for IndexEntry {
5053
}
5154
}
5255
}
56+
5357
impl From<IndexEntry> for i64 {
5458
fn from(idx: IndexEntry) -> Self {
5559
match idx {
@@ -65,7 +69,7 @@ struct DictInner<T> {
6569
used: usize,
6670
filled: usize,
6771
indices: Vec<i64>,
68-
entries: Vec<DictEntry<T>>,
72+
entries: Vec<Option<DictEntry<T>>>,
6973
}
7074

7175
impl<T: Clone> Clone for Dict<T> {
@@ -143,15 +147,19 @@ impl<T> DictInner<T> {
143147
self.indices = vec![IndexEntry::FREE; new_size];
144148
let mask = (new_size - 1) as i64;
145149
for (entry_idx, entry) in self.entries.iter_mut().enumerate() {
146-
let mut idxs = GenIndexes::new(entry.hash, mask);
147-
loop {
148-
let index_index = idxs.next();
149-
let idx = &mut self.indices[index_index];
150-
if *idx == IndexEntry::FREE {
151-
*idx = entry_idx as i64;
152-
entry.index = index_index;
153-
break;
150+
if let Some(entry) = entry {
151+
let mut idxs = GenIndexes::new(entry.hash, mask);
152+
loop {
153+
let index_index = idxs.next();
154+
let idx = &mut self.indices[index_index];
155+
if *idx == IndexEntry::FREE {
156+
*idx = entry_idx as i64;
157+
entry.index = index_index;
158+
break;
159+
}
154160
}
161+
} else {
162+
//removed entry
155163
}
156164
}
157165
self.filled = self.used;
@@ -172,7 +180,7 @@ impl<T> DictInner<T> {
172180
index,
173181
};
174182
let entry_index = self.entries.len();
175-
self.entries.push(entry);
183+
self.entries.push(Some(entry));
176184
self.indices[index] = entry_index as i64;
177185
self.used += 1;
178186
if let IndexEntry::Free = index_entry {
@@ -213,8 +221,8 @@ impl<T: Clone> Dict<T> {
213221

214222
/// Store a key
215223
pub fn insert<K>(&self, vm: &VirtualMachine, key: K, value: T) -> PyResult<()>
216-
where
217-
K: DictKey,
224+
where
225+
K: DictKey,
218226
{
219227
let hash = key.key_hash(vm)?;
220228
let _removed = loop {
@@ -223,6 +231,7 @@ impl<T: Clone> Dict<T> {
223231
let mut inner = self.write();
224232
// Update existing key
225233
if let Some(entry) = inner.entries.get_mut(index) {
234+
let entry = entry.as_mut().unwrap();
226235
if entry.index == index_index {
227236
let removed = std::mem::replace(&mut entry.value, value);
228237
// defer dec RC
@@ -266,6 +275,7 @@ impl<T: Clone> Dict<T> {
266275
if let IndexEntry::Index(index) = entry {
267276
let inner = self.read();
268277
if let Some(entry) = inner.entries.get(index) {
278+
let entry = entry.as_ref().unwrap();
269279
if entry.index == index_index {
270280
break Some(entry.value.clone());
271281
} else {
@@ -310,8 +320,8 @@ impl<T: Clone> Dict<T> {
310320

311321
/// Delete a key
312322
pub fn delete<K>(&self, vm: &VirtualMachine, key: K) -> PyResult<()>
313-
where
314-
K: DictKey,
323+
where
324+
K: DictKey,
315325
{
316326
if self.delete_if_exists(vm, &key)? {
317327
Ok(())
@@ -321,8 +331,8 @@ impl<T: Clone> Dict<T> {
321331
}
322332

323333
pub fn delete_if_exists<K>(&self, vm: &VirtualMachine, key: &K) -> PyResult<bool>
324-
where
325-
K: DictKey,
334+
where
335+
K: DictKey,
326336
{
327337
let hash = key.key_hash(vm)?;
328338
let deleted = loop {
@@ -366,9 +376,9 @@ impl<T: Clone> Dict<T> {
366376
}
367377

368378
pub fn setdefault<K, F>(&self, vm: &VirtualMachine, key: K, default: F) -> PyResult<T>
369-
where
370-
K: DictKey,
371-
F: FnOnce() -> T,
379+
where
380+
K: DictKey,
381+
F: FnOnce() -> T,
372382
{
373383
let hash = key.key_hash(vm)?;
374384
let res = loop {
@@ -377,6 +387,7 @@ impl<T: Clone> Dict<T> {
377387
if let IndexEntry::Index(index) = entry {
378388
let inner = self.read();
379389
if let Some(entry) = inner.entries.get(index) {
390+
let entry = entry.as_ref().unwrap();
380391
if entry.index == index_index {
381392
break entry.value.clone();
382393
} else {
@@ -408,9 +419,9 @@ impl<T: Clone> Dict<T> {
408419
key: K,
409420
default: F,
410421
) -> PyResult<(PyObjectRef, T)>
411-
where
412-
K: DictKey,
413-
F: FnOnce() -> T,
422+
where
423+
K: DictKey,
424+
F: FnOnce() -> T,
414425
{
415426
let hash = key.key_hash(vm)?;
416427
let res = loop {
@@ -419,6 +430,7 @@ impl<T: Clone> Dict<T> {
419430
if let IndexEntry::Index(index) = entry {
420431
let inner = self.read();
421432
if let Some(entry) = inner.entries.get(index) {
433+
let entry = entry.as_ref().unwrap();
422434
if entry.index == index_index {
423435
break (entry.key.clone(), entry.value.clone());
424436
} else {
@@ -453,10 +465,18 @@ impl<T: Clone> Dict<T> {
453465
}
454466

455467
pub fn next_entry(&self, position: &mut EntryIndex) -> Option<(PyObjectRef, T)> {
456-
self.read().entries.get(*position).map(|entry| {
457-
*position += 1;
458-
(entry.key.clone(), entry.value.clone())
459-
})
468+
let inner = self.read();
469+
loop {
470+
let entry = inner.entries.get(*position);
471+
if let Some(entry) = entry {
472+
*position += 1;
473+
if let Some(entry) = entry {
474+
break Some((entry.key.clone(), entry.value.clone()));
475+
}
476+
} else {
477+
break None;
478+
}
479+
}
460480
}
461481

462482
pub fn len_from_entry_index(&self, position: EntryIndex) -> usize {
@@ -469,7 +489,9 @@ impl<T: Clone> Dict<T> {
469489
}
470490

471491
pub fn keys(&self) -> Vec<PyObjectRef> {
472-
self.read().entries.iter().map(|v| v.key.clone()).collect()
492+
self.read().entries.iter()
493+
.filter(|v| v.is_some())
494+
.map(|v| v.as_ref().unwrap().key.clone()).collect()
473495
}
474496

475497
/// Lookup the index for the given key.
@@ -505,7 +527,7 @@ impl<T: Clone> Dict<T> {
505527
return Ok(idxs);
506528
}
507529
IndexEntry::Index(i) => {
508-
let entry = &inner.entries[i];
530+
let entry = &inner.entries[i].as_ref().unwrap();
509531
let ret = (IndexEntry::Index(i), index_index);
510532
if key.key_is(&entry.key) {
511533
break 'outer ret;
@@ -540,7 +562,7 @@ impl<T: Clone> Dict<T> {
540562
return Ok(None);
541563
};
542564
let mut inner = self.write();
543-
if matches!(inner.entries.get(entry_index), Some(entry) if entry.index == index_index) {
565+
if matches!(inner.entries.get(entry_index), Some(entry) if entry.as_ref().unwrap().index == index_index) {
544566
// all good
545567
} else {
546568
// The dict was changed since we did lookup. Let's try again.
@@ -551,12 +573,12 @@ impl<T: Clone> Dict<T> {
551573
let removed = if entry_index == inner.used {
552574
inner.entries.pop().unwrap()
553575
} else {
554-
let last_index = inner.entries.last().unwrap().index;
576+
let last_index = inner.entries.last().unwrap().as_ref().unwrap().index;
555577
let removed = inner.entries.swap_remove(entry_index);
556578
inner.indices[last_index] = entry_index as i64;
557579
removed
558580
};
559-
Ok(Some(removed))
581+
Ok(Some(removed.unwrap()))
560582
}
561583

562584
/// Retrieve and delete a key
@@ -576,6 +598,7 @@ impl<T: Clone> Dict<T> {
576598
pub fn pop_back(&self) -> Option<(PyObjectRef, T)> {
577599
let mut inner = self.write();
578600
inner.entries.pop().map(|entry| {
601+
let entry = entry.unwrap();
579602
inner.used -= 1;
580603
inner.indices[entry.index] = IndexEntry::DUMMY;
581604
(entry.key, entry.value)
@@ -638,6 +661,7 @@ impl DictKey for PyStrRef {
638661
}
639662
}
640663
}
664+
641665
impl DictKey for PyRefExact<PyStr> {
642666
fn key_hash(&self, vm: &VirtualMachine) -> PyResult<HashValue> {
643667
(**self).key_hash(vm)

0 commit comments

Comments
 (0)