Merge: doc: fixed some typos and other misc. corrections
[nit.git] / c_src / gc_chooser.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 "gc_chooser.h"
15 #include <stdlib.h>
16 #include <string.h>
17
18 #ifdef ANDROID
19 #include <android/log.h>
20 #define PRINT_ERROR(...) ((void)__android_log_print(ANDROID_LOG_WARN, "nit", __VA_ARGS__))
21
22 // FIXME bring back when the GC is fixed in Android
23 #undef WITH_LIBGC
24 #else
25 #define PRINT_ERROR(...) ((void)fprintf(stderr, __VA_ARGS__))
26 #endif
27
28 enum gc_option { gc_opt_large, gc_opt_malloc, gc_opt_boehm } gc_option;
29
30 #ifdef WITH_LIBGC
31 #include <gc/gc.h>
32 #endif
33
34 void *nit_raw_alloc(size_t s0)
35 {
36 switch (gc_option) {
37 case gc_opt_malloc: return malloc(s0);
38 #ifdef WITH_LIBGC
39 case gc_opt_boehm: return GC_MALLOC_ATOMIC(s0);
40 #endif
41
42 default: return nit_alloc(s0);
43 }
44 }
45
46 static void *large_alloc(size_t s0)
47 {
48 static char * alloc_pos = NULL;
49 static size_t alloc_size = 0;
50 void * res;
51 size_t s = ((s0+3)/4)*4;
52 if(alloc_size < s) {
53 alloc_size = s + 1024*1024;
54 alloc_pos = (char *)calloc(alloc_size, 1);
55 }
56 res = alloc_pos;
57 alloc_size -= s;
58 alloc_pos += s;
59 return res;
60 }
61
62 void nit_gcollect(void) {
63 switch (gc_option) {
64 #ifdef WITH_LIBGC
65 case gc_opt_boehm: GC_gcollect(); break;
66 #endif
67 default: break; /* nothing can be done */
68 }
69 }
70
71 void *nit_alloc(size_t s0)
72 {
73 switch (gc_option) {
74 #ifdef WITH_LIBGC
75 case gc_opt_boehm: return GC_MALLOC(s0);
76 #endif
77 case gc_opt_malloc: return calloc(1, s0);
78 case gc_opt_large:
79 default: return large_alloc(s0);
80 }
81 }
82
83 void initialize_gc_option(void) {
84 /* GC default */
85 char *def;
86 #ifdef WITH_LIBGC
87 gc_option = gc_opt_boehm;
88 def = "boehm";
89 #else
90 gc_option = gc_opt_malloc;
91 def = "malloc";
92 #endif
93
94 /* Process GC runtime selection */
95 if (getenv("NIT_GC_OPTION") != NULL) {
96 char *opt=getenv("NIT_GC_OPTION");
97 if (strcmp(opt, "boehm")==0) {
98 #ifdef WITH_LIBGC
99 gc_option = gc_opt_boehm;
100 #else
101 PRINT_ERROR( "Compiled without Boehm GC support. Using default '%s'.\n", def);
102 #endif
103 } else if (strcmp(opt, "malloc")==0) {
104 gc_option = gc_opt_malloc;
105 } else if (strcmp(opt, "large")==0) {
106 gc_option = gc_opt_large;
107 } else if (strcmp(opt, "help")==0) {
108 PRINT_ERROR( "NIT_GC_OPTION accepts 'malloc', 'large'"
109 #ifdef WITH_LIBGC
110 ", 'boehm'"
111 #endif
112 ". Default is '%s'.\n", def);
113 exit(1);
114 } else {
115 PRINT_ERROR( "Invalid GC option in NIT_GC_OPTION environment variable. Using default '%s'.\n", def);
116 }
117 }
118
119 /* Initialize GC (if needed) */
120 switch(gc_option) {
121 #ifdef WITH_LIBGC
122 case gc_opt_boehm: GC_INIT(); break;
123 #endif
124 default: break; /* Nothing */
125 }
126 }
127
128 void gc_register_finalizer(void* obj) {
129 #ifdef WITH_LIBGC
130 GC_register_finalizer(obj, &gc_finalize, NULL, NULL, NULL);
131 #endif
132 }
133
134 void __attribute__((weak)) gc_finalize(void *obj, void* client_data) {}