summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-01-21 13:20:25 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-01-21 13:21:02 -0500
commit10dbaa3391e8ad4e076a6fcd6f9790d7f625552a (patch)
tree1628328b590799e84daf0593f8eae776038338ac
parent8406747331eef16a525f0dbf4d26445d243e19d1 (diff)
only load libraries once
-rw-r--r--data_structures.c8
-rw-r--r--eval.c3
-rw-r--r--foreign.c33
-rw-r--r--main.c1
-rw-r--r--test.toc6
-rw-r--r--types.c3
-rw-r--r--types.h16
7 files changed, 50 insertions, 20 deletions
diff --git a/data_structures.c b/data_structures.c
index 970d966..19f4efd 100644
--- a/data_structures.c
+++ b/data_structures.c
@@ -287,7 +287,6 @@ static void str_hash_table_grow(StrHashTable *t) {
}
arr_cleara(&t->slots, t->allocr);
t->slots = new_slots;
- slots_cap = new_slots_cap;
}
}
@@ -340,12 +339,16 @@ static void str_hash_table_free(StrHashTable *t) {
}
static StrHashTableSlot *str_hash_table_get_(StrHashTable *t, const char *str, size_t len) {
+ size_t nslots = arr_len(t->slots);
+ if (!nslots) return NULL;
size_t slot_index = str_hash(str, len) % arr_len(t->slots);
return *str_hash_table_slot_get(t->slots, str, len, slot_index);
}
static inline void *str_hash_table_get(StrHashTable *t, const char *str, size_t len) {
- return str_hash_table_get_(t, str, len)->data;
+ StrHashTableSlot *slot = str_hash_table_get_(t, str, len);
+ if (!slot) return NULL;
+ return slot->data;
}
#ifdef TOC_DEBUG
@@ -367,6 +370,7 @@ static void str_hash_table_test(void) {
*s = 123;
int *u = str_hash_table_get(&t, "Hello", 5);
assert(p == u);
+ assert(!str_hash_table_get(&t, "Hellopf", 7));
str_hash_table_free(&t);
}
#endif
diff --git a/eval.c b/eval.c
index b3a9c5c..0866ba6 100644
--- a/eval.c
+++ b/eval.c
@@ -18,6 +18,7 @@ static void evalr_create(Evaluator *ev, Typer *tr, Allocator *allocr) {
ev->typer = tr;
ev->enabled = true;
ev->allocr = allocr;
+ ffmgr_create(&ev->ffmgr, allocr);
}
static void evalr_free(Evaluator *ev) {
@@ -1435,7 +1436,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
if (!eval_expr(ev, &e->call.arg_exprs[i], &args[i]))
return false;
}
- bool success = foreign_call(fn, &e->call.fn->type, args, e->where, v);
+ bool success = foreign_call(&ev->ffmgr, fn, &e->call.fn->type, args, e->where, v);
free(args);
if (!success)
return false;
diff --git a/foreign.c b/foreign.c
index c7951a9..6e7bc98 100644
--- a/foreign.c
+++ b/foreign.c
@@ -222,26 +222,33 @@ static bool arg_list_add(av_alist *arg_list, Value *val, Type *type, Location wh
return true;
}
-static bool foreign_call(FnExpr *fn, Type *fn_type, Value *args, Location call_where, Value *ret) {
+static void ffmgr_create(ForeignFnManager *ffmgr, Allocator *allocr) {
+ str_hash_table_create(&ffmgr->libs_loaded, sizeof(Library), allocr);
+}
+
+static bool foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *fn_type, Value *args, Location call_where, Value *ret) {
void (*fn_ptr)() = fn->foreign.fn_ptr;
if (!fn_ptr) {
assert(fn->flags & FN_EXPR_FOREIGN);
- const char *lib = fn->foreign.lib;
- const char *name = fn->foreign.name;
-
- /* TODO: IMPORTANT: only open libraries once */
- void *handle = dlopen(lib, RTLD_LAZY);
- printf("Load %s\n",lib);
- if (!handle) {
- err_print(call_where, "Could not open dynamic library: %s.", lib);
- return false;
+ const char *libname = fn->foreign.lib;
+ Library *lib = str_hash_table_get(&ffmgr->libs_loaded, libname, strlen(libname));
+ if (!lib) {
+ /* TODO: IMPORTANT: only open libraries once */
+ void *handle = dlopen(libname, RTLD_LAZY);
+ printf("Load %s\n",libname);
+ if (!handle) {
+ err_print(call_where, "Could not open dynamic library: %s.", lib);
+ return false;
+ }
+ lib = str_hash_table_insert(&ffmgr->libs_loaded, libname, strlen(libname));
+ lib->handle = handle;
}
-
+ const char *name = fn->foreign.name;
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
- fn_ptr = dlsym(handle, name);
+ fn_ptr = dlsym(lib->handle, name);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
@@ -250,7 +257,7 @@ static bool foreign_call(FnExpr *fn, Type *fn_type, Value *args, Location call_w
err_print(call_where, "Could not get function from dynamic library: %s.", name);
return false;
}
- fn->foreign.fn_ptr = fn_ptr;
+ fn->foreign.fn_ptr = fn_ptr;
}
av_alist arg_list;
diff --git a/main.c b/main.c
index fe5ea6a..a5c886f 100644
--- a/main.c
+++ b/main.c
@@ -66,6 +66,7 @@ int main(int argc, char **argv) {
char *contents = err_malloc(4096);
contents[0] = 0; /* put 0 byte at the start of the file. see err.c:err_print_location_text to find out why */
+ contents[1] = 0; /* if fgets fails the first time */
long contents_cap = 4095;
long contents_len = 1;
while (fgets(contents + contents_len, (int)(contents_cap - contents_len), in)) {
diff --git a/test.toc b/test.toc
index 3cd0b33..4bcb48e 100644
--- a/test.toc
+++ b/test.toc
@@ -24,6 +24,12 @@ foo ::= fn() i32 {
puts("Hey")
};
+malloc :: fn(u64) &u8 = #foreign "malloc", "libc.so.6";
+
+sqrt :: fn(f64) f64 = #foreign "sqrt", "libm.so";
+
main ::= fn() {
x ::= foo();
+ y ::= malloc(10);
+ sq2 ::= sqrt(2);
}; \ No newline at end of file
diff --git a/types.c b/types.c
index d0026f3..0c79d33 100644
--- a/types.c
+++ b/types.c
@@ -1476,9 +1476,6 @@ static bool types_expr(Typer *tr, Expression *e) {
- i = 0;
-
-
table_index_type.flags = TYPE_IS_RESOLVED;
table_index_type.kind = TYPE_TUPLE;
table_index_type.tuple = NULL;
diff --git a/types.h b/types.h
index 46271aa..7b0e498 100644
--- a/types.h
+++ b/types.h
@@ -813,6 +813,20 @@ typedef enum {
DECL_END_LBRACE_COMMA
} DeclEndKind;
+#if COMPILE_TIME_FOREIGN_FN_SUPPORT
+typedef struct {
+ void *handle;
+} Library;
+#endif
+
+typedef struct {
+#if COMPILE_TIME_FOREIGN_FN_SUPPORT
+ StrHashTable libs_loaded; /* of Library */
+#else
+ char unused;
+#endif
+} ForeignFnManager;
+
typedef struct Evaluator {
Allocator *allocr;
struct Typer *typer;
@@ -820,6 +834,7 @@ typedef struct Evaluator {
Value ret_val;
void **to_free; /* an array of data to free for this scope. */
bool enabled;
+ ForeignFnManager ffmgr;
} Evaluator;
typedef struct Package {
@@ -887,7 +902,6 @@ typedef struct CGenerator {
char *pkg_prefix;
} CGenerator;
-
#ifdef TOC_DEBUG
#define add_ident_decls(b, d, flags) add_ident_decls_(__FILE__, __LINE__, b, d, flags)
#endif