149 lines
2.6 KiB
C
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();
|
|
}
|
|
}
|