gc: add Nit GC
[nit.git] / clib / nit_main.c
1 /* This file is part of NIT ( http://www.nitlanguage.org ).
2 *
3 * Copyright 2006-2009 Jean Privat <jean@pryen.org>
4 *
5 * This file is free software, which comes along with NIT. This software is
6 * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
7 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
8 * PARTICULAR PURPOSE. You can modify it is you want, provided this header
9 * is kept unaltered, and a notification of the changes is added.
10 * You are allowed to redistribute it and sell it, alone or is a part of
11 * another product.
12 */
13
14 #include "nit_common.h"
15 #include <signal.h>
16 #include <stdarg.h>
17 #include "gc.h"
18
19 bigint object_id_counter = 1000000;
20 enum gc_option { large, boehm, nitgc } gc_option;
21
22 #ifdef WITH_LIBGC
23 #define GC_DEBUG
24 #include <gc/gc.h>
25 #endif
26
27 void *raw_alloc(size_t s0)
28 {
29 switch (gc_option) {
30 case nitgc: return malloc(s0); break;
31 default: return alloc(s0);
32 }
33 }
34
35 void register_static_object(val_t *o)
36 {
37 switch (gc_option) {
38 case nitgc: GC_add_static_object(o); break;
39 default: break;
40 }
41 return;
42 }
43
44 void *large_alloc(size_t s0)
45 {
46 static char * alloc_pos = NULL;
47 static size_t alloc_size = 0;
48 void * res;
49 size_t s = ((s0+3)/4)*4;
50 if(alloc_size < s) {
51 alloc_size = s + 1024*1024;
52 alloc_pos = (char *)calloc(alloc_size, 1);
53 }
54 res = alloc_pos;
55 alloc_size -= s;
56 alloc_pos += s;
57 return res;
58 }
59
60 void * alloc(size_t s0)
61 {
62 switch (gc_option) {
63 #ifdef WITH_LIBGC
64 case boehm: return GC_MALLOC(s0);
65 #endif
66 case nitgc: return Nit_gc_malloc(s0);
67 case large:
68 default: return large_alloc(s0);
69 }
70 }
71
72 int glob_argc;
73 char **glob_argv;
74 val_t G_sys;
75
76 void exithandler(int s) {
77 fprintf(stderr, "Recieved signal %d\n", s);
78 nit_exit(1);
79 }
80 void initialize_gc_option(void) {
81 /* GC default */
82 #ifdef WITH_LIBGC
83 gc_option = boehm;
84 #else
85 gc_option = large;
86 #endif
87
88 /* Process GC runtime selection */
89 if (getenv("NIT_GC_OPTION") != NULL) {
90 char *opt=getenv("NIT_GC_OPTION");
91 if (strcmp(opt, "boehm")==0) {
92 #ifdef WITH_LIBGC
93 gc_option = boehm;
94 #else
95 fprintf(stderr, "Compiled without Boehm GC support. Using default.\n");
96 #endif
97 } else if (strcmp(opt, "nitgc")==0) {
98 gc_option = nitgc;
99 } else if (strcmp(opt, "large")==0) {
100 gc_option = large;
101 } else {
102 fprintf(stderr, "Invalid GC option in NIT_GC_OPTION environment variable. Using default.\n");
103 }
104 }
105
106 /* Initialize GC (if needed) */
107 switch(gc_option) {
108 #ifdef WITH_LIBGC
109 case boehm: GC_INIT(); break;
110 #endif
111 case nitgc: Nit_gc_init(); break;
112 default: break; /* Nothing */
113 }
114 }
115 void prepare_signals(void) {
116 initialize_gc_option();
117
118 signal(SIGINT,exithandler);
119 signal(SIGABRT,exithandler);
120 signal(SIGSEGV,exithandler);
121 signal(SIGILL, exithandler);
122 signal(SIGFPE, exithandler);
123 signal(SIGTERM,exithandler);
124 signal(SIGBUS, exithandler);
125 }
126 struct trace_t *tracehead = NULL;
127 void nit_exit(int i) {
128 fprintf(stderr, ",---- Stack trace -- - - -\n");
129 while(tracehead != NULL) {
130 fprintf(stderr, "| %s (%s:%d)\n", tracehead->meth, tracehead->file, tracehead->line);
131 if (tracehead == tracehead->prev) break;
132 tracehead = tracehead->prev;
133 }
134 fprintf(stderr, "`------------------- - - -\n");
135 exit(i);
136 }