impotent/vm.h
2025-09-06 13:59:14 +03:00

149 lines
2.6 KiB
C

#pragma once
#include<stdbool.h>
#include<stdint.h>
#include<stddef.h>
#include<ctype.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<threads.h>
#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();
}
}