diff --git a/src/liballocator/mem-allocator.c b/src/liballocator/mem-allocator.c index e030c3f4f..2484c51c2 100644 --- a/src/liballocator/mem-allocator.c +++ b/src/liballocator/mem-allocator.c @@ -38,15 +38,32 @@ JERRY_STATIC_ASSERT( MEM_HEAP_AREA_SIZE <= 64 * 1024 ); void mem_init( void) { - mem_heap_init( mem_heap_area, sizeof (mem_heap_area)); - mem_pools_init(); + mem_heap_init( mem_heap_area, sizeof (mem_heap_area)); + mem_pools_init(); } /* mem_init */ +/** + * Finalize memory allocators. + */ +void +mem_finalize( bool is_show_mem_stats) /**< show heap memory stats + before finalization? */ +{ + mem_pools_finalize(); + + if (is_show_mem_stats) + { + mem_heap_print( false, false, true); + } + + mem_heap_finalize(); +} /* mem_finalize */ + /** * Get base pointer for allocation area. */ uintptr_t mem_get_base_pointer( void) { - return (uintptr_t) mem_heap_area; + return (uintptr_t) mem_heap_area; } /* mem_get_base_pointer */ diff --git a/src/liballocator/mem-allocator.h b/src/liballocator/mem-allocator.h index beffca8f2..9d2bbdf22 100644 --- a/src/liballocator/mem-allocator.h +++ b/src/liballocator/mem-allocator.h @@ -37,6 +37,7 @@ #define MEM_ALIGNMENT (1 << MEM_ALIGNMENT_LOG) extern void mem_init(void); +extern void mem_finalize(bool is_show_mem_stats); uintptr_t mem_get_base_pointer(void); #endif /* !JERRY_MEM_ALLOCATOR_H */ diff --git a/src/liballocator/mem-heap.c b/src/liballocator/mem-heap.c index 312d599af..e69bc084f 100644 --- a/src/liballocator/mem-heap.c +++ b/src/liballocator/mem-heap.c @@ -40,14 +40,14 @@ # define VALGRIND_DEFINED_STRUCT( s) (void)VALGRIND_MAKE_MEM_DEFINED( ( s ), sizeof( *( s ) ) ) # define VALGRIND_NOACCESS_SPACE( p, s) (void)VALGRIND_MAKE_MEM_NOACCESS( ( p ), ( s ) ) # define VALGRIND_UNDEFINED_SPACE( p, s) (void)VALGRIND_MAKE_MEM_UNDEFINED( ( p ), ( s ) ) -# define VALGRIND_DEFINED_SPACET( p, s) (void)VALGRIND_MAKE_MEM_DEFINED( ( p ), ( s ) ) +# define VALGRIND_DEFINED_SPACE( p, s) (void)VALGRIND_MAKE_MEM_DEFINED( ( p ), ( s ) ) #else /* !JERRRY_NVALGRIND */ # define VALGRIND_NOACCESS_STRUCT( s) # define VALGRIND_UNDEFINED_STRUCT( s) # define VALGRIND_DEFINED_STRUCT( s) # define VALGRIND_NOACCESS_SPACE( p, s) # define VALGRIND_UNDEFINED_SPACE( p, s) -# define VALGRIND_DEFINED_SPACET( p, s) +# define VALGRIND_DEFINED_SPACE( p, s) #endif /* !JERRY_NVALGRIND */ /** @@ -225,6 +225,22 @@ mem_heap_init(uint8_t *heap_start, /**< first address of heap space */ mem_heap_stat_init(); } /* mem_heap_init */ +/** + * Finalize heap + */ +void +mem_heap_finalize(void) +{ + VALGRIND_DEFINED_SPACE( mem_heap.heap_start, mem_heap.heap_size); + + JERRY_ASSERT( mem_heap.first_block_p == mem_heap.last_block_p ); + JERRY_ASSERT( mem_heap.first_block_p->magic_num == MEM_MAGIC_NUM_OF_FREE_BLOCK ); + + VALGRIND_NOACCESS_SPACE( mem_heap.heap_start, mem_heap.heap_size); + + __memset( &mem_heap, 0, sizeof(mem_heap)); +} /* mem_heap_finalize */ + /** * Initialize block header */ diff --git a/src/liballocator/mem-heap.h b/src/liballocator/mem-heap.h index 08d1a5016..59d6ae91f 100644 --- a/src/liballocator/mem-heap.h +++ b/src/liballocator/mem-heap.h @@ -39,6 +39,7 @@ typedef enum { } mem_heap_alloc_term_t; extern void mem_heap_init(uint8_t *heap_start, size_t heap_size); +extern void mem_heap_finalize(void); extern uint8_t* mem_heap_alloc_block(size_t size_in_bytes, mem_heap_alloc_term_t alloc_term); extern void mem_heap_free_block(uint8_t *ptr); extern size_t mem_heap_recommend_allocation_size(size_t minimum_allocation_size); diff --git a/src/liballocator/mem-poolman.c b/src/liballocator/mem-poolman.c index edb27b716..d5a0b4f06 100644 --- a/src/liballocator/mem-poolman.c +++ b/src/liballocator/mem-poolman.c @@ -122,6 +122,26 @@ mem_pools_init(void) mem_pools_stat_init(); } /* mem_pools_init */ +/** + * Finalize pool manager + */ +void +mem_pools_finalize(void) +{ + for ( uint32_t i = 0; i < MEM_POOL_CHUNK_TYPE__COUNT; i++ ) + { + JERRY_ASSERT( mem_pools[ i ] == NULL ); + JERRY_ASSERT( mem_free_chunks_number[ i ] == 0 ); + } + + JERRY_ASSERT( mem_pool_for_pool_headers.chunks_number == mem_pool_for_pool_headers.free_chunks_number ); + + __memset( &mem_pool_for_pool_headers, 0, sizeof(mem_pool_for_pool_headers)); + + mem_heap_free_block( mem_space_for_pool_for_pool_headers); + mem_space_for_pool_for_pool_headers = NULL; +} /* mem_pools_finalize */ + /** * Allocate a chunk of specified size * diff --git a/src/liballocator/mem-poolman.h b/src/liballocator/mem-poolman.h index d02554f0b..45cd685f1 100644 --- a/src/liballocator/mem-poolman.h +++ b/src/liballocator/mem-poolman.h @@ -54,6 +54,7 @@ typedef enum { extern size_t mem_get_chunk_size( mem_pool_chunk_type_t chunk_type); extern void mem_pools_init(void); +extern void mem_pools_finalize(void); extern uint8_t* mem_pools_alloc(mem_pool_chunk_type_t chunk_type); extern void mem_pools_free(mem_pool_chunk_type_t chunk_type, uint8_t *chunk_p); diff --git a/src/libcoreint/interpreter.c b/src/libcoreint/interpreter.c index d886483e7..023d31ad5 100644 --- a/src/libcoreint/interpreter.c +++ b/src/libcoreint/interpreter.c @@ -14,9 +14,11 @@ */ #include "deserializer.h" +#include "ecma-gc.h" #include "ecma-globals.h" #include "ecma-helpers.h" #include "ecma-lex-env.h" +#include "ecma-operations.h" #include "globals.h" #include "interpreter.h" #include "jerry-libc.h" @@ -66,6 +68,10 @@ run_int (void) } case ECMA_COMPLETION_TYPE_EXIT: { + ecma_deref_object( lex_env_p); + ecma_finalize(); + ecma_gc_run( ECMA_GC_GEN_COUNT - 1); + return ecma_is_value_true( completion.value); } case ECMA_COMPLETION_TYPE_BREAK: diff --git a/src/libecmaoperations/ecma-finalize.c b/src/libecmaoperations/ecma-finalize.c new file mode 100644 index 000000000..d017bd22f --- /dev/null +++ b/src/libecmaoperations/ecma-finalize.c @@ -0,0 +1,28 @@ +/* Copyright 2014 Samsung Electronics Co., Ltd. + * + * 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 "ecma-operations.h" +#include "ecma-globals.h" +#include "ecma-global-object.h" +#include "globals.h" + +/** + * ECMA object model finalization routine + */ +void +ecma_finalize(void) +{ + ecma_finalize_global_object(); +} /* ecma_finalize */ diff --git a/src/libecmaoperations/ecma-global-object.c b/src/libecmaoperations/ecma-global-object.c index 2275c478e..c39f255ff 100644 --- a/src/libecmaoperations/ecma-global-object.c +++ b/src/libecmaoperations/ecma-global-object.c @@ -77,6 +77,19 @@ ecma_op_create_global_object( void) return glob_obj_p; } /* ecma_op_create_global_object */ +/** + * Remove global reference to the global object. + * + * Warning: + * the routine should be called only from ecma_finalize + */ +void +ecma_finalize_global_object(void) +{ + ecma_deref_object( ecma_global_object_p); + ecma_global_object_p = NULL; +} /* ecma_free_global_object */ + /** * @} * @} diff --git a/src/libecmaoperations/ecma-global-object.h b/src/libecmaoperations/ecma-global-object.h index d0c2cdd61..901ad2121 100644 --- a/src/libecmaoperations/ecma-global-object.h +++ b/src/libecmaoperations/ecma-global-object.h @@ -27,6 +27,7 @@ extern ecma_object_t* ecma_get_global_object(void); extern ecma_object_t* ecma_op_create_global_object( void); +extern void ecma_finalize_global_object( void); /** * @} diff --git a/src/libecmaoperations/ecma-lex-env.c b/src/libecmaoperations/ecma-lex-env.c index d9dcc9aff..f09cf5aef 100644 --- a/src/libecmaoperations/ecma-lex-env.c +++ b/src/libecmaoperations/ecma-lex-env.c @@ -492,6 +492,8 @@ ecma_op_create_global_environment( void) ecma_object_t *glob_env_p = ecma_create_object_lex_env( NULL, glob_obj_p, false); + ecma_deref_object( glob_obj_p); + return glob_env_p; } /* ecma_op_create_global_environment */ diff --git a/src/libecmaoperations/ecma-operations.h b/src/libecmaoperations/ecma-operations.h index f480d1f00..0745f06ad 100644 --- a/src/libecmaoperations/ecma-operations.h +++ b/src/libecmaoperations/ecma-operations.h @@ -32,6 +32,8 @@ extern ecma_reference_t ecma_op_get_identifier_reference( ecma_object_t *lex_env extern ecma_completion_value_t ecma_op_get_value( ecma_reference_t ref); extern ecma_completion_value_t ecma_op_put_value( ecma_reference_t ref, ecma_value_t value); +extern void ecma_finalize( void); + /** * @} * @} diff --git a/src/liboptimizer/bytecode-data.h b/src/liboptimizer/bytecode-data.h index 2c7a4c653..37f9f1b01 100644 --- a/src/liboptimizer/bytecode-data.h +++ b/src/liboptimizer/bytecode-data.h @@ -31,7 +31,7 @@ U8 nums_count; U32 nums[nums_count]; } */ -uint8_t *bytecode_data; +extern uint8_t *bytecode_data; OPCODE bytecode_opcodes[MAX_OPCODES]; -#endif // BYTECODE_LINUX_H \ No newline at end of file +#endif // BYTECODE_LINUX_H diff --git a/src/liboptimizer/serializer.c b/src/liboptimizer/serializer.c index e3ef9feeb..731238808 100644 --- a/src/liboptimizer/serializer.c +++ b/src/liboptimizer/serializer.c @@ -22,6 +22,8 @@ static bool print_opcodes; +uint8_t *bytecode_data = NULL; + void serializer_init (bool show_opcodes) { @@ -142,3 +144,10 @@ serializer_print_opcodes (void) pp_opcode (loc, bytecode_opcodes[loc], false); } } + +void +serializer_free (void) +{ + mem_heap_free_block( bytecode_data); + bytecode_data = NULL; +} diff --git a/src/liboptimizer/serializer.h b/src/liboptimizer/serializer.h index 624016c2b..efb4f938b 100644 --- a/src/liboptimizer/serializer.h +++ b/src/liboptimizer/serializer.h @@ -32,4 +32,6 @@ void serializer_rewrite_opcode (const opcode_counter_t, OPCODE); void serializer_print_opcodes (void); +void serializer_free(void); + #endif // SERIALIZER_H diff --git a/src/main.c b/src/main.c index 5af6f3d43..1d553cbf9 100644 --- a/src/main.c +++ b/src/main.c @@ -68,9 +68,9 @@ parser_run (const char *script_source, size_t script_source_size, bool is_show_o return opcodes; } -static int -jerry_run (const char *script_source, size_t script_source_size, bool is_parse_only, - bool is_show_opcodes) +static bool +jerry_run (const char *script_source, size_t script_source_size, + bool is_parse_only, bool is_show_opcodes, bool is_show_mem_stats) { const OPCODE *opcodes; @@ -82,12 +82,18 @@ jerry_run (const char *script_source, size_t script_source_size, bool is_parse_o if (is_parse_only) { - return 0; + return true; } init_int (opcodes); - return run_int () ? 0 : 1; + bool is_success = run_int (); + + serializer_free(); + + mem_finalize( is_show_mem_stats); + + return is_success; } /* jerry_run */ #ifdef __TARGET_HOST_x64 @@ -199,14 +205,9 @@ main (int argc __unused, size_t source_size; const char *source_p = read_sources (file_names, files_counter, &source_size); - int ret = jerry_run (source_p, source_size, parse_only, show_opcodes); + bool is_success = jerry_run (source_p, source_size, parse_only, show_opcodes, print_mem_stats); - if (print_mem_stats) - { - mem_heap_print( false, false, true); - } - - return ret; + return is_success ? 0 : 1; } #endif @@ -229,7 +230,7 @@ main (void) set_sys_tick_counter ((uint32_t) - 1); start = get_sys_tick_counter (); jerry_run (source_p, - source_size, false, false); + source_size, false, false, false); finish_parse_ms = (start - get_sys_tick_counter ()) / 1000; } #endif