refactor & document #define-s, always-available ')gc log' and ')mem log'
This commit is contained in:
parent
ae6763f5e3
commit
ad574d2269
@ -62,7 +62,8 @@ Get statistics on memory usage.
|
||||
|
||||
`)mem t` to get usage per object type.
|
||||
`)mem s` to get a breakdown of the number of objects with a specific size.
|
||||
`)mem f` to get breakdown of free bucket counts per size.
|
||||
`)mem f` to get breakdown of free bucket counts per size.
|
||||
`)mem log` enables/disabled printing a message on OS requests for more memory.
|
||||
|
||||
## `)gc`
|
||||
|
||||
@ -70,7 +71,10 @@ Force garbage collection.
|
||||
|
||||
`)gc disable` disables automatic garabage collection, and `)gc enable` enables it again.
|
||||
|
||||
Not a system function because currently CBQN doesn't support garbage collection in the middle of program execution.
|
||||
A plain `)gc` differs from `•internal.GC@` in that it can do precise marking as there's no in-progress C stack.
|
||||
|
||||
`)gc log` enables/disables printing a message on GC.
|
||||
|
||||
|
||||
## `)internalPrint expr`
|
||||
|
||||
|
||||
@ -145,7 +145,7 @@ type field for heap-allocated objects:
|
||||
|
||||
t_funWrap, t_md1Wrap, t_md2Wrap // types wrapping builtins for RT_WRAP; see rtwrap.c
|
||||
|
||||
See src/h.h for more basics
|
||||
See src/h.h for more basic operations
|
||||
```
|
||||
|
||||
An object can be allocated with `mm_alloc(sizeInBytes, t_something)`. The returned object starts with the structure of `Value`, so custom data must be after that. `mm_free` can be used to force-free an object regardless of its reference count.
|
||||
@ -393,4 +393,67 @@ B g_t (void* x) // tag pointer with OBJ_TAG
|
||||
B g_ta(void* x) // tag pointer with ARR_TAG
|
||||
B g_tf(void* x) // tag pointer with FUN_TAG
|
||||
// invoke with "p g_p(whatever)"; requires a build with debug symbols to be usable, but e.g. "p (void)g_pst()" can be used without one
|
||||
```
|
||||
```
|
||||
|
||||
## Various `#define`s
|
||||
|
||||
Most toggles require a value of `1` to be enabled.
|
||||
|
||||
```c
|
||||
// (effective) usual default value is listed; (u) marks being not defined
|
||||
// default may change under some conditions (DEBUG, CATCH_ERRORS, heapverify, among maybe other things)
|
||||
// some things fully configured by the build system may not be listed
|
||||
|
||||
// general config:
|
||||
#define REPL_INTERRUPT 0 // support ctrl+c for interrupting some REPL execution
|
||||
#define ENABLE_GC 1 // enable garbage collection
|
||||
#define MM 1 // memory manager; 0 - malloc (no GC); 1 - buddy; 2 - 2buddy
|
||||
#define HEAP_MAX ~0ULL // initial heap max size (overridden by -M)
|
||||
#define JIT_ENABLED (u) // force-enable or force-disable JIT (x86_64-only)
|
||||
#define RANDSEED 0 // random seed used to make •rand (0 uses time)
|
||||
#define JIT_START 2 // number of calls for when to start JITting (x86_64-only); default is 2, defined in vm.h
|
||||
// -1: never JIT (≈ JIT_ENABLED=0)
|
||||
// 0: JIT everything
|
||||
// >0: JIT after n non-JIT invocations; max ¯1+2⋆16
|
||||
|
||||
// runtime configuration:
|
||||
#define ALL_R0 0 // use all of r0.bqn for runtime_0
|
||||
#define ALL_R1 0 // use all of r1.bqn for runtime
|
||||
#define NO_RT 0 // whether to completely disable self-hosted runtime loading
|
||||
#define CATCH_ERRORS 1 // allow catching errors; means refcounts might stay too high if forgotten over a throw-catch; disabled for heapverify
|
||||
#define FAKE_RUNTIME 0 // disable the self-hosted runtime
|
||||
#define FORMATTER 1 // use self-hosted formatter for output
|
||||
#define NO_EXPLAIN 0 // disable )explain
|
||||
#define NO_RYU 0 // disable usage of Ryu
|
||||
#define EACH_FILLS 0 // compute fills for ¨ and ⌜; may be forcibly disabled
|
||||
#define SFNS_FILLS 1 // compute fills for structural functions (∾, ≍, etc)
|
||||
#define CHECK_VALID 1 // check for valid arguments in places where that would be detrimental to performance
|
||||
// e.g. left argument sortedness of ⍋/⍒, incompatible changes in ⌾, etc
|
||||
|
||||
#define RYU_OPTIMIZE_SIZE 0 // reduce size of Ryu tables at the cost of some performance for number •Repr
|
||||
#define FFI_CHECKS 1 // check for valid arguments passed to FFI-d functions
|
||||
#define UNSAFE_SIZES 0 // disable safety checks on array length overflows
|
||||
|
||||
// debugging stuff:
|
||||
#define DEBUG 0 // the regular debug build
|
||||
#define HEAP_VERIFY 0 // heapverify
|
||||
#define WARN_SLOW 0 // log on various slow operations
|
||||
#define USE_PERF 0 // write a /tmp/perf-<pid>.map for JITted things for linux perf
|
||||
#define GC_LOG_DETAILED 0 // slightly more stats on GC logging
|
||||
#define DEBUG_VM 0 // print evaluation of every bytecode
|
||||
#define USE_VALGRIND 0 // adjust memory manager & code for valgrind usage
|
||||
#define VERIFY_TAIL (u) // number of bytes after the end of an array to verify not being improperly modified; 64 in DEBUG
|
||||
#define NEEQUAL_NEGZERO 0 // make negative zero not equal zero for •internal.EEqual
|
||||
#define RT_VERIFY_ARGS 1 // rtverify: preserve arguments for printing on failure
|
||||
|
||||
// some somewhat-outdated/unmaintained things:
|
||||
#define RT_PERF 0 // time runtime primitives
|
||||
#define RT_VERIFY 0 // compare native and runtime versions of primitives
|
||||
#define ALLOC_STAT 0 // store basic allocation statistics
|
||||
#define ALLOC_SIZES 0 // store per-type allocation size statistics
|
||||
#define DONT_FREE 0 // don't actually ever free objects, such that they can be printed after being freed for debugging
|
||||
#define TYPED_ARITH 1 // enable specialized loops for typed arith
|
||||
#define VM_POS 1 // whether to store detailed execution position information for stacktraces
|
||||
#define OBJ_COUNTER 0 // store a unique allocation number with each object; superseded by the existence of https://rr-project.org/
|
||||
#define OBJ_TRACK (u) // object ID to track
|
||||
```
|
||||
|
||||
@ -106,7 +106,7 @@ static B modint_AS(B w, B xv) { return modint_AA(w, C2(shape, C1(fne, incG(w))
|
||||
#define ARITH_SLOW(N) SLOWIF((!isArr(w) || TI(w,elType)!=el_B) && (!isArr(x) || TI(x,elType)!=el_B)) SLOW2("arithd " #N, w, x)
|
||||
#define P2(N) { if(isArr(w)|isArr(x)) { ARITH_SLOW(N); return arith_recd(N##_c2, w, x); }}
|
||||
|
||||
#if !TYPED_ARITH
|
||||
#if defined(TYPED_ARITH) && !TYPED_ARITH
|
||||
#define AR_I_TO_ARR(NAME) P2(NAME)
|
||||
#define AR_F_TO_ARR AR_I_TO_ARR
|
||||
#else
|
||||
|
||||
@ -917,7 +917,7 @@ B delay_c1(B t, B x) {
|
||||
return m_f64(ts.tv_sec-ts0.tv_sec+(ts.tv_nsec-ts0.tv_nsec)*1e-9);
|
||||
}
|
||||
B exit_c1(B t, B x) {
|
||||
#ifdef HEAP_VERIFY
|
||||
#if HEAP_VERIFY
|
||||
printf("(heapverify doesn't run on •Exit)\n");
|
||||
#endif
|
||||
bqn_exit(q_i32(x)? o2i(x) : 0);
|
||||
|
||||
@ -105,7 +105,7 @@ NOINLINE bool fillEqualF(B w, B x) { // doesn't consume; both args must be array
|
||||
|
||||
B withFill(B x, B fill) { // consumes both
|
||||
assert(isArr(x));
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
validateFill(fill);
|
||||
#endif
|
||||
u8 xt = TY(x);
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
#include "../core.h"
|
||||
|
||||
#ifdef HEAP_VERIFY
|
||||
#if HEAP_VERIFY
|
||||
u32 heapVerify_mode = -1;
|
||||
|
||||
Value* heap_observed;
|
||||
Value* heap_curr;
|
||||
void heapVerify_checkFn(Value* v) {
|
||||
if (v->refc!=0) {
|
||||
#ifdef OBJ_COUNTER
|
||||
#if OBJ_COUNTER
|
||||
printf("delta %d for %s @ %p, uid "N64d": ", v->refc, type_repr(v->type), v, v->uid);
|
||||
#else
|
||||
printf("delta %d for %s @ %p: ", (i32)v->refc, type_repr(v->type), v);
|
||||
|
||||
@ -12,6 +12,8 @@ static u64 prepAllocSize(u64 sz) {
|
||||
}
|
||||
#define MMAP(SZ) mmap(NULL, prepAllocSize(SZ), PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
|
||||
bool mem_log_enabled;
|
||||
|
||||
#if MM==0
|
||||
#include "../opt/mm_malloc.c"
|
||||
#elif MM==1
|
||||
|
||||
@ -16,7 +16,7 @@ NORETURN NOINLINE void fatal(char* s) {
|
||||
#endif
|
||||
if (inErr) {
|
||||
fputs("\nCBQN encountered a fatal error during information printing of another fatal error. Exiting without printing more info.", stderr);
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
__builtin_trap();
|
||||
#endif
|
||||
exit(1);
|
||||
@ -28,7 +28,7 @@ NORETURN NOINLINE void fatal(char* s) {
|
||||
vm_pstLive(); fflush(stderr); fflush(stdout);
|
||||
print_vmStack(); fflush(stderr);
|
||||
before_exit();
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
__builtin_trap();
|
||||
#endif
|
||||
exit(1);
|
||||
@ -147,7 +147,7 @@ NOINLINE void fprintI(FILE* f, B x) {
|
||||
else if (o2cG(x)>=16) fprintf(f, "\\x%x", o2cG(x));
|
||||
else fprintf(f, "\\x0%x", o2cG(x));
|
||||
} else if (isVal(x)) {
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
if (isVal(x) && (TY(x)==t_freed || TY(x)==t_empty)) {
|
||||
u8 t = TY(x);
|
||||
v(x)->type = v(x)->flags;
|
||||
@ -444,18 +444,18 @@ B bqn_merge(B x, u32 type) {
|
||||
return taga(APD_SH_GET(r, type));
|
||||
}
|
||||
|
||||
#ifdef ALLOC_STAT
|
||||
#if ALLOC_STAT
|
||||
u64* ctr_a = 0;
|
||||
u64* ctr_f = 0;
|
||||
u64 actrc = 21000;
|
||||
u64 talloc = 0;
|
||||
#ifdef ALLOC_SIZES
|
||||
#if ALLOC_SIZES
|
||||
u32** actrs;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
NOINLINE void print_allocStats() {
|
||||
#ifdef ALLOC_STAT
|
||||
#if ALLOC_STAT
|
||||
printf("total ever allocated: "N64u"\n", talloc);
|
||||
printf("allocated heap size: "N64u"\n", mm_heapAlloc);
|
||||
printf("used heap size: "N64u"\n", mm_heapUsed());
|
||||
@ -467,7 +467,7 @@ NOINLINE void print_allocStats() {
|
||||
u64 leakedCount = 0;
|
||||
for (i64 i = 0; i < t_COUNT; i++) leakedCount+= ctr_a[i]-ctr_f[i];
|
||||
printf("leaked object count: "N64u"\n", leakedCount);
|
||||
#ifdef ALLOC_SIZES
|
||||
#if ALLOC_SIZES
|
||||
for(i64 i = 0; i < actrc; i++) {
|
||||
u32* c = actrs[i];
|
||||
bool any = false;
|
||||
@ -501,10 +501,10 @@ void g_pv(void* x) { ignore_bad_tag=true; fprintI(stderr,tag(x,OBJ_TAG)); fput
|
||||
void g_iv(void* x) { ignore_bad_tag=true; B xo = tag(x, OBJ_TAG); B r = C2(info, m_f64(1), inc(xo)); fprintI(stderr,r); dec(r); fputc(10,stderr); fflush(stderr); ignore_bad_tag=false; }
|
||||
void g_pst(void) { vm_pstLive(); fflush(stdout); fflush(stderr); }
|
||||
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
bool cbqn_noAlloc;
|
||||
NOINLINE void cbqn_NOGC_start() { cbqn_noAlloc=true; }
|
||||
#ifdef OBJ_COUNTER
|
||||
#if OBJ_COUNTER
|
||||
#define PRINT_ID(X) fprintf(stderr, "Object ID: "N64u"\n", (X)->uid)
|
||||
#else
|
||||
#define PRINT_ID(X)
|
||||
|
||||
@ -290,7 +290,7 @@ static usz depth(B x) { // doesn't consume
|
||||
|
||||
|
||||
|
||||
#ifdef USE_VALGRIND
|
||||
#if USE_VALGRIND
|
||||
#include "../utils/valgrind.h"
|
||||
#else
|
||||
#define vg_def_p(X, L)
|
||||
@ -323,12 +323,12 @@ static FC2 c2fn(B f) {
|
||||
}
|
||||
|
||||
// alloc stuff
|
||||
#ifdef ALLOC_STAT
|
||||
#if ALLOC_STAT
|
||||
extern u64* ctr_a;
|
||||
extern u64* ctr_f;
|
||||
extern u64 actrc;
|
||||
extern u64 talloc;
|
||||
#ifdef ALLOC_SIZES
|
||||
#if ALLOC_SIZES
|
||||
extern u32** actrs;
|
||||
#endif
|
||||
#endif
|
||||
@ -342,9 +342,9 @@ FORCE_INLINE void preAlloc(usz sz, u8 type) {
|
||||
#ifdef OOM_TEST
|
||||
if (--oomTestLeft==0) thrOOMTest();
|
||||
#endif
|
||||
#ifdef ALLOC_STAT
|
||||
#if ALLOC_STAT
|
||||
if (!ctr_a) {
|
||||
#ifdef ALLOC_SIZES
|
||||
#if ALLOC_SIZES
|
||||
actrs = malloc(sizeof(u32*)*actrc);
|
||||
for (i32 i = 0; i < actrc; i++) actrs[i] = calloc(t_COUNT, sizeof(u32));
|
||||
#endif
|
||||
@ -352,7 +352,7 @@ FORCE_INLINE void preAlloc(usz sz, u8 type) {
|
||||
ctr_f = calloc(t_COUNT, sizeof(u64));
|
||||
}
|
||||
assert(type<t_COUNT);
|
||||
#ifdef ALLOC_SIZES
|
||||
#if ALLOC_SIZES
|
||||
actrs[(sz+3)/4>=actrc? actrc-1 : (sz+3)/4][type]++;
|
||||
#endif
|
||||
ctr_a[type]++;
|
||||
@ -369,13 +369,13 @@ void tailVerifyReinit(void* ptr, u64 s, u64 e);
|
||||
#endif
|
||||
#define FINISH_OVERALLOC_A(A, S, L) FINISH_OVERALLOC(a(A), offsetof(TyArr,a)+(S), offsetof(TyArr,a)+(S)+(L));
|
||||
FORCE_INLINE void preFree(Value* x, bool mmx) {
|
||||
#ifdef ALLOC_STAT
|
||||
#if ALLOC_STAT
|
||||
ctr_f[x->type]++;
|
||||
#endif
|
||||
#if VERIFY_TAIL
|
||||
if (!mmx) tailVerifyFree(x);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
if (x->type==t_empty) fatal("double-free");
|
||||
// u32 undef;
|
||||
// x->refc = undef;
|
||||
|
||||
67
src/h.h
67
src/h.h
@ -1,43 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef DEBUG
|
||||
// #define DEBUG_VM
|
||||
#endif
|
||||
#ifndef CATCH_ERRORS
|
||||
#define CATCH_ERRORS 1 // whether to allow catching errors
|
||||
#endif // currently means refcounts won't be accurate and can't be tested for
|
||||
#define CATCH_ERRORS 1
|
||||
#endif
|
||||
#ifndef ENABLE_GC
|
||||
#define ENABLE_GC 1 // whether to ever garbage-collect
|
||||
#endif
|
||||
#ifndef TYPED_ARITH
|
||||
#define TYPED_ARITH 1 // whether to use typed arith
|
||||
#endif
|
||||
#ifndef VM_POS
|
||||
#define VM_POS 1 // whether to store detailed execution position information for stacktraces
|
||||
#define ENABLE_GC 1
|
||||
#endif
|
||||
#ifndef CHECK_VALID
|
||||
#define CHECK_VALID 1 // whether to check for valid arguments in places where that would be detrimental to performance
|
||||
#endif // e.g. left argument sortedness of ⍋/⍒, incompatible changes in ⌾, etc
|
||||
#define CHECK_VALID 1
|
||||
#endif
|
||||
#ifndef EACH_FILLS
|
||||
#define EACH_FILLS 0 // whether to try to squeeze out fills for ¨ and ⌜
|
||||
#define EACH_FILLS 0
|
||||
#endif
|
||||
#ifndef SFNS_FILLS
|
||||
#define SFNS_FILLS 1 // whether to generate fills for structural functions (∾, ≍, etc)
|
||||
#endif
|
||||
#ifndef FAKE_RUNTIME
|
||||
#define FAKE_RUNTIME 0 // whether to disable the self-hosted runtime
|
||||
#define SFNS_FILLS 1
|
||||
#endif
|
||||
#ifndef MM
|
||||
#define MM 1 // memory manager; 0 - malloc (no GC); 1 - buddy; 2 - 2buddy
|
||||
#define MM 1
|
||||
#endif
|
||||
#ifndef HEAP_MAX
|
||||
#define HEAP_MAX ~0ULL // default heap max size
|
||||
#define HEAP_MAX ~0ULL
|
||||
#endif
|
||||
#ifndef FORMATTER
|
||||
#define FORMATTER 1 // use self-hosted formatter for output
|
||||
#define FORMATTER 1
|
||||
#endif
|
||||
#ifndef RANDSEED
|
||||
#define RANDSEED 0 // random seed used to make •rand (0 for using time)
|
||||
#define RANDSEED 0
|
||||
#endif
|
||||
#ifndef FFI
|
||||
#define FFI 2
|
||||
@ -46,25 +34,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// #define ALLOC_STAT // store basic allocation statistics
|
||||
// #define ALLOC_SIZES // store per-type allocation size statistics
|
||||
// #define USE_VALGRIND // whether to mark freed memory for valgrind
|
||||
// #define DONT_FREE // don't actually ever free objects, such that they can be printed after being freed for debugging
|
||||
// #define OBJ_COUNTER // store a unique allocation number with each object for easier analysis
|
||||
// #define ALL_R0 // use all of r0.bqn for runtime_0
|
||||
// #define ALL_R1 // use all of r1.bqn for runtime
|
||||
|
||||
// #define JIT_START 2 // number of calls for when to start JITting (x86_64-only); default is 2, defined in vm.h
|
||||
// -1: never JIT
|
||||
// 0: JIT everything
|
||||
// >0: JIT after n non-JIT invocations; max ¯1+2⋆16
|
||||
|
||||
// #define LOG_GC // log GC stats
|
||||
// #define RT_PERF // time runtime primitives
|
||||
// #define RT_VERIFY // compare native and runtime versions of primitives
|
||||
// #define NO_RT // whether to completely disable self-hosted runtime loading
|
||||
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#define __wchar_t __wchar_t2 // horrible hack for BSD
|
||||
#endif
|
||||
@ -77,7 +46,7 @@
|
||||
#if CATCH_ERRORS
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
#ifdef HEAP_VERIFY
|
||||
#if HEAP_VERIFY
|
||||
#undef CATCH_ERRORS
|
||||
#define CATCH_ERRORS 0
|
||||
#endif
|
||||
@ -92,13 +61,13 @@
|
||||
#define PROPER_FILLS 0
|
||||
#endif
|
||||
|
||||
#if defined(ALL_R0) || defined (ALL_R1)
|
||||
#if ALL_R0 || ALL_R1
|
||||
#define WRAP_NNBI 1
|
||||
#endif
|
||||
|
||||
#if defined(RT_PERF) || defined(RT_VERIFY)
|
||||
#if RT_PERF || RT_VERIFY
|
||||
#define RT_WRAP 1
|
||||
#if defined(RT_PERF) && defined(RT_VERIFY)
|
||||
#if RT_PERF && RT_VERIFY
|
||||
#error "can't have both RT_PERF and RT_VERIFY"
|
||||
#endif
|
||||
#endif
|
||||
@ -312,7 +281,7 @@ typedef struct Value {
|
||||
u8 flags; // self-hosted primitive index (plus 1) for callable, fl_* flags for arrays
|
||||
u8 type; // used by TI, among generally knowing what type of object this is
|
||||
ur extra; // whatever object-specific stuff. Rank for arrays, internal id for functions
|
||||
#ifdef OBJ_COUNTER
|
||||
#if OBJ_COUNTER
|
||||
u64 uid;
|
||||
#endif
|
||||
} Value;
|
||||
@ -322,7 +291,7 @@ typedef struct Arr {
|
||||
usz* sh;
|
||||
} Arr;
|
||||
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
NOINLINE NORETURN void assert_fail(char* expr, char* file, int line, const char fn[]);
|
||||
#define assert(X) do {if (!(X)) assert_fail(#X, __FILE__, __LINE__, __PRETTY_FUNCTION__);} while(0)
|
||||
B VALIDATE(B x);
|
||||
@ -450,7 +419,7 @@ void freeThrown(void);
|
||||
#define VTY(X,T) assert(isVal(X) && TY(X)==(T))
|
||||
|
||||
void print_vmStack(void);
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
B validate(B x);
|
||||
Value* validateP(Value* x);
|
||||
#endif
|
||||
|
||||
@ -59,6 +59,7 @@ static void* mmap_nvm(u64 sz) {
|
||||
}
|
||||
}
|
||||
|
||||
extern bool mem_log_enabled;
|
||||
#define MMAP(SZ) mmap_nvm(sz);
|
||||
#define MUL 1
|
||||
#define ALLOC_MODE 1
|
||||
|
||||
16
src/load.c
16
src/load.c
@ -4,6 +4,10 @@
|
||||
#include "ns.h"
|
||||
#include "builtins.h"
|
||||
|
||||
#ifndef FAKE_RUNTIME
|
||||
#define FAKE_RUNTIME 0
|
||||
#endif
|
||||
|
||||
#define PRECOMPILED_FILE(END) STR1(../build/BYTECODE_DIR/gen/END)
|
||||
|
||||
#define FOR_INIT(F) \
|
||||
@ -402,14 +406,14 @@ void load_init() { // very last init function
|
||||
for (u64 i = 0; i < RT_LEN; i++) inc(fruntime[i]);
|
||||
B frtObj = m_caB(RT_LEN, fruntime);
|
||||
|
||||
#ifndef NO_RT
|
||||
#if !NO_RT
|
||||
B provide[] = {
|
||||
/* actual provide: */
|
||||
bi_type,bi_fill,bi_log,bi_grLen,bi_grOrd,bi_asrt,bi_add,bi_sub,bi_mul,bi_div,bi_pow,bi_floor,bi_eq,bi_le,bi_fne,bi_shape,bi_pick,bi_ud,bi_tbl,bi_scan,bi_fillBy,bi_val,bi_catch
|
||||
/* result list from commented-out •Out line in cc.bqn: */,
|
||||
bi_root,bi_not,bi_and,bi_or,bi_feq,bi_couple,bi_shifta,bi_shiftb,bi_reverse,bi_transp,bi_gradeUp,bi_gradeDown,bi_indexOf,bi_count,bi_memberOf,bi_cell,bi_rank
|
||||
};
|
||||
#ifndef ALL_R0
|
||||
#if !ALL_R0
|
||||
B runtime_0[] = {bi_floor,bi_ceil,bi_stile,bi_lt,bi_gt,bi_ne,bi_ge,bi_rtack,bi_ltack,bi_join,bi_pair,bi_take,bi_drop,bi_select,bi_const,bi_swap,bi_each,bi_fold,bi_atop,bi_over,bi_before,bi_after,bi_cond,bi_repeat};
|
||||
#else
|
||||
Block* runtime0_b = load_compImport("(self-hosted runtime0)",
|
||||
@ -427,7 +431,7 @@ void load_init() { // very last init function
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifdef ALL_R0
|
||||
#if ALL_R0
|
||||
dec(r0r);
|
||||
#endif
|
||||
|
||||
@ -459,7 +463,7 @@ void load_init() { // very last init function
|
||||
#ifdef RT_WRAP
|
||||
r1Objs[i] = Get(rtObjRaw, i); gc_add(r1Objs[i]);
|
||||
#endif
|
||||
#ifdef ALL_R1
|
||||
#if ALL_R1
|
||||
bool nnbi = true;
|
||||
B r = Get(rtObjRaw, i);
|
||||
#else
|
||||
@ -632,7 +636,7 @@ B def_m2_im(Md2D* d, B x) { return def_fn_im(tag(d,FUN_TAG), x); }
|
||||
B def_m2_iw(Md2D* d, B w, B x) { return def_fn_iw(tag(d,FUN_TAG), w, x); }
|
||||
B def_m2_ix(Md2D* d, B w, B x) { return def_fn_ix(tag(d,FUN_TAG), w, x); }
|
||||
|
||||
#ifdef DONT_FREE
|
||||
#if DONT_FREE
|
||||
static B empty_get(Arr* x, usz n) {
|
||||
x->type = x->flags;
|
||||
if (x->type==t_empty) fatal("getting from empty without old type data");
|
||||
@ -753,7 +757,7 @@ void base_init() { // very first init function
|
||||
TIi(t_empty,freeF) = empty_free; TIi(t_invalid,freeF) = empty_free; TIi(t_freed,freeF) = def_freeF;
|
||||
TIi(t_invalid,visit) = freed_visit;
|
||||
TIi(t_freed,visit) = freed_visit;
|
||||
#ifdef DONT_FREE
|
||||
#if DONT_FREE
|
||||
TIi(t_empty,get) = empty_get;
|
||||
TIi(t_empty,getU) = empty_getU;
|
||||
#endif
|
||||
|
||||
15
src/main.c
15
src/main.c
@ -119,14 +119,14 @@ static NOINLINE i64 readInt(char** p) {
|
||||
")escaped ",
|
||||
")profile ", ")profile@",
|
||||
")t ", ")t:", ")time ", ")time:",
|
||||
")mem", ")mem t", ")mem s", ")mem f",
|
||||
")mem", ")mem t", ")mem s", ")mem f", ")mem log",
|
||||
")erase ",
|
||||
")clearImportCache",
|
||||
")kb",
|
||||
")theme dark", ")theme light", ")theme none",
|
||||
")exit", ")off",
|
||||
")vars",
|
||||
")gc", ")gc off", ")gc on",
|
||||
")gc", ")gc off", ")gc on", ")gc log",
|
||||
")internalPrint ", ")heapdump",
|
||||
#if NATIVE_COMPILER && !ONLY_NATIVE_COMP
|
||||
")switchCompiler",
|
||||
@ -602,6 +602,7 @@ bool ryu_s2d_n(u8* buffer, int len, f64* result);
|
||||
#endif
|
||||
|
||||
void heap_printInfoStr(char* str);
|
||||
extern bool gc_log_enabled, mem_log_enabled;
|
||||
void cbqn_runLine0(char* ln, i64 read) {
|
||||
if (ln[0]==0 || read==0) return;
|
||||
|
||||
@ -667,7 +668,12 @@ void cbqn_runLine0(char* ln, i64 read) {
|
||||
timeRep = am;
|
||||
output = 0;
|
||||
} else if (isCmd(cmdS, &cmdE, "mem ")) {
|
||||
heap_printInfoStr(cmdE);
|
||||
if (strcmp(cmdE,"log")==0) {
|
||||
mem_log_enabled^= true;
|
||||
printf("Allocation logging %s\n", mem_log_enabled? "enabled" : "disabled");
|
||||
} else {
|
||||
heap_printInfoStr(cmdE);
|
||||
}
|
||||
return;
|
||||
} else if (isCmd(cmdS, &cmdE, "erase ")) {
|
||||
char* name = cmdE;
|
||||
@ -773,6 +779,9 @@ void cbqn_runLine0(char* ln, i64 read) {
|
||||
gc_disable();
|
||||
printf("GC disabled\n");
|
||||
}
|
||||
} else if (strcmp(cmdE,"log")==0) {
|
||||
gc_log_enabled^= true;
|
||||
printf("GC logging %s\n", gc_log_enabled? "enabled" : "disabled");
|
||||
} else printf("Unknown GC command\n");
|
||||
#else
|
||||
printf("Macro ENABLE_GC was false at compile-time, cannot GC\n");
|
||||
|
||||
63
src/opt/gc.c
63
src/opt/gc.c
@ -2,11 +2,14 @@
|
||||
|
||||
#if ENABLE_GC
|
||||
static void mm_freeFreedAndMerge(void);
|
||||
#include "../utils/time.h"
|
||||
#if GC_LOG_DETAILED
|
||||
bool gc_log_enabled = true;
|
||||
#else
|
||||
bool gc_log_enabled;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LOG_GC
|
||||
#include "../utils/time.h"
|
||||
#endif
|
||||
|
||||
u64 gc_depth = 1;
|
||||
|
||||
@ -48,20 +51,20 @@ void gc_visitRoots() {
|
||||
|
||||
static void gc_tryFree(Value* v) {
|
||||
u8 t = v->type;
|
||||
#if defined(DEBUG) && !defined(CATCH_ERRORS)
|
||||
#if DEBUG && !CATCH_ERRORS
|
||||
if (t==t_freed) fatal("GC found t_freed\n");
|
||||
#endif
|
||||
if (t!=t_empty && !(v->mmInfo&0x80)) {
|
||||
if (t==t_shape || t==t_temp || t==t_talloc) return;
|
||||
#ifdef DONT_FREE
|
||||
#if DONT_FREE
|
||||
v->flags = t;
|
||||
#else
|
||||
#if CATCH_ERRORS
|
||||
if (t==t_freed) { mm_free(v); return; }
|
||||
#endif
|
||||
#endif
|
||||
#ifdef LOG_GC
|
||||
gc_freedBytes+= mm_size(v); gc_freedCount++;
|
||||
#if GC_LOG_DETAILED
|
||||
gcs_freedBytes+= mm_size(v); gcs_freedCount++;
|
||||
#endif
|
||||
v->type = t_freed;
|
||||
ptr_inc(v); // required as otherwise the object may free itself while not done reading its own fields
|
||||
@ -72,8 +75,8 @@ static void gc_tryFree(Value* v) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LOG_GC
|
||||
u64 gc_visitBytes, gc_visitCount, gc_freedBytes, gc_freedCount, gc_unkRefsBytes, gc_unkRefsCount;
|
||||
#if GC_LOG_DETAILED
|
||||
u64 gcs_visitBytes, gcs_visitCount, gcs_freedBytes, gcs_freedCount, gcs_unkRefsBytes, gcs_unkRefsCount; // GC stat counters
|
||||
#endif
|
||||
|
||||
i32 visit_mode;
|
||||
@ -105,8 +108,8 @@ void gc_onVisit(Value* x) {
|
||||
case GC_MARK: {
|
||||
if (x->mmInfo&0x80) return;
|
||||
x->mmInfo|= 0x80;
|
||||
#ifdef LOG_GC
|
||||
gc_visitBytes+= mm_size(x); gc_visitCount++;
|
||||
#if GC_LOG_DETAILED
|
||||
gcs_visitBytes+= mm_size(x); gcs_visitCount++;
|
||||
#endif
|
||||
TIv(x,visit)(x);
|
||||
return;
|
||||
@ -133,8 +136,8 @@ static void gcv2_unmark_visit(Value* x) {
|
||||
#if ENABLE_GC
|
||||
static void gc_visitRefcNonzero(Value* x) {
|
||||
if (x->refc == 0) return;
|
||||
#ifdef LOG_GC
|
||||
gc_unkRefsBytes+= mm_size(x); gc_unkRefsCount++;
|
||||
#if GC_LOG_DETAILED
|
||||
gcs_unkRefsBytes+= mm_size(x); gcs_unkRefsCount++;
|
||||
#endif
|
||||
mm_visitP(x);
|
||||
}
|
||||
@ -164,20 +167,28 @@ static void gcv2_unmark_visit(Value* x) {
|
||||
u64 gc_lastAlloc;
|
||||
void gc_forceGC(bool toplevel) {
|
||||
#if ENABLE_GC
|
||||
#ifdef LOG_GC
|
||||
u64 start = nsTime();
|
||||
gc_visitBytes = 0; gc_freedBytes = 0;
|
||||
gc_visitCount = 0; gc_freedCount = 0;
|
||||
gc_unkRefsBytes = 0; gc_unkRefsCount = 0;
|
||||
u64 startSize = mm_heapUsed();
|
||||
#endif
|
||||
gc_run(toplevel);
|
||||
u64 startTime=0, startSize=0;
|
||||
if (gc_log_enabled) {
|
||||
startTime = nsTime();
|
||||
startSize = mm_heapUsed();
|
||||
#if GC_LOG_DETAILED
|
||||
gcs_visitBytes = 0; gcs_freedBytes = 0;
|
||||
gcs_visitCount = 0; gcs_freedCount = 0;
|
||||
gcs_unkRefsBytes = 0; gcs_unkRefsCount = 0;
|
||||
#endif
|
||||
}
|
||||
gc_run(toplevel);
|
||||
u64 endSize = mm_heapUsed();
|
||||
#ifdef LOG_GC
|
||||
fprintf(stderr, "GC kept "N64d"B/"N64d" objs, freed "N64d"B, incl. directly "N64d"B/"N64d" objs", gc_visitBytes, gc_visitCount, startSize-endSize, gc_freedBytes, gc_freedCount);
|
||||
fprintf(stderr, "; unknown refs: "N64d"B/"N64d" objs", gc_unkRefsBytes, gc_unkRefsCount);
|
||||
fprintf(stderr, "; took %.3fms\n", (nsTime()-start)/1e6);
|
||||
#endif
|
||||
if (gc_log_enabled) {
|
||||
fprintf(stderr, "GC: before: "N64d"B/"N64d"B", startSize, mm_heapAlloc);
|
||||
#if GC_LOG_DETAILED
|
||||
fprintf(stderr, "; kept "N64d"B="N64d" objs, freed "N64d"B, incl. directly "N64d"B="N64d" objs", gcs_visitBytes, gcs_visitCount, startSize-endSize, gcs_freedBytes, gcs_freedCount);
|
||||
fprintf(stderr, "; unknown refs: "N64d"B="N64d" objs", gcs_unkRefsBytes, gcs_unkRefsCount);
|
||||
#else
|
||||
fprintf(stderr, "; freed "N64d"B, left "N64d"B", startSize-endSize, endSize);
|
||||
#endif
|
||||
fprintf(stderr, "; took %.3fms\n", (nsTime()-startTime)/1e6);
|
||||
}
|
||||
gc_lastAlloc = endSize;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -4,8 +4,8 @@ extern u64 gc_depth;
|
||||
static void gc_disable() { gc_depth++; }
|
||||
static void gc_enable() { gc_depth--; }
|
||||
|
||||
#ifdef LOG_GC
|
||||
extern u64 gc_visitBytes, gc_visitCount, gc_freedBytes, gc_freedCount;
|
||||
#if GC_LOG_DETAILED
|
||||
extern u64 gcs_visitBytes, gcs_visitCount, gcs_freedBytes, gcs_freedCount;
|
||||
#endif
|
||||
|
||||
extern void gc_onVisit(Value*);
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#endif
|
||||
#include "gc.c"
|
||||
|
||||
#ifdef OBJ_COUNTER
|
||||
#if OBJ_COUNTER
|
||||
u64 currObjCounter;
|
||||
#endif
|
||||
#if VERIFY_TAIL
|
||||
|
||||
@ -5,7 +5,7 @@ struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else ca
|
||||
struct Value;
|
||||
EmptyValue* next;
|
||||
};
|
||||
#ifdef OBJ_COUNTER
|
||||
#if OBJ_COUNTER
|
||||
extern u64 currObjCounter;
|
||||
#endif
|
||||
extern u64 mm_heapAlloc;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#endif
|
||||
#include "gc.c"
|
||||
|
||||
#ifdef OBJ_COUNTER
|
||||
#if OBJ_COUNTER
|
||||
u64 currObjCounter;
|
||||
#endif
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else ca
|
||||
struct Value;
|
||||
EmptyValue* next;
|
||||
};
|
||||
#ifdef OBJ_COUNTER
|
||||
#if OBJ_COUNTER
|
||||
extern u64 currObjCounter;
|
||||
#endif
|
||||
extern u64 mm_heapAlloc;
|
||||
|
||||
@ -60,19 +60,13 @@ static NOINLINE void* BN(allocateMore)(i64 bucket, u8 type, i64 from, i64 to) {
|
||||
thrOOM();
|
||||
}
|
||||
|
||||
#if LOG_GC || LOG_MM_MORE
|
||||
fprintf(stderr, "allocating "N64u" more " STR1(BN()) " heap (from allocation of "N64u"B/bucket %d)", sz, (u64)BSZ(bucket), (int)bucket);
|
||||
#endif
|
||||
if (mem_log_enabled) fprintf(stderr, "requesting "N64u" more " STR1(BN()) " heap (during allocation of "N64u"B t_%s)", sz, (u64)BSZ(bucket), type_repr(type));
|
||||
#if NO_MMAP
|
||||
EmptyValue* c = calloc(sz+getPageSize(), 1);
|
||||
#if LOG_GC || LOG_MM_MORE
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
if (mem_log_enabled) fprintf(stderr, "\n");
|
||||
#else
|
||||
u8* mem = MMAP(sz);
|
||||
#if LOG_GC || LOG_MM_MORE
|
||||
fprintf(stderr, ": got %p\n", mem);
|
||||
#endif
|
||||
if (mem_log_enabled) fprintf(stderr, ": %s\n", mem==MAP_FAILED? "failed" : "success");
|
||||
if (mem==MAP_FAILED) thrOOM();
|
||||
if (ptr2u64(mem)+sz > (1ULL<<48)) fatal("mmap returned address range above 2⋆48");
|
||||
#if ALLOC_MODE==0
|
||||
|
||||
@ -8,7 +8,7 @@ FORCE_INLINE void BN(freeLink)(Value* x, bool link) {
|
||||
#else
|
||||
preFree(x, false);
|
||||
#endif
|
||||
#ifdef DONT_FREE
|
||||
#if DONT_FREE
|
||||
if (x->type!=t_freed) x->flags = x->type;
|
||||
#else
|
||||
u8 b = x->mmInfo&127;
|
||||
@ -36,7 +36,7 @@ static void* BN(allocL)(i64 bucket, u8 type) {
|
||||
x->refc = 1;
|
||||
x->type = type;
|
||||
x->mmInfo = bucket;
|
||||
#ifdef OBJ_COUNTER
|
||||
#if OBJ_COUNTER
|
||||
x->uid = currObjCounter++;
|
||||
#ifdef OBJ_TRACK
|
||||
if (x->uid == OBJ_TRACK) {
|
||||
|
||||
@ -55,10 +55,10 @@ NOINLINE void mut_to(Mut* m, u8 n) {
|
||||
m->fns = &mutFns[n];
|
||||
SPRNK(m->val, 1);
|
||||
m->val->sh = &m->val->ia;
|
||||
#ifdef USE_VALGRIND
|
||||
#if USE_VALGRIND
|
||||
VALGRIND_MAKE_MEM_DEFINED(m->val, mm_size((Value*)m->val)); // it's incomplete, but it's a typed array so garbage is acceptable
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
if (n==el_B && o==el_f64) { // hack to make toHArr calling f64arr_get not cry about possible sNaN floats
|
||||
usz ia = m->val->ia;
|
||||
f64* p = f64arr_ptr(taga(m->val));
|
||||
|
||||
@ -28,7 +28,7 @@ void ryu_init(void) { }
|
||||
#include "ryu/ryu_common.h"
|
||||
|
||||
// Include either the small or the full lookup tables depending on the mode.
|
||||
#if defined(RYU_OPTIMIZE_SIZE)
|
||||
#if RYU_OPTIMIZE_SIZE
|
||||
#include "ryu/d2s_small_table.h"
|
||||
#else
|
||||
#include "ryu/d2s_full_table.h"
|
||||
@ -83,7 +83,7 @@ static inline floating_decimal_64 d2d(const uint64_t mantissa, const uint32_t ex
|
||||
e10 = (int32_t) q;
|
||||
const int32_t k = DOUBLE_POW5_INV_BITCOUNT + pow5bits((int32_t) q) - 1;
|
||||
const int32_t i = -e2 + (int32_t) q + k;
|
||||
#if defined(RYU_OPTIMIZE_SIZE)
|
||||
#if RYU_OPTIMIZE_SIZE
|
||||
uint64_t pow5[2];
|
||||
double_computeInvPow5(q, pow5);
|
||||
vr = mulShiftAll64(m2, pow5, i, &vp, &vm, mmShift);
|
||||
@ -118,7 +118,7 @@ static inline floating_decimal_64 d2d(const uint64_t mantissa, const uint32_t ex
|
||||
const int32_t i = -e2 - (int32_t) q;
|
||||
const int32_t k = pow5bits(i) - DOUBLE_POW5_BITCOUNT;
|
||||
const int32_t j = (int32_t) q - k;
|
||||
#if defined(RYU_OPTIMIZE_SIZE)
|
||||
#if RYU_OPTIMIZE_SIZE
|
||||
uint64_t pow5[2];
|
||||
double_computePow5(i, pow5);
|
||||
vr = mulShiftAll64(m2, pow5, j, &vp, &vm, mmShift);
|
||||
@ -558,7 +558,7 @@ bool ryu_s2d_n(u8* buffer, int len, f64* result) {
|
||||
// To that end, we use the DOUBLE_POW5_SPLIT table.
|
||||
int j = e2 - e10 - ceil_log2pow5(e10) + DOUBLE_POW5_BITCOUNT;
|
||||
assert(j >= 0);
|
||||
#if defined(RYU_OPTIMIZE_SIZE)
|
||||
#if RYU_OPTIMIZE_SIZE
|
||||
uint64_t pow5[2];
|
||||
double_computePow5(e10, pow5);
|
||||
m2 = mulShift64(m10, pow5, j);
|
||||
@ -575,7 +575,7 @@ bool ryu_s2d_n(u8* buffer, int len, f64* result) {
|
||||
} else {
|
||||
e2 = floor_log2(m10) + e10 - ceil_log2pow5(-e10) - (DOUBLE_MANTISSA_BITS + 1);
|
||||
int j = e2 - e10 + ceil_log2pow5(-e10) - 1 + DOUBLE_POW5_INV_BITCOUNT;
|
||||
#if defined(RYU_OPTIMIZE_SIZE)
|
||||
#if RYU_OPTIMIZE_SIZE
|
||||
uint64_t pow5[2];
|
||||
double_computeInvPow5(-e10, pow5);
|
||||
m2 = mulShift64(m10, pow5, j);
|
||||
|
||||
@ -1,7 +1,3 @@
|
||||
#ifndef DBG_VG_OVERRIDES
|
||||
#define DBG_VG_OVERRIDES 0
|
||||
#endif
|
||||
|
||||
static void printBitDef(u8 val, u8 def) {
|
||||
printf("%s", def&1? val&1?"1":"0" : val&1?"¹":"⁰");
|
||||
}
|
||||
|
||||
18
src/vm.c
18
src/vm.c
@ -692,14 +692,14 @@ FORCE_INLINE B gotoNextBody(Block* bl, Scope* sc, Body* body) {
|
||||
return execBodyInplaceI(body, nsc, bl);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VM
|
||||
#if DEBUG_VM
|
||||
i32 bcDepth=-2;
|
||||
i32* vmStack;
|
||||
i32 bcCtr = 0;
|
||||
#endif
|
||||
#define BCPOS(B,P) (B->bl->map[(P)-(u32*)B->bl->bc])
|
||||
B evalBC(Body* b, Scope* sc, Block* bl) { // doesn't consume
|
||||
#ifdef DEBUG_VM
|
||||
#if DEBUG_VM
|
||||
bcDepth+= 2;
|
||||
if (!vmStack) vmStack = malloc(400);
|
||||
i32 stackNum = bcDepth>>1;
|
||||
@ -738,7 +738,7 @@ B evalBC(Body* b, Scope* sc, Block* bl) { // doesn't consume
|
||||
#endif
|
||||
|
||||
while(true) {
|
||||
#ifdef DEBUG_VM
|
||||
#if DEBUG_VM
|
||||
u32* sbc = bc;
|
||||
i32 bcPos = BCPOS(b,sbc);
|
||||
vmStack[stackNum] = bcPos;
|
||||
@ -937,20 +937,20 @@ B evalBC(Body* b, Scope* sc, Block* bl) { // doesn't consume
|
||||
case RETN: goto end;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
printf("todo %d\n", bc[-1]); bc++; break;
|
||||
#else
|
||||
UD;
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG_VM
|
||||
#if DEBUG_VM
|
||||
for(i32 i = 0; i < bcDepth; i++) fprintf(stderr," ");
|
||||
print_BC(stderr,sbc,20); fprintf(stderr,"@%d out: ",BCPOS(b, sbc));
|
||||
for (i32 i = 0; i < lgStack-origStack; i++) { if(i)fprintf(stderr,"; "); fprintI(stderr,origStack[i]); } fputc('\n',stderr); fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
end:;
|
||||
#ifdef DEBUG_VM
|
||||
#if DEBUG_VM
|
||||
bcDepth-= 2;
|
||||
#endif
|
||||
B r = POP;
|
||||
@ -1183,7 +1183,7 @@ static void allocStack(void** curr, void** start, void** end, i32 elSize, i32 co
|
||||
#endif
|
||||
}
|
||||
void print_vmStack() {
|
||||
#ifdef DEBUG_VM
|
||||
#if DEBUG_VM
|
||||
printf("vm stack:");
|
||||
for (i32 i = 0; i < (bcDepth>>1) + 1; i++) { printf(" %d", vmStack[i]); fflush(stdout); }
|
||||
printf("\n"); fflush(stdout);
|
||||
@ -1392,7 +1392,7 @@ native_print:
|
||||
|
||||
//print_BCStream((u32*)i32arr_ptr(comp->bc)+bcPos);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
if (pos!=-1) fprintf(stderr, N64d": ", pos);
|
||||
fprintf(stderr, "source unknown\n");
|
||||
#endif
|
||||
@ -1707,7 +1707,7 @@ NOINLINE NORETURN void throwImpl(bool rethrow) {
|
||||
unwindEnv(envStart-1);
|
||||
vm_pst(envCurr+1, envEnd);
|
||||
before_exit();
|
||||
#ifdef DEBUG
|
||||
#if DEBUG
|
||||
__builtin_trap();
|
||||
#else
|
||||
exit(1);
|
||||
|
||||
3
src/vm.h
3
src/vm.h
@ -15,6 +15,9 @@
|
||||
#ifndef EXT_ONLY_GLOBAL
|
||||
#define EXT_ONLY_GLOBAL 1
|
||||
#endif
|
||||
#ifndef VM_POS
|
||||
#define VM_POS 1
|
||||
#endif
|
||||
|
||||
enum {
|
||||
PUSH = 0x00, // N; push object from objs[N]
|
||||
|
||||
@ -12,7 +12,7 @@ build/build f='-DWARN_SLOW' c && ./BQN -p 2+2 2> /dev/null || exit
|
||||
build/build f='-DMM=0 -DENABLE_GC=0' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DMM=1' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DMM=2' debug c && ./BQN "$1/test/this.bqn" || exit
|
||||
build/build usz=64 debug singeli=1 arch=generic c && ./BQN "$1/test/this.bqn" || exit
|
||||
build/build usz=64 debug singeli arch=generic c && ./BQN "$1/test/this.bqn" || exit
|
||||
build/build f='-DTYPED_ARITH=0' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DFAKE_RUNTIME' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DALL_R0' c && ./BQN -p 2+2 || exit
|
||||
@ -26,7 +26,7 @@ build/build f='-DOBJ_COUNTER' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DNO_RT' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DNATIVE_COMPILER' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DNATIVE_COMPILER -DONLY_NATIVE_COMP -DFORMATTER=0 -DNO_RT -DNO_EXPLAIN' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DLOG_GC' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DGC_LOG_DETAILED' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DUSE_PERF' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DREPL_INTERRUPT=0' c && ./BQN -p 2+2 || exit
|
||||
build/build f='-DREPL_INTERRUPT=1' c && ./BQN -p 2+2 || exit
|
||||
|
||||
Loading…
Reference in New Issue
Block a user