use incremental gc const initialization

This commit is contained in:
ValKmjolnir 2023-09-20 00:46:23 +08:00
parent 85bc699905
commit 6c8b4c6a87
4 changed files with 22 additions and 14 deletions

View File

@ -1181,13 +1181,15 @@ const error& codegen::compile(parse& parse, linker& import) {
// check global variables size
if (global.size()>=STACK_DEPTH/2) {
err.err("code",
"too many global variables: " + std::to_string(global.size()));
"too many global variables: " + std::to_string(global.size())
);
}
// check generated code size
if (code.size()>0xffffff) {
err.err("code",
"bytecode size overflow: " + std::to_string(code.size()));
"bytecode size overflow: " + std::to_string(code.size())
);
}
return err;
}

View File

@ -536,7 +536,9 @@ void gc::extend(u8 type) {
}
void gc::init(
const std::vector<std::string>& s, const std::vector<std::string>& argv) {
const std::vector<std::string>& constant_strings,
const std::vector<std::string>& argv
) {
// initialize counters
worktime = 0;
for(u8 i = 0; i<gc_type_size; ++i) {
@ -547,16 +549,24 @@ void gc::init(
cort = nullptr;
// init constant strings
strs.resize(s.size());
strs.resize(constant_strings.size());
for(u32 i = 0; i<strs.size(); ++i) {
strs[i]=var::gcobj(new nas_val(vm_str));
// incremental initialization, avoid memory leak in repl mode
if (strs[i].type==vm_str && strs[i].str()==constant_strings[i]) {
continue;
}
strs[i] = var::gcobj(new nas_val(vm_str));
strs[i].val.gcobj->unmut = 1;
strs[i].str() = s[i];
strs[i].str() = constant_strings[i];
}
// record arguments
env_argv.resize(argv.size());
for(usize i = 0; i<argv.size(); ++i) {
// incremental initialization, avoid memory leak in repl mode
if (env_argv[i].type==vm_str && env_argv[i].str()==argv[i]) {
continue;
}
env_argv[i] = var::gcobj(new nas_val(vm_str));
env_argv[i].val.gcobj->unmut = 1;
env_argv[i].str() = argv[i];

View File

@ -66,7 +66,7 @@ struct nas_val; // nas_val includes gc-managed types
struct var {
public:
u8 type;
u8 type = vm_none;
union {
u32 ret;
i64 cnt;

View File

@ -10,6 +10,9 @@ namespace nasal {
namespace repl {
void repl::add_command_history(const std::string& history) {
if (command_history.size() && command_history.back()==history) {
return;
}
command_history.push_back(history);
if (command_history.size()>1000) {
command_history.pop_front();
@ -74,16 +77,12 @@ void repl::help() {
}
bool repl::run() {
using clk = std::chrono::high_resolution_clock;
const auto den = clk::duration::period::den;
auto nasal_lexer = std::unique_ptr<lexer>(new lexer);
auto nasal_parser = std::unique_ptr<parse>(new parse);
auto nasal_linker = std::unique_ptr<linker>(new linker);
auto nasal_opt = std::unique_ptr<optimizer>(new optimizer);
auto nasal_codegen = std::unique_ptr<codegen>(new codegen);
auto start = clk::now();
update_temp_file();
if (nasal_lexer->scan("<nasal-repl>").geterr()) {
return false;
@ -102,9 +101,6 @@ bool repl::run() {
return false;
}
auto end = clk::now();
std::clog << "[compile time: " << (end-start).count()*1000.0/den << " ms]\n";
// TODO: gc init stage in this run may cause memory leak,
// because constant strings will be generated again.
// but we could not delete old strings, they maybe still on stack.