[sgen] Fix build with binary protocol.
[gc] Remove the `new object count` counter, because it's useless.

Without heavy statistics it counts almost no objects, and even with
heavy statistics turned on, it doesn't count everything.  SGen has an
accurate counter when heavy statistics are turned on.
[sgen] Optimized mark/scan loop for major collections.

The basic idea here is to make a loop that combines dequeuing from the
gray queue, scanning and marking/copying/enqueuing, with redundancies
removed and special-casing of the common case.

We make the small bitmap type descriptor only apply to small (as
opposed to LOS) objects so that we can quickly check in that case
whether an object is in the LOS or not without actually looking up its
size.

We disable evacuation and the split nursery because the code doesn't
support them yet.
[sgen] Prefetch queue for optimized mark/scan loop.

We put a short FIFO between the gray stack and the actual scanning, to
be able to prefetch objects ahead of time, with an adjustable delay.
[sgen] Make prefetch queue compile-time optional.

We want to benchmark the prefetch queue in combination with other
changes, so we make each of them configurable.
[sgen] Make enqueuing descriptors compile-time optional.

We want to test this in combination with other changes, so we make
each of them configurable.
[sgen] Mark on dequeue, not enqueue.

This is another experiment.

When marking on enqueue, what we need to do is look at the object
we're about to enqueue, to check whether it's a small or large object.
Then, when we dequeue to scan, we look at the object again, so we
essentially fetch each live object header twice.

With mark on dequeue, when we encounter a pointer we always enqueue
it, without even looking at the object.  Only when we dequeue do we
figure out whether it's marked yet, and thus whether we need to scan
it.
[sgen] Count scanned objects.
[sgen] Also prefetch the (potential) block header.

When we scan a small object in the major heap we have to read the
block header of its block.  It makes sense to prefetch that as well,
in addition to the object itself.
[sgen] Bring mark-scan loop stats up to date.
[sgen] Put block info into blocks.

Another experiment: What if we put the whole block info into the block
itself, not just a pointer to it.  There's one less indirection we
need to do.  On the other hand, many of them will share the same cache
lines.  So do the pointers to the block infos, though.
[sgen] Prefetch mark bits, not block start.

When prefetching, we calculate which mark bits we need and prefetch
those for writing.  The object itself we prefetch for reading.
[sgen] Tag cemented objects so we don't have to go through the hash.

We can do the cemented check faster by using the third vtable bit to
tag cemented objects (in addition to the pinned bit).  In workloads
that are heavy on cementing (like `lcscbench` or `perimeter`) this
significantly increases performance.
[sgen] Make block info in header optional.

So we can experiment with a variety of optimization configurations.
[sgen] Make mark on enqueue vs dequeue configurable.

So we can experiment with a variety of optimization configurations.
[sgen] Limit run-length descriptors to small object size, too.

To identify more small objects quicker.

Since we now use the runl-length descriptor types to indicate object
size as well, and strings can have any size, we can't use that type
for strings anymore, so we use the complex type which forces us to
look up its size to determine whether it's a small or large object.
[sgen] Fix heavy statistics in mark-scan loop.
[sgen] Optional scanning without the small bitmap fast path.

To experiment with different optimization combinations.
[sgen] Use HANDLE_PTR in the fast-path, too.

We had just expanded the macro verbatim and never changed it, so
there's no point in not using it directly.
[sgen] Heavy statistic counter for scanning of no-ref objects.