/** * Allocate a chunk of specified size * * @return pointer to allocated chunk, if allocation was successful, * or NULL - if not enough memory. */ void * __attr_hot___ __attr_always_inline___ jmem_pools_alloc (size_t size) /**< size of the chunk */ { #ifdef JMEM_GC_BEFORE_EACH_ALLOC jmem_run_free_unused_memory_callbacks (JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH); #endif /* JMEM_GC_BEFORE_EACH_ALLOC */ if (size <= 8) { if (JERRY_CONTEXT (jmem_free_8_byte_chunk_p) != NULL) { const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p); JMEM_POOLS_STAT_REUSE (); VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_p->next_p; VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); return (void *) chunk_p; } else { JMEM_POOLS_STAT_NEW_ALLOC (); return (void *) jmem_heap_alloc_block (8); } } #ifdef JERRY_CPOINTER_32_BIT JERRY_ASSERT (size <= 16); if (JERRY_CONTEXT (jmem_free_16_byte_chunk_p) != NULL) { const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p); JMEM_POOLS_STAT_REUSE (); VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_p->next_p; VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); return (void *) chunk_p; } else { JMEM_POOLS_STAT_NEW_ALLOC (); return (void *) jmem_heap_alloc_block (16); } #else /* !JERRY_CPOINTER_32_BIT */ JERRY_UNREACHABLE (); return NULL; #endif } /* jmem_pools_alloc */
/** * Allocate a chunk of specified size * * @return pointer to allocated chunk, if allocation was successful, * or NULL - if not enough memory. */ inline void * __attribute__((hot)) __attr_always_inline___ jmem_pools_alloc (void) { #ifdef JMEM_GC_BEFORE_EACH_ALLOC jmem_run_free_unused_memory_callbacks (JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH); #endif /* JMEM_GC_BEFORE_EACH_ALLOC */ if (JERRY_CONTEXT (jmem_free_chunk_p) != NULL) { const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_chunk_p); JMEM_POOLS_STAT_REUSE (); VALGRIND_DEFINED_SPACE (chunk_p, JMEM_POOL_CHUNK_SIZE); JERRY_CONTEXT (jmem_free_chunk_p) = chunk_p->next_p; VALGRIND_UNDEFINED_SPACE (chunk_p, JMEM_POOL_CHUNK_SIZE); return (void *) chunk_p; } else { JMEM_POOLS_STAT_NEW_ALLOC (); return (void *) jmem_heap_alloc_block (JMEM_POOL_CHUNK_SIZE); } } /* jmem_pools_alloc */
/** * Realloc the bytecode container * * @return current position in RegExp bytecode */ static uint8_t * re_realloc_regexp_bytecode_block (re_bytecode_ctx_t *bc_ctx_p) /**< RegExp bytecode context */ { JERRY_ASSERT (bc_ctx_p->block_end_p >= bc_ctx_p->block_start_p); size_t old_size = (size_t) (bc_ctx_p->block_end_p - bc_ctx_p->block_start_p); /* If one of the members of RegExp bytecode context is NULL, then all member should be NULL * (it means first allocation), otherwise all of the members should be a non NULL pointer. */ JERRY_ASSERT ((!bc_ctx_p->current_p && !bc_ctx_p->block_end_p && !bc_ctx_p->block_start_p) || (bc_ctx_p->current_p && bc_ctx_p->block_end_p && bc_ctx_p->block_start_p)); size_t new_block_size = old_size + REGEXP_BYTECODE_BLOCK_SIZE; JERRY_ASSERT (bc_ctx_p->current_p >= bc_ctx_p->block_start_p); size_t current_ptr_offset = (size_t) (bc_ctx_p->current_p - bc_ctx_p->block_start_p); uint8_t *new_block_start_p = (uint8_t *) jmem_heap_alloc_block (new_block_size); if (bc_ctx_p->current_p) { memcpy (new_block_start_p, bc_ctx_p->block_start_p, (size_t) (current_ptr_offset)); jmem_heap_free_block (bc_ctx_p->block_start_p, old_size); } bc_ctx_p->block_start_p = new_block_start_p; bc_ctx_p->block_end_p = new_block_start_p + new_block_size; bc_ctx_p->current_p = new_block_start_p + current_ptr_offset; return bc_ctx_p->current_p; } /* re_realloc_regexp_bytecode_block */
/** * Allocate new ecma-string and fill it with characters from the utf8 string * * @return pointer to ecma-string descriptor */ ecma_string_t * ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, /**< utf-8 string */ lit_utf8_size_t string_size) /**< string size */ { JERRY_ASSERT (string_p != NULL || string_size == 0); JERRY_ASSERT (lit_is_cesu8_string_valid (string_p, string_size)); lit_magic_string_id_t magic_string_id; if (lit_is_utf8_string_magic (string_p, string_size, &magic_string_id)) { return ecma_get_magic_string (magic_string_id); } lit_magic_string_ex_id_t magic_string_ex_id; if (lit_is_ex_utf8_string_magic (string_p, string_size, &magic_string_ex_id)) { return ecma_get_magic_string_ex (magic_string_ex_id); } JERRY_ASSERT (string_size > 0 && string_size <= UINT16_MAX); ecma_string_t *string_desc_p = jmem_heap_alloc_block (sizeof (ecma_string_t) + string_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; string_desc_p->hash = lit_utf8_string_calc_hash (string_p, string_size); string_desc_p->u.common_field = 0; string_desc_p->u.utf8_string.size = (uint16_t) string_size; string_desc_p->u.utf8_string.length = (uint16_t) lit_utf8_string_length (string_p, string_size); lit_utf8_byte_t *data_p = (lit_utf8_byte_t *) (string_desc_p + 1); memcpy (data_p, string_p, string_size); return string_desc_p; } /* ecma_new_ecma_string_from_utf8 */
/** * Insert a new bytecode to the bytecode container */ void re_bytecode_list_insert (re_bytecode_ctx_t *bc_ctx_p, /**< RegExp bytecode context */ size_t offset, /**< distance from the start of the container */ uint8_t *bytecode_p, /**< input bytecode */ size_t length) /**< length of input */ { JERRY_ASSERT (length <= REGEXP_BYTECODE_BLOCK_SIZE); uint8_t *current_p = bc_ctx_p->current_p; if (current_p + length > bc_ctx_p->block_end_p) { re_realloc_regexp_bytecode_block (bc_ctx_p); } uint8_t *src_p = bc_ctx_p->block_start_p + offset; if ((re_get_bytecode_length (bc_ctx_p) - offset) > 0) { uint8_t *dest_p = src_p + length; uint8_t *tmp_block_start_p; tmp_block_start_p = (uint8_t *) jmem_heap_alloc_block (re_get_bytecode_length (bc_ctx_p) - offset); memcpy (tmp_block_start_p, src_p, (size_t) (re_get_bytecode_length (bc_ctx_p) - offset)); memcpy (dest_p, tmp_block_start_p, (size_t) (re_get_bytecode_length (bc_ctx_p) - offset)); jmem_heap_free_block (tmp_block_start_p, re_get_bytecode_length (bc_ctx_p) - offset); } memcpy (src_p, bytecode_p, length); bc_ctx_p->current_p += length; } /* re_bytecode_list_insert */
/** * Allocate memory for ecma-property pair * * @return pointer to allocated memory */ inline ecma_property_pair_t * JERRY_ATTR_ALWAYS_INLINE ecma_alloc_property_pair (void) { #ifdef JMEM_STATS jmem_stats_allocate_property_bytes (sizeof (ecma_property_pair_t)); #endif /* JMEM_STATS */ return jmem_heap_alloc_block (sizeof (ecma_property_pair_t)); } /* ecma_alloc_property_pair */
/** * Allocate memory for string with character data * * @return pointer to allocated memory */ inline ecma_string_t * JERRY_ATTR_ALWAYS_INLINE ecma_alloc_string_buffer (size_t size) /**< size of string */ { #ifdef JMEM_STATS jmem_stats_allocate_string_bytes (size); #endif /* JMEM_STATS */ return jmem_heap_alloc_block (size); } /* ecma_alloc_string_buffer */
/** * Allocate memory for extended object * * @return pointer to allocated memory */ inline ecma_extended_object_t * JERRY_ATTR_ALWAYS_INLINE ecma_alloc_extended_object (size_t size) /**< size of object */ { #ifdef JMEM_STATS jmem_stats_allocate_object_bytes (size); #endif /* JMEM_STATS */ return jmem_heap_alloc_block (size); } /* ecma_alloc_extended_object */
/** * Create a PromiseReactionJob. * * @return pointer to the PromiseReactionJob */ static ecma_job_promise_reaction_t * ecma_create_promise_reaction_job (ecma_value_t reaction, /**< PromiseReaction */ ecma_value_t argument) /**< argument for the reaction */ { JERRY_ASSERT (ecma_is_value_object (reaction)); ecma_job_promise_reaction_t *job_p; job_p = (ecma_job_promise_reaction_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_reaction_t)); job_p->reaction = ecma_copy_value (reaction); job_p->argument = ecma_copy_value (argument); return job_p; } /* ecma_create_promise_reaction_job */
/** * Allocate block and store block size. * * Note: block will only be aligned to 4 bytes. */ inline void * __attr_always_inline___ jmem_heap_alloc_block_store_size (size_t size) /**< required size */ { if (unlikely (size == 0)) { return NULL; } size += sizeof (jmem_heap_free_t); jmem_heap_free_t *const data_space_p = (jmem_heap_free_t *) jmem_heap_alloc_block (size); data_space_p->size = (uint32_t) size; return (void *) (data_space_p + 1); } /* jmem_heap_alloc_block_store_size */
int main () { TEST_INIT (); jmem_heap_init (); jmem_register_free_unused_memory_callback (test_heap_give_some_memory_back); #ifdef JMEM_STATS jmem_heap_stats_print (); #endif /* JMEM_STATS */ for (uint32_t i = 0; i < test_iters; i++) { for (uint32_t j = 0; j < test_sub_iters; j++) { size_t size = (size_t) rand () % test_threshold_block_size; ptrs[j] = (uint8_t *) jmem_heap_alloc_block (size); sizes[j] = size; TEST_ASSERT (sizes[j] == 0 || ptrs[j] != NULL); memset (ptrs[j], 0, sizes[j]); } /* jmem_heap_print (true); */ for (uint32_t j = 0; j < test_sub_iters; j++) { if (ptrs[j] != NULL) { for (size_t k = 0; k < sizes[j]; k++) { TEST_ASSERT (ptrs[j][k] == 0); } jmem_heap_free_block (ptrs[j], sizes[j]); ptrs[j] = NULL; } } } #ifdef JMEM_STATS jmem_heap_stats_print (); #endif /* JMEM_STATS */ return 0; } /* main */
/** * Allocate new ecma-string and fill it with ecma-number * * @return pointer to ecma-string descriptor */ ecma_string_t * ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */ { uint32_t uint32_num = ecma_number_to_uint32 (num); if (num == ((ecma_number_t) uint32_num)) { return ecma_new_ecma_string_from_uint32 (uint32_num); } if (ecma_number_is_nan (num)) { return ecma_get_magic_string (LIT_MAGIC_STRING_NAN); } if (ecma_number_is_infinity (num)) { lit_magic_string_id_t id = (ecma_number_is_negative (num) ? LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL : LIT_MAGIC_STRING_INFINITY_UL); return ecma_get_magic_string (id); } lit_utf8_byte_t str_buf[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; lit_utf8_size_t str_size = ecma_number_to_utf8_string (num, str_buf, sizeof (str_buf)); JERRY_ASSERT (str_size > 0); #ifndef JERRY_NDEBUG lit_magic_string_id_t magic_string_id; lit_magic_string_ex_id_t magic_string_ex_id; JERRY_ASSERT (!lit_is_utf8_string_magic (str_buf, str_size, &magic_string_id) && !lit_is_ex_utf8_string_magic (str_buf, str_size, &magic_string_ex_id)); #endif /* !JERRY_NDEBUG */ ecma_string_t *string_desc_p = jmem_heap_alloc_block (sizeof (ecma_string_t) + str_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; string_desc_p->hash = lit_utf8_string_calc_hash (str_buf, str_size); string_desc_p->u.common_field = 0; string_desc_p->u.utf8_string.size = (uint16_t) str_size; string_desc_p->u.utf8_string.length = (uint16_t) str_size; lit_utf8_byte_t *data_p = (lit_utf8_byte_t *) (string_desc_p + 1); memcpy (data_p, str_buf, str_size); return string_desc_p; } /* ecma_new_ecma_string_from_number */
/** * Create a PromiseResolveThenableJob * * @return pointer to the PromiseResolveThenableJob */ static ecma_job_promise_resolve_thenable_t * ecma_create_promise_resolve_thenable_job (ecma_value_t promise, /**< promise to be resolved */ ecma_value_t thenable, /**< thenable object */ ecma_value_t then) /**< 'then' function */ { JERRY_ASSERT (ecma_is_promise (ecma_get_object_from_value (promise))); JERRY_ASSERT (ecma_is_value_object (thenable)); JERRY_ASSERT (ecma_op_is_callable (then)); ecma_job_promise_resolve_thenable_t *job_p; job_p = (ecma_job_promise_resolve_thenable_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_resolve_thenable_t)); job_p->promise = ecma_copy_value (promise); job_p->thenable = ecma_copy_value (thenable); job_p->then = ecma_copy_value (then); return job_p; } /* ecma_create_promise_resolve_thenable_job */
/** * Enqueue a Promise job into the jobqueue. */ static void ecma_enqueue_job (ecma_job_handler_t handler, /**< the handler for the job */ void *job_p) /**< the job */ { ecma_job_queueitem_t *item_p = jmem_heap_alloc_block (sizeof (ecma_job_queueitem_t)); item_p->job_p = job_p; item_p->handler = handler; item_p->next_p = NULL; if (JERRY_CONTEXT (job_queue_head_p) == NULL) { JERRY_CONTEXT (job_queue_head_p) = item_p; JERRY_CONTEXT (job_queue_tail_p) = item_p; } else { JERRY_CONTEXT (job_queue_tail_p)->next_p = item_p; JERRY_CONTEXT (job_queue_tail_p) = item_p; } } /* ecma_enqueue_job */
/** * Receive message from the client. * * @return true - if message is processed successfully * false - otherwise */ inline bool __attr_always_inline___ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer to the received data */ uint32_t message_size, /**< message size */ bool *resume_exec_p, /**< pointer to the resume exec flag */ uint8_t *expected_message_type_p, /**< message type */ jerry_debugger_uint8_data_t **message_data_p) /**< custom message data */ { /* Process the received message. */ if (recv_buffer_p[0] >= JERRY_DEBUGGER_CONTINUE && !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE)) { JERRY_ERROR_MSG ("Message requires breakpoint mode\n"); jerry_debugger_close_connection (); return false; } if (*expected_message_type_p != 0) { JERRY_ASSERT (*expected_message_type_p == JERRY_DEBUGGER_EVAL_PART || *expected_message_type_p == JERRY_DEBUGGER_CLIENT_SOURCE_PART); jerry_debugger_uint8_data_t *uint8_data_p = (jerry_debugger_uint8_data_t *) *message_data_p; if (recv_buffer_p[0] != *expected_message_type_p) { jmem_heap_free_block (uint8_data_p, uint8_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t)); JERRY_ERROR_MSG ("Unexpected message\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_uint8_data_part_t, uint8_data_part_p); if (message_size < sizeof (jerry_debugger_receive_uint8_data_part_t) + 1) { jmem_heap_free_block (uint8_data_p, uint8_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t)); JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } uint32_t expected_data = uint8_data_p->uint8_size - uint8_data_p->uint8_offset; message_size -= (uint32_t) sizeof (jerry_debugger_receive_uint8_data_part_t); if (message_size > expected_data) { jmem_heap_free_block (uint8_data_p, uint8_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t)); JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } lit_utf8_byte_t *string_p = (lit_utf8_byte_t *) (uint8_data_p + 1); memcpy (string_p + uint8_data_p->uint8_offset, (lit_utf8_byte_t *) (uint8_data_part_p + 1), message_size); if (message_size < expected_data) { uint8_data_p->uint8_offset += message_size; return true; } bool result; if (*expected_message_type_p == JERRY_DEBUGGER_EVAL_PART) { if (jerry_debugger_send_eval (string_p, uint8_data_p->uint8_size)) { *resume_exec_p = true; } result = (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) != 0; } else { result = true; JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_CLIENT_SOURCE_MODE); *resume_exec_p = true; } *expected_message_type_p = 0; return result; } switch (recv_buffer_p[0]) { case JERRY_DEBUGGER_FREE_BYTE_CODE_CP: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_byte_code_cp_t); JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_byte_code_cp_t, byte_code_p); jmem_cpointer_t byte_code_free_cp; memcpy (&byte_code_free_cp, byte_code_p->byte_code_cp, sizeof (jmem_cpointer_t)); if (byte_code_free_cp != JERRY_CONTEXT (debugger_byte_code_free_tail)) { JERRY_ERROR_MSG ("Invalid byte code free order\n"); jerry_debugger_close_connection (); return false; } jerry_debugger_byte_code_free_t *byte_code_free_p; byte_code_free_p = JMEM_CP_GET_NON_NULL_POINTER (jerry_debugger_byte_code_free_t, byte_code_free_cp); if (byte_code_free_p->prev_cp != ECMA_NULL_POINTER) { JERRY_CONTEXT (debugger_byte_code_free_tail) = byte_code_free_p->prev_cp; } else { JERRY_CONTEXT (debugger_byte_code_free_head) = ECMA_NULL_POINTER; JERRY_CONTEXT (debugger_byte_code_free_tail) = ECMA_NULL_POINTER; } #ifdef JMEM_STATS jmem_stats_free_byte_code_bytes (((size_t) byte_code_free_p->size) << JMEM_ALIGNMENT_LOG); #endif /* JMEM_STATS */ jmem_heap_free_block (byte_code_free_p, ((size_t) byte_code_free_p->size) << JMEM_ALIGNMENT_LOG); return true; } case JERRY_DEBUGGER_UPDATE_BREAKPOINT: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_update_breakpoint_t); JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_update_breakpoint_t, update_breakpoint_p); jmem_cpointer_t byte_code_cp; memcpy (&byte_code_cp, update_breakpoint_p->byte_code_cp, sizeof (jmem_cpointer_t)); uint8_t *byte_code_p = JMEM_CP_GET_NON_NULL_POINTER (uint8_t, byte_code_cp); uint32_t offset; memcpy (&offset, update_breakpoint_p->offset, sizeof (uint32_t)); byte_code_p += offset; JERRY_ASSERT (*byte_code_p == CBC_BREAKPOINT_ENABLED || *byte_code_p == CBC_BREAKPOINT_DISABLED); *byte_code_p = update_breakpoint_p->is_set_breakpoint ? CBC_BREAKPOINT_ENABLED : CBC_BREAKPOINT_DISABLED; 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); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = NULL; *resume_exec_p = false; return true; } case JERRY_DEBUGGER_CONTINUE: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = NULL; *resume_exec_p = true; return true; } case JERRY_DEBUGGER_STEP: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = NULL; *resume_exec_p = true; return true; } case JERRY_DEBUGGER_NEXT: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = JERRY_CONTEXT (vm_top_context_p); *resume_exec_p = true; return true; } case JERRY_DEBUGGER_FINISH: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); /* This will point to the current context's parent (where the function was called) * and in case of NULL the result will the same as in case of STEP. */ JERRY_CONTEXT (debugger_stop_context) = JERRY_CONTEXT (vm_top_context_p->prev_context_p); *resume_exec_p = true; return true; } case JERRY_DEBUGGER_GET_BACKTRACE: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_get_backtrace_t); jerry_debugger_send_backtrace (recv_buffer_p); return true; } case JERRY_DEBUGGER_EXCEPTION_CONFIG: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_exception_config_t); JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_exception_config_t, exception_config_p); if (exception_config_p->enable == 0) { JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION); JERRY_DEBUG_MSG ("Stop at exception disabled\n"); } else { JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION); JERRY_DEBUG_MSG ("Stop at exception enabled\n"); } return true; } case JERRY_DEBUGGER_PARSER_CONFIG: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_parser_config_t); JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_parser_config_t, parser_config_p); if (parser_config_p->enable_wait != 0) { JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_PARSER_WAIT); JERRY_DEBUG_MSG ("Waiting after parsing enabled\n"); } else { JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_PARSER_WAIT); JERRY_DEBUG_MSG ("Waiting after parsing disabled\n"); } return true; } case JERRY_DEBUGGER_PARSER_RESUME: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_PARSER_WAIT_MODE)) { JERRY_ERROR_MSG ("Not in parser wait mode\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_PARSER_WAIT_MODE); return true; } case JERRY_DEBUGGER_EVAL: { if (message_size < sizeof (jerry_debugger_receive_eval_first_t) + 1) { JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_eval_first_t, eval_first_p); uint32_t eval_size; memcpy (&eval_size, eval_first_p->eval_size, sizeof (uint32_t)); if (eval_size <= JERRY_CONTEXT (debugger_max_receive_size) - sizeof (jerry_debugger_receive_eval_first_t)) { if (eval_size != message_size - sizeof (jerry_debugger_receive_eval_first_t)) { JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } if (jerry_debugger_send_eval ((lit_utf8_byte_t *) (eval_first_p + 1), eval_size)) { *resume_exec_p = true; } return (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) != 0; } jerry_debugger_uint8_data_t *eval_uint8_data_p; size_t eval_data_size = sizeof (jerry_debugger_uint8_data_t) + eval_size; eval_uint8_data_p = (jerry_debugger_uint8_data_t *) jmem_heap_alloc_block (eval_data_size); eval_uint8_data_p->uint8_size = eval_size; eval_uint8_data_p->uint8_offset = (uint32_t) (message_size - sizeof (jerry_debugger_receive_eval_first_t)); lit_utf8_byte_t *eval_string_p = (lit_utf8_byte_t *) (eval_uint8_data_p + 1); memcpy (eval_string_p, (lit_utf8_byte_t *) (eval_first_p + 1), message_size - sizeof (jerry_debugger_receive_eval_first_t)); *message_data_p = eval_uint8_data_p; *expected_message_type_p = JERRY_DEBUGGER_EVAL_PART; return true; } case JERRY_DEBUGGER_CLIENT_SOURCE: { if (message_size <= sizeof (jerry_debugger_receive_client_source_first_t)) { JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE)) { JERRY_ERROR_MSG ("Not in client source mode\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_client_source_first_t, client_source_first_p); uint32_t client_source_size; memcpy (&client_source_size, client_source_first_p->code_size, sizeof (uint32_t)); uint32_t header_size = sizeof (jerry_debugger_receive_client_source_first_t); if (client_source_size <= JERRY_CONTEXT (debugger_max_receive_size) - header_size && client_source_size != message_size - header_size) { JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } jerry_debugger_uint8_data_t *client_source_data_p; size_t client_source_data_size = sizeof (jerry_debugger_uint8_data_t) + client_source_size; client_source_data_p = (jerry_debugger_uint8_data_t *) jmem_heap_alloc_block (client_source_data_size); client_source_data_p->uint8_size = client_source_size; client_source_data_p->uint8_offset = (uint32_t) (message_size - sizeof (jerry_debugger_receive_client_source_first_t)); lit_utf8_byte_t *client_source_string_p = (lit_utf8_byte_t *) (client_source_data_p + 1); memcpy (client_source_string_p, (lit_utf8_byte_t *) (client_source_first_p + 1), message_size - sizeof (jerry_debugger_receive_client_source_first_t)); *message_data_p = client_source_data_p; if (client_source_data_p->uint8_size != client_source_data_p->uint8_offset) { *expected_message_type_p = JERRY_DEBUGGER_CLIENT_SOURCE_PART; } else { JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_CLIENT_SOURCE_MODE); *resume_exec_p = true; } return true; } case JERRY_DEBUGGER_NO_MORE_SOURCES: { if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE)) { JERRY_ERROR_MSG ("Not in client source mode\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_UPDATE_FLAGS (JERRY_DEBUGGER_CLIENT_NO_SOURCE, JERRY_DEBUGGER_CLIENT_SOURCE_MODE); *resume_exec_p = true; return true; } case JERRY_DEBUGGER_CONTEXT_RESET: { if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE)) { JERRY_ERROR_MSG ("Not in client source mode\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_UPDATE_FLAGS (JERRY_DEBUGGER_CONTEXT_RESET_MODE, JERRY_DEBUGGER_CLIENT_SOURCE_MODE); *resume_exec_p = true; return true; } default: { JERRY_ERROR_MSG ("Unexpected message."); jerry_debugger_close_connection (); return false; } } } /* jerry_debugger_process_message */
/** * Allocate memory for extended object * * @return pointer to allocated memory */ inline ecma_extended_object_t * __attr_always_inline___ ecma_alloc_extended_object (void) { return jmem_heap_alloc_block (sizeof (ecma_extended_object_t)); } /* ecma_alloc_extended_object */
/** * Allocate memory for ecma-property pair * * @return pointer to allocated memory */ inline ecma_property_pair_t * __attr_always_inline___ ecma_alloc_property_pair (void) { return jmem_heap_alloc_block (sizeof (ecma_property_pair_t)); } /* ecma_alloc_property_pair */
/** * Allocate memory for extended object * * @return pointer to allocated memory */ inline ecma_extended_object_t * __attr_always_inline___ ecma_alloc_extended_object (size_t size) /**< size of object */ { return jmem_heap_alloc_block (size); } /* ecma_alloc_extended_object */
/** * Allocate memory for ecma-property pair * * @return pointer to allocated memory */ ecma_property_pair_t * ecma_alloc_property_pair (void) { return jmem_heap_alloc_block (sizeof (ecma_property_pair_t)); } /* ecma_alloc_property_pair */
/** * Concatenate ecma-strings * * @return concatenation of two ecma-strings */ ecma_string_t * ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ ecma_string_t *string2_p) /**< second ecma-string */ { JERRY_ASSERT (string1_p != NULL && string2_p != NULL); if (ecma_string_is_empty (string1_p)) { ecma_ref_ecma_string (string2_p); return string2_p; } else if (ecma_string_is_empty (string2_p)) { ecma_ref_ecma_string (string1_p); return string1_p; } const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p; lit_utf8_size_t utf8_string1_size, utf8_string2_size; lit_utf8_size_t utf8_string1_length, utf8_string2_length; lit_utf8_byte_t uint32_to_string_buffer1[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; switch (ECMA_STRING_GET_CONTAINER (string1_p)) { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: { utf8_string1_p = (lit_utf8_byte_t *) (string1_p + 1); utf8_string1_size = string1_p->u.utf8_string.size; utf8_string1_length = string1_p->u.utf8_string.length; break; } case ECMA_STRING_CONTAINER_UINT32_IN_DESC: { utf8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number, uint32_to_string_buffer1, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); utf8_string1_p = uint32_to_string_buffer1; utf8_string1_length = utf8_string1_size; break; } case ECMA_STRING_CONTAINER_MAGIC_STRING: { utf8_string1_p = lit_get_magic_string_utf8 (string1_p->u.magic_string_id); utf8_string1_size = lit_get_magic_string_size (string1_p->u.magic_string_id); utf8_string1_length = utf8_string1_size; break; } default: { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); utf8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_id); utf8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_id); utf8_string1_length = utf8_string1_size; break; } } switch (ECMA_STRING_GET_CONTAINER (string2_p)) { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: { utf8_string2_p = (lit_utf8_byte_t *) (string2_p + 1); utf8_string2_size = string2_p->u.utf8_string.size; utf8_string2_length = string2_p->u.utf8_string.length; break; } case ECMA_STRING_CONTAINER_UINT32_IN_DESC: { utf8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number, uint32_to_string_buffer2, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); utf8_string2_p = uint32_to_string_buffer2; utf8_string2_length = utf8_string2_size; break; } case ECMA_STRING_CONTAINER_MAGIC_STRING: { utf8_string2_p = lit_get_magic_string_utf8 (string2_p->u.magic_string_id); utf8_string2_size = lit_get_magic_string_size (string2_p->u.magic_string_id); utf8_string2_length = utf8_string2_size; break; } default: { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); utf8_string2_p = lit_get_magic_string_ex_utf8 (string2_p->u.magic_string_id); utf8_string2_size = lit_get_magic_string_ex_size (string2_p->u.magic_string_id); utf8_string2_length = utf8_string2_size; break; } } JERRY_ASSERT (utf8_string1_size > 0); JERRY_ASSERT (utf8_string2_size > 0); JERRY_ASSERT (utf8_string1_length <= utf8_string1_size); JERRY_ASSERT (utf8_string2_length <= utf8_string2_size); lit_utf8_size_t new_size = utf8_string1_size + utf8_string2_size; JERRY_ASSERT (new_size <= UINT16_MAX); ecma_string_t *string_desc_p = jmem_heap_alloc_block (sizeof (ecma_string_t) + new_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; string_desc_p->hash = lit_utf8_string_hash_combine (string1_p->hash, utf8_string2_p, utf8_string2_size); string_desc_p->u.common_field = 0; string_desc_p->u.utf8_string.size = (uint16_t) new_size; string_desc_p->u.utf8_string.length = (uint16_t) (utf8_string1_length + utf8_string2_length); lit_utf8_byte_t *data_p = (lit_utf8_byte_t *) (string_desc_p + 1); memcpy (data_p, utf8_string1_p, utf8_string1_size); memcpy (data_p + utf8_string1_size, utf8_string2_p, utf8_string2_size); return string_desc_p; } /* ecma_concat_ecma_strings */