mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
0d748ad58e
This change fixes Cosmopolitan so it has fewer opinions about compiler warnings. The whole repository had to be cleaned up to be buildable in -Werror -Wall mode. This lets us benefit from things like strict const checking. Some actual bugs might have been caught too.
156 lines
4.6 KiB
C
156 lines
4.6 KiB
C
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
|
│ │
|
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
│ any purpose with or without fee is hereby granted, provided that the │
|
|
│ above copyright notice and this permission notice appear in all copies. │
|
|
│ │
|
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
#include "tool/plinko/lib/gc.h"
|
|
#include "libc/assert.h"
|
|
#include "libc/intrin/bsf.h"
|
|
#include "libc/intrin/popcnt.h"
|
|
#include "libc/limits.h"
|
|
#include "libc/log/check.h"
|
|
#include "libc/log/countbranch.h"
|
|
#include "libc/log/log.h"
|
|
#include "libc/macros.internal.h"
|
|
#include "libc/mem/mem.h"
|
|
#include "libc/str/str.h"
|
|
#include "tool/plinko/lib/cons.h"
|
|
#include "tool/plinko/lib/histo.h"
|
|
#include "tool/plinko/lib/plinko.h"
|
|
#include "tool/plinko/lib/print.h"
|
|
#include "tool/plinko/lib/printf.h"
|
|
#include "tool/plinko/lib/stack.h"
|
|
|
|
forceinline void SetBit(dword M[], unsigned i) {
|
|
M[i / DWBITS] |= (dword)1 << (i % DWBITS);
|
|
}
|
|
|
|
forceinline nosideeffect bool HasBit(const dword M[], unsigned i) {
|
|
return (M[i / DWBITS] >> (i % DWBITS)) & 1;
|
|
}
|
|
|
|
struct Gc *NewGc(int A) {
|
|
int B = cx;
|
|
unsigned n;
|
|
struct Gc *G;
|
|
DCHECK_LE(B, A);
|
|
DCHECK_LE(A, 0);
|
|
if (B < cHeap) cHeap = B;
|
|
n = ROUNDUP(A - B, DWBITS) / DWBITS;
|
|
G = Addr(BANE);
|
|
bzero(G->M, n * sizeof(G->M[0]));
|
|
G->n = n;
|
|
G->A = A;
|
|
G->B = B;
|
|
G->P = (unsigned *)(G->M + n);
|
|
*G->P++ = 0;
|
|
return G;
|
|
}
|
|
|
|
void Marker(const dword M[], int A, int x) {
|
|
int i;
|
|
dword t;
|
|
do {
|
|
i = ~(x - A);
|
|
if (HasBit(M, i)) return;
|
|
SetBit((void *)M, i);
|
|
if (HI(GetShadow(x)) < A) {
|
|
Marker(M, A, HI(GetShadow(x)));
|
|
}
|
|
t = Get(x);
|
|
if (LO(t) < A) {
|
|
Marker(M, A, LO(t));
|
|
}
|
|
} while ((x = HI(t)) < A);
|
|
}
|
|
|
|
int Census(struct Gc *G) {
|
|
int n, t, l;
|
|
unsigned i, j;
|
|
i = G->A - G->B;
|
|
n = i / DWBITS;
|
|
for (j = t = 0; j < n; ++j) {
|
|
G->P[j] = t += popcnt(G->M[j]);
|
|
}
|
|
if (i % DWBITS) {
|
|
t += popcnt(G->M[j]);
|
|
}
|
|
G->noop = t == i;
|
|
for (l = j = 0; j < G->n; ++j) {
|
|
if (!~G->M[j]) {
|
|
l += DWBITS;
|
|
} else {
|
|
l += _bsfl(~G->M[j]);
|
|
break;
|
|
}
|
|
}
|
|
G->C = G->A - l;
|
|
#if HISTO_GARBAGE
|
|
HISTO(g_gc_marks_histogram, t);
|
|
HISTO(g_gc_discards_histogram, i - t);
|
|
HISTO(g_gc_lop_histogram, l);
|
|
#endif
|
|
return t;
|
|
}
|
|
|
|
int Relocater(const dword M[], const unsigned P[], int A, int x) {
|
|
long n;
|
|
unsigned i, r;
|
|
i = ~(x - A);
|
|
n = i / DWBITS;
|
|
r = i % DWBITS;
|
|
return A + ~(P[n - 1] + popcnt(M[n] & (((dword)1 << r) - 1)));
|
|
}
|
|
|
|
void Sweep(struct Gc *G) {
|
|
dword m;
|
|
int a, b, d, i, j;
|
|
if (G->noop) return;
|
|
i = 0;
|
|
b = d = G->A;
|
|
for (; i < G->n; ++i) {
|
|
m = G->M[i];
|
|
if (~m) {
|
|
j = _bsfl(~m);
|
|
m >>= j;
|
|
m <<= j;
|
|
d -= j;
|
|
break;
|
|
} else {
|
|
b -= DWBITS;
|
|
d -= DWBITS;
|
|
}
|
|
}
|
|
for (; i < G->n; b -= DWBITS, m = G->M[++i]) {
|
|
for (; m; m &= ~((dword)1 << j)) {
|
|
a = b + ~(j = _bsfl(m));
|
|
Set(--d, MAKE(Relocate(G, LO(Get(a))), Relocate(G, HI(Get(a)))));
|
|
SetShadow(d, MAKE(LO(GetShadow(a)), Relocate(G, HI(GetShadow(a)))));
|
|
}
|
|
}
|
|
cx = d;
|
|
}
|
|
|
|
int MarkSweep(int A, int x) {
|
|
struct Gc *G;
|
|
if (x >= A) return cx = A, x;
|
|
G = NewGc(A);
|
|
Mark(G, x);
|
|
Census(G);
|
|
x = Relocate(G, x);
|
|
Sweep(G);
|
|
return x;
|
|
}
|