Global Metrics

path: .metrics.nexits.average
old: 0.6666666666666666
new: 0.625

path: .metrics.nexits.sum
old: 2.0
new: 10.0

path: .metrics.mi.mi_original
old: 47.36758446757308
new: 34.47695963612769

path: .metrics.mi.mi_sei
old: 29.53892801721436
new: 14.120119608881318

path: .metrics.mi.mi_visual_studio
old: 27.700341793902385
new: 20.16196469948988

path: .metrics.nargs.sum
old: 9.0
new: 4.0

path: .metrics.nargs.average
old: 3.0
new: 0.25

path: .metrics.cognitive.sum
old: 16.0
new: 8.0

path: .metrics.cognitive.average
old: 5.333333333333333
new: 0.5

path: .metrics.halstead.bugs
old: 1.1770127325598896
new: 1.1121853057972957

path: .metrics.halstead.level
old: 0.013403880070546737
new: 0.01908957415565345

path: .metrics.halstead.purity_ratio
old: 0.7019340643881582
new: 0.9618939744912592

path: .metrics.halstead.N1
old: 257.0
new: 333.0

path: .metrics.halstead.difficulty
old: 74.60526315789474
new: 52.38461538461539

path: .metrics.halstead.length
old: 467.0
new: 560.0

path: .metrics.halstead.n1
old: 27.0
new: 30.0

path: .metrics.halstead.n2
old: 38.0
new: 65.0

path: .metrics.halstead.effort
old: 209823.2566899989
new: 192729.24113793

path: .metrics.halstead.estimated_program_length
old: 327.8032080692699
new: 538.6606257151051

path: .metrics.halstead.time
old: 11656.847593888828
new: 10707.180063218337

path: .metrics.halstead.N2
old: 210.0
new: 227.0

path: .metrics.halstead.volume
old: 2812.4457686842884
new: 3679.11914066533

path: .metrics.halstead.vocabulary
old: 65.0
new: 95.0

path: .metrics.loc.lloc
old: 49.0
new: 36.0

path: .metrics.loc.blank
old: 6.0
new: 33.0

path: .metrics.loc.cloc
old: 35.0
new: 62.0

path: .metrics.loc.sloc
old: 134.0
new: 214.0

path: .metrics.loc.ploc
old: 93.0
new: 119.0

path: .metrics.cyclomatic.average
old: 3.25
new: 1.4285714285714286

path: .metrics.cyclomatic.sum
old: 13.0
new: 30.0

path: .metrics.nom.functions
old: 3.0
new: 16.0

path: .metrics.nom.total
old: 3.0
new: 16.0

Spaces Data

Minimal test - lines (23, 212)

path: .spaces[0].metrics.loc.ploc
old: 6.0
new: 105.0

path: .spaces[0].metrics.loc.sloc
old: 6.0
new: 190.0

path: .spaces[0].metrics.loc.blank
old: 0.0
new: 30.0

path: .spaces[0].metrics.loc.lloc
old: 2.0
new: 36.0

path: .spaces[0].metrics.loc.cloc
old: 0.0
new: 55.0

path: .spaces[0].metrics.nom.functions
old: 1.0
new: 16.0

path: .spaces[0].metrics.nom.total
old: 1.0
new: 16.0

path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 1.45

path: .spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 29.0

path: .spaces[0].metrics.mi.mi_original
old: 115.7111656028849
new: 36.8657240421452

path: .spaces[0].metrics.mi.mi_sei
old: 91.33689265815536
new: 17.45266100771967

path: .spaces[0].metrics.mi.mi_visual_studio
old: 67.66734830578065
new: 21.55890294862293

path: .spaces[0].metrics.nexits.sum
old: 1.0
new: 10.0

path: .spaces[0].metrics.nexits.average
old: 1.0
new: 0.625

path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 8.0

path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 0.5

path: .spaces[0].metrics.halstead.time
old: 56.56772438427192
new: 11515.927496529594

path: .spaces[0].metrics.halstead.n1
old: 10.0
new: 30.0

path: .spaces[0].metrics.halstead.level
old: 0.14666666666666667
new: 0.016975308641975308

path: .spaces[0].metrics.halstead.estimated_program_length
old: 71.27302875388389
new: 465.18150211211184

path: .spaces[0].metrics.halstead.N1
old: 19.0
new: 333.0

path: .spaces[0].metrics.halstead.purity_ratio
old: 2.0962655515848203
new: 0.8473251404592201

path: .spaces[0].metrics.halstead.n2
old: 11.0
new: 55.0

path: .spaces[0].metrics.halstead.effort
old: 1018.2190389168944
new: 207286.69493753268

path: .spaces[0].metrics.halstead.N2
old: 15.0
new: 216.0

path: .spaces[0].metrics.halstead.bugs
old: 0.033736981332150334
new: 1.167507547056946

path: .spaces[0].metrics.halstead.difficulty
old: 6.818181818181818
new: 58.90909090909091

path: .spaces[0].metrics.halstead.vocabulary
old: 21.0
new: 85.0

path: .spaces[0].metrics.halstead.volume
old: 149.33879237447786
new: 3518.755623939598

path: .spaces[0].metrics.halstead.length
old: 34.0
new: 549.0

path: .spaces[0].metrics.nargs.average
old: 2.0
new: 0.25

path: .spaces[0].metrics.nargs.sum
old: 2.0
new: 4.0

Code

