Merge pull request #72 from ValKmjolnir/develop
Nasal Interpreter Test / mac-aarch64 (push) Has been cancelled Details
Nasal Interpreter Test / linux-x86_64 (push) Has been cancelled Details

🐛 fix #69
This commit is contained in:
ValK 2025-07-31 20:24:40 +08:00 committed by GitHub
commit 9f1d50bfe6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 67 additions and 74 deletions

View File

@ -128,9 +128,9 @@ target_link_libraries(nasock module-used-object)
if (NOT MSVC) if (NOT MSVC)
add_library(nasal-web SHARED add_library(nasal-web SHARED
src/nasal_web.cpp src/nasal_web.cpp
${NASAL_OBJECT_SOURCE_FILE}
) )
target_include_directories(nasal-web PRIVATE ${CMAKE_SOURCE_DIR}/src) target_include_directories(nasal-web PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_link_libraries(nasal-web nasal-object)
set_target_properties(nasal-web PROPERTIES set_target_properties(nasal-web PROPERTIES
C_VISIBILITY_PRESET hidden C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden CXX_VISIBILITY_PRESET hidden

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#ifndef __nasver__ #ifndef __nasver__
#define __nasver__ "11.3.2" #define __nasver__ "11.3.3"
#endif #endif
#include <cstddef> #include <cstddef>
@ -18,7 +18,7 @@ using usize = std::size_t;
using f64 = double; using f64 = double;
// virtual machine stack depth, both global depth and value stack depth // virtual machine stack depth, both global depth and value stack depth
const u32 VM_STACK_DEPTH = UINT16_MAX; const u32 VM_STACK_DEPTH = UINT16_MAX + 1;
// avoid error loading function bug in MSVC version nasal.exe // avoid error loading function bug in MSVC version nasal.exe
#ifdef _MSC_VER #ifdef _MSC_VER

View File

@ -189,8 +189,7 @@ void vm::value_info(var& val) {
} }
void vm::function_detail_info(const nas_func& func) { void vm::function_detail_info(const nas_func& func) {
std::clog << "func@"; std::clog << "func ";
std::clog << std::hex << reinterpret_cast<u64>(&func) << std::dec;
std::vector<std::string> argument_list = {}; std::vector<std::string> argument_list = {};
argument_list.resize(func.keys.size()); argument_list.resize(func.keys.size());
@ -222,54 +221,34 @@ void vm::function_call_trace() {
var* top = ctx.top; var* top = ctx.top;
// generate trace back // generate trace back
std::stack<const nas_func*> functions; std::vector<const nas_func*> functions;
std::stack<u64> callsite; std::vector<u64> callsite;
// load call trace, from bottom to top var* prev_func = &ctx.funcr;
for (var* i = bottom; i <= top; ++i) { functions.push_back(&prev_func->func());
// i-1 is the callsite program counter of this function for (var* i = top; i >= bottom; i--) {
// +-------+----------------+ // +-------+------------------+
// | func | func() {..} | <-- i + 2 // | ret | 0x3bf | <-- i + 1 (should not be 0, except coroutine)
// +-------+----------------+ // +-------+------------------+
// | ret | 0x3bf | <-- i + 1 (value should not be 0x0) // | addr | 0x7ff5f61ae020 | <-- i
// +-------+----------------+ // +-------+------------------+
// | addr | 0x7ff5f61ae020 | <-- i // | upval | ... | <-- i - 1
// +-------+----------------+ // +-------+------------------+
// TODO: op_cnt may destroy the order, so maybe this need refact // | locals| ... |
if (i + 2 > top) { // +-------+------------------+
continue; // | func | function | <-- i - 1 - prev_func->local_size - 1
// +-------+------------------+
if (i + 1 <= top && i[0].is_addr() && i[1].is_ret()) {
auto r_addr = i[1].ret();
callsite.push_back(r_addr);
i--;
i -= prev_func->func().local_size;
i--;
if (i >= bottom && i[0].is_func()) {
prev_func = i;
functions.push_back(&prev_func->func());
}
} }
if (!i->is_addr()) {
continue;
}
if ((i+1)->is_ret() && (i+1)->ret()>0 && (i+2)->is_func()) {
functions.push(&(i+2)->func());
callsite.push((i+1)->ret());
}
}
// another condition may exist
// have ret pc on stack, but no function at the top of the ret pc
for (var * i = top; i >= bottom; --i) {
// +-------+----------------+
// | xxxx | xxxx | <-- i + 2 (not function or not exist)
// +-------+----------------+
// | ret | 0x3bf | <-- i + 1 (value should not be 0x0)
// +-------+----------------+
// | addr | 0x7ff5f61ae020 | <-- i
// +-------+----------------+
if ((i->is_addr() && i+2<=top && (i+1)->is_ret() && !(i+2)->is_func()) ||
(i->is_addr() && i+1<=top && i+2>top && (i+1)->is_ret())) {
functions.push(&ctx.funcr.func());
callsite.push((i+1)->ret());
break;
}
}
// function register stores the latest-called function
if (functions.empty() && !ctx.funcr.is_func()) {
cp.restore_code_page();
return;
} }
std::clog << "\ncall trace "; std::clog << "\ncall trace ";
@ -279,35 +258,35 @@ void vm::function_call_trace() {
std::clog << " at " << files[bytecode[ctx.pc].fidx] << ":"; std::clog << " at " << files[bytecode[ctx.pc].fidx] << ":";
std::clog << bytecode[ctx.pc].line << "\n"; std::clog << bytecode[ctx.pc].line << "\n";
const nas_func* last = nullptr; const nas_func* prev = nullptr;
u64 last_callsite = SIZE_MAX; u64 prev_addr = 0;
u64 same_count = 0; u64 same_call_count = 0;
for (; !functions.empty() && !callsite.empty(); functions.pop(), callsite.pop()) { for (int i = 0; i < functions.size(); ++i) {
auto func = functions.top(); if (functions[i] == prev && callsite[i] == prev_addr) {
auto place = callsite.top(); same_call_count++;
if (last==func && last_callsite==place) {
++same_count;
continue; continue;
} else if (same_count) { } else if (same_call_count) {
std::clog << " `--> " << same_count << " same call(s)\n"; std::clog << " `--> " << same_call_count << " same call(s)\n";
same_count = 0; same_call_count = 0;
} }
last = func; // in coroutine
last_callsite = place; if (callsite[i] == 0 && ngc.cort) {
std::clog << " call by coroutine\n";
break;
}
// output called function
std::clog << " call "; std::clog << " call ";
function_detail_info(*func); function_detail_info(*functions[i]);
auto r_addr = callsite[i];
std::clog << " from " << files[bytecode[r_addr].fidx] << ":";
std::clog << bytecode[r_addr].line << "\n";
// output callsite prev = functions[i];
std::clog << " from "; prev_addr = r_addr;
std::clog << files[bytecode[place].fidx] << ":";
std::clog << bytecode[place].line << "\n";
} }
if (same_count) { if (same_call_count) {
std::clog << " `--> " << same_count << " same call(s)\n"; std::clog << " `--> " << same_call_count << " same call(s)\n";
} }
cp.restore_code_page(); cp.restore_code_page();

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <iomanip> #include <iomanip>
#include <stack>
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
#include <atomic> #include <atomic>

View File

@ -0,0 +1,15 @@
var f = func() {
append({}, []);
}
var b = func(f...) {
foreach(var i; f) {
i();
}
}
b(f);
func(a, b, c) {
f()
}(0, 1, 2);