⚡ little optimization
This commit is contained in:
parent
9455a83df0
commit
eca978e2b3
3
nasal.h
3
nasal.h
|
@ -140,8 +140,7 @@ string rawstr(const string& str,const usize maxlen=0) {
|
||||||
string ret("");
|
string ret("");
|
||||||
for(auto i:str) {
|
for(auto i:str) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// windows ps or cmd doesn't output unicode normally
|
// windows doesn't output unicode normally, so we output the hex
|
||||||
// if 'chcp65001' is not enabled, we output the hex
|
|
||||||
if (i<=0) {
|
if (i<=0) {
|
||||||
ret+="\\x"+chrhex(i);
|
ret+="\\x"+chrhex(i);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "nasal.h"
|
||||||
|
|
||||||
enum ast_node:u32 {
|
enum ast_node:u32 {
|
||||||
ast_null=0, // null node
|
ast_null=0, // null node
|
||||||
ast_root, // mark the root node of ast
|
ast_root, // mark the root node of ast
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nasal_err.h"
|
#include "nasal_err.h"
|
||||||
|
#include "nasal_builtin.h"
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "nasal_import.h"
|
||||||
#include "nasal_err.h"
|
#include "nasal_err.h"
|
||||||
#include "nasal_vm.h"
|
#include "nasal_vm.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream> // MSVC need this to use std::getline
|
#include <sstream> // MSVC need this to use std::getline
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "nasal.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h> // use SetConsoleTextAttribute
|
#include <windows.h> // use SetConsoleTextAttribute
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "nasal.h"
|
||||||
#include "nasal_err.h"
|
#include "nasal_err.h"
|
||||||
|
|
||||||
enum vm_type:u8 {
|
enum vm_type:u8 {
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
#define F_OK 0
|
#define F_OK 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "nasal_ast.h"
|
||||||
|
#include "nasal_lexer.h"
|
||||||
|
#include "nasal_parse.h"
|
||||||
|
|
||||||
class linker{
|
class linker{
|
||||||
private:
|
private:
|
||||||
bool show_path;
|
bool show_path;
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "nasal.h"
|
||||||
|
#include "nasal_err.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define S_ISREG(m) (((m)&0xF000)==0x8000)
|
#define S_ISREG(m) (((m)&0xF000)==0x8000)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "nasal_ast.h"
|
||||||
|
|
||||||
void const_str(ast& root) {
|
void const_str(ast& root) {
|
||||||
auto& vec=root.child();
|
auto& vec=root.child();
|
||||||
root.set_str(vec[0].str()+vec[1].str());
|
root.set_str(vec[0].str()+vec[1].str());
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "nasal.h"
|
||||||
|
#include "nasal_lexer.h"
|
||||||
|
#include "nasal_ast.h"
|
||||||
|
#include "nasal_err.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
_,,,_
|
_,,,_
|
||||||
.' `'.
|
.' `'.
|
||||||
|
|
87
nasal_vm.h
87
nasal_vm.h
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
|
#include "nasal_import.h"
|
||||||
|
#include "nasal_gc.h"
|
||||||
#include "nasal_codegen.h"
|
#include "nasal_codegen.h"
|
||||||
|
|
||||||
class vm {
|
class vm {
|
||||||
|
@ -46,7 +49,6 @@ protected:
|
||||||
void ustate();
|
void ustate();
|
||||||
void detail();
|
void detail();
|
||||||
void die(const string&);
|
void die(const string&);
|
||||||
#define vm_error(info) {die(info);return;}
|
|
||||||
/* vm calculation functions*/
|
/* vm calculation functions*/
|
||||||
bool cond(var&);
|
bool cond(var&);
|
||||||
/* vm operands */
|
/* vm operands */
|
||||||
|
@ -441,7 +443,10 @@ inline void vm::o_unot() {
|
||||||
top[0]=num?zero:one;
|
top[0]=num?zero:one;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default:vm_error("incorrect value type");break;
|
default:{
|
||||||
|
die("incorrect value type");
|
||||||
|
return;
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,7 +592,8 @@ inline void vm::o_jf() {
|
||||||
|
|
||||||
inline void vm::o_cnt() {
|
inline void vm::o_cnt() {
|
||||||
if (top[0].type!=vm_vec) {
|
if (top[0].type!=vm_vec) {
|
||||||
vm_error("must use vector in forindex/foreach");
|
die("must use vector in forindex/foreach");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
(++top)[0]={vm_cnt,(i64)-1};
|
(++top)[0]={vm_cnt,(i64)-1};
|
||||||
}
|
}
|
||||||
|
@ -630,15 +636,18 @@ inline void vm::o_callv() {
|
||||||
if (vec.type==vm_vec) {
|
if (vec.type==vm_vec) {
|
||||||
top[0]=vec.vec().get_val(val.tonum());
|
top[0]=vec.vec().get_val(val.tonum());
|
||||||
if (top[0].type==vm_none) {
|
if (top[0].type==vm_none) {
|
||||||
vm_error("out of range:"+std::to_string(val.tonum()));
|
die("out of range:"+std::to_string(val.tonum()));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else if (vec.type==vm_hash) {
|
} else if (vec.type==vm_hash) {
|
||||||
if (val.type!=vm_str) {
|
if (val.type!=vm_str) {
|
||||||
vm_error("must use string as the key");
|
die("must use string as the key");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
top[0]=vec.hash().get_val(val.str());
|
top[0]=vec.hash().get_val(val.str());
|
||||||
if (top[0].type==vm_none) {
|
if (top[0].type==vm_none) {
|
||||||
vm_error("cannot find member \""+val.str()+"\"");
|
die("cannot find member \""+val.str()+"\"");
|
||||||
|
return;
|
||||||
} else if (top[0].type==vm_func) {
|
} else if (top[0].type==vm_func) {
|
||||||
top[0].func().local[0]=val; // 'me'
|
top[0].func().local[0]=val; // 'me'
|
||||||
}
|
}
|
||||||
|
@ -647,34 +656,40 @@ inline void vm::o_callv() {
|
||||||
i32 num=val.tonum();
|
i32 num=val.tonum();
|
||||||
i32 len=str.length();
|
i32 len=str.length();
|
||||||
if (num<-len || num>=len) {
|
if (num<-len || num>=len) {
|
||||||
vm_error("out of range:"+std::to_string(val.tonum()));
|
die("out of range:"+std::to_string(val.tonum()));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
top[0]={vm_num,f64((u8)str[num>=0? num:num+len])};
|
top[0]={vm_num,f64((u8)str[num>=0? num:num+len])};
|
||||||
} else {
|
} else {
|
||||||
vm_error("must call a vector/hash/string");
|
die("must call a vector/hash/string");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_callvi() {
|
inline void vm::o_callvi() {
|
||||||
var val=top[0];
|
var val=top[0];
|
||||||
if (val.type!=vm_vec) {
|
if (val.type!=vm_vec) {
|
||||||
vm_error("must use a vector");
|
die("must use a vector");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// cannot use operator[],because this may cause overflow
|
// cannot use operator[],because this may cause overflow
|
||||||
(++top)[0]=val.vec().get_val(imm[pc]);
|
(++top)[0]=val.vec().get_val(imm[pc]);
|
||||||
if (top[0].type==vm_none) {
|
if (top[0].type==vm_none) {
|
||||||
vm_error("out of range:"+std::to_string(imm[pc]));
|
die("out of range:"+std::to_string(imm[pc]));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_callh() {
|
inline void vm::o_callh() {
|
||||||
var val=top[0];
|
var val=top[0];
|
||||||
if (val.type!=vm_hash) {
|
if (val.type!=vm_hash) {
|
||||||
vm_error("must call a hash");
|
die("must call a hash");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
top[0]=val.hash().get_val(cstr[imm[pc]]);
|
top[0]=val.hash().get_val(cstr[imm[pc]]);
|
||||||
if (top[0].type==vm_none) {
|
if (top[0].type==vm_none) {
|
||||||
vm_error("member \""+cstr[imm[pc]]+"\" does not exist");
|
die("member \""+cstr[imm[pc]]+"\" does not exist");
|
||||||
|
return;
|
||||||
} else if (top[0].type==vm_func) {
|
} else if (top[0].type==vm_func) {
|
||||||
top[0].func().local[0]=val; // 'me'
|
top[0].func().local[0]=val; // 'me'
|
||||||
}
|
}
|
||||||
|
@ -684,7 +699,8 @@ inline void vm::o_callfv() {
|
||||||
u32 argc=imm[pc]; // arguments counter
|
u32 argc=imm[pc]; // arguments counter
|
||||||
var* local=top-argc+1; // arguments begin address
|
var* local=top-argc+1; // arguments begin address
|
||||||
if (local[-1].type!=vm_func) {
|
if (local[-1].type!=vm_func) {
|
||||||
vm_error("must call a function");
|
die("must call a function");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
auto& func=local[-1].func();
|
auto& func=local[-1].func();
|
||||||
var tmp=local[-1];
|
var tmp=local[-1];
|
||||||
|
@ -692,12 +708,14 @@ inline void vm::o_callfv() {
|
||||||
funcr=tmp;
|
funcr=tmp;
|
||||||
// top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
// top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
||||||
if (top-argc+func.lsize+3>=canary) {
|
if (top-argc+func.lsize+3>=canary) {
|
||||||
vm_error("stack overflow");
|
die("stack overflow");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// parameter size is func->psize-1, 1 is reserved for "me"
|
// parameter size is func->psize-1, 1 is reserved for "me"
|
||||||
u32 psize=func.psize-1;
|
u32 psize=func.psize-1;
|
||||||
if (argc<psize && func.local[argc+1].type==vm_none) {
|
if (argc<psize && func.local[argc+1].type==vm_none) {
|
||||||
vm_error("lack argument(s)");
|
die("lack argument(s)");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var dynamic=nil;
|
var dynamic=nil;
|
||||||
|
@ -733,7 +751,8 @@ inline void vm::o_callfv() {
|
||||||
inline void vm::o_callfh() {
|
inline void vm::o_callfh() {
|
||||||
auto& hash=top[0].hash().elems;
|
auto& hash=top[0].hash().elems;
|
||||||
if (top[-1].type!=vm_func) {
|
if (top[-1].type!=vm_func) {
|
||||||
vm_error("must call a function");
|
die("must call a function");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
auto& func=top[-1].func();
|
auto& func=top[-1].func();
|
||||||
var tmp=top[-1];
|
var tmp=top[-1];
|
||||||
|
@ -741,10 +760,12 @@ inline void vm::o_callfh() {
|
||||||
funcr=tmp;
|
funcr=tmp;
|
||||||
// top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
// top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
||||||
if (top+func.lsize+2>=canary) {
|
if (top+func.lsize+2>=canary) {
|
||||||
vm_error("stack overflow");
|
die("stack overflow");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (func.dpara>=0) {
|
if (func.dpara>=0) {
|
||||||
vm_error("special call cannot use dynamic argument");
|
die("special call cannot use dynamic argument");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var* local=top;
|
var* local=top;
|
||||||
|
@ -758,7 +779,8 @@ inline void vm::o_callfh() {
|
||||||
if (hash.count(key)) {
|
if (hash.count(key)) {
|
||||||
local[i.second]=hash[key];
|
local[i.second]=hash[key];
|
||||||
} else if (local[i.second].type==vm_none) {
|
} else if (local[i.second].type==vm_none) {
|
||||||
vm_error("lack argument(s): \""+key+"\"");
|
die("lack argument(s): \""+key+"\"");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,7 +801,8 @@ inline void vm::o_callb() {
|
||||||
// (top) will be set to another context.top, instead of main_context.top
|
// (top) will be set to another context.top, instead of main_context.top
|
||||||
top[0]=(*builtin[imm[pc]].func)(localr,ngc);
|
top[0]=(*builtin[imm[pc]].func)(localr,ngc);
|
||||||
if (top[0].type==vm_none) {
|
if (top[0].type==vm_none) {
|
||||||
vm_error("native function error");
|
die("native function error");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -791,7 +814,8 @@ inline void vm::o_slcbeg() {
|
||||||
// +--------------+
|
// +--------------+
|
||||||
(++top)[0]=ngc.alloc(vm_vec);
|
(++top)[0]=ngc.alloc(vm_vec);
|
||||||
if (top[-1].type!=vm_vec) {
|
if (top[-1].type!=vm_vec) {
|
||||||
vm_error("must slice a vector");
|
die("must slice a vector");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,7 +828,8 @@ inline void vm::o_slc() {
|
||||||
var val=(top--)[0];
|
var val=(top--)[0];
|
||||||
var res=top[-1].vec().get_val(val.tonum());
|
var res=top[-1].vec().get_val(val.tonum());
|
||||||
if (res.type==vm_none) {
|
if (res.type==vm_none) {
|
||||||
vm_error("out of range:"+std::to_string(val.tonum()));
|
die("out of range:"+std::to_string(val.tonum()));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
top[0].vec().elems.push_back(res);
|
top[0].vec().elems.push_back(res);
|
||||||
}
|
}
|
||||||
|
@ -829,10 +854,12 @@ inline void vm::o_slc2() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num1<-size || num1>=size || num2<-size || num2>=size) {
|
if (num1<-size || num1>=size || num2<-size || num2>=size) {
|
||||||
vm_error("index "+std::to_string(num1)+":"+std::to_string(num2)+" out of range.");
|
die("index "+std::to_string(num1)+":"+std::to_string(num2)+" out of range.");
|
||||||
|
return;
|
||||||
} else if (num1<=num2) {
|
} else if (num1<=num2) {
|
||||||
for(i32 i=num1;i<=num2;++i)
|
for(i32 i=num1;i<=num2;++i) {
|
||||||
aim.push_back(i>=0?ref[i]:ref[i+size]);
|
aim.push_back(i>=0?ref[i]:ref[i+size]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,11 +890,13 @@ inline void vm::o_mcallv() {
|
||||||
if (vec.type==vm_vec) {
|
if (vec.type==vm_vec) {
|
||||||
memr=vec.vec().get_mem(val.tonum());
|
memr=vec.vec().get_mem(val.tonum());
|
||||||
if (!memr) {
|
if (!memr) {
|
||||||
vm_error("out of range:"+std::to_string(val.tonum()));
|
die("out of range:"+std::to_string(val.tonum()));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else if (vec.type==vm_hash) { // do mcallh but use the mcallv way
|
} else if (vec.type==vm_hash) { // do mcallh but use the mcallv way
|
||||||
if (val.type!=vm_str) {
|
if (val.type!=vm_str) {
|
||||||
vm_error("must use string as the key");
|
die("must use string as the key");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
nas_hash& ref=vec.hash();
|
nas_hash& ref=vec.hash();
|
||||||
string& str=val.str();
|
string& str=val.str();
|
||||||
|
@ -877,14 +906,16 @@ inline void vm::o_mcallv() {
|
||||||
memr=ref.get_mem(str);
|
memr=ref.get_mem(str);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vm_error("cannot get memory space in this type");
|
die("cannot get memory space in this type");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_mcallh() {
|
inline void vm::o_mcallh() {
|
||||||
var hash=top[0]; // mcall hash, reserved on stack to avoid gc
|
var hash=top[0]; // mcall hash, reserved on stack to avoid gc
|
||||||
if (hash.type!=vm_hash) {
|
if (hash.type!=vm_hash) {
|
||||||
vm_error("must call a hash");
|
die("must call a hash");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
auto& ref=hash.hash();
|
auto& ref=hash.hash();
|
||||||
auto& str=cstr[imm[pc]];
|
auto& str=cstr[imm[pc]];
|
||||||
|
|
|
@ -73,25 +73,30 @@ println("coroutine state:\e[91m ",coroutine.status(co),"\e[0m");
|
||||||
println("ok");
|
println("ok");
|
||||||
|
|
||||||
# pressure test
|
# pressure test
|
||||||
var productor=func(){
|
var main=func(){
|
||||||
for(var i=0;;i+=1)
|
var productor=func(){
|
||||||
coroutine.yield(i);
|
for(var i=0;;i+=1)
|
||||||
}
|
coroutine.yield(i);
|
||||||
var total=1000; # ms
|
}
|
||||||
var co=coroutine.create(productor);
|
var total=1000; # ms
|
||||||
var tm=maketimestamp();
|
var co=coroutine.create(productor);
|
||||||
|
var tm=maketimestamp();
|
||||||
|
|
||||||
var counter=0;
|
var counter=0;
|
||||||
var bar=process_bar.high_resolution_bar(40);
|
var bar=process_bar.high_resolution_bar(40);
|
||||||
var consumer=func(){
|
var consumer=func(){
|
||||||
counter+=1;
|
counter+=1;
|
||||||
for(var i=0;i<5;i+=1)
|
for(var i=0;i<5;i+=1)
|
||||||
coroutine.resume(co);
|
coroutine.resume(co);
|
||||||
var rate=(tm.elapsedMSec()+1)/total;
|
var rate=(tm.elapsedMSec()+1)/total;
|
||||||
print(bar.bar(rate)," ",rate*100,"% \r");
|
print(" ",bar.bar(rate)," ",int(rate*100),"% | ",counter," tasks \r");
|
||||||
|
}
|
||||||
|
|
||||||
|
tm.stamp();
|
||||||
|
while(tm.elapsedMSec()<total)
|
||||||
|
consumer();
|
||||||
|
println();
|
||||||
}
|
}
|
||||||
|
|
||||||
tm.stamp();
|
for(var i=0;i<5;i+=1)
|
||||||
while(tm.elapsedMSec()<total)
|
main();
|
||||||
consumer();
|
|
||||||
println("\nexecute ",counter," tasks during ",total," ms, avg ",counter/total," tasks/ms.");
|
|
Loading…
Reference in New Issue