summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/ucode/types.h20
-rw-r--r--include/ucode/util.h28
-rw-r--r--tests/custom/03_stdlib/60_gc50
-rw-r--r--types.c95
-rw-r--r--vm.c50
5 files changed, 192 insertions, 51 deletions
diff --git a/include/ucode/types.h b/include/ucode/types.h
index bf8b9f2..85c3eb8 100644
--- a/include/ucode/types.h
+++ b/include/ucode/types.h
@@ -206,11 +206,6 @@ typedef struct {
uc_declare_vector(uc_resource_types_t, uc_resource_type_t *);
-
-/* Object iteration */
-
-extern uc_list_t uc_object_iterators;
-
typedef struct {
uc_list_t list;
struct lh_table *table;
@@ -270,6 +265,19 @@ uc_search_path_free(uc_search_path_t *search_path) {
}
+/* TLS data */
+
+typedef struct {
+ /* VM owning installed signal handlers */
+ uc_vm_t *signal_handler_vm;
+
+ /* Object iteration */
+ uc_list_t object_iterators;
+} uc_thread_context_t;
+
+__hidden uc_thread_context_t *uc_thread_context_get(void);
+
+
/* VM definitions */
typedef enum {
@@ -388,6 +396,7 @@ uc_value_t *ucv_array_push(uc_value_t *, uc_value_t *);
uc_value_t *ucv_array_shift(uc_value_t *);
uc_value_t *ucv_array_unshift(uc_value_t *, uc_value_t *);
void ucv_array_sort(uc_value_t *, int (*)(const void *, const void *));
+void ucv_array_sort_r(uc_value_t *, int (*)(uc_value_t *, uc_value_t *, void *), void *);
bool ucv_array_delete(uc_value_t *, size_t, size_t);
bool ucv_array_set(uc_value_t *, size_t, uc_value_t *);
size_t ucv_array_length(uc_value_t *);
@@ -396,6 +405,7 @@ uc_value_t *ucv_object_new(uc_vm_t *);
uc_value_t *ucv_object_get(uc_value_t *, const char *, bool *);
bool ucv_object_add(uc_value_t *, const char *, uc_value_t *);
void ucv_object_sort(uc_value_t *, int (*)(const void *, const void *));
+void ucv_object_sort_r(uc_value_t *, int (*)(const char *, uc_value_t *, const char *, uc_value_t *, void *), void *);
bool ucv_object_delete(uc_value_t *, const char *);
size_t ucv_object_length(uc_value_t *);
diff --git a/include/ucode/util.h b/include/ucode/util.h
index cc92e33..1360d28 100644
--- a/include/ucode/util.h
+++ b/include/ucode/util.h
@@ -267,4 +267,32 @@ uc_vector_extend_(char **base, size_t itemsize, size_t count, size_t add)
iter != NULL && iter >= (vec)->entries; \
iter--)
+#ifdef __APPLE__
+
+# define uc_vector_sort_cb(fn_, optype_, udtype_, ...) \
+ int fn_(void *ud, const void *k1, const void *k2) { \
+ optype_ v1 = *(optype_ *)k1; \
+ optype_ v2 = *(optype_ *)k2; \
+ udtype_ ctx = (udtype_)ud; \
+ __VA_ARGS__ \
+ }
+
+# define uc_vector_sort(v_, cmp_, ud_) \
+ qsort_r((v_)->entries, (v_)->count, sizeof((v_)->entries[0]), ud_, cmp_)
+
+#else
+
+# define uc_vector_sort_cb(fn_, optype_, udtype_, ...) \
+ int fn_(const void *k1, const void *k2, void *ud) { \
+ optype_ v1 = *(optype_ *)k1; \
+ optype_ v2 = *(optype_ *)k2; \
+ udtype_ ctx = (udtype_)ud; \
+ __VA_ARGS__ \
+ }
+
+# define uc_vector_sort(v_, cmp_, ud_) \
+ qsort_r((v_)->entries, (v_)->count, sizeof((v_)->entries[0]), cmp_, ud_)
+
+#endif
+
#endif /* UCODE_UTIL_H */
diff --git a/tests/custom/03_stdlib/60_gc b/tests/custom/03_stdlib/60_gc
index 28c0d00..44e5d9e 100644
--- a/tests/custom/03_stdlib/60_gc
+++ b/tests/custom/03_stdlib/60_gc
@@ -45,11 +45,11 @@ Returns an object count if the given operation is `count`.
-- End --
-- Expect stdout --
-Count #1: 6
-Count #2: 7
-Count #3: 6
-Count #4: 7
-Count #5: 6
+Count #1: 5
+Count #2: 6
+Count #3: 5
+Count #4: 6
+Count #5: 5
-- End --
@@ -84,24 +84,24 @@ Testing enabling the automatic collector.
-- End --
-- Expect stdout --
-Count #1: 7
-Count #2: 14
-Count #3: 14
-Count #4: 14
-Count #5: 14
-Count #6: 14
-Count #7: 14
-Count #8: 14
-Count #9: 14
-Count #10: 14
-Count #11: 14
-Count #12: 24
-Count #13: 34
-Count #14: 44
-Count #15: 54
-Count #16: 64
-Count #17: 74
-Count #18: 84
-Count #19: 94
-Count #20: 104
+Count #1: 6
+Count #2: 12
+Count #3: 12
+Count #4: 12
+Count #5: 12
+Count #6: 12
+Count #7: 12
+Count #8: 12
+Count #9: 12
+Count #10: 12
+Count #11: 12
+Count #12: 22
+Count #13: 32
+Count #14: 42
+Count #15: 52
+Count #16: 62
+Count #17: 72
+Count #18: 82
+Count #19: 92
+Count #20: 102
-- End --
diff --git a/types.c b/types.c
index 26f588e..5dbf6a8 100644
--- a/types.c
+++ b/types.c
@@ -29,11 +29,6 @@
#include "ucode/vm.h"
#include "ucode/program.h"
-uc_list_t uc_object_iterators = {
- .prev = &uc_object_iterators,
- .next = &uc_object_iterators
-};
-
static char *uc_default_search_path[] = { LIB_SEARCH_PATH };
uc_parse_config_t uc_default_parse_config = {
@@ -785,6 +780,28 @@ ucv_array_unshift(uc_value_t *uv, uc_value_t *item)
return item;
}
+typedef struct {
+ int (*cmp)(uc_value_t *, uc_value_t *, void *);
+ void *ud;
+} array_sort_ctx_t;
+
+static uc_vector_sort_cb(ucv_array_sort_r_cb, uc_value_t *, array_sort_ctx_t *, {
+ return ctx->cmp(v1, v2, ctx->ud);
+});
+
+void
+ucv_array_sort_r(uc_value_t *uv,
+ int (*cmp)(uc_value_t *, uc_value_t *, void *), void *ud)
+{
+ array_sort_ctx_t ctx = { .cmp = cmp, .ud = ud };
+ uc_array_t *array = (uc_array_t *)uv;
+
+ if (ucv_type(uv) != UC_ARRAY || array->count <= 1)
+ return;
+
+ uc_vector_sort(array, ucv_array_sort_r_cb, &ctx);
+}
+
void
ucv_array_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
{
@@ -876,7 +893,7 @@ ucv_array_length(uc_value_t *uv)
static void
ucv_free_object_entry(struct lh_entry *entry)
{
- uc_list_foreach(item, &uc_object_iterators) {
+ uc_list_foreach(item, &uc_thread_context_get()->object_iterators) {
uc_object_iterator_t *iter = (uc_object_iterator_t *)item;
if (iter->u.pos == entry)
@@ -933,7 +950,7 @@ ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val)
/* insert will rehash table, backup affected iterator states */
if (rehash) {
- uc_list_foreach(item, &uc_object_iterators) {
+ uc_list_foreach(item, &uc_thread_context_get()->object_iterators) {
uc_object_iterator_t *iter = (uc_object_iterator_t *)item;
if (iter->table != object->table)
@@ -957,7 +974,7 @@ ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val)
/* restore affected iterator state pointer after rehash */
if (rehash) {
- uc_list_foreach(item, &uc_object_iterators) {
+ uc_list_foreach(item, &uc_thread_context_get()->object_iterators) {
uc_object_iterator_t *iter = (uc_object_iterator_t *)item;
if (iter->table != object->table)
@@ -985,8 +1002,29 @@ ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val)
return true;
}
-void
-ucv_object_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
+
+typedef struct {
+ int (*cmp)(const void *, const void *);
+ int (*cmpr)(const char *, uc_value_t *, const char *, uc_value_t *, void *);
+ void *ud;
+} object_sort_ctx_t;
+
+static uc_vector_sort_cb(ucv_object_sort_cb, const void *, object_sort_ctx_t *, {
+ (void)v1;
+ (void)v2;
+
+ return ctx->cmp(k1, k2);
+});
+
+static uc_vector_sort_cb(ucv_object_sort_r_cb, const struct lh_entry *, object_sort_ctx_t *, {
+ return ctx->cmpr(
+ v1 ? lh_entry_k(v1) : NULL, v1 ? lh_entry_v(v1) : NULL,
+ v2 ? lh_entry_k(v2) : NULL, v2 ? lh_entry_v(v2) : NULL,
+ ctx->ud);
+});
+
+static void
+ucv_object_sort_common(uc_value_t *uv, object_sort_ctx_t *ctx)
{
uc_object_t *object = (uc_object_t *)uv;
struct lh_table *t;
@@ -1007,7 +1045,8 @@ ucv_object_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
if (!keys.entries)
return;
- qsort(keys.entries, keys.count, sizeof(keys.entries[0]), cmp);
+ uc_vector_sort(&keys,
+ ctx->cmpr ? ucv_object_sort_r_cb : ucv_object_sort_cb, ctx);
for (i = 0; i < keys.count; i++) {
e = keys.entries[i];
@@ -1027,6 +1066,25 @@ ucv_object_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
uc_vector_clear(&keys);
}
+void
+ucv_object_sort_r(uc_value_t *uv,
+ int (*cmp)(const char *, uc_value_t *,
+ const char *, uc_value_t *, void *),
+ void *ud)
+{
+ object_sort_ctx_t ctx = { .cmp = NULL, .cmpr = cmp, .ud = ud };
+
+ ucv_object_sort_common(uv, &ctx);
+}
+
+void
+ucv_object_sort(uc_value_t *uv, int (*cmp)(const void *, const void *))
+{
+ object_sort_ctx_t ctx = { .cmp = cmp, .cmpr = NULL, .ud = NULL };
+
+ ucv_object_sort_common(uv, &ctx);
+}
+
bool
ucv_object_delete(uc_value_t *uv, const char *key)
{
@@ -2418,3 +2476,18 @@ uc_search_path_init(uc_search_path_t *search_path)
for (i = 0; i < ARRAY_SIZE(uc_default_search_path); i++)
uc_vector_push(search_path, xstrdup(uc_default_search_path[i]));
}
+
+
+static __thread uc_thread_context_t *tls_ctx;
+
+uc_thread_context_t *
+uc_thread_context_get(void)
+{
+ if (tls_ctx == NULL) {
+ tls_ctx = xalloc(sizeof(*tls_ctx));
+ tls_ctx->object_iterators.prev = &tls_ctx->object_iterators;
+ tls_ctx->object_iterators.next = &tls_ctx->object_iterators;
+ }
+
+ return tls_ctx;
+}
diff --git a/vm.c b/vm.c
index 9488288..1c40307 100644
--- a/vm.c
+++ b/vm.c
@@ -145,37 +145,64 @@ uc_vm_alloc_global_scope(uc_vm_t *vm)
static void
uc_vm_output_exception(uc_vm_t *vm, uc_exception_t *ex);
-static uc_vm_t *signal_handler_vm;
-
static void
uc_vm_signal_handler(int sig)
{
- assert(signal_handler_vm);
+ uc_vm_t *vm = uc_thread_context_get()->signal_handler_vm;
+
+ assert(vm);
- uc_vm_signal_raise(signal_handler_vm, sig);
+ uc_vm_signal_raise(vm, sig);
}
static void
uc_vm_signal_handlers_setup(uc_vm_t *vm)
{
+ uc_thread_context_t *tctx;
+
memset(&vm->signal, 0, sizeof(vm->signal));
vm->signal.sigpipe[0] = -1;
vm->signal.sigpipe[1] = -1;
- if (!vm->config->setup_signal_handlers)
+ if (vm->config->setup_signal_handlers)
return;
- if (pipe2(vm->signal.sigpipe, O_CLOEXEC | O_NONBLOCK) != 0)
+ tctx = uc_thread_context_get();
+
+ if (tctx->signal_handler_vm)
return;
- signal_handler_vm = vm;
+ if (pipe2(vm->signal.sigpipe, O_CLOEXEC | O_NONBLOCK) != 0)
+ return;
vm->signal.handler = ucv_array_new_length(vm, UC_SYSTEM_SIGNAL_COUNT);
vm->signal.sa.sa_handler = uc_vm_signal_handler;
vm->signal.sa.sa_flags = SA_RESTART | SA_ONSTACK;
sigemptyset(&vm->signal.sa.sa_mask);
+
+ tctx->signal_handler_vm = vm;
+}
+
+static void
+uc_vm_signal_handlers_reset(uc_vm_t *vm)
+{
+ uc_thread_context_t *tctx = uc_thread_context_get();
+ struct sigaction sa = { 0 };
+ size_t signo;
+
+ if (vm != tctx->signal_handler_vm)
+ return;
+
+ sa.sa_handler = SIG_DFL;
+ sigemptyset(&sa.sa_mask);
+
+ for (signo = 0; signo < ucv_array_length(vm->signal.handler); signo++)
+ if (ucv_is_callable(ucv_array_get(vm->signal.handler, signo)))
+ sigaction(signo, &sa, NULL);
+
+ tctx->signal_handler_vm = NULL;
}
void uc_vm_init(uc_vm_t *vm, uc_parse_config_t *config)
@@ -210,6 +237,8 @@ void uc_vm_free(uc_vm_t *vm)
uc_upvalref_t *ref;
size_t i;
+ uc_vm_signal_handlers_reset(vm);
+
ucv_put(vm->exception.stacktrace);
free(vm->exception.message);
@@ -778,11 +807,10 @@ uc_vm_exception_tostring(uc_vm_t *vm, size_t nargs)
return message ? ucv_get(message) : ucv_string_new("Exception");
}
-static uc_value_t *exception_prototype = NULL;
-
static uc_value_t *
uc_vm_exception_new(uc_vm_t *vm, uc_exception_type_t type, const char *message, uc_value_t *stacktrace)
{
+ uc_value_t *exception_prototype = uc_vm_registry_get(vm, "vm.exception.proto");
uc_value_t *exo;
if (exception_prototype == NULL) {
@@ -790,6 +818,8 @@ uc_vm_exception_new(uc_vm_t *vm, uc_exception_type_t type, const char *message,
ucv_object_add(exception_prototype, "tostring",
ucv_cfunction_new("tostring", uc_vm_exception_tostring));
+
+ uc_vm_registry_set(vm, "vm.exception.proto", exception_prototype);
}
exo = ucv_object_new(vm);
@@ -2222,7 +2252,7 @@ uc_vm_object_iterator_next(uc_vm_t *vm, uc_vm_insn_t insn,
iter->table = obj->table;
iter->u.pos = obj->table->head;
- uc_list_insert(&uc_object_iterators, &iter->list);
+ uc_list_insert(&uc_thread_context_get()->object_iterators, &iter->list);
}
else if (ucv_type(k) == UC_RESOURCE &&
res->type == &uc_vm_object_iterator_type && res->data != NULL) {