namespace mozilla {

/**
 * A very simple arena allocator based on NSPR's PLArena.
 *
 * The arena allocator only provides for allocation, all memory is retained
 * until the allocator is destroyed. It's useful for situations where a large
 * amount of small transient allocations are expected.
 *
 * Example usage:
 *
 * // Define an allocator that is page sized and returns allocations that are
 * // 8-byte aligned.
 * ArenaAllocator<4096, 8> a;
 * for (int i = 0; i < 1000; i++) {
 *   DoSomething(a.Allocate(i));
 * }
 */
template 
class ArenaAllocator {
 public:
  constexpr ArenaAllocator() : mHead(), mCurrent(nullptr) {
    static_assert(mozilla::tl::FloorLog2::value ==
                      mozilla::tl::CeilingLog2::value,
                  "ArenaAllocator alignment must be a power of two");
  }

  ArenaAllocator(const ArenaAllocator&) = delete;
  ArenaAllocator& operator=(const ArenaAllocator&) = delete;

  /**
   * Frees all internal arenas but does not call destructors for objects
   * allocated out of the arena.
   */
  ~ArenaAllocator() { Clear(); }

  /**
   * Fallibly allocates a chunk of memory with the given size from the internal
   * arenas. If the allocation size is larger than the chosen arena a size an
   * entire arena is allocated and used.
   */
  MOZ_ALWAYS_INLINE void* Allocate(size_t aSize, const fallible_t&) {
    MOZ_RELEASE_ASSERT(aSize, "Allocation size must be non-zero");
    return InternalAllocate(AlignedSize(aSize));
  }

  void* Allocate(size_t aSize) {
    void* p = Allocate(aSize, fallible);
    if (MOZ_UNLIKELY(!p)) {
      NS_ABORT_OOM(std::max(aSize, ArenaSize));
    }

    return p;
  }

  /**
   * Frees all entries. The allocator can be reused after this is called.
   *
   * NB: This will not run destructors of any objects that were allocated from
   * the arena.
   */
  void Clear() {
    // Free all chunks.
    auto a = mHead.next;
    while (a) {
      auto tmp = a;
      a = a->next;
      free(tmp);
    }

    // Reset the list head.
    mHead.next = nullptr;
    mCurrent = nullptr;
  }

  /**
   * Adjusts the given size to the required alignment.
   */
  static constexpr size_t AlignedSize(size_t aSize) {
    return (aSize + (Alignment - 1)) & ~(Alignment - 1);
  }

  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
    size_t s = 0;
    for (auto arena = mHead.next; arena; arena = arena->next) {
      s += aMallocSizeOf(arena);
    }

    return s;
  }

  void Check() {
    if (mCurrent) {
      mCurrent->canary.Check();
    }
  }

 private:
  struct ArenaHeader {
    /**
     * The location in memory of the data portion of the arena.
     */
    uintptr_t offset;
    /**
     * The location in memory of the end of the data portion of the arena.
     */
    uintptr_t tail;
  };

  struct ArenaChunk {
    constexpr ArenaChunk() : header{0, 0}, next(nullptr) {}

    explicit ArenaChunk(size_t aSize)
        : header{AlignedSize(uintptr_t(this + 1)), uintptr_t(this) + aSize},
          next(nullptr) {}

    CorruptionCanary canary;
    ArenaHeader header;
    ArenaChunk* next;

    /**
     * Allocates a chunk of memory out of the arena and advances the offset.
     */
    void* Allocate(size_t aSize) {
      MOZ_ASSERT(aSize <= Available());
      char* p = reinterpret_cast(header.offset);
      MOZ_RELEASE_ASSERT(p);
      header.offset += aSize;
      canary.Check();
      MOZ_MAKE_MEM_UNDEFINED(p, aSize);
      return p;
    }

    /**
     * Calculates the amount of space available for allocation in this chunk.
     */
    size_t Available() const { return header.tail - header.offset; }
  };

  /**
   * Allocates an arena chunk of the given size and initializes its header.
   */
  ArenaChunk* AllocateChunk(size_t aSize) {
    static const size_t kOffset = AlignedSize(sizeof(ArenaChunk));
    MOZ_ASSERT(kOffset < aSize);

    const size_t chunkSize = aSize + kOffset;
    void* p = malloc(chunkSize);
    if (!p) {
      return nullptr;
    }

    ArenaChunk* arena = new (KnownNotNull, p) ArenaChunk(chunkSize);
    MOZ_MAKE_MEM_NOACCESS((void*)arena->header.offset,
                          arena->header.tail - arena->header.offset);

    // Insert into the head of the list.
    arena->next = mHead.next;
    mHead.next = arena;

    // Only update |mCurrent| if this is a standard allocation, large
    // allocations will always end up full so there's no point in updating
    // |mCurrent| in that case.
    if (aSize == ArenaSize - kOffset) {
      mCurrent = arena;
    }

    return arena;
  }

  MOZ_ALWAYS_INLINE void* InternalAllocate(size_t aSize) {
    static_assert(ArenaSize > AlignedSize(sizeof(ArenaChunk)),
                  "Arena size must be greater than the header size");

    static const size_t kMaxArenaCapacity =
        ArenaSize - AlignedSize(sizeof(ArenaChunk));

    if (mCurrent && aSize <= mCurrent->Available()) {
      return mCurrent->Allocate(aSize);
    }

    ArenaChunk* arena = AllocateChunk(std::max(kMaxArenaCapacity, aSize));
    return arena ? arena->Allocate(aSize) : nullptr;
  }

  ArenaChunk mHead;
  ArenaChunk* mCurrent;
};

}  // namespace mozilla