diff --git a/src/Debug/debugger.cpp b/src/Debug/debugger.cpp index f84651b0..c4fa6247 100644 --- a/src/Debug/debugger.cpp +++ b/src/Debug/debugger.cpp @@ -508,12 +508,15 @@ void Debugger::dump(Module *m, bool full) const { this->dumpCallstack(m); if (full) { - this->channel->write(R"(, "locals": )"); + this->channel->write(R"( "locals": )"); this->dumpLocals(m); this->channel->write(", "); this->dumpEvents(0, static_cast(CallbackHandler::event_count())); + this->channel->write(", "); } + this->dumpHeapInfo(m); + this->channel->write("}\n\n"); // fflush(stdout); } @@ -581,7 +584,7 @@ void Debugger::dumpCallstack(Module *m) const { this->channel->write("\"start\":%" PRIu32 ",\"ra\":%d,\"callsite\":%d}%s", toVA(f->block->start_ptr), retaddr, - callsite_retaddr, (i < m->csp) ? "," : "]"); + callsite_retaddr, (i < m->csp) ? "," : "],"); } } @@ -668,6 +671,10 @@ void Debugger::dumpCallbackmapping() const { this->channel->write("%s\n", CallbackHandler::dump_callbacks().c_str()); } +void Debugger::dumpHeapInfo(Module *m) const { + this->channel->write(R"("heap":{"used":%u})", m->warduino->get_heap_used()); +} + /** * Read the change in bytes array. * @@ -970,6 +977,13 @@ void Debugger::inspect(Module *m, const uint16_t sizeStateArray, addComma = true; break; } + case heapState: { + uint32_t heap_used = m->warduino->get_heap_used(); + this->channel->write(R"(%s"heap":{"used":%d})", + addComma ? "," : "", heap_used); + addComma = true; + break; + } default: { debug("dumpExecutionState: Received unknown state request\n"); break; diff --git a/src/Debug/debugger.h b/src/Debug/debugger.h index 1cfda22a..c612ddf8 100644 --- a/src/Debug/debugger.h +++ b/src/Debug/debugger.h @@ -51,6 +51,7 @@ enum ExecutionState { eventsState = 0x0A, ioState = 0x0B, overridesState = 0x0C, + heapState = 0x0D, }; enum InterruptTypes { @@ -186,6 +187,8 @@ class Debugger { void dumpCallbackmapping() const; + void dumpHeapInfo(Module *m) const; + void inspect(Module *m, uint16_t sizeStateArray, const uint8_t *state) const; diff --git a/src/Primitives/arduino.cpp b/src/Primitives/arduino.cpp index 80329573..cb150d6a 100644 --- a/src/Primitives/arduino.cpp +++ b/src/Primitives/arduino.cpp @@ -692,6 +692,11 @@ def_prim(mqtt_loop, NoneToOneU32) { return true; } +def_prim(heap_used, zeroToOneU32) { + pushUInt32(m->warduino->get_heap_used()); + return true; +} + //------------------------------------------------------ // Util functions //------------------------------------------------------ @@ -863,6 +868,8 @@ void install_primitives(Interpreter *interpreter) { install_primitive(chip_ledc_attach); install_primitive(chip_ledc_set_duty); + install_primitive(heap_used); + dbg_info("INSTALLING ISRs\n"); install_isrs(); } diff --git a/src/Primitives/emulated.cpp b/src/Primitives/emulated.cpp index 94bccf83..885a4acd 100644 --- a/src/Primitives/emulated.cpp +++ b/src/Primitives/emulated.cpp @@ -462,6 +462,12 @@ def_prim(chip_ledc_attach_pin, twoToNoneU32) { return true; } +def_prim(heap_used, zeroToOneU32) { + printf("EMU: heap_used()\n"); + pushUInt32(m->warduino->get_heap_used()); + return true; +} + //------------------------------------------------------ // Installing all the primitives //------------------------------------------------------ @@ -516,6 +522,8 @@ void install_primitives(Interpreter *interpreter) { install_primitive(read_uart_sensor); install_primitive(nxt_touch_sensor); install_primitive(ev3_touch_sensor); + + install_primitive(heap_used); } Memory external_mem{}; diff --git a/src/Primitives/primitives.h b/src/Primitives/primitives.h index 2a58761c..b0c146c9 100644 --- a/src/Primitives/primitives.h +++ b/src/Primitives/primitives.h @@ -205,6 +205,15 @@ inline Type sevenToNoneU32 = { I32; 1 = I32; 1 = I32; 1 = I32*/ }; +inline Type zeroToOneU32 = { + .form = FUNC, + .param_count = 0, + .params = param_arr_len0, + .result_count = 1, + .results = param_I32_arr_len1, + .mask = 0x810 /* 0x8 1=I32 0=endRet ; no params*/ +}; + inline Type oneToOneU32 = { .form = FUNC, .param_count = 1, diff --git a/src/WARDuino.h b/src/WARDuino.h index c1e5aa07..150efe90 100644 --- a/src/WARDuino.h +++ b/src/WARDuino.h @@ -71,4 +71,6 @@ class WARDuino { void instantiate_module(Module *m, uint8_t *bytes, uint32_t byte_count); void free_module_state(Module *m); + + uint32_t get_heap_used(); }; diff --git a/src/WARDuino/WARDuino.cpp b/src/WARDuino/WARDuino.cpp index b08de243..16a40f40 100644 --- a/src/WARDuino/WARDuino.cpp +++ b/src/WARDuino/WARDuino.cpp @@ -1092,4 +1092,21 @@ uint32_t WARDuino::get_main_fidx(Module *m) { if (fidx == UNDEF) fidx = this->get_export_fidx(m, "_main"); if (fidx == UNDEF) fidx = this->get_export_fidx(m, "_Main"); return fidx; -} \ No newline at end of file +} + +#if defined(ARDUINO) +#include +#define TOTAL_MALLOC (ESP.getHeapSize() - ESP.getFreeHeap()) +#elif defined(ESP_PLATFORM) +#include +#define TOTAL_MALLOC \ + (heap_caps_get_total_size(MALLOC_CAP_DEFAULT) - \ + heap_caps_get_free_size(MALLOC_CAP_DEFAULT)) +#elif defined(__APPLE__) +#include +#define TOTAL_MALLOC mstats().bytes_used +#else +#include +#define TOTAL_MALLOC mallinfo2().uordblks +#endif +uint32_t WARDuino::get_heap_used() { return TOTAL_MALLOC; } \ No newline at end of file diff --git a/tutorials/wat/main/heap_used.wast b/tutorials/wat/main/heap_used.wast new file mode 100644 index 00000000..d825bd22 --- /dev/null +++ b/tutorials/wat/main/heap_used.wast @@ -0,0 +1,24 @@ +;; This test program shows how to use the `heap_used` function +;; to determine how much of the heap is currently in use. + +;; The same used heap size can be obtained from the debugger, +;; but note that the debugger introduces some overhead, so +;; the value obtained there may be slightly higher +;; than the value obtained from teh `heap_used` primitive. + +(module + (import "env" "heap_used" (func $heap_used (result i32))) + (import "env" "print_int" (func $print_int (param i32))) + (memory (export "memory") 1) + + (func (export "main") + (call $heap_used) ;; A + (call $print_int) + + (memory.grow (i32.const 1)) ;; grow memory by 1 page (64KB = 65536 bytes) + (drop) + + (call $heap_used) ;; should be >= A + 65536 + (call $print_int) + ) +) \ No newline at end of file