-
Notifications
You must be signed in to change notification settings - Fork 56
Description
I believe it's possible to shave an instruction off len() (and probably as_slice() too) if static string had same discriminant as heap.
Static string could instead be represented as a heap string with capacity 0, which I assume isn't otherwise a possible state. Then:
const HEAP_MASK_AFTER_SUB: usize = (HEAP_MASK as usize)
.wrapping_sub(LENGTH_MASK as usize);
pub fn len(&self) -> usize {
let len_heap = ensure_read(self.1);
let last_byte = self.last_byte() as usize;
let mut len = last_byte.wrapping_sub(LENGTH_MASK as usize);
let is_heap = len == HEAP_MASK_AFTER_SUB;
len = len.min(MAX_SIZE);
if is_heap {
len = len_heap;
}
len
}On 64-bit machines, MAX_SIZE and HEAP_MASK_AFTER_SUB are the same (24). So this shaves off a cmp instruction as len == HEAP_MASK_AFTER_SUB and .min(MAX_SIZE) both work off the result of a single cmp, rather than requiring 2. And (if I'm reading the ASM right) it also uses one less register.
https://godbolt.org/z/e7Kc4PMTE
Quite possibly handling the special case of zero-capacity heap strings (which are actually static strings) would introduce costs elsewhere, but I'm not familiar enough with the code to say. Can anyone advise if that's likely to negate the gain?