06:16 陳厚成: 小葉的 inner loop 會越鑽越深,把 CPU stack 爆掉。我的辦法 (前述的 if (addr == KVMRet) break; ) 也不週全,到現在也解不了。希望能用改用政昌兄的 inner loop 邏輯搬過來試試看。
08:45 吳政昌 : KVMCall 的作法,會在 Inner loop 中判斷 addr 是否在字典中。我想這個設計少了一個處理 colon definition 的 nest 指令。
吳政昌 : 我不確定那個 inner loop中的遞迴會造成 CPU stack 爆掉。Forth colon definition 應該不會很深才對。另外,這個系統使用 catch throw 處理 Abort 嗎?有 error 時它如何跳出這個 recursive 呼叫?
14:30 吳政昌 這是我的 nest。感覺 KSanaVM 用副程式 call 性能會比較好。但我不能用 call,因為 Rust 沒有 catch throw。Call 了後不好離開。
14:36 吳政昌 圖片
14:39 吳政昌 這是和 nest 對應的 exit。我覺得 KasanaVm 的 CPU Stack 爆掉不一定是那個 recursive 的 call 造成。可能要確認到底這個 call 有多深。
14:48 吳政昌 KasanaVm 的這個作法會使得難以實現 multitasker。設計 Forth VM 就是這樣,有捨有得,沒有最好的設計。
14:52 陳厚成 感謝您!
2020.09.15 星期二
10:00 陳厚成 幸得 政昌兄 點撥,問題似乎解了。我從 NEST 去思索,發現這來源的 does> words 也有 inner loop 累積不退的問題。照著 NEST 的啟發,想出的辦法就是加個 exit 指令 (只舉個 flag 而已) 當作原來的 ; 指令的 decorator 把 ; 修飾成令 inner loop BREAK 出去。應用在 does> 的場合,例如 : constant create , does> r> @ exit ; 有效。
10:01 陳厚成 附註: 上面的 r> 是 yap 的得意發明,與一般 FORTH 不同。
for(;;) {
addr = *((__int64 *)vm->ip); // fetch the instruction from ip. Forth 是以 function entry point or colon word cfa 為 instruction.
vm->ip += POINTERSIZE; // advance to next CELL 還沒用就先指到下一個 word.
if (inDictionary(vm,addr)) { // 這意味 dictionary 裡面的都是 KVMXT, 以 entry addrerss cfa 當 instruction
KVMRPush(vm,vm->ip); // save the next xt for returning from caller , see *1*
KVMCall(vm,addr); // jmp to the addr , recursive call
} else {
(*(KVMXT)(addr))(vm); // call as a C function ( code-word )
}
if (vm->abortexec == 1) break; // abort 所有 inner loop 回到 outer loop 去 *2*
if (vm->abortexec == 2){ // 08:04 2020/09/15 解決 does> words 的 deep call 問題。 2 只用來 BREAK 當前這一個 KVMCall 不是整個結束掉,inner loop 還沒完。
vm->abortexec = 0;
break;
}
}
}
// 這個是 ; 的 run time 應該就是 NEST
void KVMRet(KsanaVm *vm) // return to caller
{
if (vm->rp<0) {
vm->abortexec=1; // quit innerloop if no more item on return stack *2*
return;
}
vm->ip = KVMRPop(vm); // recover the ip from return stack *1*
}
// 這個是我新增的 decorator 名喚 exit 用來修飾 KVMRet
void KVMdoExit(KsanaVm *vm)
{
vm->abortexec = 2; // explicitly BREAK the KVMCall 但 colon word 還沒完,讓前一級 KVMCall 繼續跑
}
// ( -- ) Compile the exit forth instruction
void KVMExit(KsanaVm *vm) // begin a colon compiler
{
DictPointerCompile(vm, KVMdoExit); // must add this for does> words
}