Skip to content

Commit 636f507

Browse files
committed
---
yaml --- r: 98157 b: refs/heads/master c: e52f7c9 h: refs/heads/master i: 98155: 151f438 v: v3
1 parent e02ede7 commit 636f507

File tree

2 files changed

+30
-23
lines changed

2 files changed

+30
-23
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 1130886138f1dc6285ac2011c6bcabefd564bb7d
2+
refs/heads/master: e52f7c9239a0a523c04651f5eba3cad6f15fa217
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: b6400f998497c3958f40997a71756ead344a776d
55
refs/heads/try: c274a6888410ce3e357e014568b43310ed787d36

trunk/src/libextra/ebml.rs

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -130,32 +130,39 @@ pub mod reader {
130130
return vuint_at_slow(data, start);
131131
}
132132

133+
// Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/
134+
// The Element IDs are parsed by reading a big endian u32 positioned at data[start].
135+
// Using the four most significant bits of the u32 we lookup in the table below how the
136+
// element ID should be derived from it.
137+
//
138+
// The table stores tuples (shift, mask) where shift is the number the u32 should be right
139+
// shifted with and mask is the value the right shifted value should be masked with.
140+
// If for example the most significant bit is set this means it's a class A ID and the u32
141+
// should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at
142+
// index 0x8 - 0xF (four bit numbers where the most significant bit is set).
143+
//
144+
// By storing the number of shifts and masks in a table instead of checking in order if
145+
// the most significant bit is set, the second most significant bit is set etc. we can
146+
// replace up to three "and+branch" with a single table lookup which gives us a measured
147+
// speedup of around 2x on x86_64.
148+
static SHIFT_MASK_TABLE: [(u32, u32), ..16] = [
149+
(0, 0x0), (0, 0x0fffffff),
150+
(8, 0x1fffff), (8, 0x1fffff),
151+
(16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
152+
(24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
153+
];
154+
133155
unsafe {
134156
let (ptr, _): (*u8, uint) = transmute(data);
135157
let ptr = offset(ptr, start as int);
136158
let ptr: *i32 = transmute(ptr);
137-
let val = from_be32(*ptr);
138-
let val: u32 = transmute(val);
139-
if (val & 0x80000000) != 0 {
140-
Res {
141-
val: ((val >> 24) & 0x7f) as uint,
142-
next: start + 1
143-
}
144-
} else if (val & 0x40000000) != 0 {
145-
Res {
146-
val: ((val >> 16) & 0x3fff) as uint,
147-
next: start + 2
148-
}
149-
} else if (val & 0x20000000) != 0 {
150-
Res {
151-
val: ((val >> 8) & 0x1fffff) as uint,
152-
next: start + 3
153-
}
154-
} else {
155-
Res {
156-
val: (val & 0x0fffffff) as uint,
157-
next: start + 4
158-
}
159+
let val = from_be32(*ptr) as u32;
160+
161+
let i = (val >> 28u) as uint;
162+
let (shift, mask) = SHIFT_MASK_TABLE[i];
163+
Res {
164+
val: ((val >> shift) & mask) as uint,
165+
next: start + (((32 - shift) >> 3) as uint)
159166
}
160167
}
161168
}

0 commit comments

Comments
 (0)