extern mlval unix_rusage(mlval unit) { mlval utime, stime, result; /* on Solaris we can't do getrusage without the BSD-compatibility * library, which sucks, so we have to fake it : */ prusage_t usage; prpsinfo_t psinfo; if (pioc(PIOCPSINFO,&psinfo) == -1 || pioc(PIOCUSAGE,&usage) == -1) exn_raise_syserr(ml_string(strerror(errno)), errno); utime = ml_time(&usage.pr_utime); declare_root(&utime, 0); stime = ml_time(&usage.pr_stime); declare_root(&stime, 0); result = allocate_record(16); retract_root(&utime); retract_root(&stime); /* Lexical ordering for fields -- the result is a record with name fields. * * idrss integral resident set size * inblock block input operations * isrss currently 0 * ixrss currently 0 * majflt page faults requiring physical I/O * maxrss maximum resident set size Solaris : resident set size * minflt page faults not requiring physical I/O * msgrcv messages received * msgsnd messages sent * nivcsw involuntary context switches * nsignals signals received * nswap swaps voluntary * nvcsw context switches * oublock block output operations * stime system time used * utime user time used */ FIELD(result, 0) = MLINT(psinfo.pr_rssize); FIELD(result, 1) = MLINT(usage.pr_inblk); FIELD(result, 2) = MLINT(0); FIELD(result, 3) = MLINT(0); FIELD(result, 4) = MLINT(usage.pr_majf); FIELD(result, 5) = MLINT(psinfo.pr_rssize); FIELD(result, 6) = MLINT(usage.pr_minf); FIELD(result, 7) = MLINT(usage.pr_msnd); FIELD(result, 8) = MLINT(usage.pr_mrcv); FIELD(result, 9) = MLINT(usage.pr_ictx); FIELD(result, 10) = MLINT(usage.pr_sigs); FIELD(result, 11) = MLINT(usage.pr_nswap); FIELD(result, 12) = MLINT(usage.pr_vctx); FIELD(result, 13) = MLINT(usage.pr_oublk); FIELD(result, 14) = stime; FIELD(result, 15) = utime; return result; }
GC_USER_FUNC int main (int argc, char ** argv) { #ifdef MEMWATCH mwInit(); mwDoFlush(1); #endif // MEMWATCH ML_START_TIMING(main_time); GC_init(); //ml_print_gc_stats(); printf("Compiled for " #if defined(GC_CHERI) "GC_CHERI" #elif defined(GC_BOEHM) "GC_BOEHM" #elif defined(GC_NONE) "GC_NONE" #elif defined(GC_NOCAP) "GC_NOCAP" #else #error "Define one of GC_CHERI, GC_BOEHM, GC_NONE." #endif // GC_CHERI, GC_BOEHM, GC_NONE " at %s\n", __TIME__ " " __DATE__); //GC_CAP const char * filename = GC_cheri_ptr("ml-tmp", sizeof("ml-tmp")); //lex_read_file(filename); //const char str[] = "(fn x . ((fn x . x) 3) + x) 2"; //const char str[] = "fn f . (fn g. (f (fn a . (g g) a))) (fn g. (f (fn a . (g g) a)))"; //const char str[] = //"((fn f . fn n . if n then n * f (n-1) else 1) (fn n . n)) 5"; // factorial: //const char str[] = // "((fn f . (fn g. (f (fn a . (g g) a))) (fn g. (f (fn a . (g g) a)))) (fn f . fn n . if n then n * f (n-1) else 1)) 6"; // for the benchmark: if (argc < 2) { printf("Need a program argument\n"); return 1; } if (argc < 3) { printf("Need a number argument\n"); return 1; } printf("Program should be evaluating something to do with the number %s\n", argv[2]); int num = atoi(argv[2]); #ifdef GC_CHERI gc_cheri_grow_heap(num); #endif #ifdef GC_BOEHM GC_set_max_heap_size(num >= 1024 ? 350000*(num/1024) : num >= 256 ? 200000 : 65536); #endif /*const char str[] = "((fn f . (fn g. (f (fn a . (g g) a))) (fn g. (f (fn f . (g g) f)))) (fn f . fn n . if n then n + f (n-1) else 1)) "; GC_CAP char * str2 = ml_malloc(sizeof(str)+strlen(argv[1])); cmemcpy(str2, GC_cheri_ptr(str, sizeof(str)), sizeof(str)); cmemcpy(str2+sizeof(str)-1, GC_cheri_ptr(argv[1], strlen(argv[1]+1)), strlen(argv[1]+1)); */ GC_CAP const char * str2 = GC_cheri_ptr(argv[1], strlen(argv[1])+1); unsigned long long before = ml_time(); lex_read_string(str2); printf("program: %s\n\n", (void*)(str2)); /*size_t i; for (i=0; i<lex_state.max; i++) { putchar(((char*)lex_state.file)[i]); } GC_CAP token_t * t; t = lex(); while (t->type != TKEOF) { printf("[%d] (tag=%d alloc=%d) %s\n", ((token_t*)t)->type, (int) GC_cheri_gettag(((token_t*)t)->str), (int) GC_IS_GC_ALLOCATED(((token_t*)t)->str), (char*) ((token_t*)t)->str); GC_malloc(5000); t = lex(); } printf("Finished\n"); return 0;*/ parse_init(); GC_CAP expr_t * expr = GC_INVALID_PTR(); GC_STORE_CAP(expr, parse()); printf("AST:\n"); print_ast(expr); printf("\nDone printing AST\n"); /*printf("collecting loads\n"); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); ml_collect(); printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~done collecting loads\n"); GC_debug_print_region_stats(&GC_state.thread_local_region);*/ GC_CAP val_t * val = GC_INVALID_PTR(); int i; for (i=0; i<10; i++) { GC_STORE_CAP(val, eval(expr, GC_INVALID_PTR())); } unsigned long long after = ml_time(); unsigned long long diff = after - before; printf("eval: "); if (!PTR_VALID(val)) printf("(invalid"); else print_val(val); printf("\n\n"); printf("[plotdata] %s %llu\n", argv[2], (unsigned long long) diff); #ifdef GC_CHERI printf("(young) heap size:\n"); printf("[altplotdata] %s %llu\n", argv[2], (unsigned long long) (GC_cheri_getlen(GC_state.thread_local_region.tospace))); #ifdef GC_GENERATIONAL printf("old heap size:\n"); printf("[altplotdataold] %s %llu\n", argv[2], (unsigned long long) (GC_cheri_getlen(GC_state.old_generation.tospace))); #endif // GC_GENERATIONAL #endif // GC_CHERI #ifdef GC_BOEHM printf("[altplotdata] %s %llu\n", argv[2], (unsigned long long) GC_get_heap_size()); #endif // GC_BOEHM ML_STOP_TIMING(main_time, "main()"); ml_print_gc_stats(); ml_print_plot_data(); #ifdef MEMWATCH mwTerm(); #endif // MEMWATCH return 0; }