little optimization

This commit is contained in:
ValKmjolnir 2022-11-30 01:11:26 +08:00
parent 9455a83df0
commit eca978e2b3
13 changed files with 110 additions and 49 deletions

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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());

View File

@ -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"
/* /*
_,,,_ _,,,_
.' `'. .' `'.

View File

@ -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]];

View File

@ -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.");