--- /dev/null
+/* This file is part of NIT ( http://www.nitlanguage.org ).
+ *
+ * Copyright 2006-2009 Jean Privat <jean@pryen.org>
+ *
+ * This file is free software, which comes along with NIT. This software is
+ * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. You can modify it is you want, provided this header
+ * is kept unaltered, and a notification of the changes is added.
+ * You are allowed to redistribute it and sell it, alone or is a part of
+ * another product.
+ */
+
+#include "gc_chooser.h"
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef ANDROID
+ #include <android/log.h>
+ #define PRINT_ERROR(...) ((void)__android_log_print(ANDROID_LOG_WARN, "nit", __VA_ARGS__))
+#else
+ #define PRINT_ERROR(...) ((void)fprintf(stderr, __VA_ARGS__))
+#endif
+
+enum gc_option { gc_opt_large, gc_opt_malloc, gc_opt_boehm } gc_option;
+
+#ifdef WITH_LIBGC
+#define GC_DEBUG
+#include <gc/gc.h>
+#endif
+
+void *nit_raw_alloc(size_t s0)
+{
+ switch (gc_option) {
+ case gc_opt_malloc: return malloc(s0);
+#ifdef WITH_LIBGC
+ case gc_opt_boehm: return GC_MALLOC_ATOMIC(s0);
+#endif
+
+ default: return nit_alloc(s0);
+ }
+}
+
+static void *large_alloc(size_t s0)
+{
+ static char * alloc_pos = NULL;
+ static size_t alloc_size = 0;
+ void * res;
+ size_t s = ((s0+3)/4)*4;
+ if(alloc_size < s) {
+ alloc_size = s + 1024*1024;
+ alloc_pos = (char *)calloc(alloc_size, 1);
+ }
+ res = alloc_pos;
+ alloc_size -= s;
+ alloc_pos += s;
+ return res;
+}
+
+void nit_gcollect(void) {
+ switch (gc_option) {
+#ifdef WITH_LIBGC
+ case gc_opt_boehm: GC_gcollect(); break;
+#endif
+ }
+}
+
+void *nit_alloc(size_t s0)
+{
+ switch (gc_option) {
+#ifdef WITH_LIBGC
+ case gc_opt_boehm: return GC_MALLOC(s0);
+#endif
+ case gc_opt_malloc: return calloc(1, s0);
+ case gc_opt_large:
+ default: return large_alloc(s0);
+ }
+}
+
+void initialize_gc_option(void) {
+ /* GC default */
+ char *def;
+#ifdef WITH_LIBGC
+ gc_option = gc_opt_boehm;
+ def = "boehm";
+#else
+ gc_option = gc_opt_malloc;
+ def = "malloc";
+#endif
+
+ /* Process GC runtime selection */
+ if (getenv("NIT_GC_OPTION") != NULL) {
+ char *opt=getenv("NIT_GC_OPTION");
+ if (strcmp(opt, "boehm")==0) {
+#ifdef WITH_LIBGC
+ gc_option = gc_opt_boehm;
+#else
+ PRINT_ERROR( "Compiled without Boehm GC support. Using default '%s'.\n", def);
+#endif
+ } else if (strcmp(opt, "malloc")==0) {
+ gc_option = gc_opt_malloc;
+ } else if (strcmp(opt, "large")==0) {
+ gc_option = gc_opt_large;
+ } else if (strcmp(opt, "help")==0) {
+ PRINT_ERROR( "NIT_GC_OPTION accepts 'malloc', 'large'"
+#ifdef WITH_LIBGC
+ ", 'boehm'"
+#endif
+ ". Default is '%s'.\n", def);
+ exit(1);
+ } else {
+ PRINT_ERROR( "Invalid GC option in NIT_GC_OPTION environment variable. Using default '%s'.\n", def);
+ }
+ }
+
+ /* Initialize GC (if needed) */
+ switch(gc_option) {
+#ifdef WITH_LIBGC
+ case gc_opt_boehm: GC_INIT(); break;
+#endif
+ default: break; /* Nothing */
+ }
+}
--- /dev/null
+#ifndef NIT_GC_CHOOSER_H
+#define NIT_GC_CHOOSER_H
+
+/* This file is part of NIT ( http://www.nitlanguage.org ).
+ *
+ * This file is free software, which comes along with NIT. This software is
+ * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. You can modify it is you want, provided this header
+ * is kept unaltered, and a notification of the changes is added.
+ * You are allowed to redistribute it and sell it, alone or is a part of
+ * another product.
+ */
+
+#include <stdio.h>
+
+/* GC and memory management */
+void *nit_alloc(size_t); /* allocate memory to store an object with an object header */
+void *nit_raw_alloc(size_t); /* allocate raw memory to store a raw stram of byte */
+void nit_gcollect(void); /* force a garbage collection */
+void initialize_gc_option(void); /* Select the wanted GC using envvar `NIT_GC_OPTION` */
+
+#endif
makefile.write("{o}: {f}\n\t$(CC) $(CFLAGS) -D NONITCNI -c -o {o} {f}\n\n")
ofiles.add(o)
end
+
+ # Add gc_choser.h to aditionnal bodies
+ var gc_chooser = new ExternCFile("{cc_paths.first}/gc_chooser.c", "-DWITH_LIBGC")
+ compiler.extern_bodies.add(gc_chooser)
+
# Compile each required extern body into a specific .o
for f in compiler.extern_bodies do
var basename = f.filename.basename(".c")
self.header.add_decl("#include <stdlib.h>")
self.header.add_decl("#include <stdio.h>")
self.header.add_decl("#include <string.h>")
- self.header.add_decl("#ifndef NOBOEHM")
- self.header.add_decl("#include <gc/gc.h>")
- self.header.add_decl("#ifdef NOBOEHM_ATOMIC")
- self.header.add_decl("#undef GC_MALLOC_ATOMIC")
- self.header.add_decl("#define GC_MALLOC_ATOMIC(x) GC_MALLOC(x)")
- self.header.add_decl("#endif /*NOBOEHM_ATOMIC*/")
- self.header.add_decl("#else /*NOBOEHM*/")
- self.header.add_decl("#define GC_MALLOC(x) calloc(1, (x))")
- self.header.add_decl("#define GC_MALLOC_ATOMIC(x) calloc(1, (x))")
- self.header.add_decl("#endif /*NOBOEHM*/")
+ self.header.add_decl("#include <gc_chooser.h>")
compile_header_structs
end
v.add_decl("int main(int argc, char** argv) \{")
v.add("glob_argc = argc; glob_argv = argv;")
+ v.add("initialize_gc_option();")
var main_type = mainmodule.sys_type
if main_type != null then
var mainmodule = v.compiler.mainmodule
v.ret(v.new_expr("glob_sys", ret.as(not null)))
return
else if pname == "calloc_string" then
- v.ret(v.new_expr("(char*)GC_MALLOC_ATOMIC({arguments[1]})", ret.as(not null)))
+ v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null)))
return
else if pname == "calloc_array" then
v.calloc_array(ret.as(not null), arguments)
v.ret(v.new_expr("(char*){nat}", ret.as(not null)))
return
else if pname == "force_garbage_collection" then
- v.add("GC_gcollect();")
+ v.add("nit_gcollect();")
return
end
v.add("printf(\"NOT YET IMPLEMENTED {class_name}:{mpropdef} at {location.to_s}\\n\");")
res.is_exact = true
if is_native_array then
var mtype_elt = mtype.arguments.first
- v.add("{res} = GC_MALLOC(sizeof(struct {mtype.c_name}) + length*sizeof({mtype_elt.ctype}));")
+ v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}) + length*sizeof({mtype_elt.ctype}));")
else
- v.add("{res} = GC_MALLOC(sizeof(struct {mtype.c_name}));")
+ v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}));")
end
v.add("{res}->classid = {self.classid(mtype)};")
self.header.add_decl("val* BOX_{mtype.c_name}({mtype.ctype});")
v.add_decl("/* allocate {mtype} */")
v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{")
- v.add("struct {mtype.c_name}*res = GC_MALLOC(sizeof(struct {mtype.c_name}));")
+ v.add("struct {mtype.c_name}*res = nit_alloc(sizeof(struct {mtype.c_name}));")
v.add("res->classid = {self.classid(mtype)};")
v.add("res->value = value;")
v.add("return (val*)res;")
self.header.add_decl("val* BOX_{c_name}({mtype.ctype});")
v.add_decl("/* allocate {mtype} */")
v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{")
- v.add("struct instance_{c_name}*res = GC_MALLOC(sizeof(struct instance_{c_name}));")
+ v.add("struct instance_{c_name}*res = nit_alloc(sizeof(struct instance_{c_name}));")
v.require_declaration("type_{c_name}")
v.add("res->type = &type_{c_name};")
v.require_declaration("class_{c_name}")
var res = v.new_named_var(mtype, "self")
res.is_exact = true
var mtype_elt = mtype.arguments.first
- v.add("{res} = GC_MALLOC(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));")
+ v.add("{res} = nit_alloc(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));")
v.add("{res}->type = type;")
hardening_live_type(v, "type")
v.require_declaration("class_{c_name}")
v.add_decl("{mtype.ctype} NEW_{c_name}(const struct type* type) \{")
var res = v.new_named_var(mtype, "self")
res.is_exact = true
- v.add("{res} = GC_MALLOC(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));")
+ v.add("{res} = nit_alloc(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));")
v.add("{res}->type = type;")
hardening_live_type(v, "type")
v.require_declaration("class_{c_name}")
self.header.add_decl("val* BOX_{c_name}({mtype.ctype});")
v.add_decl("/* allocate {mtype} */")
v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{")
- v.add("struct instance_{c_name}*res = GC_MALLOC(sizeof(struct instance_{c_name}));")
+ v.add("struct instance_{c_name}*res = nit_alloc(sizeof(struct instance_{c_name}));")
v.require_declaration("class_{c_name}")
v.add("res->class = &class_{c_name};")
v.add("res->value = value;")
var res = v.new_named_var(mtype, "self")
res.is_exact = true
var mtype_elt = mtype.arguments.first
- v.add("{res} = GC_MALLOC(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));")
+ v.add("{res} = nit_alloc(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));")
v.require_declaration("class_{c_name}")
v.add("{res}->class = &class_{c_name};")
v.add("return {res};")
v.add_decl("{mtype.ctype} NEW_{c_name}(void) \{")
var res = v.new_named_var(mtype, "self")
res.is_exact = true
- v.add("{res} = GC_MALLOC(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));")
+ v.add("{res} = nit_alloc(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));")
v.require_declaration("class_{c_name}")
v.add("{res}->class = &class_{c_name};")
self.generate_init_attr(v, res, mtype)