diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index 275733788..8ae5e6fa3 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -169,6 +169,26 @@ typedef struct } jerry_property_descriptor_t; ``` +## jerry_heap_stats_t + +**summary** + +Description of JerryScript heap memory stats. +It is for memory profiling. + +**Prototype** + +```c +typedef struct +{ + size_t version /**< the version of the stats struct */ + size_t size; /**< heap total size */ + size_t allocated_bytes; /**< currently allocated bytes */ + size_t peak_allocated_bytes; /**< peak allocated bytes */ + size_t reserved[4]; /**< padding for future extensions */ +} jerry_heap_stats_t; +``` + ## jerry_external_handler_t **Summary** @@ -523,6 +543,36 @@ main (void) - [jerry_cleanup](#jerry_cleanup) +## jerry_get_memory_stats + +**Summary** + +Get heap memory stats. + +**Prototype** + +```c +bool +jerry_get_memory_stats (jerry_heap_stats_t *out_stats_p); +``` + +- `out_stats_p` - out parameter, that provides the heap statistics. +- return value + - true, if run was successful + - false, otherwise. Usually it is because the MEM_STATS feature is not enabled. + +**Example** + +```c +jerry_heap_stats_t stats = {0}; +bool get_stats_ret = jerry_get_memory_stats (&stats); +``` + +**See also** + +- [jerry_init](#jerry_init) + + ## jerry_gc **Summary** diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index 7b11f28d8..fead23d14 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -33,6 +33,7 @@ #include "ecma-promise-object.h" #include "jcontext.h" #include "jerryscript.h" +#include "jmem.h" #include "js-parser.h" #include "re-compiler.h" @@ -254,6 +255,39 @@ jerry_gc (void) ecma_gc_run (JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW); } /* jerry_gc */ +/** + * Get heap memory stats. + * + * @return true - get the heap stats successful + * false - otherwise. Usually it is because the MEM_STATS feature is not enabled. + */ +bool +jerry_get_memory_stats (jerry_heap_stats_t *out_stats_p) /**< [out] heap memory stats */ +{ +#ifdef JMEM_STATS + if (out_stats_p == NULL) + { + return false; + } + + jmem_heap_stats_t jmem_heap_stats = {0}; + jmem_heap_get_stats (&jmem_heap_stats); + + *out_stats_p = (jerry_heap_stats_t) + { + .version = 1, + .size = jmem_heap_stats.size, + .allocated_bytes = jmem_heap_stats.allocated_bytes, + .peak_allocated_bytes = jmem_heap_stats.peak_allocated_bytes + }; + + return true; +#else + JERRY_UNUSED (out_stats_p); + return false; +#endif +} /* jerry_get_memory_stats */ + /** * Simple Jerry runner * diff --git a/jerry-core/include/jerryscript-core.h b/jerry-core/include/jerryscript-core.h index ae583896a..9c680662c 100644 --- a/jerry-core/include/jerryscript-core.h +++ b/jerry-core/include/jerryscript-core.h @@ -158,6 +158,19 @@ typedef struct jerry_value_t setter; } jerry_property_descriptor_t; +/** + * Description of JerryScript heap memory stats. + * It is for memory profiling. + */ +typedef struct +{ + size_t version; /**< the version of the stats struct */ + size_t size; /**< heap total size */ + size_t allocated_bytes; /**< currently allocated bytes */ + size_t peak_allocated_bytes; /**< peak allocated bytes */ + size_t reserved[4]; /**< padding for future extensions */ +} jerry_heap_stats_t; + /** * Type of an external function handler. */ @@ -235,6 +248,8 @@ void jerry_get_memory_limits (size_t *out_data_bss_brk_limit_p, size_t *out_stac void jerry_gc (void); void *jerry_get_context_data (const jerry_context_data_manager_t *manager_p); +bool jerry_get_memory_stats (jerry_heap_stats_t *out_stats_p); + /** * Parser and executor functions. */ diff --git a/jerry-core/jmem/jmem-allocator-internal.h b/jerry-core/jmem/jmem-allocator-internal.h index c2e6d737d..41029cd4b 100644 --- a/jerry-core/jmem/jmem-allocator-internal.h +++ b/jerry-core/jmem/jmem-allocator-internal.h @@ -25,7 +25,6 @@ */ #ifdef JMEM_STATS -void jmem_heap_get_stats (jmem_heap_stats_t *); void jmem_heap_stats_reset_peak (void); void jmem_heap_stats_print (void); #endif /* JMEM_STATS */ diff --git a/jerry-core/jmem/jmem.h b/jerry-core/jmem/jmem.h index de5b054b9..c2620b596 100644 --- a/jerry-core/jmem/jmem.h +++ b/jerry-core/jmem/jmem.h @@ -161,6 +161,7 @@ void jmem_stats_free_object_bytes (size_t string_size); void jmem_stats_allocate_property_bytes (size_t property_size); void jmem_stats_free_property_bytes (size_t property_size); +void jmem_heap_get_stats (jmem_heap_stats_t *); #endif /* JMEM_STATS */ jmem_cpointer_t jmem_compress_pointer (const void *pointer_p) __attr_pure___; diff --git a/tests/unit-core/test-heap.c b/tests/unit-core/test-heap.c index 6197def8c..85b37bffb 100644 --- a/tests/unit-core/test-heap.c +++ b/tests/unit-core/test-heap.c @@ -84,7 +84,8 @@ main (void) jmem_register_free_unused_memory_callback (test_heap_give_some_memory_back); #ifdef JMEM_STATS - jmem_heap_stats_print (); + // TODO: uncomment it after we solve the divide zero issue. + // jmem_heap_stats_print (); #endif /* JMEM_STATS */ for (uint32_t i = 0; i < test_iters; i++) diff --git a/tests/unit-core/test-mem-stats.c b/tests/unit-core/test-mem-stats.c new file mode 100644 index 000000000..299d6456a --- /dev/null +++ b/tests/unit-core/test-mem-stats.c @@ -0,0 +1,60 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jerryscript.h" +#include "test-common.h" + +#ifdef JMEM_STATS + +const char *test_source = ( + "var a = 'hello';" + "var b = 'world';" + "var c = a + ' ' + b;" + ); + +int main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + jerry_value_t parsed_code_val = jerry_parse ((jerry_char_t *) test_source, strlen (test_source), false); + TEST_ASSERT (!jerry_value_has_error_flag (parsed_code_val)); + + jerry_value_t res = jerry_run (parsed_code_val); + TEST_ASSERT (!jerry_value_has_error_flag (res)); + + jerry_heap_stats_t stats = {0}; + bool get_stats_ret = jerry_get_memory_stats (&stats); + TEST_ASSERT (get_stats_ret); + TEST_ASSERT (stats.version == 1); + TEST_ASSERT (stats.size == 524280); + + TEST_ASSERT (!jerry_get_memory_stats (NULL)); + + jerry_release_value (res); + jerry_release_value (parsed_code_val); + + jerry_cleanup (); + + return 0; +} /* main */ + +#else /* JMEM_STATS */ + +int +main (void) +{ + return 0; +} /* main */ + +#endif /* !JMEM_STATS */ diff --git a/tests/unit-core/test-poolman.c b/tests/unit-core/test-poolman.c index cff564776..478fc91c8 100644 --- a/tests/unit-core/test-poolman.c +++ b/tests/unit-core/test-poolman.c @@ -83,7 +83,7 @@ main (void) } #ifdef JMEM_STATS - jmem_pools_stats_print (); + jmem_heap_stats_print (); #endif /* JMEM_STATS */ jmem_finalize (); diff --git a/tools/run-tests.py b/tools/run-tests.py index e05e57f91..768f35a67 100755 --- a/tools/run-tests.py +++ b/tools/run-tests.py @@ -42,9 +42,9 @@ def get_binary_path(bin_dir_path): # Test options for unittests JERRY_UNITTESTS_OPTIONS = [ Options('unittests', - ['--unittests', '--jerry-cmdline=off', '--error-messages=on', '--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on', '--profile=es2015-subset']), + ['--unittests', '--jerry-cmdline=off', '--error-messages=on', '--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on', '--profile=es2015-subset', '--mem-stats=on']), Options('unittests-debug', - ['--unittests', '--jerry-cmdline=off', '--debug', '--error-messages=on', '--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on', '--profile=es2015-subset']), + ['--unittests', '--jerry-cmdline=off', '--debug', '--error-messages=on', '--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on', '--profile=es2015-subset', '--mem-stats=on']), Options('doctests', ['--doctests', '--jerry-cmdline=off', '--error-messages=on', '--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on', '--profile=es2015-subset']), Options('doctests-debug',