Files
jerryscript/jerry-core/jmem/jmem-poolman.c
T
Akos Kiss a2d5acb43c Follow-up refactoring of logging-related parts
This patch:
* Ensures that all calls to `jerry_port_log` in jerry-core happen
  via macros defined in jrt.h. Also, it unifies the names of those
  macros: as `JERRY_ERROR_MSG` and `JERRY_WARNING_MSG` gave a good
  pattern that was well aligned with the naming scheme of the log
  level enum, `JERRY_DLOG` and `JERRY_DDLOG` were rewritten to
  `JERRY_DEBUG_MSG` and `JERRY_TRACE_MSG`.
* Ensures that all debug logging code parts of jerry-core (i.e.,
  memory statistics, JS byte-code dumps, and RegExp byte-code
  dumps) are guarded by macros: `JMEM_STATS`,
  `PARSER_DUMP_BYTE_CODE`, and `REGEXP_DUMP_BYTE_CODE`, which in
  turn are controled by cmake build system feature flags
  `FEATURE_MEM_STATS`, `FEATURE_PARSER_DUMP`, and
  `FEATURE_REGEXP_DUMP`.
* Ensures that all debug logging functionalities can be controled
  during run time (provided that they were enabled during build
  time): the engine has `JERRY_INIT_MEM_STATS[_SEPARATE]`,
  `JERRY_INIT_SHOW_OPCODES`, `JERRY_INIT_SHOW_REGEXP_OPCODES` init
  flags, and the default unix/linux command line app has
  corresponding command line switches.`
* Drops `FEATURE_LOG`, `JERRY_ENABLE_LOG`, and
  `JERRY_INIT_ENABLE_LOG`, as their name was misleadingly general,
  even though they mostly controled the regexp engine only. The
  above-mentioned `*REGEXP*` things mostly act as their
  replacements.
* Updates build, test, and measurement tool scripts, and
  documentation.

JerryScript-DCO-1.0-Signed-off-by: Akos Kiss akiss@inf.u-szeged.hu
2016-08-11 22:00:12 +02:00

280 lines
7.7 KiB
C

/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2016 University of Szeged.
*
* 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.
*/
/**
* Memory pool manager implementation
*/
#include "jcontext.h"
#include "jmem-allocator.h"
#include "jmem-heap.h"
#include "jmem-poolman.h"
#include "jrt-libc-includes.h"
#define JMEM_ALLOCATOR_INTERNAL
#include "jmem-allocator-internal.h"
/** \addtogroup mem Memory allocation
* @{
*
* \addtogroup poolman Memory pool manager
* @{
*/
#ifdef JMEM_STATS
static void jmem_pools_stat_free_pool (void);
static void jmem_pools_stat_new_alloc (void);
static void jmem_pools_stat_reuse (void);
static void jmem_pools_stat_dealloc (void);
# define JMEM_POOLS_STAT_FREE_POOL() jmem_pools_stat_free_pool ()
# define JMEM_POOLS_STAT_NEW_ALLOC() jmem_pools_stat_new_alloc ()
# define JMEM_POOLS_STAT_REUSE() jmem_pools_stat_reuse ()
# define JMEM_POOLS_STAT_DEALLOC() jmem_pools_stat_dealloc ()
#else /* !JMEM_STATS */
# define JMEM_POOLS_STAT_FREE_POOL()
# define JMEM_POOLS_STAT_NEW_ALLOC()
# define JMEM_POOLS_STAT_REUSE()
# define JMEM_POOLS_STAT_DEALLOC()
#endif /* JMEM_STATS */
/*
* Valgrind-related options and headers
*/
#ifdef JERRY_VALGRIND
# include "memcheck.h"
# define VALGRIND_NOACCESS_SPACE(p, s) VALGRIND_MAKE_MEM_NOACCESS((p), (s))
# define VALGRIND_UNDEFINED_SPACE(p, s) VALGRIND_MAKE_MEM_UNDEFINED((p), (s))
# define VALGRIND_DEFINED_SPACE(p, s) VALGRIND_MAKE_MEM_DEFINED((p), (s))
#else /* !JERRY_VALGRIND */
# define VALGRIND_NOACCESS_SPACE(p, s)
# define VALGRIND_UNDEFINED_SPACE(p, s)
# define VALGRIND_DEFINED_SPACE(p, s)
#endif /* JERRY_VALGRIND */
#ifdef JERRY_VALGRIND_FREYA
# include "memcheck.h"
# define VALGRIND_FREYA_MALLOCLIKE_SPACE(p, s) VALGRIND_MALLOCLIKE_BLOCK((p), (s), 0, 0)
# define VALGRIND_FREYA_FREELIKE_SPACE(p) VALGRIND_FREELIKE_BLOCK((p), 0)
#else /* !JERRY_VALGRIND_FREYA */
# define VALGRIND_FREYA_MALLOCLIKE_SPACE(p, s)
# define VALGRIND_FREYA_FREELIKE_SPACE(p)
#endif /* JERRY_VALGRIND_FREYA */
JERRY_STATIC_ASSERT (sizeof (jmem_pools_chunk_t) <= JMEM_POOL_CHUNK_SIZE,
size_of_mem_pools_chunk_t_must_be_less_than_or_equal_to_MEM_POOL_CHUNK_SIZE);
/**
* Finalize pool manager
*/
void
jmem_pools_finalize (void)
{
jmem_pools_collect_empty ();
JERRY_ASSERT (JERRY_CONTEXT (jmem_free_chunk_p) == NULL);
} /* jmem_pools_finalize */
/**
* 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 */
/**
* Free the chunk
*/
void __attribute__((hot))
jmem_pools_free (void *chunk_p) /**< pointer to the chunk */
{
jmem_pools_chunk_t *const chunk_to_free_p = (jmem_pools_chunk_t *) chunk_p;
VALGRIND_DEFINED_SPACE (chunk_to_free_p, JMEM_POOL_CHUNK_SIZE);
chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_chunk_p);
JERRY_CONTEXT (jmem_free_chunk_p) = chunk_to_free_p;
VALGRIND_NOACCESS_SPACE (chunk_to_free_p, JMEM_POOL_CHUNK_SIZE);
JMEM_POOLS_STAT_FREE_POOL ();
} /* jmem_pools_free */
/**
* Collect empty pool chunks
*/
void
jmem_pools_collect_empty ()
{
while (JERRY_CONTEXT (jmem_free_chunk_p))
{
VALGRIND_DEFINED_SPACE (JERRY_CONTEXT (jmem_free_chunk_p), sizeof (jmem_pools_chunk_t));
jmem_pools_chunk_t *const next_p = JERRY_CONTEXT (jmem_free_chunk_p)->next_p;
VALGRIND_NOACCESS_SPACE (JERRY_CONTEXT (jmem_free_chunk_p), sizeof (jmem_pools_chunk_t));
jmem_heap_free_block (JERRY_CONTEXT (jmem_free_chunk_p), JMEM_POOL_CHUNK_SIZE);
JMEM_POOLS_STAT_DEALLOC ();
JERRY_CONTEXT (jmem_free_chunk_p) = next_p;
}
} /* jmem_pools_collect_empty */
#ifdef JMEM_STATS
/**
* Get pools memory usage statistics
*/
void
jmem_pools_get_stats (jmem_pools_stats_t *out_pools_stats_p) /**< [out] pools' stats */
{
JERRY_ASSERT (out_pools_stats_p != NULL);
*out_pools_stats_p = JERRY_CONTEXT (jmem_pools_stats);
} /* jmem_pools_get_stats */
/**
* Reset peak values in memory usage statistics
*/
void
jmem_pools_stats_reset_peak (void)
{
JERRY_CONTEXT (jmem_pools_stats).peak_pools_count = JERRY_CONTEXT (jmem_pools_stats.pools_count);
} /* jmem_pools_stats_reset_peak */
/**
* Print pools memory usage statistics
*/
void
jmem_pools_stats_print (void)
{
jmem_pools_stats_t *pools_stats = &JERRY_CONTEXT (jmem_pools_stats);
JERRY_DEBUG_MSG ("Pools stats:\n"
" Chunk size: %zu\n"
" Pool chunks: %zu\n"
" Peak pool chunks: %zu\n"
" Free chunks: %zu\n"
" Pool reuse ratio: %zu.%04zu\n",
JMEM_POOL_CHUNK_SIZE,
pools_stats->pools_count,
pools_stats->peak_pools_count,
pools_stats->free_chunks,
pools_stats->reused_count / pools_stats->new_alloc_count,
pools_stats->reused_count % pools_stats->new_alloc_count * 10000 / pools_stats->new_alloc_count);
} /* jmem_pools_stats_print */
/**
* Account for allocation of new pool chunk
*/
static void
jmem_pools_stat_new_alloc (void)
{
jmem_pools_stats_t *pools_stats = &JERRY_CONTEXT (jmem_pools_stats);
pools_stats->pools_count++;
pools_stats->new_alloc_count++;
if (pools_stats->pools_count > pools_stats->peak_pools_count)
{
pools_stats->peak_pools_count = pools_stats->pools_count;
}
if (pools_stats->pools_count > pools_stats->global_peak_pools_count)
{
pools_stats->global_peak_pools_count = pools_stats->pools_count;
}
} /* jmem_pools_stat_new_alloc */
/**
* Account for reuse of pool chunk
*/
static void
jmem_pools_stat_reuse (void)
{
jmem_pools_stats_t *pools_stats = &JERRY_CONTEXT (jmem_pools_stats);
pools_stats->pools_count++;
pools_stats->free_chunks--;
pools_stats->reused_count++;
if (pools_stats->pools_count > pools_stats->peak_pools_count)
{
pools_stats->peak_pools_count = pools_stats->pools_count;
}
if (pools_stats->pools_count > pools_stats->global_peak_pools_count)
{
pools_stats->global_peak_pools_count = pools_stats->pools_count;
}
} /* jmem_pools_stat_reuse */
/**
* Account for freeing a chunk
*/
static void
jmem_pools_stat_free_pool (void)
{
jmem_pools_stats_t *pools_stats = &JERRY_CONTEXT (jmem_pools_stats);
JERRY_ASSERT (pools_stats->pools_count > 0);
pools_stats->pools_count--;
pools_stats->free_chunks++;
} /* jmem_pools_stat_free_pool */
/**
* Account for freeing a chunk
*/
static void
jmem_pools_stat_dealloc (void)
{
JERRY_CONTEXT (jmem_pools_stats).free_chunks--;
} /* jmem_pools_stat_dealloc */
#endif /* JMEM_STATS */
/**
* @}
* @}
*/