Skip to content

Commit 6f95acc

Browse files
authored
Merge pull request #78 from maciejhirsz/0.9.1
0.9.1
2 parents e9fc7db + 9c2a568 commit 6f95acc

File tree

5 files changed

+372
-170
lines changed

5 files changed

+372
-170
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "json"
3-
version = "0.9.0"
3+
version = "0.9.1"
44
authors = ["Maciej Hirsz <maciej.hirsz@gmail.com>"]
55
description = "JSON implementation in Rust"
66
repository = "https://github.com/maciejhirsz/json-rust"

src/object.rs

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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 {
230228
impl 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

Comments
 (0)