@@ -115,13 +115,13 @@ impl Node {
115115 }
116116
117117 #[ inline( always) ]
118- fn new ( value : JsonValue ) -> Node {
118+ fn new ( value : JsonValue , hash : u64 , len : usize ) -> Node {
119119 unsafe {
120120 Node {
121121 key_buf : mem:: uninitialized ( ) ,
122- key_len : 0 ,
122+ key_len : len ,
123123 key_ptr : mem:: uninitialized ( ) ,
124- key_hash : mem :: uninitialized ( ) ,
124+ key_hash : hash ,
125125 value : value,
126126 left : 0 ,
127127 right : 0 ,
@@ -134,20 +134,18 @@ impl Node {
134134 // `Node`, only once the `Node` is somewhere on the heap, a persisting
135135 // pointer to the key can be obtained.
136136 #[ 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 {
141139 unsafe {
142140 ptr:: copy_nonoverlapping (
143141 key. as_ptr ( ) ,
144142 self . key_buf . as_mut_ptr ( ) ,
145- key . len ( )
143+ self . key_len
146144 ) ;
147145 }
148146 self . key_ptr = self . key_buf . as_mut_ptr ( ) ;
149147 } else {
150- let mut heap: Vec < u8 > = key. to_vec ( ) ;
148+ let mut heap = key. to_vec ( ) ;
151149 self . key_ptr = heap. as_mut_ptr ( ) ;
152150 mem:: forget ( heap) ;
153151 }
@@ -230,6 +228,7 @@ pub struct Object {
230228impl Object {
231229 /// Create a new, empty instance of `Object`. Empty `Object` performs no
232230 /// allocation until a value is inserted into it.
231+ #[ inline( always) ]
233232 pub fn new ( ) -> Self {
234233 Object {
235234 store : Vec :: new ( )
@@ -238,23 +237,24 @@ impl Object {
238237
239238 /// Create a new `Object` with memory preallocated for `capacity` number
240239 /// of entries.
240+ #[ inline( always) ]
241241 pub fn with_capacity ( capacity : usize ) -> Self {
242242 Object {
243243 store : Vec :: with_capacity ( capacity)
244244 }
245245 }
246246
247+ #[ inline( always) ]
247248 fn node_at_index < ' a > ( & self , index : usize ) -> & ' a Node {
248- let store_ptr = self . store . as_ptr ( ) ;
249249 unsafe {
250- & * store_ptr . offset ( index as isize )
250+ & * self . store . as_ptr ( ) . offset ( index as isize )
251251 }
252252 }
253253
254+ #[ inline( always) ]
254255 fn node_at_index_mut < ' a > ( & mut self , index : usize ) -> & ' a mut Node {
255- let store_ptr = self . store . as_mut_ptr ( ) ;
256256 unsafe {
257- & mut * store_ptr . offset ( index as isize )
257+ & mut * self . store . as_mut_ptr ( ) . offset ( index as isize )
258258 }
259259 }
260260
@@ -263,15 +263,35 @@ impl Object {
263263 let index = self . store . len ( ) ;
264264
265265 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) ;
268287 } 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) ;
271290
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 ( ) ;
275295 }
276296 }
277297
@@ -287,8 +307,8 @@ impl Object {
287307 let hash = hash_key ( key) ;
288308
289309 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) ;
292312 return ;
293313 }
294314
@@ -430,10 +450,12 @@ impl Object {
430450 Some ( removed)
431451 }
432452
453+ #[ inline( always) ]
433454 pub fn len ( & self ) -> usize {
434455 self . store . len ( )
435456 }
436457
458+ #[ inline( always) ]
437459 pub fn is_empty ( & self ) -> bool {
438460 self . store . is_empty ( )
439461 }
0 commit comments