static void interp_mem_stats_opcode_enter (const vm_instr_t *instrs_p, vm_instr_counter_t instr_position, mem_heap_stats_t *out_heap_stats_p, mem_pools_stats_t *out_pools_stats_p) { if (likely (!interp_mem_stats_enabled)) { return; } const uint32_t indentation = JERRY_MIN (interp_mem_stats_print_indentation, INTERP_MEM_PRINT_INDENTATION_MAX); char indent_prefix[INTERP_MEM_PRINT_INDENTATION_MAX + 2]; memset (indent_prefix, ' ', sizeof (indent_prefix)); indent_prefix[indentation] = '|'; indent_prefix[indentation + 1] = '\0'; interp_mem_get_stats (out_heap_stats_p, out_pools_stats_p, true, false); vm_instr_t instr = vm_get_instr (instrs_p, instr_position); printf ("%s-- Opcode: %s (position %u) --\n", indent_prefix, __op_names[instr.op_idx], (uint32_t) instr_position); interp_mem_stats_print_indentation += INTERP_MEM_PRINT_INDENTATION_STEP; }
static void interp_mem_stats_context_enter (vm_frame_ctx_t *frame_ctx_p, vm_instr_counter_t block_position) { if (likely (!interp_mem_stats_enabled)) { return; } const uint32_t indentation = JERRY_MIN (interp_mem_stats_print_indentation, INTERP_MEM_PRINT_INDENTATION_MAX); char indent_prefix[INTERP_MEM_PRINT_INDENTATION_MAX + 2]; memset (indent_prefix, ' ', sizeof (indent_prefix)); indent_prefix[indentation] = '|'; indent_prefix[indentation + 1] = '\0'; frame_ctx_p->context_peak_allocated_heap_bytes = 0; frame_ctx_p->context_peak_waste_heap_bytes = 0; frame_ctx_p->context_peak_pools_count = 0; frame_ctx_p->context_peak_allocated_pool_chunks = 0; interp_mem_get_stats (&frame_ctx_p->heap_stats_context_enter, &frame_ctx_p->pools_stats_context_enter, false, false); printf ("\n%s--- Beginning interpretation of a block at position %u ---\n" "%s Allocated heap bytes: %5u\n" "%s Waste heap bytes: %5u\n" "%s Pools: %5u\n" "%s Allocated pool chunks: %5u\n\n", indent_prefix, (uint32_t) block_position, indent_prefix, (uint32_t) frame_ctx_p->heap_stats_context_enter.allocated_bytes, indent_prefix, (uint32_t) frame_ctx_p->heap_stats_context_enter.waste_bytes, indent_prefix, (uint32_t) frame_ctx_p->pools_stats_context_enter.pools_count, indent_prefix, (uint32_t) frame_ctx_p->pools_stats_context_enter.allocated_chunks); }
/** * Allocation of memory region. * * See also: * mem_heap_alloc_block * * @return pointer to allocated memory block - if allocation is successful, * NULL - if there is not enough memory. */ static void* mem_heap_alloc_block_internal (size_t size_in_bytes, /**< size of region to allocate in bytes */ mem_block_length_type_t length_type, /**< length type of the block * (one-chunked or general) */ mem_heap_alloc_term_t alloc_term) /**< expected allocation term */ { mem_block_header_t *block_p; mem_direction_t direction; JERRY_ASSERT (size_in_bytes != 0); JERRY_ASSERT (length_type != mem_block_length_type_t::ONE_CHUNKED || size_in_bytes == mem_heap_get_chunked_block_data_size ()); mem_check_heap (); if (alloc_term == MEM_HEAP_ALLOC_LONG_TERM) { block_p = mem_heap.first_block_p; direction = MEM_DIRECTION_NEXT; } else { JERRY_ASSERT (alloc_term == MEM_HEAP_ALLOC_SHORT_TERM); block_p = mem_heap.last_block_p; direction = MEM_DIRECTION_PREV; } /* searching for appropriate block */ while (block_p != NULL) { VALGRIND_DEFINED_STRUCT (block_p); if (mem_is_block_free (block_p)) { if (mem_get_block_data_space_size (block_p) >= size_in_bytes) { break; } } else { JERRY_ASSERT (!mem_is_block_free (block_p)); } mem_block_header_t *next_block_p = mem_get_next_block_by_direction (block_p, direction); VALGRIND_NOACCESS_STRUCT (block_p); block_p = next_block_p; } if (block_p == NULL) { /* not enough free space */ return NULL; } /* appropriate block found, allocating space */ size_t new_block_size_in_chunks = mem_get_block_chunks_count_from_data_size (size_in_bytes); size_t found_block_size_in_chunks = mem_get_block_chunks_count (block_p); JERRY_ASSERT (new_block_size_in_chunks <= found_block_size_in_chunks); mem_heap.allocated_chunks += new_block_size_in_chunks; JERRY_ASSERT (mem_heap.allocated_chunks * MEM_HEAP_CHUNK_SIZE <= mem_heap.heap_size); if (mem_heap.allocated_chunks * MEM_HEAP_CHUNK_SIZE >= mem_heap.limit) { mem_heap.limit = JERRY_MIN (mem_heap.heap_size, JERRY_MAX (mem_heap.limit + CONFIG_MEM_HEAP_DESIRED_LIMIT, mem_heap.allocated_chunks * MEM_HEAP_CHUNK_SIZE)); JERRY_ASSERT (mem_heap.limit >= mem_heap.allocated_chunks * MEM_HEAP_CHUNK_SIZE); } mem_block_header_t *prev_block_p = mem_get_next_block_by_direction (block_p, MEM_DIRECTION_PREV); mem_block_header_t *next_block_p = mem_get_next_block_by_direction (block_p, MEM_DIRECTION_NEXT); if (new_block_size_in_chunks < found_block_size_in_chunks) { MEM_HEAP_STAT_FREE_BLOCK_SPLIT (); if (direction == MEM_DIRECTION_PREV) { prev_block_p = block_p; uint8_t *block_end_p = (uint8_t*) block_p + found_block_size_in_chunks * MEM_HEAP_CHUNK_SIZE; block_p = (mem_block_header_t*) (block_end_p - new_block_size_in_chunks * MEM_HEAP_CHUNK_SIZE); VALGRIND_DEFINED_STRUCT (prev_block_p); mem_set_block_next (prev_block_p, block_p); VALGRIND_NOACCESS_STRUCT (prev_block_p); if (next_block_p == NULL) { mem_heap.last_block_p = block_p; } else { VALGRIND_DEFINED_STRUCT (next_block_p); mem_set_block_prev (next_block_p, block_p); VALGRIND_NOACCESS_STRUCT (next_block_p); } } else { uint8_t *new_free_block_first_chunk_p = (uint8_t*) block_p + new_block_size_in_chunks * MEM_HEAP_CHUNK_SIZE; mem_init_block_header (new_free_block_first_chunk_p, 0, MEM_BLOCK_FREE, mem_block_length_type_t::GENERAL, block_p, next_block_p); mem_block_header_t *new_free_block_p = (mem_block_header_t*) new_free_block_first_chunk_p; if (next_block_p == NULL) { mem_heap.last_block_p = new_free_block_p; } else { VALGRIND_DEFINED_STRUCT (next_block_p); mem_block_header_t* new_free_block_p = (mem_block_header_t*) new_free_block_first_chunk_p; mem_set_block_prev (next_block_p, new_free_block_p); VALGRIND_NOACCESS_STRUCT (next_block_p); } next_block_p = new_free_block_p; } } mem_init_block_header ((uint8_t*) block_p, size_in_bytes, MEM_BLOCK_ALLOCATED, length_type, prev_block_p, next_block_p); VALGRIND_DEFINED_STRUCT (block_p); MEM_HEAP_STAT_ALLOC_BLOCK (block_p); JERRY_ASSERT (mem_get_block_data_space_size (block_p) >= size_in_bytes); VALGRIND_NOACCESS_STRUCT (block_p); /* return data space beginning address */ uint8_t *data_space_p = (uint8_t*) (block_p + 1); JERRY_ASSERT ((uintptr_t) data_space_p % MEM_ALIGNMENT == 0); VALGRIND_UNDEFINED_SPACE (data_space_p, size_in_bytes); mem_check_heap (); return data_space_p; } /* mem_heap_alloc_block_internal */
/** * Helper for stringifying numbers * * @return the length of the generated string representation */ static lit_utf8_size_t ecma_builtin_number_prototype_helper_to_string (lit_utf8_byte_t *digits_p, /**< number as string in decimal form */ lit_utf8_size_t num_digits, /**< length of the string representation */ int32_t exponent, /**< decimal exponent */ lit_utf8_byte_t *to_digits_p, /**< [out] buffer to write */ lit_utf8_size_t to_num_digits) /**< requested number of digits */ { lit_utf8_byte_t *p = to_digits_p; if (exponent <= 0) { /* Add zero to the integer part. */ *p++ = '0'; to_num_digits--; if (to_num_digits > 0) { *p++ = '.'; /* Add leading zeros to the fraction part. */ for (int i = 0; i < -exponent && to_num_digits > 0; i++) { *p++ = '0'; to_num_digits--; } } } else { /* Add significant digits of the integer part. */ lit_utf8_size_t to_copy = JERRY_MIN (num_digits, to_num_digits); to_copy = JERRY_MIN (to_copy, (lit_utf8_size_t) exponent); memmove (p, digits_p, (size_t) to_copy); p += to_copy; to_num_digits -= to_copy; digits_p += to_copy; num_digits -= to_copy; exponent -= (int32_t) to_copy; /* Add zeros before decimal point. */ while (exponent > 0 && to_num_digits > 0) { JERRY_ASSERT (num_digits == 0); *p++ = '0'; to_num_digits--; exponent--; } if (to_num_digits > 0) { *p++ = '.'; } } if (to_num_digits > 0) { /* Add significant digits of the fraction part. */ lit_utf8_size_t to_copy = JERRY_MIN (num_digits, to_num_digits); memmove (p, digits_p, (size_t) to_copy); p += to_copy; to_num_digits -= to_copy; /* Add trailing zeros. */ while (to_num_digits > 0) { *p++ = '0'; to_num_digits--; } } return (lit_utf8_size_t) (p - to_digits_p); } /* ecma_builtin_number_prototype_helper_to_string */
static void interp_mem_stats_opcode_exit (vm_frame_ctx_t *frame_ctx_p, vm_instr_counter_t instr_position, mem_heap_stats_t *heap_stats_before_p, mem_pools_stats_t *pools_stats_before_p) { if (likely (!interp_mem_stats_enabled)) { return; } interp_mem_stats_print_indentation -= INTERP_MEM_PRINT_INDENTATION_STEP; const uint32_t indentation = JERRY_MIN (interp_mem_stats_print_indentation, INTERP_MEM_PRINT_INDENTATION_MAX); char indent_prefix[INTERP_MEM_PRINT_INDENTATION_MAX + 2]; memset (indent_prefix, ' ', sizeof (indent_prefix)); indent_prefix[indentation] = '|'; indent_prefix[indentation + 1] = '\0'; mem_heap_stats_t heap_stats_after; mem_pools_stats_t pools_stats_after; interp_mem_get_stats (&heap_stats_after, &pools_stats_after, false, true); frame_ctx_p->context_peak_allocated_heap_bytes = JERRY_MAX (frame_ctx_p->context_peak_allocated_heap_bytes, heap_stats_after.allocated_bytes); frame_ctx_p->context_peak_waste_heap_bytes = JERRY_MAX (frame_ctx_p->context_peak_waste_heap_bytes, heap_stats_after.waste_bytes); frame_ctx_p->context_peak_pools_count = JERRY_MAX (frame_ctx_p->context_peak_pools_count, pools_stats_after.pools_count); frame_ctx_p->context_peak_allocated_pool_chunks = JERRY_MAX (frame_ctx_p->context_peak_allocated_pool_chunks, pools_stats_after.allocated_chunks); vm_instr_t instr = vm_get_instr (frame_ctx_p->instrs_p, instr_position); printf ("%s Allocated heap bytes: %5u -> %5u (%+5d, local %5u, peak %5u)\n", indent_prefix, (uint32_t) heap_stats_before_p->allocated_bytes, (uint32_t) heap_stats_after.allocated_bytes, (uint32_t) (heap_stats_after.allocated_bytes - heap_stats_before_p->allocated_bytes), (uint32_t) (heap_stats_after.peak_allocated_bytes - JERRY_MAX (heap_stats_before_p->allocated_bytes, heap_stats_after.allocated_bytes)), (uint32_t) heap_stats_after.global_peak_allocated_bytes); if (heap_stats_before_p->waste_bytes != heap_stats_after.waste_bytes) { printf ("%s Waste heap bytes: %5u -> %5u (%+5d, local %5u, peak %5u)\n", indent_prefix, (uint32_t) heap_stats_before_p->waste_bytes, (uint32_t) heap_stats_after.waste_bytes, (uint32_t) (heap_stats_after.waste_bytes - heap_stats_before_p->waste_bytes), (uint32_t) (heap_stats_after.peak_waste_bytes - JERRY_MAX (heap_stats_before_p->waste_bytes, heap_stats_after.waste_bytes)), (uint32_t) heap_stats_after.global_peak_waste_bytes); } if (pools_stats_before_p->pools_count != pools_stats_after.pools_count) { printf ("%s Pools: %5u -> %5u (%+5d, local %5u, peak %5u)\n", indent_prefix, (uint32_t) pools_stats_before_p->pools_count, (uint32_t) pools_stats_after.pools_count, (uint32_t) (pools_stats_after.pools_count - pools_stats_before_p->pools_count), (uint32_t) (pools_stats_after.peak_pools_count - JERRY_MAX (pools_stats_before_p->pools_count, pools_stats_after.pools_count)), (uint32_t) pools_stats_after.global_peak_pools_count); } if (pools_stats_before_p->allocated_chunks != pools_stats_after.allocated_chunks) { printf ("%s Allocated pool chunks: %5u -> %5u (%+5d, local %5u, peak %5u)\n", indent_prefix, (uint32_t) pools_stats_before_p->allocated_chunks, (uint32_t) pools_stats_after.allocated_chunks, (uint32_t) (pools_stats_after.allocated_chunks - pools_stats_before_p->allocated_chunks), (uint32_t) (pools_stats_after.peak_allocated_chunks - JERRY_MAX (pools_stats_before_p->allocated_chunks, pools_stats_after.allocated_chunks)), (uint32_t) pools_stats_after.global_peak_allocated_chunks); } printf ("%s-- End of execution of opcode %s (position %u) --\n\n", indent_prefix, __op_names[instr.op_idx], instr_position); }
static void interp_mem_stats_context_exit (vm_frame_ctx_t *frame_ctx_p, vm_instr_counter_t block_position) { if (likely (!interp_mem_stats_enabled)) { return; } const uint32_t indentation = JERRY_MIN (interp_mem_stats_print_indentation, INTERP_MEM_PRINT_INDENTATION_MAX); char indent_prefix[INTERP_MEM_PRINT_INDENTATION_MAX + 2]; memset (indent_prefix, ' ', sizeof (indent_prefix)); indent_prefix[indentation] = '|'; indent_prefix[indentation + 1] = '\0'; mem_heap_stats_t heap_stats_context_exit; mem_pools_stats_t pools_stats_context_exit; interp_mem_get_stats (&heap_stats_context_exit, &pools_stats_context_exit, false, true); frame_ctx_p->context_peak_allocated_heap_bytes -= JERRY_MAX (frame_ctx_p->heap_stats_context_enter.allocated_bytes, heap_stats_context_exit.allocated_bytes); frame_ctx_p->context_peak_waste_heap_bytes -= JERRY_MAX (frame_ctx_p->heap_stats_context_enter.waste_bytes, heap_stats_context_exit.waste_bytes); frame_ctx_p->context_peak_pools_count -= JERRY_MAX (frame_ctx_p->pools_stats_context_enter.pools_count, pools_stats_context_exit.pools_count); frame_ctx_p->context_peak_allocated_pool_chunks -= JERRY_MAX (frame_ctx_p->pools_stats_context_enter.allocated_chunks, pools_stats_context_exit.allocated_chunks); printf ("%sAllocated heap bytes in the context: %5u -> %5u (%+5d, local %5u, peak %5u)\n", indent_prefix, (uint32_t) frame_ctx_p->heap_stats_context_enter.allocated_bytes, (uint32_t) heap_stats_context_exit.allocated_bytes, (uint32_t) (heap_stats_context_exit.allocated_bytes - frame_ctx_p->heap_stats_context_enter.allocated_bytes), (uint32_t) frame_ctx_p->context_peak_allocated_heap_bytes, (uint32_t) heap_stats_context_exit.global_peak_allocated_bytes); printf ("%sWaste heap bytes in the context: %5u -> %5u (%+5d, local %5u, peak %5u)\n", indent_prefix, (uint32_t) frame_ctx_p->heap_stats_context_enter.waste_bytes, (uint32_t) heap_stats_context_exit.waste_bytes, (uint32_t) (heap_stats_context_exit.waste_bytes - frame_ctx_p->heap_stats_context_enter.waste_bytes), (uint32_t) frame_ctx_p->context_peak_waste_heap_bytes, (uint32_t) heap_stats_context_exit.global_peak_waste_bytes); printf ("%sPools count in the context: %5u -> %5u (%+5d, local %5u, peak %5u)\n", indent_prefix, (uint32_t) frame_ctx_p->pools_stats_context_enter.pools_count, (uint32_t) pools_stats_context_exit.pools_count, (uint32_t) (pools_stats_context_exit.pools_count - frame_ctx_p->pools_stats_context_enter.pools_count), (uint32_t) frame_ctx_p->context_peak_pools_count, (uint32_t) pools_stats_context_exit.global_peak_pools_count); printf ("%sAllocated pool chunks in the context: %5u -> %5u (%+5d, local %5u, peak %5u)\n", indent_prefix, (uint32_t) frame_ctx_p->pools_stats_context_enter.allocated_chunks, (uint32_t) pools_stats_context_exit.allocated_chunks, (uint32_t) (pools_stats_context_exit.allocated_chunks - frame_ctx_p->pools_stats_context_enter.allocated_chunks), (uint32_t) frame_ctx_p->context_peak_allocated_pool_chunks, (uint32_t) pools_stats_context_exit.global_peak_allocated_chunks); printf ("\n%s--- End of interpretation of a block at position %u ---\n\n", indent_prefix, (uint32_t) block_position); }