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