table.insert and basics threads api
This commit is contained in:
parent
8cd83188ad
commit
5d6734be4a
79
main.c
79
main.c
@ -5,38 +5,102 @@
|
|||||||
#include"lexer.h"
|
#include"lexer.h"
|
||||||
#include"str.h"
|
#include"str.h"
|
||||||
#include"dump.h"
|
#include"dump.h"
|
||||||
|
#include<stdatomic.h>
|
||||||
|
#include<math.h>
|
||||||
|
|
||||||
static size_t native_print(LVM *lvm, void *ud, size_t argn, LRegSet *regset) {
|
static size_t native_print(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset) {
|
||||||
if(lvalue_tag(regset->regs[0]) == LTAG_STRING) {
|
if(lvalue_tag(regset->regs[0]) == LTAG_STRING) {
|
||||||
LString *lstr = (void*) (regset->regs[0].u & ~LTAG_MASK);
|
LString *lstr = (void*) (regset->regs[0].u & ~LTAG_MASK);
|
||||||
printf("%.*s\n", (int) lstr->length, lstr->data);
|
printf("%.*s\n", (int) lstr->length, lstr->data);
|
||||||
} else if(lvalue_tag(regset->regs[0]) == LTAG_I32) {
|
} else if(lvalue_tag(regset->regs[0]) == LTAG_I32) {
|
||||||
printf("%i\n", lvalue_to_int32(regset->regs[0]));
|
printf("%i\n", lvalue_to_int32(regset->regs[0]));
|
||||||
|
} else if(lvalue_tag(regset->regs[0]) == LTAG_TABLE) {
|
||||||
|
printf("table: 0x%lx\n", (uintptr_t) (regset->regs[0].u & ~LTAG_MASK));
|
||||||
|
} else if(lvalue_tag(regset->regs[0]) == LTAG_FUNCTION) {
|
||||||
|
printf("function: 0x%lx\n", (uintptr_t) (regset->regs[0].u & ~LTAG_MASK));
|
||||||
} else if(regset->regs[0].u == LTAG_NIL) {
|
} else if(regset->regs[0].u == LTAG_NIL) {
|
||||||
printf("nil\n");
|
printf("nil\n");
|
||||||
|
} else if(regset->regs[0].u == LTAG_TRUE) {
|
||||||
|
printf("true\n");
|
||||||
|
} else if(regset->regs[0].u == LTAG_FALSE) {
|
||||||
|
printf("false\n");
|
||||||
|
} else if(!isnan(regset->regs[0].f)) {
|
||||||
|
printf("%f\n", regset->regs[0].f);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t table_insert(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset) {
|
||||||
|
LTable *tbl = (LTable*) (regset->regs[0].u & ~LTAG_MASK);
|
||||||
|
ltable_insert(tbl, regset->regs[1], 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is intended for small-medium runtimes, since the caller thread's heap is not touchable during this call.
|
||||||
|
static size_t threads_parallel(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset) {
|
||||||
|
size_t no = lvalue_to_int32(regset->regs[0]);
|
||||||
|
LFunc *func = (LFunc*) (regset->regs[1].u & ~LTAG_MASK);
|
||||||
|
|
||||||
|
atomic_fetch_sub(&lvm->active_thread_count, 1);
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for(size_t i = 0; i < no; i++) {
|
||||||
|
LRegSet regset = {};
|
||||||
|
lvm_reset_regs(®set);
|
||||||
|
lvm_run(lvm, func, 0, ®set);
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_fetch_add(&lvm->active_thread_count, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static char* read_full_file(const char *fn) {
|
static char* read_full_file(const char *fn) {
|
||||||
FILE *f = fopen(fn, "rb");
|
FILE *f = fn ? fopen(fn, "rb") : stdin;
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
size_t filesize = ftell(f);
|
size_t filesize = ftell(f);
|
||||||
fseek(f, 0, SEEK_SET);
|
fseek(f, 0, SEEK_SET);
|
||||||
char *buf = malloc(filesize + 1);
|
char *buf = malloc(filesize + 1);
|
||||||
fread(buf, 1, filesize, f);
|
fread(buf, 1, filesize, f);
|
||||||
buf[filesize] = '\0';
|
buf[filesize] = '\0';
|
||||||
fclose(f);
|
if(fn) fclose(f);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
LTable *env = ltable_new(128);
|
LTable *env = ltable_new(128);
|
||||||
|
|
||||||
LString *key = lstring_newz("print");
|
ltable_set(env,
|
||||||
LFunc *func = lvm_func_from_native(native_print, NULL);
|
lvalue_from_string(lstring_newz("print")),
|
||||||
|
lvalue_from_func(lvm_func_from_native(native_print, NULL)));
|
||||||
|
|
||||||
ltable_set(env, lvalue_from_string(key), lvalue_from_func(func));
|
LTable *table = ltable_new(16);
|
||||||
|
{
|
||||||
|
ltable_set(table,
|
||||||
|
lvalue_from_string(lstring_newz("insert")),
|
||||||
|
lvalue_from_func(lvm_func_from_native(table_insert, NULL)));
|
||||||
|
}
|
||||||
|
ltable_set(env,
|
||||||
|
lvalue_from_string(lstring_newz("table")),
|
||||||
|
lvalue_from_table(table));
|
||||||
|
|
||||||
|
LTable *threads = ltable_new(16);
|
||||||
|
{
|
||||||
|
ltable_set(threads,
|
||||||
|
lvalue_from_string(lstring_newz("parallel")),
|
||||||
|
lvalue_from_func(lvm_func_from_native(threads_parallel, NULL)));
|
||||||
|
}
|
||||||
|
ltable_set(env,
|
||||||
|
lvalue_from_string(lstring_newz("threads")),
|
||||||
|
lvalue_from_table(threads));
|
||||||
|
|
||||||
|
LTable *math = ltable_new(16);
|
||||||
|
{
|
||||||
|
ltable_set(math, lvalue_from_string(lstring_newz("pi")), (LValue) {.f = 3.141592653589793238463});
|
||||||
|
}
|
||||||
|
ltable_set(env,
|
||||||
|
lvalue_from_string(lstring_newz("math")),
|
||||||
|
lvalue_from_table(math));
|
||||||
|
|
||||||
//const char *bufs = "for i = 1, 10000 do print(i) if i % 3 == 0 then print(\"Fizz\") end if i % 5 == 0 then print(\"Buzz\") end end";
|
//const char *bufs = "for i = 1, 10000 do print(i) if i % 3 == 0 then print(\"Fizz\") end if i % 5 == 0 then print(\"Buzz\") end end";
|
||||||
//const char *bufs = "local t = {a = 9} print(t.a)";
|
//const char *bufs = "local t = {a = 9} print(t.a)";
|
||||||
@ -59,12 +123,9 @@ int main(int argc, char **argv) {
|
|||||||
LVM lvm = {};
|
LVM lvm = {};
|
||||||
lvm_init(&lvm);
|
lvm_init(&lvm);
|
||||||
|
|
||||||
//#pragma omp parallel for
|
|
||||||
for(int i = 0; i < 1; i++) {
|
|
||||||
LRegSet regset = {.parent = NULL};
|
LRegSet regset = {.parent = NULL};
|
||||||
lvm_reset_regs(®set);
|
lvm_reset_regs(®set);
|
||||||
lvm_run(&lvm, &unit->funcs[0], 0, ®set);
|
lvm_run(&lvm, &unit->funcs[0], 0, ®set);
|
||||||
}
|
|
||||||
|
|
||||||
lvm_destroy(&lvm);
|
lvm_destroy(&lvm);
|
||||||
}
|
}
|
||||||
|
21
vm.c
21
vm.c
@ -7,9 +7,9 @@
|
|||||||
#include<math.h>
|
#include<math.h>
|
||||||
#include<malloc.h>
|
#include<malloc.h>
|
||||||
|
|
||||||
static size_t lvm_run_internal(LVM *L, LFunc *func, size_t arg_count, set_LValueU *heap, LRegSet *regset) {
|
size_t lvm_call(LVM *L, LFunc *func, size_t arg_count, set_LValueU *heap, LRegSet *regset) {
|
||||||
if(func->is_native) {
|
if(func->is_native) {
|
||||||
return func->native_func(L, func->ud, arg_count, regset);
|
return func->native_func(L, func->ud, arg_count, heap, regset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const void *dispatch_table[] = {
|
static const void *dispatch_table[] = {
|
||||||
@ -38,6 +38,7 @@ static size_t lvm_run_internal(LVM *L, LFunc *func, size_t arg_count, set_LValue
|
|||||||
[L_COND_NEQ] = &&do_cond_neq,
|
[L_COND_NEQ] = &&do_cond_neq,
|
||||||
[L_SETFIELD] = &&do_setfield,
|
[L_SETFIELD] = &&do_setfield,
|
||||||
[L_GETFIELD] = &&do_getfield,
|
[L_GETFIELD] = &&do_getfield,
|
||||||
|
[L_LEN] = &&do_len,
|
||||||
};
|
};
|
||||||
|
|
||||||
LUnit *unit = func->unit;
|
LUnit *unit = func->unit;
|
||||||
@ -248,7 +249,7 @@ do_call:;
|
|||||||
for(int i = 0; i < arg_count; i++) {
|
for(int i = 0; i < arg_count; i++) {
|
||||||
regset2.regs[i] = regset->regs[args[i]];
|
regset2.regs[i] = regset->regs[args[i]];
|
||||||
}
|
}
|
||||||
size_t returned_count = lvm_run_internal(L, (LFunc*) (regset->regs[inst->a].u & ~LTAG_MASK), arg_count, heap, ®set2);
|
size_t returned_count = lvm_call(L, (LFunc*) (regset->regs[inst->a].u & ~LTAG_MASK), arg_count, heap, ®set2);
|
||||||
|
|
||||||
if(returned_count) {
|
if(returned_count) {
|
||||||
// TODO: more than 1 return
|
// TODO: more than 1 return
|
||||||
@ -286,7 +287,7 @@ do_setfield:;
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lvalue_tag(regset->regs[inst->b]) == LTAG_NIL) {
|
if(regset->regs[inst->b].u == LTAG_NIL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,6 +309,14 @@ do_getfield:;
|
|||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
|
||||||
|
do_len:
|
||||||
|
if(lvalue_tag(regset->regs[inst->b]) == LTAG_STRING) {
|
||||||
|
regset->regs[inst->a] = lvalue_from_int32(((LString*) (regset->regs[inst->b].u & ~LTAG_MASK))->length);
|
||||||
|
} else if(lvalue_tag(regset->regs[inst->b]) == LTAG_TABLE) {
|
||||||
|
regset->regs[inst->a] = lvalue_from_int32(ltable_len((LTable*) (regset->regs[inst->b].u & ~LTAG_MASK)));
|
||||||
|
} else goto err;
|
||||||
|
DISPATCH();
|
||||||
|
|
||||||
err:;
|
err:;
|
||||||
puts("Error");
|
puts("Error");
|
||||||
do_ret:;
|
do_ret:;
|
||||||
@ -320,7 +329,7 @@ size_t lvm_run(LVM *L, LFunc *func, size_t arg_count, LRegSet *regset) {
|
|||||||
|
|
||||||
atomic_fetch_add(&L->active_thread_count, 1);
|
atomic_fetch_add(&L->active_thread_count, 1);
|
||||||
|
|
||||||
size_t ret = lvm_run_internal(L, func, arg_count, &heap, regset);
|
size_t ret = lvm_call(L, func, arg_count, &heap, regset);
|
||||||
|
|
||||||
mtx_lock(&L->dead_heap_mut);
|
mtx_lock(&L->dead_heap_mut);
|
||||||
for(c_each(i, set_LValueU, heap)) {
|
for(c_each(i, set_LValueU, heap)) {
|
||||||
@ -400,7 +409,7 @@ static void gc_mark(LValue v) {
|
|||||||
LTable *tbl = gco;
|
LTable *tbl = gco;
|
||||||
tbl->ref = true;
|
tbl->ref = true;
|
||||||
|
|
||||||
for(size_t i = 0; tbl->buckets->capacity; i++) {
|
for(size_t i = 0; i < tbl->buckets->capacity; i++) {
|
||||||
LTableEntry e = tbl->buckets->data[i];
|
LTableEntry e = tbl->buckets->data[i];
|
||||||
gc_mark(e.key);
|
gc_mark(e.key);
|
||||||
gc_mark(e.val);
|
gc_mark(e.val);
|
||||||
|
14
vm.h
14
vm.h
@ -42,6 +42,7 @@ typedef enum {
|
|||||||
L_SETFIELD,
|
L_SETFIELD,
|
||||||
L_GETFIELD,
|
L_GETFIELD,
|
||||||
L_SETINT32,
|
L_SETINT32,
|
||||||
|
L_LEN,
|
||||||
} LOp;
|
} LOp;
|
||||||
|
|
||||||
typedef union __attribute__((packed)) {
|
typedef union __attribute__((packed)) {
|
||||||
@ -74,7 +75,12 @@ typedef struct LRegSet {
|
|||||||
LValue regs[256];
|
LValue regs[256];
|
||||||
} LRegSet;
|
} LRegSet;
|
||||||
|
|
||||||
typedef size_t(*LFuncCallback)(struct LVM*, void *ud, size_t argn, LRegSet *regset);
|
#define i_header
|
||||||
|
#define T set_LValueU, uint64_t
|
||||||
|
#include"stc/hashset.h"
|
||||||
|
#undef i_header
|
||||||
|
|
||||||
|
typedef size_t(*LFuncCallback)(struct LVM*, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset);
|
||||||
typedef struct LFunc {
|
typedef struct LFunc {
|
||||||
struct LUnit *unit;
|
struct LUnit *unit;
|
||||||
bool is_native;
|
bool is_native;
|
||||||
@ -99,11 +105,6 @@ typedef struct LUnit {
|
|||||||
LFunc *funcs;
|
LFunc *funcs;
|
||||||
} LUnit;
|
} LUnit;
|
||||||
|
|
||||||
#define i_header
|
|
||||||
#define T set_LValueU, uint64_t
|
|
||||||
#include"stc/hashset.h"
|
|
||||||
#undef i_header
|
|
||||||
|
|
||||||
typedef struct LThreadPrivates {
|
typedef struct LThreadPrivates {
|
||||||
set_LValueU *heap;
|
set_LValueU *heap;
|
||||||
LRegSet *regset;
|
LRegSet *regset;
|
||||||
@ -130,6 +131,7 @@ typedef struct LVM {
|
|||||||
set_LValueU dead_heap;
|
set_LValueU dead_heap;
|
||||||
} LVM;
|
} LVM;
|
||||||
|
|
||||||
|
size_t lvm_call(LVM *L, LFunc *func, size_t arg_count, set_LValueU *heap, LRegSet *regset);
|
||||||
size_t lvm_run(LVM *L, LFunc *func, size_t arg_count, LRegSet *regset);
|
size_t lvm_run(LVM *L, LFunc *func, size_t arg_count, LRegSet *regset);
|
||||||
|
|
||||||
LFunc *lvm_func_from_native(LFuncCallback, void *ud);
|
LFunc *lvm_func_from_native(LFuncCallback, void *ud);
|
||||||
|
Loading…
Reference in New Issue
Block a user