1/* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16/**
17 * Allocator implementation
18 */
19#include "ecma-globals.h"
20#include "jcontext.h"
21#include "jmem.h"
22#include "jrt-libc-includes.h"
23
24#define JMEM_ALLOCATOR_INTERNAL
25#include "jmem-allocator-internal.h"
26
27#if ENABLED (JERRY_MEM_STATS)
28/**
29 * Register byte code allocation.
30 */
31void
32jmem_stats_allocate_byte_code_bytes (size_t byte_code_size)
33{
34  jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats);
35
36  heap_stats->byte_code_bytes += byte_code_size;
37
38  if (heap_stats->byte_code_bytes >= heap_stats->peak_byte_code_bytes)
39  {
40    heap_stats->peak_byte_code_bytes = heap_stats->byte_code_bytes;
41  }
42} /* jmem_stats_allocate_byte_code_bytes */
43
44/**
45 * Register byte code free.
46 */
47void
48jmem_stats_free_byte_code_bytes (size_t byte_code_size)
49{
50  jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats);
51
52  JERRY_ASSERT (heap_stats->byte_code_bytes >= byte_code_size);
53
54  heap_stats->byte_code_bytes -= byte_code_size;
55} /* jmem_stats_free_byte_code_bytes */
56
57/**
58 * Register string allocation.
59 */
60void
61jmem_stats_allocate_string_bytes (size_t string_size)
62{
63  jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats);
64
65  heap_stats->string_bytes += string_size;
66
67  if (heap_stats->string_bytes >= heap_stats->peak_string_bytes)
68  {
69    heap_stats->peak_string_bytes = heap_stats->string_bytes;
70  }
71} /* jmem_stats_allocate_string_bytes */
72
73/**
74 * Register string free.
75 */
76void
77jmem_stats_free_string_bytes (size_t string_size)
78{
79  jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats);
80
81  JERRY_ASSERT (heap_stats->string_bytes >= string_size);
82
83  heap_stats->string_bytes -= string_size;
84} /* jmem_stats_free_string_bytes */
85
86/**
87 * Register object allocation.
88 */
89void
90jmem_stats_allocate_object_bytes (size_t object_size)
91{
92  jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats);
93
94  heap_stats->object_bytes += object_size;
95
96  if (heap_stats->object_bytes >= heap_stats->peak_object_bytes)
97  {
98    heap_stats->peak_object_bytes = heap_stats->object_bytes;
99  }
100} /* jmem_stats_allocate_object_bytes */
101
102/**
103 * Register object free.
104 */
105void
106jmem_stats_free_object_bytes (size_t object_size)
107{
108  jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats);
109
110  JERRY_ASSERT (heap_stats->object_bytes >= object_size);
111
112  heap_stats->object_bytes -= object_size;
113} /* jmem_stats_free_object_bytes */
114
115/**
116 * Register property allocation.
117 */
118void
119jmem_stats_allocate_property_bytes (size_t property_size)
120{
121  jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats);
122
123  heap_stats->property_bytes += property_size;
124
125  if (heap_stats->property_bytes >= heap_stats->peak_property_bytes)
126  {
127    heap_stats->peak_property_bytes = heap_stats->property_bytes;
128  }
129} /* jmem_stats_allocate_property_bytes */
130
131/**
132 * Register property free.
133 */
134void
135jmem_stats_free_property_bytes (size_t property_size)
136{
137  jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats);
138
139  JERRY_ASSERT (heap_stats->property_bytes >= property_size);
140
141  heap_stats->property_bytes -= property_size;
142} /* jmem_stats_free_property_bytes */
143
144#endif /* ENABLED (JERRY_MEM_STATS) */
145
146/**
147 * Initialize memory allocators.
148 */
149void
150jmem_init (void)
151{
152  jmem_heap_init ();
153} /* jmem_init */
154
155/**
156 * Finalize memory allocators.
157 */
158void
159jmem_finalize (void)
160{
161  jmem_pools_finalize ();
162
163#if ENABLED (JERRY_MEM_STATS)
164  if (JERRY_CONTEXT (jerry_init_flags) & ECMA_INIT_MEM_STATS)
165  {
166    jmem_heap_stats_print ();
167  }
168#endif /* ENABLED (JERRY_MEM_STATS) */
169
170  jmem_heap_finalize ();
171} /* jmem_finalize */
172
173/**
174 * Compress pointer
175 *
176 * @return packed pointer
177 */
178inline jmem_cpointer_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
179jmem_compress_pointer (const void *pointer_p) /**< pointer to compress */
180{
181  JERRY_ASSERT (pointer_p != NULL);
182  JERRY_ASSERT (jmem_is_heap_pointer (pointer_p));
183
184  uintptr_t uint_ptr = (uintptr_t) pointer_p;
185
186  JERRY_ASSERT (uint_ptr % JMEM_ALIGNMENT == 0);
187
188#if defined (ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY) && ENABLED (JERRY_CPOINTER_32_BIT)
189  JERRY_ASSERT (((jmem_cpointer_t) uint_ptr) == uint_ptr);
190#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY || !ENABLED (JERRY_CPOINTER_32_BIT) */
191  const uintptr_t heap_start = (uintptr_t) &JERRY_HEAP_CONTEXT (first);
192
193  uint_ptr -= heap_start;
194  uint_ptr >>= JMEM_ALIGNMENT_LOG;
195
196#if ENABLED (JERRY_CPOINTER_32_BIT)
197  JERRY_ASSERT (uint_ptr <= UINT32_MAX);
198#else /* !ENABLED (JERRY_CPOINTER_32_BIT) */
199  JERRY_ASSERT (uint_ptr <= UINT16_MAX);
200#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
201  JERRY_ASSERT (uint_ptr != JMEM_CP_NULL);
202#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY && ENABLED (JERRY_CPOINTER_32_BIT) */
203
204  return (jmem_cpointer_t) uint_ptr;
205} /* jmem_compress_pointer */
206
207/**
208 * Decompress pointer
209 *
210 * @return unpacked pointer
211 */
212inline void * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
213jmem_decompress_pointer (uintptr_t compressed_pointer) /**< pointer to decompress */
214{
215  JERRY_ASSERT (compressed_pointer != JMEM_CP_NULL);
216
217  uintptr_t uint_ptr = compressed_pointer;
218
219  JERRY_ASSERT (((jmem_cpointer_t) uint_ptr) == uint_ptr);
220
221#if defined (ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY) && ENABLED (JERRY_CPOINTER_32_BIT)
222  JERRY_ASSERT (uint_ptr % JMEM_ALIGNMENT == 0);
223#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY || !ENABLED (JERRY_CPOINTER_32_BIT) */
224  const uintptr_t heap_start = (uintptr_t) &JERRY_HEAP_CONTEXT (first);
225
226  uint_ptr <<= JMEM_ALIGNMENT_LOG;
227  uint_ptr += heap_start;
228
229  JERRY_ASSERT (jmem_is_heap_pointer ((void *) uint_ptr));
230#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY && ENABLED (JERRY_CPOINTER_32_BIT) */
231
232  return (void *) uint_ptr;
233} /* jmem_decompress_pointer */
234