155 lines
3.8 KiB
C++
155 lines
3.8 KiB
C++
#pragma once
|
|
|
|
// avoid MSVC warnings
|
|
#ifdef _MSC_VER
|
|
#pragma warning (disable:4244)
|
|
#pragma warning (disable:4267)
|
|
#pragma warning (disable:4102)
|
|
#endif
|
|
|
|
#include <iomanip>
|
|
#include <vector>
|
|
#include <chrono>
|
|
#include <thread>
|
|
#include <cstring>
|
|
#include <sstream>
|
|
#include <iostream>
|
|
|
|
#include "nasal.h"
|
|
#include "nasal_type.h"
|
|
|
|
namespace nasal {
|
|
|
|
struct free_list {
|
|
std::vector<nas_val*> elem[gc_type_size];
|
|
|
|
auto& operator[](i64 index) {
|
|
return elem[index];
|
|
}
|
|
};
|
|
|
|
struct gc {
|
|
/* main context temporary storage */
|
|
context main_context;
|
|
|
|
/* global storage */
|
|
var* main_context_global = nullptr;
|
|
usize main_context_global_size = 0;
|
|
|
|
/* runtime context */
|
|
context* running_context = nullptr;
|
|
nas_co* cort = nullptr; // running coroutine
|
|
|
|
/* temporary space used in native/module functions */
|
|
var temp = nil;
|
|
|
|
/* constants and memory pool */
|
|
std::vector<var> strs = {}; // reserved address for const vm_str
|
|
std::vector<var> env_argv = {}; // command line arguments
|
|
std::vector<nas_val*> memory; // gc memory
|
|
free_list unused; // gc free list
|
|
|
|
/* heap increase size */
|
|
u64 incr[gc_type_size] = {
|
|
256, // vm_str
|
|
512, // vm_vec
|
|
512, // vm_hash
|
|
256, // vm_func
|
|
256, // vm_upval
|
|
4, // vm_obj
|
|
4, // vm_co
|
|
1, // vm_map
|
|
};
|
|
// total memory usage, not very accurate
|
|
u64 total_memory_usage = 0;
|
|
|
|
/* values for analysis */
|
|
u64 size[gc_type_size];
|
|
u64 gcnt[gc_type_size];
|
|
u64 acnt[gc_type_size];
|
|
i64 worktime = 0;
|
|
i64 max_time = 0;
|
|
i64 max_mark_time = 0;
|
|
i64 max_sweep_time = 0;
|
|
bool flag_concurrent_mark_triggered = false;
|
|
|
|
void set(context* _ctx, var* _global, usize _size) {
|
|
running_context = _ctx;
|
|
main_context_global = _global;
|
|
main_context_global_size = _size;
|
|
}
|
|
|
|
private:
|
|
/* gc functions */
|
|
void do_mark_sweep();
|
|
void mark();
|
|
void concurrent_mark(std::vector<var>&, usize, usize);
|
|
void mark_context_root(std::vector<var>&);
|
|
void mark_var(std::vector<var>&, var&);
|
|
void mark_vec(std::vector<var>&, nas_vec&);
|
|
void mark_hash(std::vector<var>&, nas_hash&);
|
|
void mark_func(std::vector<var>&, nas_func&);
|
|
void mark_upval(std::vector<var>&, nas_upval&);
|
|
void mark_ghost(std::vector<var>&, nas_ghost&);
|
|
void mark_co(std::vector<var>&, nas_co&);
|
|
void mark_map(std::vector<var>&, nas_map&);
|
|
void sweep();
|
|
void concurrent_sweep(free_list&, usize, usize);
|
|
|
|
static const auto concurrent_threshold() {
|
|
return UINT16_MAX * 16;
|
|
}
|
|
|
|
public:
|
|
void extend(const vm_type);
|
|
void init(const std::vector<std::string>&, const std::vector<std::string>&);
|
|
void clear();
|
|
void info() const;
|
|
var alloc(const vm_type);
|
|
void context_change(nas_co*);
|
|
void context_reserve();
|
|
|
|
public:
|
|
double get_gc_time_ms() const {
|
|
const auto den = std::chrono::high_resolution_clock::duration::period::den;
|
|
return worktime * 1.0 / den * 1000.0;
|
|
}
|
|
|
|
double get_total_memory() const {
|
|
return total_memory_usage * 1.0 / 1024.0 / 1024.0;
|
|
}
|
|
|
|
public:
|
|
var newstr(char c) {
|
|
var s = alloc(vm_type::vm_str);
|
|
s.str() = c;
|
|
return s;
|
|
}
|
|
|
|
var newstr(const char* buff) {
|
|
var s = alloc(vm_type::vm_str);
|
|
s.str() = std::string(buff);
|
|
return s;
|
|
}
|
|
|
|
var newstr(const std::string& buff) {
|
|
var s = alloc(vm_type::vm_str);
|
|
s.str() = buff;
|
|
return s;
|
|
}
|
|
};
|
|
|
|
// module function type
|
|
typedef var (*module_func)(var*, usize, gc*);
|
|
|
|
// module function stores in tables with this type, end with {nullptr, nullptr}
|
|
struct module_func_info {
|
|
const char* name;
|
|
module_func fd;
|
|
};
|
|
|
|
// module function "get" type
|
|
typedef module_func_info* (*get_func_ptr)();
|
|
|
|
}
|