2021-02-07 15:40:00 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2021 Thakee Nathees
|
|
|
|
* Licensed under: MIT License
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef VM_H
|
|
|
|
#define VM_H
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "compiler.h"
|
|
|
|
#include "var.h"
|
|
|
|
|
|
|
|
// The maximum number of temporary object reference to protect them from being
|
|
|
|
// garbage collected.
|
2021-05-05 13:55:34 +08:00
|
|
|
#define MAX_TEMP_REFERENCE 16
|
2021-02-07 15:40:00 +08:00
|
|
|
|
2021-05-15 17:29:44 +08:00
|
|
|
// The capacity of the builtin function array in the VM.
|
|
|
|
#define BUILTIN_FN_CAPACITY 50
|
|
|
|
|
2021-02-09 16:21:10 +08:00
|
|
|
typedef enum {
|
2021-02-12 01:35:43 +08:00
|
|
|
#define OPCODE(name, _, __) OP_##name,
|
|
|
|
#include "opcodes.h"
|
|
|
|
#undef OPCODE
|
2021-02-09 16:21:10 +08:00
|
|
|
} Opcode;
|
|
|
|
|
2021-05-15 17:29:44 +08:00
|
|
|
// Builtin functions are stored in an array in the VM (unlike script functions
|
|
|
|
// they're member of function buffer of the script) and this struct is a single
|
|
|
|
// entry of the array.
|
|
|
|
typedef struct {
|
|
|
|
const char* name; //< Name of the function.
|
|
|
|
int length; //< Length of the name.
|
|
|
|
Function* fn; //< Native function pointer.
|
|
|
|
} BuiltinFn;
|
|
|
|
|
2021-05-09 18:28:00 +08:00
|
|
|
struct PKVM {
|
2021-02-07 15:40:00 +08:00
|
|
|
|
2021-02-12 01:35:43 +08:00
|
|
|
// The first object in the link list of all heap allocated objects.
|
|
|
|
Object* first;
|
|
|
|
|
2021-04-25 23:19:39 +08:00
|
|
|
// The number of bytes allocated by the vm and not (yet) garbage collected.
|
2021-02-12 01:35:43 +08:00
|
|
|
size_t bytes_allocated;
|
|
|
|
|
2021-04-25 23:19:39 +08:00
|
|
|
// The number of bytes that'll trigger the next GC.
|
|
|
|
size_t next_gc;
|
|
|
|
|
|
|
|
// In the tri coloring scheme gray is the working list. We recursively pop
|
|
|
|
// from the list color it balck and add it's referenced objects to gray_list.
|
2021-05-01 18:13:39 +08:00
|
|
|
Object** gray_list;
|
|
|
|
int gray_list_count;
|
|
|
|
int gray_list_capacity;
|
2021-04-25 23:19:39 +08:00
|
|
|
|
2021-02-12 01:35:43 +08:00
|
|
|
// A stack of temporary object references to ensure that the object
|
|
|
|
// doesn't garbage collected.
|
|
|
|
Object* temp_reference[MAX_TEMP_REFERENCE];
|
|
|
|
int temp_reference_count;
|
2021-02-07 15:40:00 +08:00
|
|
|
|
2021-02-12 01:35:43 +08:00
|
|
|
// VM's configurations.
|
2021-05-09 18:28:00 +08:00
|
|
|
pkConfiguration config;
|
2021-02-07 15:40:00 +08:00
|
|
|
|
2021-04-26 17:34:30 +08:00
|
|
|
// Current compiler reference to mark it's heap allocated objects. Note that
|
|
|
|
// The compiler isn't heap allocated.
|
2021-02-12 01:35:43 +08:00
|
|
|
Compiler* compiler;
|
2021-02-07 15:40:00 +08:00
|
|
|
|
2021-05-06 22:19:30 +08:00
|
|
|
// A cache of the compiled scripts with their path as key and the Scrpit
|
|
|
|
// object as the value.
|
|
|
|
Map* scripts;
|
2021-02-16 02:51:00 +08:00
|
|
|
|
2021-05-15 17:29:44 +08:00
|
|
|
// A map of core libraries with their name as the key and the Script object
|
|
|
|
// as the value.
|
|
|
|
Map* core_libs;
|
|
|
|
|
|
|
|
// Array of all builtin functions.
|
|
|
|
BuiltinFn builtins[BUILTIN_FN_CAPACITY];
|
|
|
|
int builtins_count;
|
|
|
|
|
2021-02-12 01:35:43 +08:00
|
|
|
// Execution variables ////////////////////////////////////////////////////
|
2021-02-08 02:30:29 +08:00
|
|
|
|
2021-04-26 17:34:30 +08:00
|
|
|
// The root script of the runtime and it's one of the VM's reference root.
|
|
|
|
// VM is responsible to manage the memory (TODO: implement handlers).
|
|
|
|
Script* script;
|
2021-02-11 01:23:48 +08:00
|
|
|
|
2021-02-25 17:03:06 +08:00
|
|
|
// Current fiber.
|
|
|
|
Fiber* fiber;
|
2021-02-07 15:40:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
// A realloc wrapper which handles memory allocations of the VM.
|
|
|
|
// - To allocate new memory pass NULL to parameter [memory] and 0 to
|
|
|
|
// parameter [old_size] on failure it'll return NULL.
|
|
|
|
// - To free an already allocated memory pass 0 to parameter [old_size]
|
|
|
|
// and it'll returns NULL.
|
|
|
|
// - The [old_size] parameter is required to keep track of the VM's
|
|
|
|
// allocations to trigger the garbage collections.
|
2021-02-11 01:23:48 +08:00
|
|
|
// If deallocating (free) using vmRealloc the old_size should be 0 as it's not
|
|
|
|
// going to track deallocated bytes, instead use garbage collector to do it.
|
2021-05-09 18:28:00 +08:00
|
|
|
void* vmRealloc(PKVM* self, void* memory, size_t old_size, size_t new_size);
|
2021-02-07 15:40:00 +08:00
|
|
|
|
|
|
|
// Push the object to temporary references stack.
|
2021-05-09 18:28:00 +08:00
|
|
|
void vmPushTempRef(PKVM* self, Object* obj);
|
2021-02-07 15:40:00 +08:00
|
|
|
|
|
|
|
// Pop the top most object from temporary reference stack.
|
2021-05-09 18:28:00 +08:00
|
|
|
void vmPopTempRef(PKVM* self);
|
2021-02-07 15:40:00 +08:00
|
|
|
|
2021-04-25 23:19:39 +08:00
|
|
|
// Trigger garbage collection manually.
|
2021-05-09 18:28:00 +08:00
|
|
|
void vmCollectGarbage(PKVM* self);
|
2021-04-25 23:19:39 +08:00
|
|
|
|
2021-02-11 01:23:48 +08:00
|
|
|
// Runs the script and return result.
|
2021-05-09 18:28:00 +08:00
|
|
|
PKInterpretResult vmRunScript(PKVM* vm, Script* script);
|
2021-02-12 01:35:43 +08:00
|
|
|
|
|
|
|
#endif // VM_H
|