#pragma once #include #include #include #include #include #include #include #include #include"table.h" typedef enum { L_GETGLOBAL, L_SETGLOBAL, L_SETINT16, L_SETFLOAT, L_SETSTR, L_SETTABLE, L_SETBOOL, L_SETNIL, L_SETFUNC, L_ADD, L_SUB, L_MUL, L_DIV, L_IDIV, L_MOD, L_POW, L_BOR, L_BAND, L_BXOR, L_COND_EQ, L_COND_NEQ, L_JUMP, L_JNOTCOND, L_RET, L_MOVE, L_CALL, L_ADVANCETEST, L_SETFIELD, L_GETFIELD, L_SETINT32, L_LEN, } LOp; typedef union __attribute__((packed)) { struct { uint8_t opcode; union { uint8_t argb[3]; struct __attribute__((packed)) { uint8_t a; union { uint16_t bc; struct __attribute__((packed)) { uint8_t b; uint8_t c; }; }; }; }; }; struct { uint32_t hahalol; } extension; } LInst; struct LUnit; struct LVM; typedef struct LRegSet { struct LRegSet *parent; LValue regs[256]; } LRegSet; #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 { struct LUnit *unit; bool is_native; uint8_t upvalue_count; LValue *upvalues; union { struct { LFuncCallback native_func; void *ud; }; struct { LInst *lua_instrs; LTable *env; }; }; } LFunc; typedef struct LUnit { uint8_t *abyss; size_t func_count; LFunc *funcs; } LUnit; typedef struct LThreadPrivates { set_LValueU *heap; LRegSet *regset; } LThreadPrivates; #define L_THREADS_MAX 32 typedef struct LVM { size_t unit_count; LUnit **units; // The following is all used for GC _Atomic bool gcInProgress; _Atomic size_t nextGCThreshold; _Atomic intmax_t memUsage; _Atomic size_t active_thread_count; _Atomic size_t privates_index; _Atomic size_t privates_ready; LThreadPrivates privates[L_THREADS_MAX]; void(*safepoint_func)(struct LVM*, set_LValueU*, LRegSet*); // The dead heap stores the heap of threads that have exited // This is rare enough that it's done with a lock mtx_t dead_heap_mut; set_LValueU dead_heap; } 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); LFunc *lvm_func_from_native(LFuncCallback, void *ud); void lvm_init(LVM *L); void lvm_destroy(LVM *L); void lvm_gc_alert(LVM *L, LThreadPrivates*, intmax_t diff); static inline void lvm_reset_regs(LRegSet *regset) { for(int i = 0; i < 256; i++) { regset->regs[i] = lvalue_from_nil(); } }