Skip to content

Commit 68fa9f4

Browse files
committed
Optimize map shim
1 parent d9f4f28 commit 68fa9f4

6 files changed

Lines changed: 222 additions & 81 deletions

File tree

‎rules/map/shim.rs‎

Lines changed: 54 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
use std::cell::RefCell;
55
use std::collections::BTreeMap;
6-
use std::ops::Bound;
76
use std::rc::{Rc, Weak};
87

98
use crate::{
@@ -87,11 +86,24 @@ impl<K, T> Default for Map<K, T> {
8786

8887
impl<K: 'static, T: 'static> ByteRepr for Map<K, T> {}
8988

90-
impl<K: Ord + Clone, T> Clone for Map<K, T> {
89+
impl<K: Ord + Clone, V: Clone> Clone for Map<K, (Value<K>, Value<V>)> {
9190
fn clone(&self) -> Self {
9291
let mut map = Self::default();
93-
for (key, value) in self.entries() {
94-
map.link(key.clone(), value);
92+
let mut prev = map.header.clone();
93+
for (key, node) in &self.nodes {
94+
let value = {
95+
let node = node.borrow();
96+
let entry = node
97+
.value
98+
.as_ref()
99+
.expect("map node without a value")
100+
.borrow();
101+
(
102+
Rc::new(RefCell::new(entry.0.borrow().clone())),
103+
Rc::new(RefCell::new(entry.1.borrow().clone())),
104+
)
105+
};
106+
prev = map.link_after(prev, key.clone(), Rc::new(RefCell::new(value)));
95107
}
96108
map
97109
}
@@ -117,23 +129,15 @@ impl<K, T> Map<K, T> {
117129
pub fn end(&self) -> BidirectionalIterator<T> {
118130
BidirectionalIterator::Map(self.header.clone())
119131
}
120-
121-
pub fn entries(&self) -> impl Iterator<Item = (&K, Value<T>)> + '_ {
122-
self.nodes.iter().map(|(key, node)| {
123-
let value = node.borrow().value.clone();
124-
(key, value.expect("map node without a value"))
125-
})
126-
}
127132
}
128133

129134
impl<K: Ord, T> Map<K, T> {
130-
fn link(&mut self, key: K, value: Value<T>) -> Value<MapNode<T>> {
131-
let prev = self
132-
.nodes
133-
.range((Bound::Unbounded, Bound::Excluded(&key)))
134-
.next_back()
135-
.map(|(_, node)| node.clone())
136-
.unwrap_or_else(|| self.header.clone());
135+
fn link_after(
136+
&mut self,
137+
prev: Value<MapNode<T>>,
138+
key: K,
139+
value: Value<T>,
140+
) -> Value<MapNode<T>> {
137141
let next = MapNode::next(&prev);
138142
let node = Rc::new(RefCell::new(MapNode {
139143
value: Some(value),
@@ -156,20 +160,22 @@ impl<K: Ord, T> Map<K, T> {
156160
}
157161

158162
pub fn get_or_insert_with(&mut self, key: K, value: impl FnOnce() -> T) -> Value<T> {
159-
if let Some(existing) = self.get(&key) {
160-
return existing;
161-
}
163+
let prev = match self.nodes.range(..=&key).next_back() {
164+
Some((k, node)) if *k == key => {
165+
return node
166+
.borrow()
167+
.value
168+
.clone()
169+
.expect("map node without a value");
170+
}
171+
Some((_, node)) => node.clone(),
172+
None => self.header.clone(),
173+
};
162174
let value = Rc::new(RefCell::new(value()));
163-
self.link(key, value.clone());
175+
self.link_after(prev, key, value.clone());
164176
value
165177
}
166178

167-
pub fn insert(&mut self, key: K, value: Value<T>) {
168-
if !self.nodes.contains_key(&key) {
169-
self.link(key, value);
170-
}
171-
}
172-
173179
pub fn find(&self, key: &K) -> BidirectionalIterator<T> {
174180
match self.nodes.get(key) {
175181
Some(node) => BidirectionalIterator::Map(node.clone()),
@@ -292,11 +298,10 @@ impl<K, T> Default for UnsafeMap<K, T> {
292298
impl<K: Ord + Clone, T: Clone> Clone for UnsafeMap<K, T> {
293299
fn clone(&self) -> Self {
294300
let mut map = Self::default();
301+
let mut prev = map.header_ptr();
295302
for (key, node) in &self.nodes {
296-
map.link(
297-
key.clone(),
298-
node.value.clone().expect("map node without a value"),
299-
);
303+
let value = node.value.clone().expect("map node without a value");
304+
prev = map.link_after(prev, key.clone(), value);
300305
}
301306
map
302307
}
@@ -340,13 +345,12 @@ impl<K, T> UnsafeMap<K, T> {
340345
}
341346

342347
impl<K: Ord, T> UnsafeMap<K, T> {
343-
fn link(&mut self, key: K, value: T) -> *mut UnsafeMapNode<T> {
344-
let prev = self
345-
.nodes
346-
.range((Bound::Unbounded, Bound::Excluded(&key)))
347-
.next_back()
348-
.map(|(_, node)| &**node as *const UnsafeMapNode<T> as *mut UnsafeMapNode<T>)
349-
.unwrap_or_else(|| self.header_ptr());
348+
fn link_after(
349+
&mut self,
350+
prev: *mut UnsafeMapNode<T>,
351+
key: K,
352+
value: T,
353+
) -> *mut UnsafeMapNode<T> {
350354
let next = UnsafeMapNode::next(prev);
351355
let mut node = Box::new(UnsafeMapNode {
352356
value: Some(value),
@@ -369,10 +373,17 @@ impl<K: Ord, T> UnsafeMap<K, T> {
369373
}
370374

371375
pub fn get_or_insert_with(&mut self, key: K, value: impl FnOnce() -> T) -> *mut T {
372-
if let Some(existing) = self.get(&key) {
373-
return existing;
374-
}
375-
UnsafeMapNode::value(self.link(key, value()))
376+
let prev = match self.nodes.range(..=&key).next_back() {
377+
Some((k, node)) => {
378+
let node = &**node as *const UnsafeMapNode<T> as *mut UnsafeMapNode<T>;
379+
if *k == key {
380+
return UnsafeMapNode::value(node);
381+
}
382+
node
383+
}
384+
None => self.header_ptr(),
385+
};
386+
UnsafeMapNode::value(self.link_after(prev, key, value()))
376387
}
377388

378389
pub fn find(&self, key: &K) -> UnsafeBidirectionalIterator<T> {

‎rules/map/tgt_refcount.rs‎

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,7 @@ fn f5<T1, T2>() -> Map<T1, (Value<T1>, Value<T2>)> {
4242
}
4343

4444
fn f6<T1: Ord + Clone, T2: Clone>(a0: Map<T1, (Value<T1>, Value<T2>)>) -> Map<T1, (Value<T1>, Value<T2>)> {
45-
let mut __m = Map::new();
46-
for (__k, __v) in a0.entries() {
47-
let __v = __v.borrow();
48-
__m.insert(
49-
__k.clone(),
50-
Rc::new(RefCell::new((
51-
Rc::new(RefCell::new(__v.0.borrow().clone())),
52-
Rc::new(RefCell::new(__v.1.borrow().clone())),
53-
))),
54-
);
55-
}
56-
__m
45+
a0.clone()
5746
}
5847

5948
fn f7<T1: Ord, T2>(a0: &mut Map<T1, (Value<T1>, Value<T2>)>, a1: T1) -> Ptr<T2> {
@@ -111,18 +100,7 @@ fn f25<T1: 'static, T2: 'static>(a0: Ptr<Map<T1, (Value<T1>, Value<T2>)>>, a1: P
111100
}
112101

113102
fn f26<T1: Ord + Clone + 'static, T2: Clone + 'static>(a0: Ptr<Map<T1, (Value<T1>, Value<T2>)>>, a1: Map<T1, (Value<T1>, Value<T2>)>) {
114-
let mut __m = Map::new();
115-
for (__k, __v) in a1.entries() {
116-
let __v = __v.borrow();
117-
__m.insert(
118-
__k.clone(),
119-
Rc::new(RefCell::new((
120-
Rc::new(RefCell::new(__v.0.borrow().clone())),
121-
Rc::new(RefCell::new(__v.1.borrow().clone())),
122-
))),
123-
);
124-
}
125-
a0.write(__m)
103+
a0.write(a1.clone())
126104
}
127105

128106
fn f27<T1: Ord + Clone + 'static, T2: 'static>(

‎tests/unit/map_copy.cpp‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <cassert>
2+
#include <map>
3+
4+
struct S {
5+
std::map<int, int> m;
6+
};
7+
8+
int main() {
9+
S a;
10+
a.m[1] = 10;
11+
S b = a;
12+
b.m[1] = 20;
13+
assert(a.m[1] == 10);
14+
std::map<int, int> x;
15+
x[2] = 3;
16+
std::map<int, int> y = x;
17+
y[2] = 4;
18+
assert(x[2] == 3);
19+
return 0;
20+
}

‎tests/unit/out/refcount/clone_vs_move.rs‎

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -274,20 +274,8 @@ fn main_0() -> i32 {
274274
.write(__rhs);
275275
i.prefix_inc();
276276
}
277-
let map2: Value<Map<i32, (Value<i32>, Value<i32>)>> = Rc::new(RefCell::new({
278-
let mut __m = Map::new();
279-
for (__k, __v) in (*map1.borrow()).entries() {
280-
let __v = __v.borrow();
281-
__m.insert(
282-
__k.clone(),
283-
Rc::new(RefCell::new((
284-
Rc::new(RefCell::new(__v.0.borrow().clone())),
285-
Rc::new(RefCell::new(__v.1.borrow().clone())),
286-
))),
287-
);
288-
}
289-
__m
290-
}));
277+
let map2: Value<Map<i32, (Value<i32>, Value<i32>)>> =
278+
Rc::new(RefCell::new((*map1.borrow()).clone()));
291279
let mut i: i32 = 0;
292280
'loop_: while (i < N) {
293281
assert!(
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)]
10+
#[byte_size(48)]
11+
pub struct S {
12+
#[offset(0)]
13+
#[byte_size(48)]
14+
pub m: Map<i32, (Value<i32>, Value<i32>)>,
15+
}
16+
pub fn main() {
17+
__cpp2rust_init_globals();
18+
std::process::exit(main_0());
19+
}
20+
fn main_0() -> i32 {
21+
let a: Value<S> = Rc::new(RefCell::new(<S>::default()));
22+
(field_ptr!(a.as_pointer(), m) as Ptr<Map<i32, (Value<i32>, Value<i32>)>>)
23+
.with_mut(|__m: &mut Map<i32, (Value<i32>, Value<i32>)>| {
24+
__m.get_or_insert_with(1.clone(), || {
25+
(
26+
Rc::new(RefCell::new(1)),
27+
Rc::new(RefCell::new(<i32>::default())),
28+
)
29+
})
30+
.borrow()
31+
.1
32+
.as_pointer()
33+
})
34+
.write(10);
35+
let b: Value<S> = Rc::new(RefCell::new((*a.borrow()).clone()));
36+
(field_ptr!(b.as_pointer(), m) as Ptr<Map<i32, (Value<i32>, Value<i32>)>>)
37+
.with_mut(|__m: &mut Map<i32, (Value<i32>, Value<i32>)>| {
38+
__m.get_or_insert_with(1.clone(), || {
39+
(
40+
Rc::new(RefCell::new(1)),
41+
Rc::new(RefCell::new(<i32>::default())),
42+
)
43+
})
44+
.borrow()
45+
.1
46+
.as_pointer()
47+
})
48+
.write(20);
49+
assert!(
50+
(((field_ptr!(a.as_pointer(), m) as Ptr<Map<i32, (Value<i32>, Value<i32>)>>)
51+
.with_mut(|__m: &mut Map<i32, (Value<i32>, Value<i32>)>| {
52+
__m.get_or_insert_with(1.clone(), || {
53+
(
54+
Rc::new(RefCell::new(1)),
55+
Rc::new(RefCell::new(<i32>::default())),
56+
)
57+
})
58+
.borrow()
59+
.1
60+
.as_pointer()
61+
})
62+
.read())
63+
== 10)
64+
);
65+
let x: Value<Map<i32, (Value<i32>, Value<i32>)>> = Rc::new(RefCell::new(Map::new()));
66+
(x.as_pointer() as Ptr<Map<i32, (Value<i32>, Value<i32>)>>)
67+
.with_mut(|__m: &mut Map<i32, (Value<i32>, Value<i32>)>| {
68+
__m.get_or_insert_with(2.clone(), || {
69+
(
70+
Rc::new(RefCell::new(2)),
71+
Rc::new(RefCell::new(<i32>::default())),
72+
)
73+
})
74+
.borrow()
75+
.1
76+
.as_pointer()
77+
})
78+
.write(3);
79+
let y: Value<Map<i32, (Value<i32>, Value<i32>)>> = Rc::new(RefCell::new((*x.borrow()).clone()));
80+
(y.as_pointer() as Ptr<Map<i32, (Value<i32>, Value<i32>)>>)
81+
.with_mut(|__m: &mut Map<i32, (Value<i32>, Value<i32>)>| {
82+
__m.get_or_insert_with(2.clone(), || {
83+
(
84+
Rc::new(RefCell::new(2)),
85+
Rc::new(RefCell::new(<i32>::default())),
86+
)
87+
})
88+
.borrow()
89+
.1
90+
.as_pointer()
91+
})
92+
.write(4);
93+
assert!(
94+
(((x.as_pointer() as Ptr<Map<i32, (Value<i32>, Value<i32>)>>)
95+
.with_mut(|__m: &mut Map<i32, (Value<i32>, Value<i32>)>| {
96+
__m.get_or_insert_with(2.clone(), || {
97+
(
98+
Rc::new(RefCell::new(2)),
99+
Rc::new(RefCell::new(<i32>::default())),
100+
)
101+
})
102+
.borrow()
103+
.1
104+
.as_pointer()
105+
})
106+
.read())
107+
== 3)
108+
);
109+
return 0;
110+
}
111+
pub fn __cpp2rust_init_globals() {}

‎tests/unit/out/unsafe/map_copy.rs‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
#[repr(C)]
10+
#[derive(Clone, VaArg, FnPtrArg, Default)]
11+
pub struct S {
12+
pub m: UnsafeMap<i32, (i32, i32)>,
13+
}
14+
pub fn main() {
15+
unsafe {
16+
__cpp2rust_init_globals();
17+
std::process::exit(main_0() as i32);
18+
}
19+
}
20+
unsafe fn main_0() -> i32 {
21+
let mut a: S = <S>::default();
22+
(*&mut (*a.m.get_or_insert_with(1.clone(), || (1, <i32>::default()))).1) = 10;
23+
let mut b: S = a.clone();
24+
(*&mut (*b.m.get_or_insert_with(1.clone(), || (1, <i32>::default()))).1) = 20;
25+
assert!(((*&mut (*a.m.get_or_insert_with(1.clone(), || (1, <i32>::default()))).1) == (10)));
26+
let mut x: UnsafeMap<i32, (i32, i32)> = UnsafeMap::new();
27+
(*&mut (*x.get_or_insert_with(2.clone(), || (2, <i32>::default()))).1) = 3;
28+
let mut y: UnsafeMap<i32, (i32, i32)> = x.clone();
29+
(*&mut (*y.get_or_insert_with(2.clone(), || (2, <i32>::default()))).1) = 4;
30+
assert!(((*&mut (*x.get_or_insert_with(2.clone(), || (2, <i32>::default()))).1) == (3)));
31+
return 0;
32+
}
33+
pub unsafe fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)