@@ -115,13 +115,13 @@ impl Node {
115
115
}
116
116
117
117
#[ inline( always) ]
118
- fn new ( value : JsonValue ) -> Node {
118
+ fn new ( value : JsonValue , hash : u64 , len : usize ) -> Node {
119
119
unsafe {
120
120
Node {
121
121
key_buf : mem:: uninitialized ( ) ,
122
- key_len : 0 ,
122
+ key_len : len ,
123
123
key_ptr : mem:: uninitialized ( ) ,
124
- key_hash : mem :: uninitialized ( ) ,
124
+ key_hash : hash ,
125
125
value : value,
126
126
left : 0 ,
127
127
right : 0 ,
@@ -134,20 +134,18 @@ impl Node {
134
134
// `Node`, only once the `Node` is somewhere on the heap, a persisting
135
135
// pointer to the key can be obtained.
136
136
#[ inline( always) ]
137
- fn attach_key ( & mut self , key : & [ u8 ] , hash : u64 ) {
138
- self . key_len = key. len ( ) ;
139
- self . key_hash = hash;
140
- if key. len ( ) <= KEY_BUF_LEN {
137
+ fn attach_key ( & mut self , key : & [ u8 ] ) {
138
+ if self . key_len <= KEY_BUF_LEN {
141
139
unsafe {
142
140
ptr:: copy_nonoverlapping (
143
141
key. as_ptr ( ) ,
144
142
self . key_buf . as_mut_ptr ( ) ,
145
- key . len ( )
143
+ self . key_len
146
144
) ;
147
145
}
148
146
self . key_ptr = self . key_buf . as_mut_ptr ( ) ;
149
147
} else {
150
- let mut heap: Vec < u8 > = key. to_vec ( ) ;
148
+ let mut heap = key. to_vec ( ) ;
151
149
self . key_ptr = heap. as_mut_ptr ( ) ;
152
150
mem:: forget ( heap) ;
153
151
}
@@ -230,6 +228,7 @@ pub struct Object {
230
228
impl Object {
231
229
/// Create a new, empty instance of `Object`. Empty `Object` performs no
232
230
/// allocation until a value is inserted into it.
231
+ #[ inline( always) ]
233
232
pub fn new ( ) -> Self {
234
233
Object {
235
234
store : Vec :: new ( )
@@ -238,23 +237,24 @@ impl Object {
238
237
239
238
/// Create a new `Object` with memory preallocated for `capacity` number
240
239
/// of entries.
240
+ #[ inline( always) ]
241
241
pub fn with_capacity ( capacity : usize ) -> Self {
242
242
Object {
243
243
store : Vec :: with_capacity ( capacity)
244
244
}
245
245
}
246
246
247
+ #[ inline( always) ]
247
248
fn node_at_index < ' a > ( & self , index : usize ) -> & ' a Node {
248
- let store_ptr = self . store . as_ptr ( ) ;
249
249
unsafe {
250
- & * store_ptr . offset ( index as isize )
250
+ & * self . store . as_ptr ( ) . offset ( index as isize )
251
251
}
252
252
}
253
253
254
+ #[ inline( always) ]
254
255
fn node_at_index_mut < ' a > ( & mut self , index : usize ) -> & ' a mut Node {
255
- let store_ptr = self . store . as_mut_ptr ( ) ;
256
256
unsafe {
257
- & mut * store_ptr . offset ( index as isize )
257
+ & mut * self . store . as_mut_ptr ( ) . offset ( index as isize )
258
258
}
259
259
}
260
260
@@ -263,15 +263,35 @@ impl Object {
263
263
let index = self . store . len ( ) ;
264
264
265
265
if index < self . store . capacity ( ) {
266
- self . store . push ( Node :: new ( value) ) ;
267
- self . store [ index] . attach_key ( key, hash) ;
266
+ // Because we've just checked the capacity, we can avoid
267
+ // using `push`, and instead do unsafe magic to memcpy
268
+ // the new node at the correct index without additional
269
+ // capacity or bound checks.
270
+ unsafe {
271
+ let node = Node :: new ( value, hash, key. len ( ) ) ;
272
+ self . store . set_len ( index + 1 ) ;
273
+
274
+ // To whomever gets concerned: I got better results with
275
+ // copy than write. Difference in benchmarks wasn't big though.
276
+ ptr:: copy_nonoverlapping (
277
+ & node as * const Node ,
278
+ self . store . as_mut_ptr ( ) . offset ( index as isize ) ,
279
+ 1 ,
280
+ ) ;
281
+
282
+ // Since the Node has been copied, we need to forget about
283
+ // the owned value, else we may run into use after free.
284
+ mem:: forget ( node) ;
285
+ }
286
+ self . node_at_index_mut ( index) . attach_key ( key) ;
268
287
} else {
269
- self . store . push ( Node :: new ( value) ) ;
270
- self . store [ index] . attach_key ( key, hash ) ;
288
+ self . store . push ( Node :: new ( value, hash , key . len ( ) ) ) ;
289
+ self . node_at_index_mut ( index) . attach_key ( key) ;
271
290
272
- // FIXME: don't fix the last element again
273
- for node in self . store . iter_mut ( ) {
274
- node. fix_key_ptr ( ) ;
291
+ // Index up to the index (old length), we don't need to fix
292
+ // anything on the Node that just got pushed.
293
+ for i in 0 .. index {
294
+ self . node_at_index_mut ( i) . fix_key_ptr ( ) ;
275
295
}
276
296
}
277
297
@@ -287,8 +307,8 @@ impl Object {
287
307
let hash = hash_key ( key) ;
288
308
289
309
if self . store . len ( ) == 0 {
290
- self . store . push ( Node :: new ( value) ) ;
291
- self . store [ 0 ] . attach_key ( key, hash ) ;
310
+ self . store . push ( Node :: new ( value, hash , key . len ( ) ) ) ;
311
+ self . store [ 0 ] . attach_key ( key) ;
292
312
return ;
293
313
}
294
314
@@ -430,10 +450,12 @@ impl Object {
430
450
Some ( removed)
431
451
}
432
452
453
+ #[ inline( always) ]
433
454
pub fn len ( & self ) -> usize {
434
455
self . store . len ( )
435
456
}
436
457
458
+ #[ inline( always) ]
437
459
pub fn is_empty ( & self ) -> bool {
438
460
self . store . is_empty ( )
439
461
}
0 commit comments