Skip to content

[Perf] - can we remove usage of GcRefCell in the inline_cache? #5399

Description

@jasonwilliams

Describe the bug
When running the "Richards" test, a high proportion of cache misses are coming from the inline cache.
Image

This is because the IC goes through a GcRefCell borrow to get entries:

pub(crate) entries: GcRefCell<ArrayVec<CacheEntry, PIC_CAPACITY>>,

When these are borrowed here, its nearly always a cache miss.

We have 2 options.

  1. As the hot path is through the some branch the mutable borrow isn't even needed, as thats only used when a weakShape has been collected, so most of these calls don't even need a mutable borrow, a shared one should be fine and offer less over head.

A quick fix could be something like this:

 pub(crate) fn get(&self, shape: &Shape) -> Option<(Shape, Slot)> {
      if self.megamorphic.get() { return None; }

      let entries = self.entries.borrow();   // shared borrow — no write to borrow flag
      let shape_addr = shape.to_addr_usize();

      for (i, entry) in entries.iter().enumerate() {
          if let Some(upgraded) = entry.shape.upgrade() {
              if upgraded.to_addr_usize() == shape_addr {
                  return Some((upgraded, entry.slot));
              }
          } else {
              // stale entry found — drop shared borrow, take exclusive, clean up
              drop(entries);
              let mut entries = self.entries.borrow_mut();
              entries.swap_remove(i);
              return None;  // shape didn't match anyway (it was stale)
          }
      }
      None
  }

2: Do we need to wrap in GcRefCell at all? CacheEntry only holds a weakShape, so probably doesn't require the wrapping in GcRefCell as by its very nature a weakShape wouldn't keep the value alive anyway. Could we just swap this to a Cell and have this still work?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions