Skip to content

Shave an instruction off len() #357

@overlookmotel

Description

@overlookmotel

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions