From 8894077656a2d61ccdb50ae217f1bc4d04bbbd0f Mon Sep 17 00:00:00 2001 From: Daniel Balla Date: Tue, 23 May 2017 11:19:15 +0200 Subject: [PATCH] Implement memstats command in the debugger (#1838) Implementation of memstats command in jerry-debugger, python and html client. Shows the allocated bytes, byte code bytes, string bytes, object bytes, property bytes and heap size. JerryScript-DCO-1.0-Signed-off-by: Daniel Balla dballa@inf.u-szeged.hu --- jerry-core/debugger/jerry-debugger.c | 46 +++++++++++++++++++++++++ jerry-core/debugger/jerry-debugger.h | 47 +++++++++++++++++-------- jerry-debugger/jerry-client-ws.html | 49 ++++++++++++++++++-------- jerry-debugger/jerry-client-ws.py | 51 ++++++++++++++++++++-------- tests/debugger/do_help.expected | 6 ++-- 5 files changed, 151 insertions(+), 48 deletions(-) diff --git a/jerry-core/debugger/jerry-debugger.c b/jerry-core/debugger/jerry-debugger.c index 6fe55e2f6..0517d7cec 100644 --- a/jerry-core/debugger/jerry-debugger.c +++ b/jerry-core/debugger/jerry-debugger.c @@ -347,6 +347,14 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec return true; } + case JERRY_DEBUGGER_MEMSTATS: + { + JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); + + jerry_debugger_send_memstats (); + return true; + } + case JERRY_DEBUGGER_STOP: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); @@ -669,4 +677,42 @@ jerry_debugger_send_parse_function (uint32_t line, /**< line */ return jerry_debugger_send (sizeof (jerry_debugger_send_parse_function_t)); } /* jerry_debugger_send_parse_function */ +/** + * Send memory statistics to the debugger client. + */ +void +jerry_debugger_send_memstats (void) +{ + JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED); + + JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_memstats_t, memstats_p); + JERRY_DEBUGGER_INIT_SEND_MESSAGE (memstats_p); + JERRY_DEBUGGER_SET_SEND_MESSAGE_SIZE_FROM_TYPE (memstats_p, jerry_debugger_send_memstats_t); + + memstats_p->type = JERRY_DEBUGGER_MEMSTATS_RECEIVE; + +#ifdef JMEM_STATS /* if jmem_stats are defined */ + jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats); + + uint32_t allocated_bytes = (uint32_t) heap_stats->allocated_bytes; + memcpy (memstats_p->allocated_bytes, &allocated_bytes, sizeof (uint32_t)); + uint32_t byte_code_bytes = (uint32_t) heap_stats->byte_code_bytes; + memcpy (memstats_p->byte_code_bytes, &byte_code_bytes, sizeof (uint32_t)); + uint32_t string_bytes = (uint32_t) heap_stats->string_bytes; + memcpy (memstats_p->string_bytes, &string_bytes, sizeof (uint32_t)); + uint32_t object_bytes = (uint32_t) heap_stats->object_bytes; + memcpy (memstats_p->object_bytes, &object_bytes, sizeof (uint32_t)); + uint32_t property_bytes = (uint32_t) heap_stats->property_bytes; + memcpy (memstats_p->property_bytes, &property_bytes, sizeof (uint32_t)); +#else /* if not, just put zeros */ + memset (memstats_p->allocated_bytes, 0, sizeof (uint32_t)); + memset (memstats_p->byte_code_bytes, 0, sizeof (uint32_t)); + memset (memstats_p->string_bytes, 0, sizeof (uint32_t)); + memset (memstats_p->object_bytes, 0, sizeof (uint32_t)); + memset (memstats_p->property_bytes, 0, sizeof (uint32_t)); +#endif + + jerry_debugger_send (sizeof (jerry_debugger_send_memstats_t)); +} /* jerry_debugger_send_memstats */ + #endif /* JERRY_DEBUGGER */ diff --git a/jerry-core/debugger/jerry-debugger.h b/jerry-core/debugger/jerry-debugger.h index 88d0f5c2b..0232000f6 100644 --- a/jerry-core/debugger/jerry-debugger.h +++ b/jerry-core/debugger/jerry-debugger.h @@ -99,14 +99,15 @@ typedef enum JERRY_DEBUGGER_FUNCTION_NAME = 11, /**< function name fragment */ JERRY_DEBUGGER_FUNCTION_NAME_END = 12, /**< function name last fragment */ JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13, /**< invalidate byte code compressed pointer */ - JERRY_DEBUGGER_BREAKPOINT_HIT = 14, /**< notify breakpoint hit */ - JERRY_DEBUGGER_EXCEPTION_HIT = 15, /**< notify exception hit */ - JERRY_DEBUGGER_BACKTRACE = 16, /**< backtrace data */ - JERRY_DEBUGGER_BACKTRACE_END = 17, /**< last backtrace data */ - JERRY_DEBUGGER_EVAL_RESULT = 18, /**< eval result */ - JERRY_DEBUGGER_EVAL_RESULT_END = 19, /**< last part of eval result */ - JERRY_DEBUGGER_EVAL_ERROR = 20, /**< eval result when an error is occured */ - JERRY_DEBUGGER_EVAL_ERROR_END = 21, /**< last part of eval result when an error is occured */ + JERRY_DEBUGGER_MEMSTATS_RECEIVE = 14, /**< memstats sent to the client*/ + JERRY_DEBUGGER_BREAKPOINT_HIT = 15, /**< notify breakpoint hit */ + JERRY_DEBUGGER_EXCEPTION_HIT = 16, /**< notify exception hit */ + JERRY_DEBUGGER_BACKTRACE = 17, /**< backtrace data */ + JERRY_DEBUGGER_BACKTRACE_END = 18, /**< last backtrace data */ + JERRY_DEBUGGER_EVAL_RESULT = 19, /**< eval result */ + JERRY_DEBUGGER_EVAL_RESULT_END = 20, /**< last part of eval result */ + JERRY_DEBUGGER_EVAL_ERROR = 21, /**< eval result when an error is occured */ + JERRY_DEBUGGER_EVAL_ERROR_END = 22, /**< last part of eval result when an error is occured */ /* Messages sent by the client to server. */ @@ -114,17 +115,18 @@ typedef enum JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1, /**< free byte code compressed pointer */ JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2, /**< update breakpoint status */ JERRY_DEBUGGER_EXCEPTION_CONFIG = 3, /**< exception handler config */ - JERRY_DEBUGGER_STOP = 4, /**< stop execution */ + JERRY_DEBUGGER_MEMSTATS = 4, /**< list memory statistics */ + JERRY_DEBUGGER_STOP = 5, /**< stop execution */ /* The following messages are only available in breakpoint * mode and they switch the engine to run mode. */ - JERRY_DEBUGGER_CONTINUE = 5, /**< continue execution */ - JERRY_DEBUGGER_STEP = 6, /**< next breakpoint, step into functions */ - JERRY_DEBUGGER_NEXT = 7, /**< next breakpoint in the same context */ + JERRY_DEBUGGER_CONTINUE = 6, /**< continue execution */ + JERRY_DEBUGGER_STEP = 7, /**< next breakpoint, step into functions */ + JERRY_DEBUGGER_NEXT = 8, /**< next breakpoint in the same context */ /* The following messages are only available in breakpoint * mode and this mode is kept after the message is processed. */ - JERRY_DEBUGGER_GET_BACKTRACE = 8, /**< get backtrace */ - JERRY_DEBUGGER_EVAL = 9, /**< first message of evaluating a string */ - JERRY_DEBUGGER_EVAL_PART = 10, /**< next message of evaluating a string */ + JERRY_DEBUGGER_GET_BACKTRACE = 9, /**< get backtrace */ + JERRY_DEBUGGER_EVAL = 10, /**< first message of evaluating a string */ + JERRY_DEBUGGER_EVAL_PART = 11, /**< next message of evaluating a string */ } jerry_debugger_header_type_t; /** @@ -216,6 +218,20 @@ typedef struct uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */ } jerry_debugger_receive_update_breakpoint_t; +/** + * Outgoing message: send memory statistics + */ +typedef struct +{ + jerry_debugger_send_header_t header; /**< message header */ + uint8_t type; /**< type of the message */ + uint8_t allocated_bytes[sizeof (uint32_t)]; /**< allocated bytes */ + uint8_t byte_code_bytes[sizeof (uint32_t)]; /**< byte code bytes */ + uint8_t string_bytes[sizeof (uint32_t)]; /**< string bytes */ + uint8_t object_bytes[sizeof (uint32_t)]; /**< object bytes */ + uint8_t property_bytes[sizeof (uint32_t)]; /**< property bytes */ +} jerry_debugger_send_memstats_t; + /** * Outgoing message: notify breakpoint hit. */ @@ -299,6 +315,7 @@ void jerry_debugger_send_data (jerry_debugger_header_type_t type, const void *da bool jerry_debugger_send_string (uint8_t message_type, const uint8_t *string_p, size_t string_length); bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_compiled_code_t *compiled_code_p); bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column); +void jerry_debugger_send_memstats (void); #endif /* JERRY_DEBUGGER */ diff --git a/jerry-debugger/jerry-client-ws.html b/jerry-debugger/jerry-client-ws.html index d0c609cd1..602cf175b 100644 --- a/jerry-debugger/jerry-client-ws.html +++ b/jerry-debugger/jerry-client-ws.html @@ -48,25 +48,27 @@ var JERRY_DEBUGGER_SOURCE_CODE_NAME_END = 10; var JERRY_DEBUGGER_FUNCTION_NAME = 11; var JERRY_DEBUGGER_FUNCTION_NAME_END = 12; var JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13; -var JERRY_DEBUGGER_BREAKPOINT_HIT = 14; -var JERRY_DEBUGGER_EXCEPTION_HIT = 15; -var JERRY_DEBUGGER_BACKTRACE = 16; -var JERRY_DEBUGGER_BACKTRACE_END = 17; -var JERRY_DEBUGGER_EVAL_RESULT = 18; -var JERRY_DEBUGGER_EVAL_RESULT_END = 19; -var JERRY_DEBUGGER_EVAL_ERROR = 20; -var JERRY_DEBUGGER_EVAL_ERROR_END = 21; +var JERRY_DEBUGGER_MEMSTATS_RECEIVE = 14; +var JERRY_DEBUGGER_BREAKPOINT_HIT = 15; +var JERRY_DEBUGGER_EXCEPTION_HIT = 16; +var JERRY_DEBUGGER_BACKTRACE = 17; +var JERRY_DEBUGGER_BACKTRACE_END = 18; +var JERRY_DEBUGGER_EVAL_RESULT = 19; +var JERRY_DEBUGGER_EVAL_RESULT_END = 20; +var JERRY_DEBUGGER_EVAL_ERROR = 21; +var JERRY_DEBUGGER_EVAL_ERROR_END = 22; var JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1; var JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2; var JERRY_DEBUGGER_EXCEPTION_CONFIG = 3; -var JERRY_DEBUGGER_STOP = 4; -var JERRY_DEBUGGER_CONTINUE = 5; -var JERRY_DEBUGGER_STEP = 6; -var JERRY_DEBUGGER_NEXT = 7; -var JERRY_DEBUGGER_GET_BACKTRACE = 8; -var JERRY_DEBUGGER_EVAL = 9; -var JERRY_DEBUGGER_EVAL_PART = 10; +var JERRY_DEBUGGER_MEMSTATS = 4; +var JERRY_DEBUGGER_STOP = 5; +var JERRY_DEBUGGER_CONTINUE = 6; +var JERRY_DEBUGGER_STEP = 7; +var JERRY_DEBUGGER_NEXT = 8; +var JERRY_DEBUGGER_GET_BACKTRACE = 9; +var JERRY_DEBUGGER_EVAL = 10; +var JERRY_DEBUGGER_EVAL_PART = 11; var textBox = document.getElementById("log"); var commandBox = document.getElementById("command"); @@ -806,6 +808,18 @@ function DebuggerClient(address) return; } + case JERRY_DEBUGGER_MEMSTATS_RECEIVE: + { + var messagedata = decodeMessage("IIIII", message, 1); + + appendLog("Allocated bytes: " + messagedata[0]); + appendLog("Byte code bytes: " + messagedata[1]); + appendLog("String bytes: " + messagedata[2]); + appendLog("Object bytes: " + messagedata[3]); + appendLog("Property bytes: " + messagedata[4]); + return; + } + case JERRY_DEBUGGER_BREAKPOINT_HIT: case JERRY_DEBUGGER_EXCEPTION_HIT: { @@ -1287,6 +1301,11 @@ function debuggerCommand(event) debuggerObj.encodeMessage("B", [ JERRY_DEBUGGER_STOP ]); break; + case "ms": + case "memstats": + debuggerObj.encodeMessage("B", [ JERRY_DEBUGGER_MEMSTATS ]); + break; + case "c": case "continue": debuggerObj.sendResumeExec(JERRY_DEBUGGER_CONTINUE); diff --git a/jerry-debugger/jerry-client-ws.py b/jerry-debugger/jerry-client-ws.py index 96ca5a4a1..92ac50bf1 100755 --- a/jerry-debugger/jerry-client-ws.py +++ b/jerry-debugger/jerry-client-ws.py @@ -39,27 +39,29 @@ JERRY_DEBUGGER_SOURCE_CODE_NAME_END = 10 JERRY_DEBUGGER_FUNCTION_NAME = 11 JERRY_DEBUGGER_FUNCTION_NAME_END = 12 JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13 -JERRY_DEBUGGER_BREAKPOINT_HIT = 14 -JERRY_DEBUGGER_EXCEPTION_HIT = 15 -JERRY_DEBUGGER_BACKTRACE = 16 -JERRY_DEBUGGER_BACKTRACE_END = 17 -JERRY_DEBUGGER_EVAL_RESULT = 18 -JERRY_DEBUGGER_EVAL_RESULT_END = 19 -JERRY_DEBUGGER_EVAL_ERROR = 20 -JERRY_DEBUGGER_EVAL_ERROR_END = 21 +JERRY_DEBUGGER_MEMSTATS_RECEIVE = 14 +JERRY_DEBUGGER_BREAKPOINT_HIT = 15 +JERRY_DEBUGGER_EXCEPTION_HIT = 16 +JERRY_DEBUGGER_BACKTRACE = 17 +JERRY_DEBUGGER_BACKTRACE_END = 18 +JERRY_DEBUGGER_EVAL_RESULT = 19 +JERRY_DEBUGGER_EVAL_RESULT_END = 20 +JERRY_DEBUGGER_EVAL_ERROR = 21 +JERRY_DEBUGGER_EVAL_ERROR_END = 22 # Messages sent by the client to server. JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1 JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2 JERRY_DEBUGGER_EXCEPTION_CONFIG = 3 -JERRY_DEBUGGER_STOP = 4 -JERRY_DEBUGGER_CONTINUE = 5 -JERRY_DEBUGGER_STEP = 6 -JERRY_DEBUGGER_NEXT = 7 -JERRY_DEBUGGER_GET_BACKTRACE = 8 -JERRY_DEBUGGER_EVAL = 9 -JERRY_DEBUGGER_EVAL_PART = 10 +JERRY_DEBUGGER_MEMSTATS = 4 +JERRY_DEBUGGER_STOP = 5 +JERRY_DEBUGGER_CONTINUE = 6 +JERRY_DEBUGGER_STEP = 7 +JERRY_DEBUGGER_NEXT = 8 +JERRY_DEBUGGER_GET_BACKTRACE = 9 +JERRY_DEBUGGER_EVAL = 10 +JERRY_DEBUGGER_EVAL_PART = 11 MAX_BUFFER_SIZE = 128 WEBSOCKET_BINARY_FRAME = 2 @@ -389,6 +391,12 @@ class DebuggerPrompt(Cmd): self.debugger.send_exception_config(enable) + def do_memstats(self, args): + """ Memory statistics """ + self.exec_command(args, JERRY_DEBUGGER_MEMSTATS); + return + + do_ms = do_memstats class Multimap(object): @@ -932,6 +940,19 @@ def main(): prompt.cmdloop() + elif buffer_type == JERRY_DEBUGGER_MEMSTATS_RECEIVE: + + memory_stats = struct.unpack(debugger.byte_order + debugger.idx_format *5, + data[3: 3 + 4 *5]) + + print("Allocated bytes: %d" % (memory_stats[0])) + print("Byte code bytes: %d" % (memory_stats[1])) + print("String bytes: %d" % (memory_stats[2])) + print("Object bytes: %d" % (memory_stats[3])) + print("Property bytes: %d" % (memory_stats[4])) + + prompt.cmdloop() + else: raise Exception("Unknown message") diff --git a/tests/debugger/do_help.expected b/tests/debugger/do_help.expected index 340a79005..5ac4677ec 100644 --- a/tests/debugger/do_help.expected +++ b/tests/debugger/do_help.expected @@ -4,8 +4,8 @@ Stopped at tests/debugger/do_help.js:15 Documented commands (type help ): ======================================== -b bt delete eval help next s -backtrace c dump exception list pendingdel src -break continue e fbreak n quit step +b bt delete eval help ms pendingdel src +backtrace c dump exception list n quit step +break continue e fbreak memstats next s (jerry-debugger) quit