From b33c0c564c51252ff241a2143e467dadfb8d8994 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Wed, 8 Nov 2023 15:31:44 -0500 Subject: [PATCH] fib.fth benchmark; some minor coreword optimizations --- alee.cpp | 17 +++++ forth/fib.fth | 19 ++++++ libalee/corewords.cpp | 150 +++++++++++++++++++----------------------- libalee/state.hpp | 25 +++++-- 4 files changed, 121 insertions(+), 90 deletions(-) create mode 100644 forth/fib.fth diff --git a/alee.cpp b/alee.cpp index 55cae57..99bc276 100644 --- a/alee.cpp +++ b/alee.cpp @@ -20,6 +20,7 @@ #include "memdict.hpp" #include +#include #include #include #include @@ -82,6 +83,8 @@ static void load(State& state) void user_sys(State& state) { + static std::chrono::time_point last; + static bool start = false; char buf[32] = {0}; switch (state.pop()) { @@ -102,6 +105,20 @@ void user_sys(State& state) case 4: // load load(state); break; + case 5: // time + if (!start) { + start = true; + last = std::chrono::high_resolution_clock::now(); + } else { + start = false; + auto diff = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - last); + state.push((Cell)diff.count()); + } + break; + case 6: // double-add + { auto sum = state.popd() + state.popd(); state.pushd(sum); } + break; default: break; } diff --git a/forth/fib.fth b/forth/fib.fth new file mode 100644 index 0000000..82c87cd --- /dev/null +++ b/forth/fib.fth @@ -0,0 +1,19 @@ +: fib ( n -- d ) + >r 0 dup 1 0 r> 0 do + 2dup 2>r 2swap 6 sys 2r> 2swap loop 2drop ; + +: fibtest ( n -- ) + 0 do i fib <# #s #> type space loop ; + +: fibbench ( n -- ) + 5 sys fib 5 sys >r 2drop r> ; + +variable avg 0 avg ! +100 constant iters + +: bench ( -- ) + iters 0 do 100 fibbench avg +! loop + avg @ iters / avg ! ; + +bench ." avg time: " avg @ . ." us" cr +bye diff --git a/libalee/corewords.cpp b/libalee/corewords.cpp index e3ba6b3..e323ed9 100644 --- a/libalee/corewords.cpp +++ b/libalee/corewords.cpp @@ -39,31 +39,17 @@ void find(State& state, Word word) void CoreWords::run(Cell ins, State& state) { - Cell cell; DoubleCell dcell; - - Addr index = ins; - + const Addr index = ins; auto& ip = state.ip(); - auto popd = [](State& s) { - DoubleCell dcell = s.pop(); - dcell <<= sizeof(Cell) * 8; - dcell |= static_cast(s.pop()); - return dcell; - }; - - auto pushd = [](State& s, DoubleCell d) { - s.push(static_cast(d)); - s.push(static_cast(d >> (sizeof(Cell) * 8))); - }; - -execute: if (index >= Dictionary::Begin) { // must be calling a defined subroutine state.pushr(ip); ip = index; return; + } else if (index >= WordCount) { + state.push(index - WordCount); } else switch (index) { case 0: // _lit state.push(state.beyondip()); @@ -84,27 +70,25 @@ execute: user_sys(state); break; case 6: // add - cell = state.pop(); - state.top() += cell; + { auto& cell = state.pop(); state.top() += cell; } break; case 7: // sub - cell = state.pop(); - state.top() -= cell; + { auto& cell = state.pop(); state.top() -= cell; } break; case 8: // mul ( n n -- d ) - cell = state.pop(); - dcell = state.pop() * cell; - pushd(state, dcell); + { auto& cell = state.pop(); + dcell = state.pop() * cell; + state.pushd(dcell); } break; case 9: // div ( d n -- n ) - cell = state.pop(); - dcell = popd(state); - state.push(static_cast(dcell / cell)); + { auto& cell = state.pop(); + dcell = state.popd(); + state.push(static_cast(dcell / cell)); } break; case 10: // mod ( d n -- n ) - cell = state.pop(); - dcell = popd(state); - state.push(static_cast(dcell % cell)); + { auto& cell = state.pop(); + dcell = state.popd(); + state.push(static_cast(dcell % cell)); } break; case 11: // peek if (state.pop()) @@ -113,11 +97,11 @@ execute: state.push(state.dict.readbyte(state.pop())); break; case 12: // poke - cell = state.pop(); - if (auto addr = state.pop(); cell) - state.dict.write(addr, state.pop()); - else - state.dict.writebyte(addr, state.pop() & 0xFFu); + { auto& cell = state.pop(); + if (auto addr = state.pop(); cell) + state.dict.write(addr, state.pop()); + else + state.dict.writebyte(addr, state.pop() & 0xFFu); } break; case 13: // pushr state.pushr(state.pop()); @@ -126,32 +110,29 @@ execute: state.push(state.popr()); break; case 15: // equal - cell = state.pop(); - state.top() = state.top() == cell ? -1 : 0; + { auto& cell = state.pop(); + state.top() = state.top() == cell ? -1 : 0; } break; case 16: // lt - cell = state.pop(); - state.top() = state.top() < cell ? -1 : 0; + { auto& cell = state.pop(); + state.top() = state.top() < cell ? -1 : 0; } break; case 17: // and - cell = state.pop(); - state.top() &= cell; + { auto& cell = state.pop(); state.top() &= cell; } break; case 18: // or - cell = state.pop(); - state.top() |= cell; + { auto& cell = state.pop(); state.top() |= cell; } break; case 19: // xor - cell = state.pop(); - state.top() ^= cell; + { auto& cell = state.pop(); state.top() ^= cell; } break; case 20: // shl - cell = state.pop(); - reinterpret_cast(state.top()) <<= static_cast(cell); + { auto& cell = state.pop(); + reinterpret_cast(state.top()) <<= static_cast(cell); } break; case 21: // shr - cell = state.pop(); - reinterpret_cast(state.top()) >>= static_cast(cell); + { auto& cell = state.pop(); + reinterpret_cast(state.top()) >>= static_cast(cell); } break; case 22: // colon state.push(state.dict.alignhere()); @@ -167,8 +148,8 @@ execute: find(state, state.dict.input()); break; case 24: // execute - index = state.pop(); - goto execute; + ip = state.pop(); + return; case 25: // exit ip = state.popr(); state.verify(ip != 0, Error::exit); @@ -177,14 +158,18 @@ execute: state.dict.add(findi("exit")); state.compiling(false); - cell = state.pop(); - dcell = cell - state.dict.latest(); - if (dcell > (1 << (sizeof(Cell) * 8 - 6)) - 1) { - state.dict.write(static_cast(cell) + sizeof(Cell), static_cast(dcell)); - dcell = ((1 << (sizeof(Cell) * 8 - 6)) - 1); + { + auto& cell = state.pop(); + dcell = cell - state.dict.latest(); + if (dcell > (1 << (sizeof(Cell) * 8 - 6)) - 1) { + state.dict.write(static_cast(cell) + sizeof(Cell), + static_cast(dcell)); + dcell = ((1 << (sizeof(Cell) * 8 - 6)) - 1); + } + state.dict.write(cell, + (state.dict.read(cell) & 0x1F) | static_cast(dcell << 6)); + state.dict.latest(cell); } - state.dict.write(cell, (state.dict.read(cell) & 0x1F) | static_cast(dcell << 6)); - state.dict.latest(cell); break; case 27: // _jmp0 if (state.pop()) { @@ -213,39 +198,38 @@ execute: } break; case 33: // find - cell = state.pop(); - find(state, - Word::fromLength(static_cast(cell + 1), - state.dict.readbyte(cell))); + { auto& cell = state.pop(); + find(state, + Word::fromLength(static_cast(cell + 1), + state.dict.readbyte(cell))); } break; case 34: // _uma { - const auto plus = state.pop(); - cell = state.pop(); - dcell = popd(state); - dcell *= static_cast(cell); - dcell += static_cast(plus); - pushd(state, dcell); + const auto& plus = state.pop(); + const auto& cell = state.pop(); + dcell = state.popd(); + dcell *= static_cast(cell); + dcell += static_cast(plus); + state.pushd(dcell); } break; case 35: // u< - cell = state.pop(); - state.top() = static_cast(state.top()) < - static_cast(cell) ? -1 : 0; + { auto& cell = state.pop(); + state.top() = static_cast(state.top()) < + static_cast(cell) ? -1 : 0; } break; case 36: // um/mod - cell = state.pop(); - dcell = popd(state); - - state.push(static_cast( - static_cast(dcell) % - static_cast(cell))); - state.push(static_cast( - static_cast(dcell) / - static_cast(cell))); - break; - default: - state.push(ins - WordCount); + { + const auto& cell = state.pop(); + dcell = state.popd(); + + state.push(static_cast( + static_cast(dcell) % + static_cast(cell))); + state.push(static_cast( + static_cast(dcell) / + static_cast(cell))); + } break; } diff --git a/libalee/state.hpp b/libalee/state.hpp index e77a223..2e69463 100644 --- a/libalee/state.hpp +++ b/libalee/state.hpp @@ -87,31 +87,42 @@ public: *dsp++ = value; } - inline Cell pop() { + inline const Cell& pop() { verify(dsp > dstack, Error::pop); return *--dsp; } + inline DoubleCell popd() { + DoubleCell dcell = pop(); + dcell <<= sizeof(Cell) * 8; + dcell |= static_cast(pop()); + return dcell; + } + + inline void pushd(DoubleCell d) { + push(static_cast(d)); + push(static_cast(d >> (sizeof(Cell) * 8))); + } + inline void pushr(Cell value) { verify(rsp < rstack + ReturnStackSize, Error::pushr); *rsp++ = value; } - inline Cell popr() { + inline const Cell& popr() { verify(rsp > rstack, Error::popr); return *--rsp; } - inline Cell& top() { - verify(dsp > dstack, Error::top); - return *(dsp - 1); - } - inline Cell& pick(std::size_t i) { verify(dsp - i > dstack, Error::pick); return *(dsp - i - 1); } + inline Cell& top() { + return pick(0); + } + // Advances the instruction pointer and returns that cell's contents. inline Cell beyondip() { context.ip += sizeof(Cell);