diff --git a/CMakeLists.txt b/CMakeLists.txt index 34383ad7fa..03fc892b5b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ project (Jerry C ASM) string(TOUPPER "${PLATFORM}" PLATFORM) # Compiler configuration - if(NOT ("${PLATFORM}" STREQUAL "DARWIN")) + if(NOT (("${PLATFORM}" STREQUAL "DARWIN") OR ("${PLATFORM}" STREQUAL "EXTERNAL"))) if(NOT CMAKE_COMPILER_IS_GNUCC) message(FATAL_ERROR "gcc compiler is required") endif() @@ -131,6 +131,15 @@ project (Jerry C ASM) set(INCLUDE_LIBC_INTERFACE ${EXTERNAL_LIBC_INTERFACE}) endif() + + # Should we use external jerry-port.c? + if(DEFINED EXTERNAL_PORT_FILE AND NOT EXTERNAL_PORT_FILE STREQUAL "UNDEFINED") + set(SOURCE_PORT_IMPLEMENTATION ${EXTERNAL_PORT_FILE}) + set(USE_DEFAULT_PORT FALSE) + else() + set(USE_DEFAULT_PORT TRUE) + endif() + # Are there any interfaces for external libraries, other than libc, that should be registered? if(DEFINED EXTERNAL_LIBS_INTERFACE AND NOT EXTERNAL_LIBS_INTERFACE STREQUAL "UNDEFINED") set(INCLUDE_EXTERNAL_LIBS_INTERFACE ) diff --git a/build/configs/toolchain_external.cmake b/build/configs/toolchain_external.cmake index 30f004d71c..9eea941e10 100644 --- a/build/configs/toolchain_external.cmake +++ b/build/configs/toolchain_external.cmake @@ -17,4 +17,4 @@ include(CMakeForceCompiler) set(CMAKE_SYSTEM_NAME EXTERNAL) set(CMAKE_SYSTEM_PROCESSOR "${EXTERNAL_CMAKE_SYSTEM_PROCESSOR}") -CMAKE_FORCE_C_COMPILER(${EXTERNAL_CMAKE_C_COMPILER} GNU) +CMAKE_FORCE_C_COMPILER(${EXTERNAL_CMAKE_C_COMPILER} ${EXTERNAL_CMAKE_C_COMPILER_FAMILY}) diff --git a/jerry-core/CMakeLists.txt b/jerry-core/CMakeLists.txt index a500393d43..0c8aec78c4 100644 --- a/jerry-core/CMakeLists.txt +++ b/jerry-core/CMakeLists.txt @@ -147,6 +147,13 @@ project (JerryCore C ASM) ${SOURCE_CORE_PARSER_REGEXP} ${SOURCE_CORE_JRT}) + # Jerry port + if(USE_DEFAULT_PORT) + file(GLOB SOURCE_PORT_FILES ${CMAKE_SOURCE_DIR}/targets/default/*.c) + else() + set(SOURCE_PORT_FILES ${SOURCE_PORT_IMPLEMENTATION}) + endif() + # All-in-one build if("${ENABLE_ALL_IN_ONE}" STREQUAL "ON") set(ALL_IN_FILE "${CMAKE_BINARY_DIR}/jerry-all-in.c") @@ -157,9 +164,13 @@ project (JerryCore C ASM) file(APPEND ${ALL_IN_FILE} "#include \"${FILE}\"\n") endforeach() + foreach(FILE ${SOURCE_PORT_FILES}) + file(APPEND ${ALL_IN_FILE} "#include \"${FILE}\"\n") + endforeach() + set(SOURCE_CORE ${ALL_IN_FILE}) else() - set(SOURCE_CORE ${SOURCE_CORE_FILES}) + set(SOURCE_CORE ${SOURCE_CORE_FILES} ${SOURCE_PORT_FILES}) endif() # Per-option configuration diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-global.c b/jerry-core/ecma/builtin-objects/ecma-builtin-global.c index 95fbe8f3be..59c506d28b 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-global.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-global.c @@ -100,31 +100,32 @@ ecma_builtin_global_object_print (ecma_value_t this_arg __attr_unused___, /**< t if (code_point == LIT_CHAR_NULL) { - printf ("\\u0000"); + jerry_port_putchar ('\0'); } else if (code_point <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) { - printf ("%c", (char) code_point); + jerry_port_putchar ((char) code_point); } else { JERRY_STATIC_ASSERT (sizeof (code_point) == 2, size_of_code_point_must_be_equal_to_2_bytes); - uint32_t byte_high = (uint32_t) JRT_EXTRACT_BIT_FIELD (ecma_char_t, code_point, + uint8_t byte_high = (uint8_t) JRT_EXTRACT_BIT_FIELD (ecma_char_t, code_point, JERRY_BITSINBYTE, JERRY_BITSINBYTE); - uint32_t byte_low = (uint32_t) JRT_EXTRACT_BIT_FIELD (ecma_char_t, code_point, + uint8_t byte_low = (uint8_t) JRT_EXTRACT_BIT_FIELD (ecma_char_t, code_point, 0, JERRY_BITSINBYTE); - printf ("\\u%02x%02x", byte_high, byte_low); + jerry_port_putchar (byte_high); + jerry_port_putchar (byte_low); } } if (arg_index < args_number - 1) { - printf (" "); + jerry_port_putchar (' '); } MEM_FINALIZE_LOCAL_ARRAY (utf8_str_p); @@ -132,7 +133,7 @@ ecma_builtin_global_object_print (ecma_value_t this_arg __attr_unused___, /**< t ECMA_FINALIZE (str_value); } - printf ("\n"); + jerry_port_putchar ('\n'); if (ecma_is_value_empty (ret_value)) { diff --git a/jerry-core/jerry-port.h b/jerry-core/jerry-port.h index 5de51909b3..069f322b93 100644 --- a/jerry-core/jerry-port.h +++ b/jerry-core/jerry-port.h @@ -24,6 +24,12 @@ extern "C" { #endif /* !__cplusplus */ +/** + * Forward definition of heap data structure + */ +struct mem_heap; +typedef struct mem_heap mem_heap_t; + /** \addtogroup jerry_port Jerry engine port * @{ */ @@ -35,6 +41,18 @@ int jerry_port_logmsg (FILE *stream, const char *format, ...); int jerry_port_errormsg (const char *format, ...); int jerry_port_putchar (int c); +void jerry_port_abort (void); + + +/** + * Target port functions for memory management + */ +mem_heap_t *jerry_port_init_heap (void); + +void jerry_port_finalize_heap (mem_heap_t *mem_heap); + +mem_heap_t *jerry_port_get_heap (void); + /** * @} */ diff --git a/jerry-core/jerry.c b/jerry-core/jerry.c index 443fcf8d4a..5c43fbf6dc 100644 --- a/jerry-core/jerry.c +++ b/jerry-core/jerry.c @@ -2444,15 +2444,3 @@ jerry_api_get_string_size (const jerry_api_string_t *str_p) /**< input string */ return ecma_string_get_size ((ecma_string_t *) str_p); } /* jerry_api_get_string_size */ -/** - * Get length of Jerry string - * - * @return number of characters in the string - */ -jerry_api_length_t -jerry_api_get_string_length (const jerry_api_string_t *str_p) /**< input string */ -{ - jerry_assert_api_available (); - - return ecma_string_get_length ((ecma_string_t *) str_p); -} /* jerry_api_get_string_length */ diff --git a/jerry-core/jrt/jrt-fatals.c b/jerry-core/jrt/jrt-fatals.c index 498df0c47d..8523c9dbfc 100644 --- a/jerry-core/jrt/jrt-fatals.c +++ b/jerry-core/jrt/jrt-fatals.c @@ -33,13 +33,13 @@ void __noreturn jerry_fatal (jerry_fatal_code_t code) /**< status code */ { #ifndef JERRY_NDEBUG - printf ("Error: "); + jerry_port_errormsg ("Error: "); switch (code) { case ERR_OUT_OF_MEMORY: { - printf ("ERR_OUT_OF_MEMORY\n"); + jerry_port_errormsg ("ERR_OUT_OF_MEMORY\n"); break; } case ERR_SYSCALL: @@ -54,12 +54,12 @@ jerry_fatal (jerry_fatal_code_t code) /**< status code */ } case ERR_UNIMPLEMENTED_CASE: { - printf ("ERR_UNIMPLEMENTED_CASE\n"); + jerry_port_errormsg ("ERR_UNIMPLEMENTED_CASE\n"); break; } case ERR_FAILED_INTERNAL_ASSERTION: { - printf ("ERR_FAILED_INTERNAL_ASSERTION\n"); + jerry_port_errormsg ("ERR_FAILED_INTERNAL_ASSERTION\n"); break; } } @@ -69,7 +69,7 @@ jerry_fatal (jerry_fatal_code_t code) /**< status code */ && code != ERR_OUT_OF_MEMORY && jerry_is_abort_on_fail ()) { - abort (); + jerry_port_abort (); } else { @@ -92,7 +92,7 @@ jerry_assert_fail (const char *assertion, /**< assertion condition string */ const uint32_t line) /**< line */ { #if !defined (JERRY_NDEBUG) || !defined (JERRY_DISABLE_HEAVY_DEBUG) - printf ("ICE: Assertion '%s' failed at %s(%s):%lu.\n", + jerry_port_errormsg ("ICE: Assertion '%s' failed at %s(%s):%lu.\n", assertion, file, function, (unsigned long) line); #else /* !JERRY_NDEBUG || !JERRY_DISABLE_HEAVY_DEBUG */ (void) assertion; @@ -115,7 +115,8 @@ jerry_unreachable (const char *comment, /**< comment to unreachable mark if exis const uint32_t line) /**< line */ { #ifndef JERRY_NDEBUG - printf ("ICE: Unreachable control path at %s(%s):%lu was executed", file, function, (unsigned long) line); + jerry_port_errormsg ("ICE: Unreachable control path at %s(%s):%lu was executed", + file, function, (unsigned long) line); #else /* !JERRY_NDEBUG */ (void) file; (void) function; @@ -124,9 +125,9 @@ jerry_unreachable (const char *comment, /**< comment to unreachable mark if exis if (comment != NULL) { - printf ("(%s)", comment); + jerry_port_errormsg ("(%s)", comment); } - printf (".\n"); + jerry_port_errormsg (".\n"); jerry_fatal (ERR_FAILED_INTERNAL_ASSERTION); } /* jerry_unreachable */ @@ -142,7 +143,7 @@ jerry_unimplemented (const char *comment, /**< comment to unimplemented mark if const uint32_t line) /**< line */ { #ifndef JERRY_NDEBUG - printf ("SORRY: Unimplemented case at %s(%s):%lu was executed", file, function, (unsigned long) line); + jerry_port_errormsg ("SORRY: Unimplemented case at %s(%s):%lu was executed", file, function, (unsigned long) line); #else /* !JERRY_NDEBUG */ (void) file; (void) function; @@ -151,9 +152,9 @@ jerry_unimplemented (const char *comment, /**< comment to unimplemented mark if if (comment != NULL) { - printf ("(%s)", comment); + jerry_port_errormsg ("(%s)", comment); } - printf (".\n"); + jerry_port_errormsg (".\n"); jerry_fatal (ERR_UNIMPLEMENTED_CASE); } /* jerry_unimplemented */ diff --git a/jerry-core/mem/mem-heap-internal.h b/jerry-core/mem/mem-heap-internal.h new file mode 100644 index 0000000000..d5e4f2df55 --- /dev/null +++ b/jerry-core/mem/mem-heap-internal.h @@ -0,0 +1,81 @@ +/* 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. + */ + +#ifndef MEM_HEAP_INTERNAL_H +#define MEM_HEAP_INTERNAL_H + +#ifndef MEM_HEAP_INTERNAL +# error "The header is for internal routines of memory heap component. Please, don't use the routines directly." +#endif /* !MEM_HEAP_INTERNAL */ + +#include "mem-allocator.h" +#include "mem-config.h" + +/** \addtogroup mem Memory allocation + * @{ + */ + +/* Calculate heap area size, leaving space for a pointer to the free list */ +#define MEM_HEAP_AREA_SIZE (MEM_HEAP_SIZE - MEM_ALIGNMENT) +#define MEM_HEAP_END_OF_LIST ((mem_heap_free_t *const) ~((uint32_t) 0x0)) + +/** + * Free region node + */ +typedef struct +{ + uint32_t next_offset; /* Offset of next region in list */ + uint32_t size; /* Size of region */ +} mem_heap_free_t; + +#ifdef MEM_HEAP_PTR_64 +#define MEM_HEAP_GET_OFFSET_FROM_ADDR(h, p) ((uint32_t) ((uint8_t *) (p) - (uint8_t *) (h)->area)) +#define MEM_HEAP_GET_ADDR_FROM_OFFSET(h, u) ((mem_heap_free_t *) &(h)->area[u]) +#else +/* In this case we simply store the pointer, since it fits anyway. */ +#define MEM_HEAP_GET_OFFSET_FROM_ADDR(h, p) ((uint32_t) (p)) +#define MEM_HEAP_GET_ADDR_FROM_OFFSET(h, u) ((mem_heap_free_t *)(u)) +#endif + +/** + * Heap structure + */ +struct mem_heap +{ + mem_heap_free_t first; + /* This is used to speed up deallocation. */ + mem_heap_free_t *list_skip_p; + /** + * Size of allocated regions + */ + size_t allocated_size; + + /** + * Current limit of heap usage, that is upon being reached, causes call of "try give memory back" callbacks + */ + size_t limit; + + /** + * Heap area + */ + uint8_t area[MEM_HEAP_AREA_SIZE] __attribute__ ((aligned (MEM_ALIGNMENT))); +}; + + +/** + * @} + */ + +#endif /* MEM_HEAP_INTERNAL_H */ diff --git a/jerry-core/mem/mem-heap.c b/jerry-core/mem/mem-heap.c index a522b2926f..a257956f0a 100644 --- a/jerry-core/mem/mem-heap.c +++ b/jerry-core/mem/mem-heap.c @@ -33,7 +33,9 @@ #include "mem-heap.h" #define MEM_ALLOCATOR_INTERNAL +#define MEM_HEAP_INTERNAL +#include "mem-heap-internal.h" #include "mem-allocator-internal.h" /* @@ -52,6 +54,8 @@ # define VALGRIND_DEFINED_SPACE(p, s) #endif /* JERRY_VALGRIND */ +static void mem_check_heap (mem_heap_t *mem_heap); + #ifdef JERRY_VALGRIND_FREYA # include "memcheck.h" @@ -90,28 +94,6 @@ void mem_heap_valgrind_freya_mempool_request (void) # define VALGRIND_FREYA_FREELIKE_SPACE(p) #endif /* JERRY_VALGRIND_FREYA */ -/* Calculate heap area size, leaving space for a pointer to the free list */ -#define MEM_HEAP_AREA_SIZE (MEM_HEAP_SIZE - MEM_ALIGNMENT) -#define MEM_HEAP_END_OF_LIST ((mem_heap_free_t *const) ~((uint32_t) 0x0)) - -/** - * Free region node - */ -typedef struct -{ - uint32_t next_offset; /* Offset of next region in list */ - uint32_t size; /* Size of region */ -} mem_heap_free_t; - -#ifdef MEM_HEAP_PTR_64 -#define MEM_HEAP_GET_OFFSET_FROM_ADDR(p) ((uint32_t) ((uint8_t *) (p) - (uint8_t *) mem_heap.area)) -#define MEM_HEAP_GET_ADDR_FROM_OFFSET(u) ((mem_heap_free_t *) &mem_heap.area[u]) -#else -/* In this case we simply store the pointer, since it fits anyway. */ -#define MEM_HEAP_GET_OFFSET_FROM_ADDR(p) ((uint32_t) (p)) -#define MEM_HEAP_GET_ADDR_FROM_OFFSET(u) ((mem_heap_free_t *)(u)) -#endif - /** * Get end of region */ @@ -121,48 +103,6 @@ mem_heap_get_region_end (mem_heap_free_t *curr_p) /**< current region */ return (mem_heap_free_t *)((uint8_t *) curr_p + curr_p->size); } /* mem_heap_get_region_end */ -/** - * Heap structure - */ -typedef struct -{ - /** First node in free region list */ - mem_heap_free_t first; - - /** - * Heap area - */ - uint8_t area[MEM_HEAP_AREA_SIZE] __attribute__ ((aligned (MEM_ALIGNMENT))); -} mem_heap_t; - -/** - * Heap - */ -#ifndef JERRY_HEAP_SECTION_ATTR -mem_heap_t mem_heap; -#else -mem_heap_t mem_heap __attribute__ ((section (JERRY_HEAP_SECTION_ATTR))); -#endif - -/** - * Check size of heap is corresponding to configuration - */ -JERRY_STATIC_ASSERT (sizeof (mem_heap) <= MEM_HEAP_SIZE, - size_of_mem_heap_must_be_less_than_or_equal_to_MEM_HEAP_SIZE); - -/** - * Size of allocated regions - */ -size_t mem_heap_allocated_size; - -/** - * Current limit of heap usage, that is upon being reached, causes call of "try give memory back" callbacks - */ -size_t mem_heap_limit; - -/* This is used to speed up deallocation. */ -mem_heap_free_t *mem_heap_list_skip_p; - #ifdef MEM_STATS /** * Heap's memory usage statistics @@ -200,20 +140,22 @@ static void mem_heap_stat_free_iter (); void mem_heap_init (void) { - JERRY_STATIC_ASSERT ((uintptr_t) mem_heap.area % MEM_ALIGNMENT == 0, + mem_heap_t *mem_heap = jerry_port_init_heap (); + + JERRY_STATIC_ASSERT ((uintptr_t) mem_heap->area % MEM_ALIGNMENT == 0, mem_heap_area_must_be_multiple_of_MEM_ALIGNMENT); - mem_heap_allocated_size = 0; - mem_heap_limit = CONFIG_MEM_HEAP_DESIRED_LIMIT; - mem_heap.first.size = 0; - mem_heap_free_t *const region_p = (mem_heap_free_t *) mem_heap.area; - mem_heap.first.next_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (region_p); - region_p->size = sizeof (mem_heap.area); - region_p->next_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (MEM_HEAP_END_OF_LIST); + mem_heap->allocated_size = 0; + mem_heap->limit = CONFIG_MEM_HEAP_DESIRED_LIMIT; + mem_heap->first.size = 0; + mem_heap_free_t *const region_p = (mem_heap_free_t *) mem_heap->area; + mem_heap->first.next_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (mem_heap, region_p); + region_p->size = sizeof (mem_heap->area); + region_p->next_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (mem_heap, MEM_HEAP_END_OF_LIST); - mem_heap_list_skip_p = &mem_heap.first; + mem_heap->list_skip_p = &mem_heap->first; - VALGRIND_NOACCESS_SPACE (mem_heap.area, MEM_HEAP_AREA_SIZE); + VALGRIND_NOACCESS_SPACE (mem_heap->area, MEM_HEAP_AREA_SIZE); MEM_HEAP_STAT_INIT (); } /* mem_heap_init */ @@ -223,8 +165,9 @@ mem_heap_init (void) */ void mem_heap_finalize (void) { - JERRY_ASSERT (mem_heap_allocated_size == 0); - VALGRIND_NOACCESS_SPACE (&mem_heap, sizeof (mem_heap)); + mem_heap_t *mem_heap = jerry_port_get_heap (); + JERRY_ASSERT (mem_heap->allocated_size == 0); + VALGRIND_NOACCESS_SPACE (mem_heap, sizeof (*mem_heap)); } /* mem_heap_finalize */ /** @@ -243,46 +186,48 @@ void *mem_heap_alloc_block_internal (const size_t size) const size_t required_size = ((size + MEM_ALIGNMENT - 1) / MEM_ALIGNMENT) * MEM_ALIGNMENT; mem_heap_free_t *data_space_p = NULL; - VALGRIND_DEFINED_SPACE (&mem_heap.first, sizeof (mem_heap_free_t)); + mem_heap_t *mem_heap = jerry_port_get_heap (); + + VALGRIND_DEFINED_SPACE (&mem_heap->first, sizeof (mem_heap_free_t)); // Fast path for 8 byte chunks, first region is guaranteed to be sufficient if (required_size == MEM_ALIGNMENT - && likely (mem_heap.first.next_offset != MEM_HEAP_GET_OFFSET_FROM_ADDR (MEM_HEAP_END_OF_LIST))) + && likely (mem_heap->first.next_offset != MEM_HEAP_GET_OFFSET_FROM_ADDR (mem_heap, MEM_HEAP_END_OF_LIST))) { - data_space_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap.first.next_offset); + data_space_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap, mem_heap->first.next_offset); VALGRIND_DEFINED_SPACE (data_space_p, sizeof (mem_heap_free_t)); - mem_heap_allocated_size += MEM_ALIGNMENT; + mem_heap->allocated_size += MEM_ALIGNMENT; MEM_HEAP_STAT_ALLOC_ITER (); if (data_space_p->size == MEM_ALIGNMENT) { - mem_heap.first.next_offset = data_space_p->next_offset; + mem_heap->first.next_offset = data_space_p->next_offset; } else { - JERRY_ASSERT (MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap.first.next_offset)->size > MEM_ALIGNMENT); - mem_heap_free_t *const remaining_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap.first.next_offset) + 1; + JERRY_ASSERT (MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap, mem_heap->first.next_offset)->size > MEM_ALIGNMENT); + mem_heap_free_t *const remaining_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap, mem_heap->first.next_offset) + 1; VALGRIND_DEFINED_SPACE (remaining_p, sizeof (mem_heap_free_t)); remaining_p->size = data_space_p->size - MEM_ALIGNMENT; remaining_p->next_offset = data_space_p->next_offset; VALGRIND_NOACCESS_SPACE (remaining_p, sizeof (mem_heap_free_t)); - mem_heap.first.next_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (remaining_p); + mem_heap->first.next_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (mem_heap, remaining_p); } VALGRIND_UNDEFINED_SPACE (data_space_p, sizeof (mem_heap_free_t)); - if (unlikely (data_space_p == mem_heap_list_skip_p)) + if (unlikely (data_space_p == mem_heap->list_skip_p)) { - mem_heap_list_skip_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap.first.next_offset); + mem_heap->list_skip_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap, mem_heap->first.next_offset); } } // Slow path for larger regions else { - mem_heap_free_t *current_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap.first.next_offset); - mem_heap_free_t *prev_p = &mem_heap.first; + mem_heap_free_t *current_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap, mem_heap->first.next_offset); + mem_heap_free_t *prev_p = &mem_heap->first; while (current_p != MEM_HEAP_END_OF_LIST) { VALGRIND_DEFINED_SPACE (current_p, sizeof (mem_heap_free_t)); @@ -293,7 +238,7 @@ void *mem_heap_alloc_block_internal (const size_t size) { // Region is sufficiently big, store address data_space_p = current_p; - mem_heap_allocated_size += required_size; + mem_heap->allocated_size += required_size; // Region was larger than necessary if (current_p->size > required_size) @@ -309,7 +254,7 @@ void *mem_heap_alloc_block_internal (const size_t size) // Update list VALGRIND_DEFINED_SPACE (prev_p, sizeof (mem_heap_free_t)); - prev_p->next_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (remaining_p); + prev_p->next_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (mem_heap, remaining_p); VALGRIND_NOACCESS_SPACE (prev_p, sizeof (mem_heap_free_t)); } // Block is an exact fit @@ -321,7 +266,7 @@ void *mem_heap_alloc_block_internal (const size_t size) VALGRIND_NOACCESS_SPACE (prev_p, sizeof (mem_heap_free_t)); } - mem_heap_list_skip_p = prev_p; + mem_heap->list_skip_p = prev_p; // Found enough space break; @@ -330,16 +275,16 @@ void *mem_heap_alloc_block_internal (const size_t size) VALGRIND_NOACCESS_SPACE (current_p, sizeof (mem_heap_free_t)); // Next in list prev_p = current_p; - current_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (next_offset); + current_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap, next_offset); } } - while (mem_heap_allocated_size >= mem_heap_limit) + while (mem_heap->allocated_size >= mem_heap->limit) { - mem_heap_limit += CONFIG_MEM_HEAP_DESIRED_LIMIT; + mem_heap->limit += CONFIG_MEM_HEAP_DESIRED_LIMIT; } - VALGRIND_NOACCESS_SPACE (&mem_heap.first, sizeof (mem_heap_free_t)); + VALGRIND_NOACCESS_SPACE (&mem_heap->first, sizeof (mem_heap_free_t)); if (unlikely (!data_space_p)) { @@ -371,11 +316,13 @@ mem_heap_alloc_block (const size_t size) VALGRIND_FREYA_CHECK_MEMPOOL_REQUEST; + mem_heap_t *mem_heap = jerry_port_get_heap (); + #ifdef MEM_GC_BEFORE_EACH_ALLOC mem_run_try_to_give_memory_back_callbacks (MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_HIGH); #endif /* MEM_GC_BEFORE_EACH_ALLOC */ - if (mem_heap_allocated_size + size >= mem_heap_limit) + if (mem_heap->allocated_size + size >= mem_heap->limit) { mem_run_try_to_give_memory_back_callbacks (MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_LOW); } @@ -436,11 +383,12 @@ mem_heap_free_block (void *ptr, /**< pointer to beginning of data space of the b const size_t size) /**< size of allocated region */ { VALGRIND_FREYA_CHECK_MEMPOOL_REQUEST; + mem_heap_t *mem_heap = jerry_port_get_heap (); /* checking that ptr points to the heap */ - JERRY_ASSERT ((uint8_t *) ptr >= mem_heap.area && (uint8_t *) ptr <= mem_heap.area + MEM_HEAP_AREA_SIZE); + JERRY_ASSERT ((uint8_t *) ptr >= mem_heap->area && (uint8_t *) ptr <= mem_heap->area + MEM_HEAP_AREA_SIZE); JERRY_ASSERT (size > 0); - JERRY_ASSERT (mem_heap_limit >= mem_heap_allocated_size); + JERRY_ASSERT (mem_heap->limit >= mem_heap->allocated_size); VALGRIND_FREYA_FREELIKE_SPACE (ptr); VALGRIND_NOACCESS_SPACE (ptr, size); @@ -450,31 +398,31 @@ mem_heap_free_block (void *ptr, /**< pointer to beginning of data space of the b mem_heap_free_t *prev_p; mem_heap_free_t *next_p; - VALGRIND_DEFINED_SPACE (&mem_heap.first, sizeof (mem_heap_free_t)); + VALGRIND_DEFINED_SPACE (&mem_heap->first, sizeof (mem_heap_free_t)); - if (block_p > mem_heap_list_skip_p) + if (block_p > mem_heap->list_skip_p) { - prev_p = mem_heap_list_skip_p; + prev_p = mem_heap->list_skip_p; MEM_HEAP_STAT_SKIP (); } else { - prev_p = &mem_heap.first; + prev_p = &mem_heap->first; MEM_HEAP_STAT_NONSKIP (); } - const uint32_t block_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (block_p); + const uint32_t block_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (mem_heap, block_p); VALGRIND_DEFINED_SPACE (prev_p, sizeof (mem_heap_free_t)); // Find position of region in the list while (prev_p->next_offset < block_offset) { - mem_heap_free_t *const next_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (prev_p->next_offset); + mem_heap_free_t *const next_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap, prev_p->next_offset); VALGRIND_DEFINED_SPACE (next_p, sizeof (mem_heap_free_t)); VALGRIND_NOACCESS_SPACE (prev_p, sizeof (mem_heap_free_t)); prev_p = next_p; MEM_HEAP_STAT_FREE_ITER (); } - next_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (prev_p->next_offset); + next_p = MEM_HEAP_GET_ADDR_FROM_OFFSET (mem_heap, prev_p->next_offset); VALGRIND_DEFINED_SPACE (next_p, sizeof (mem_heap_free_t)); /* Realign size */ @@ -500,37 +448,36 @@ mem_heap_free_block (void *ptr, /**< pointer to beginning of data space of the b // Update next if (mem_heap_get_region_end (block_p) == next_p) { - if (unlikely (next_p == mem_heap_list_skip_p)) + if (unlikely (next_p == mem_heap->list_skip_p)) { - mem_heap_list_skip_p = block_p; + mem_heap->list_skip_p = block_p; } // Can be merged block_p->size += next_p->size; block_p->next_offset = next_p->next_offset; - } else { - block_p->next_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (next_p); + block_p->next_offset = MEM_HEAP_GET_OFFSET_FROM_ADDR (mem_heap, next_p); } - mem_heap_list_skip_p = prev_p; + mem_heap->list_skip_p = prev_p; VALGRIND_NOACCESS_SPACE (prev_p, sizeof (mem_heap_free_t)); VALGRIND_NOACCESS_SPACE (block_p, size); VALGRIND_NOACCESS_SPACE (next_p, sizeof (mem_heap_free_t)); - JERRY_ASSERT (mem_heap_allocated_size > 0); - mem_heap_allocated_size -= aligned_size; + JERRY_ASSERT (mem_heap->allocated_size > 0); + mem_heap->allocated_size -= aligned_size; - while (mem_heap_allocated_size + CONFIG_MEM_HEAP_DESIRED_LIMIT <= mem_heap_limit) + while (mem_heap->allocated_size + CONFIG_MEM_HEAP_DESIRED_LIMIT <= mem_heap->limit) { - mem_heap_limit -= CONFIG_MEM_HEAP_DESIRED_LIMIT; + mem_heap->limit -= CONFIG_MEM_HEAP_DESIRED_LIMIT; } - VALGRIND_NOACCESS_SPACE (&mem_heap.first, sizeof (mem_heap_free_t)); - JERRY_ASSERT (mem_heap_limit >= mem_heap_allocated_size); + VALGRIND_NOACCESS_SPACE (&mem_heap->first, sizeof (mem_heap_free_t)); + JERRY_ASSERT (mem_heap->limit >= mem_heap->allocated_size); MEM_HEAP_STAT_FREE (size); } /* mem_heap_free_block */ @@ -555,8 +502,9 @@ mem_heap_compress_pointer (const void *pointer_p) /**< pointer to compress */ { JERRY_ASSERT (pointer_p != NULL); + mem_heap_t *mem_heap = jerry_port_get_heap (); uintptr_t int_ptr = (uintptr_t) pointer_p; - const uintptr_t heap_start = (uintptr_t) &mem_heap; + const uintptr_t heap_start = (uintptr_t) mem_heap; JERRY_ASSERT (int_ptr % MEM_ALIGNMENT == 0); @@ -580,8 +528,9 @@ mem_heap_decompress_pointer (uintptr_t compressed_pointer) /**< pointer to decom { JERRY_ASSERT (compressed_pointer != MEM_CP_NULL); + mem_heap_t *mem_heap = jerry_port_get_heap (); uintptr_t int_ptr = compressed_pointer; - const uintptr_t heap_start = (uintptr_t) &mem_heap; + const uintptr_t heap_start = (uintptr_t) mem_heap; int_ptr <<= MEM_ALIGNMENT_LOG; int_ptr += heap_start; @@ -602,8 +551,9 @@ mem_heap_decompress_pointer (uintptr_t compressed_pointer) /**< pointer to decom bool mem_is_heap_pointer (const void *pointer) /**< pointer */ { - return ((uint8_t *) pointer >= mem_heap.area - && (uint8_t *) pointer <= ((uint8_t *) mem_heap.area + MEM_HEAP_AREA_SIZE)); + mem_heap_t *mem_heap = jerry_port_get_heap (); + return ((uint8_t *) pointer >= mem_heap->area + && (uint8_t *) pointer <= ((uint8_t *) mem_heap->area + MEM_HEAP_AREA_SIZE)); } /* mem_is_heap_pointer */ #endif /* !JERRY_NDEBUG */ diff --git a/jerry-core/jerry-port.c b/targets/default/jerry-port.c similarity index 75% rename from jerry-core/jerry-port.c rename to targets/default/jerry-port.c index 4812410927..a91462019d 100644 --- a/jerry-core/jerry-port.c +++ b/targets/default/jerry-port.c @@ -16,6 +16,10 @@ #include "jerry-port.h" #include +#define MEM_HEAP_INTERNAL + +#include "mem-heap-internal.h" + /** * Provide log message to filestream implementation for the engine. */ @@ -52,3 +56,29 @@ int jerry_port_putchar (int c) /**< character to put */ { return putchar (c); } /* jerry_port_putchar */ + +/** + * Provide abort implementation for the engine + */ +void jerry_port_abort() { + abort(); +} /* jerry_port_abort */ + +#ifndef JERRY_HEAP_SECTION_ATTR +static mem_heap_t mem_heap; +#else +static mem_heap_t mem_heap __attribute__ ((section (JERRY_HEAP_SECTION_ATTR))); +#endif + +mem_heap_t *jerry_port_init_heap(void) { + return &mem_heap; +} + +void jerry_port_finalize_heap(mem_heap_t *mem_heap) { + return; +} + +mem_heap_t *jerry_port_get_heap(void) { + return &mem_heap; +} + diff --git a/targets/pebble/Makefile.pebble b/targets/pebble/Makefile.pebble new file mode 100644 index 0000000000..b29bafb381 --- /dev/null +++ b/targets/pebble/Makefile.pebble @@ -0,0 +1,65 @@ +CURDIR = `pwd` +SRCPATH = ${CURDIR}/targets/pebble/source +TYPE = release +MODIFIER ?= +BUILD_DIR ?= build +INTERM = $(BUILD_DIR)/obj-pebble +OUTPUT = $(BUILD_DIR)/bin/$(TYPE).pebble +COPYTARGET = $(BUILD_DIR)/lib +JERRYHEAP ?= 16 +PORT_FILE = $(SRCPATH)/jerry_port.c + +CFLAGS += -Wno-error=format +CFLAGS += -Wno-error=unused-parameter +CFLAGS += -Wno-error=unused-variable +CFLAGS += -Wno-strict-aliasing +CFLAGS += -Wno-pedantic + +CMAKE_FLAGS = \ + -DENABLE_LTO=OFF \ + -DCMAKE_RULE_MESSAGES=OFF \ + -DCMAKE_TOOLCHAIN_FILE=build/configs/toolchain_external.cmake \ + -DEXTERNAL_CMAKE_C_COMPILER=$(CC) \ + -DEXTERNAL_CMAKE_SYSTEM_PROCESSOR=arm7-m \ + -DEXTERNAL_COMPILE_FLAGS="$(CFLAGS)" \ + -DEXTERNAL_PORT_FILE="$(PORT_FILE)" \ + -DEXTERNAL_MEM_HEAP_SIZE_KB=$(JERRYHEAP) + + +ifdef PBLTEST +$(warning RUNNING PBLTEST) +CFLAGS += -Wno-conversion +CFLAGS += -Wno-unknown-warning-option +CFLAGS += -Wno-error=int-to-pointer-cast +CFLAGS += -DMEM_HEAP_PTR_64 +CMAKE_FLAGS += -DUSE_COMPILER_DEFAULT_LIBC=NO +CMAKE_FLAGS += -DEXTERNAL_CMAKE_C_COMPILER_FAMILY=CLANG +else +# Building firmware -> use pblibc +CMAKE_FLAGS += -DUSE_COMPILER_DEFAULT_LIBC=NO +CMAKE_FLAGS += -DEXTERNAL_LIBC_INTERFACE=$(CURDIR)/../../../libc/include/ +CMAKE_FLAGS += -DEXTERNAL_CMAKE_C_COMPILER_FAMILY=GNU +endif + + +.PHONY: jerry clean + + +all: jerry + + +jerry: + mkdir -p $(INTERM) + mkdir -p $(OUTPUT) + mkdir -p $(COPYTARGET) + cmake -B$(INTERM) -H./ $(CMAKE_FLAGS) + make -s -C $(INTERM) $(TYPE).external$(MODIFIER) + cp `cat $(INTERM)/$(TYPE).external$(MODIFIER)/list` $(OUTPUT)/. + cp $(OUTPUT)/lib$(TYPE)$(MODIFIER).jerry-core.a $(COPYTARGET)/libjerrycore.a + cp $(OUTPUT)/lib$(TYPE)$(MODIFIER).jerry-fdlibm.third_party.lib.a $(COPYTARGET)/libfdlibm.a + + +clean: + rm -rf $(INTERM) + rm -rf $(OUTPUT) + diff --git a/targets/pebble/source/jerry_port.c b/targets/pebble/source/jerry_port.c new file mode 100644 index 0000000000..26a5fe7e5f --- /dev/null +++ b/targets/pebble/source/jerry_port.c @@ -0,0 +1,80 @@ +#include "jerry-port.h" +#include +#include + +#define MEM_HEAP_INTERNAL + +#include "mem-heap-internal.h" + +void pbl_log(uint8_t log_level, const char* src_filename, int src_line_number, const char* fmt, ...); + +#define LOG_LEVEL_DEBUG 200 +#define LOG_LEVEL_ERROR 1 + +/** + * Provide log message to filestream implementation for the engine. + */ +int jerry_port_logmsg (FILE* stream, const char* format, ...) +{ + va_list args; + va_start(args, format); + + pbl_log(LOG_LEVEL_DEBUG, "JERRY-LOG", 0, format, args); + + va_end(args); + + return 0; +} + +/** + * Provide error message to console implementation for the engine. + */ +int jerry_port_errormsg (const char* format, ...) +{ + va_list args; + va_start(args, format); + + pbl_log(LOG_LEVEL_ERROR, "JERRY-ERROR", 0, format, args); + + va_end(args); + + return 0; +} + +void dbgserial_putchar(uint8_t c); + +/** + * Provide output character to console implementation for the engine. + */ +int jerry_port_putchar (int c) +{ + dbgserial_putchar((uint8_t)c); + return c; +} + +void wtf(void); + +void jerry_port_abort () { + wtf(); +} + +void *task_zalloc(size_t bytes); +void task_free(void *p); +void app_state_set_js_state(void *data); +void *app_state_get_js_state(void); + +mem_heap_t *jerry_port_init_heap(void) { + mem_heap_t *mem_heap = task_zalloc(sizeof(mem_heap_t)); + app_state_set_js_state(mem_heap); + return mem_heap; +} + +void jerry_port_finalize_heap(mem_heap_t *mem_heap) { + task_free(mem_heap); +} + +mem_heap_t *jerry_port_get_heap(void) { + mem_heap_t *mem_heap = app_state_get_js_state(); + return mem_heap; +} +