Hi,

In bug 972712 I implemented class-based memory reporting. An example:

│   │  │  │  ├───0.69 MB (00.64%) -- compartment([System Principal],
resource://gre/modules/addons/XPIProvider.jsm)
│   │  │  │  │   ├──0.45 MB (00.42%) -- classes
│   │  │  │  │   │  ├──0.21 MB (00.20%) -- class(Function)
│   │  │  │  │   │  │  ├──0.16 MB (00.15%) -- objects
│   │  │  │  │   │  │  │  ├──0.16 MB (00.15%) ── gc-heap
│   │  │  │  │   │  │  │  └──0.00 MB (00.00%) ── malloc-heap/slots
│   │  │  │  │   │  │  └──0.05 MB (00.04%) -- shapes
│   │  │  │  │   │  │     ├──0.05 MB (00.04%) -- gc-heap
│   │  │  │  │   │  │     │  ├──0.03 MB (00.03%) ── base
│   │  │  │  │   │  │     │  └──0.02 MB (00.02%) ── tree
│   │  │  │  │   │  │     └──0.00 MB (00.00%) -- malloc-heap
│   │  │  │  │   │  │        ├──0.00 MB (00.00%) ── tree-kids
│   │  │  │  │   │  │        └──0.00 MB (00.00%) ── tree-tables

This is pretty nice, but I had to back it out a while ago due to
intermittent complaints from ASAN.

Here is the code that ASAN complains about:

      case JSTRACE_SHAPE: {
        Shape *shape = static_cast<Shape *>(thing);
        CompartmentStats *cStats = GetCompartmentStats(shape->compartment());

        JS::ClassInfo info;        // This zeroes all the sizes.
        if (shape->inDictionary())
            info.shapesGCHeapDict += thingSize;
        else
            info.shapesGCHeapTree += thingSize;
        shape->addSizeOfExcludingThis(rtStats->mallocSizeOf_, &info);

        cStats->classInfo.add(info);

        const BaseShape *base = shape->base();
        const Class *clasp = base->clasp();           // <-- ASAN complains
        const char *className = clasp->name;
        AddClassInfo(granularity, cStats, className, info);
        break;
      }

The code being complained about is just getting the shape's classname.

Here's example ASAN output (note that the first ASAN complaint is a
red herring; it's the second one that's relevant):

https://tbpl.mozilla.org/php/getParsedLog.php?id=37913274&tree=Try&full=1#error1

ASAN indicates that the memory access is wild, e.g. possibly a heap
buffer overflow. (I.e. it's not a use-after-free.) I don't think I'm
doing anything unreasonable here. Are shape->base() and base->clasp()
and clasp->name always safe to call? It might be worth mentioning that
this is a full JS heap traversal, so it's possible that |shape| is
non-reachable but hasn't yet been collected.

It only happens on about 1 in 20 runs, which is annoying.

Any insights appreciated. Thanks!

Nick
_______________________________________________
dev-tech-js-engine-internals mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals

Reply via email to