mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Allocate stack memory by chunks
This commit is contained in:
parent
1c3bf4951d
commit
9d129e15dc
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,6 +4,8 @@ out/
|
||||
|
||||
# IDE related files
|
||||
nbproject
|
||||
**.sublime-project
|
||||
**.sublime-workspace
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
#ifndef HASH_TABLE_H
|
||||
#define HASH_TABLE_H
|
||||
|
||||
#include "linked-list.h"
|
||||
|
||||
#define DEFINE_BACKET_TYPE(NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
typedef struct \
|
||||
{ \
|
||||
@ -35,11 +37,14 @@ typedef struct \
|
||||
__packed \
|
||||
NAME##_backet;
|
||||
|
||||
TODO (/*Rewrite to NAME##_backet **backets when neccesary*/)
|
||||
#define DEFINE_HASH_TYPE(NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
typedef struct \
|
||||
{ \
|
||||
uint8_t size; \
|
||||
NAME##_backet_stack *backets; \
|
||||
uint8_t max_lens; \
|
||||
uint8_t *lens; \
|
||||
NAME##_backet *backets; \
|
||||
} \
|
||||
__packed \
|
||||
NAME##_hash_table;
|
||||
@ -47,19 +52,19 @@ NAME##_hash_table;
|
||||
#define HASH_INIT(NAME, SIZE) \
|
||||
do { \
|
||||
NAME.size = SIZE; \
|
||||
size_t size = mem_heap_recommend_allocation_size (SIZE * sizeof (NAME##_backet_stack)); \
|
||||
NAME.backets = (NAME##_backet_stack *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
__memset (NAME.backets, 0, size); \
|
||||
size_t backets_size = mem_heap_recommend_allocation_size (SIZE * sizeof (NAME##_backet)); \
|
||||
size_t lens_size = mem_heap_recommend_allocation_size (SIZE); \
|
||||
NAME.backets = (NAME##_backet *) mem_heap_alloc_block (backets_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
NAME.lens = mem_heap_alloc_block (lens_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
__memset (NAME.backets, 0, SIZE); \
|
||||
__memset (NAME.lens, 0, SIZE); \
|
||||
NAME.max_lens = 1; \
|
||||
} while (0);
|
||||
|
||||
#define HASH_FREE(NAME) \
|
||||
do { \
|
||||
for (uint8_t i = 0; i < NAME.size; i++) { \
|
||||
if (NAME.backets[i].length != 0) { \
|
||||
mem_heap_free_block ((uint8_t *) NAME.backets[i].data); \
|
||||
} \
|
||||
} \
|
||||
mem_heap_free_block ((uint8_t *) NAME.backets); \
|
||||
mem_heap_free_block (NAME.lens); \
|
||||
} while (0)
|
||||
|
||||
#define DEFINE_HASH_INSERT(NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
@ -69,42 +74,9 @@ static void hash_insert_##NAME (KEY_TYPE key, VALUE_TYPE value) { \
|
||||
uint8_t hash = KEY_TYPE##_hash (key); \
|
||||
JERRY_ASSERT (hash < NAME.size); \
|
||||
JERRY_ASSERT (NAME.backets != NULL); \
|
||||
if (NAME.backets[hash].length == 0) \
|
||||
{ \
|
||||
size_t stack_size = mem_heap_recommend_allocation_size (0); \
|
||||
NAME.backets[hash].data = (NAME##_backet *) mem_heap_alloc_block \
|
||||
(stack_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
NAME.backets[hash].current = 0; \
|
||||
NAME.backets[hash].length = (__typeof__ (NAME.backets[hash].length)) \
|
||||
(stack_size / sizeof (NAME##_backet)); \
|
||||
} \
|
||||
else if (NAME.backets[hash].current == NAME.backets[hash].length) \
|
||||
{ \
|
||||
size_t old_size = NAME.backets[hash].length * sizeof (NAME##_backet); \
|
||||
size_t temp1_size = mem_heap_recommend_allocation_size ( \
|
||||
(size_t) (sizeof (NAME##_backet))); \
|
||||
size_t new_size = mem_heap_recommend_allocation_size ( \
|
||||
(size_t) (temp1_size + old_size)); \
|
||||
NAME##_backet *temp1 = (NAME##_backet *) mem_heap_alloc_block \
|
||||
(temp1_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
NAME##_backet *temp2 = (NAME##_backet *) mem_heap_alloc_block \
|
||||
(old_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
if (temp2 == NULL) \
|
||||
{ \
|
||||
mem_heap_print (true, false, true); \
|
||||
JERRY_UNREACHABLE (); \
|
||||
} \
|
||||
__memcpy (temp2, NAME.backets[hash].data, old_size); \
|
||||
mem_heap_free_block ((uint8_t *) NAME.backets[hash].data); \
|
||||
mem_heap_free_block ((uint8_t *) temp1); \
|
||||
NAME.backets[hash].data = (NAME##_backet *) mem_heap_alloc_block \
|
||||
(new_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
__memcpy (NAME.backets[hash].data, temp2, old_size); \
|
||||
mem_heap_free_block ((uint8_t *) temp2); \
|
||||
NAME.backets[hash].length = (__typeof__ (NAME.backets[hash].length)) \
|
||||
(new_size / sizeof (NAME##_backet)); \
|
||||
} \
|
||||
NAME.backets[hash].data[NAME.backets[hash].current++] = backet; \
|
||||
JERRY_ASSERT (NAME.lens[hash] == 0); \
|
||||
NAME.backets[hash] = backet; \
|
||||
NAME.lens[hash] = 1; \
|
||||
}
|
||||
|
||||
#define HASH_INSERT(NAME, KEY, VALUE) \
|
||||
@ -114,16 +86,17 @@ do { \
|
||||
|
||||
#define DEFINE_HASH_LOOKUP(NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
static VALUE_TYPE *lookup_##NAME (KEY_TYPE key) __unused; \
|
||||
static VALUE_TYPE *lookup_##NAME (KEY_TYPE key) { \
|
||||
static VALUE_TYPE *lookup_##NAME (KEY_TYPE key) \
|
||||
{ \
|
||||
uint8_t hash = KEY_TYPE##_hash (key); \
|
||||
JERRY_ASSERT (hash < NAME.size); \
|
||||
if (NAME.backets[hash].length == 0) { \
|
||||
if (NAME.lens[hash] == 0) \
|
||||
{ \
|
||||
return NULL; \
|
||||
} \
|
||||
for (size_t i = 0; i < NAME.backets[hash].current; i++) { \
|
||||
if (KEY_TYPE##_equal (NAME.backets[hash].data[i].key, key)) { \
|
||||
return &NAME.backets[hash].data[i].value; \
|
||||
} \
|
||||
if (KEY_TYPE##_equal (NAME.backets[hash].key, key)) \
|
||||
{ \
|
||||
return &NAME.backets[hash].value; \
|
||||
} \
|
||||
return NULL; \
|
||||
}
|
||||
@ -133,7 +106,6 @@ lookup_##NAME (KEY)
|
||||
|
||||
#define HASH_TABLE(NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
DEFINE_BACKET_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
DEFINE_STACK_TYPE (NAME##_backet, uint8_t, NAME##_backet) \
|
||||
DEFINE_HASH_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
NAME##_hash_table NAME; \
|
||||
DEFINE_HASH_INSERT (NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
@ -141,7 +113,6 @@ DEFINE_HASH_LOOKUP (NAME, KEY_TYPE, VALUE_TYPE)
|
||||
|
||||
#define STATIC_HASH_TABLE(NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
DEFINE_BACKET_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
DEFINE_STACK_TYPE (NAME##_backet, uint8_t, NAME##_backet) \
|
||||
DEFINE_HASH_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
static NAME##_hash_table NAME; \
|
||||
DEFINE_HASH_INSERT (NAME, KEY_TYPE, VALUE_TYPE) \
|
||||
|
||||
49
src/libintstructs/linked-list.h
Normal file
49
src/libintstructs/linked-list.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* 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 LINKED_LIST_H
|
||||
#define LINKED_LIST_H
|
||||
|
||||
#define DEFINE_LINKED_LIST_TYPE(NAME, TYPE) \
|
||||
typedef struct NAME##_linked_list \
|
||||
{ \
|
||||
struct NAME##_linked_list *next; \
|
||||
struct NAME##_linked_list *prev; \
|
||||
} \
|
||||
__packed \
|
||||
NAME##_linked_list;
|
||||
|
||||
#define DEFINE_LIST_FREE(NAME) \
|
||||
static void free_##NAME##_linked_list (uint8_t *) __unused;\
|
||||
static void free_##NAME##_linked_list (uint8_t *list) { \
|
||||
if (((NAME##_linked_list *)list)->next) { \
|
||||
free_##NAME##_linked_list ((uint8_t *) ((NAME##_linked_list *)list)->next); \
|
||||
} \
|
||||
mem_heap_free_block (list); \
|
||||
}
|
||||
|
||||
#define DEFINE_LIST_ELEMENT(NAME, TYPE) \
|
||||
static TYPE NAME##_list_element (uint8_t *, uint8_t) __unused; \
|
||||
static TYPE NAME##_list_element (uint8_t * raw, uint8_t i) { \
|
||||
return ((TYPE *) (raw + sizeof (NAME##_linked_list)))[i]; \
|
||||
}
|
||||
|
||||
#define DEFINE_SET_LIST_ELEMENT(NAME, TYPE) \
|
||||
static void set_##NAME##_list_element (uint8_t *, uint8_t, TYPE) __unused; \
|
||||
static void set_##NAME##_list_element (uint8_t * raw, uint8_t i, TYPE value) { \
|
||||
((TYPE *) (raw + sizeof (NAME##_linked_list)))[i] = value; \
|
||||
}
|
||||
|
||||
#endif /* LINKED_LIST_H */
|
||||
@ -23,6 +23,11 @@
|
||||
DO NOT FORGET to free stack memory by calling STACK_FREE macro.
|
||||
For check usage of stack during a function, use STACK_DECLARE_USAGE and STACK_CHECK_USAGE macros.
|
||||
|
||||
For the purpose of memory fragmentation reduction, the memory is allocated by chunks and them are
|
||||
used to store data. The chunks are connected to each other in manner of double-linked list.
|
||||
|
||||
Macro STACK_CONVERT_TO_RAW_DATA allocates memory, so use it after finishing working with the stack.
|
||||
|
||||
Example (parser.c):
|
||||
|
||||
enum
|
||||
@ -61,12 +66,22 @@
|
||||
#ifndef STACK_H
|
||||
#define STACK_H
|
||||
|
||||
#include "linked-list.h"
|
||||
|
||||
#define DEFINE_STACK_TYPE(NAME, DATA_TYPE, TYPE) \
|
||||
DEFINE_LINKED_LIST_TYPE (NAME, TYPE) \
|
||||
DEFINE_LIST_FREE (NAME) \
|
||||
DEFINE_LIST_ELEMENT (NAME, TYPE) \
|
||||
DEFINE_SET_LIST_ELEMENT (NAME, TYPE) \
|
||||
typedef TYPE NAME##_stack_value_type; \
|
||||
typedef DATA_TYPE NAME##_stack_data_type; \
|
||||
typedef struct \
|
||||
{ \
|
||||
DATA_TYPE length; \
|
||||
DATA_TYPE current; \
|
||||
TYPE *data; \
|
||||
DATA_TYPE block_len; \
|
||||
uint8_t *blocks; \
|
||||
uint8_t *last; \
|
||||
} \
|
||||
__packed \
|
||||
NAME##_stack;
|
||||
@ -74,114 +89,212 @@ NAME##_stack;
|
||||
#define STACK_INIT(TYPE, NAME) \
|
||||
do { \
|
||||
size_t stack_size = mem_heap_recommend_allocation_size (sizeof (TYPE) * NAME##_global_size); \
|
||||
NAME.data = (TYPE *) mem_heap_alloc_block (stack_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
NAME.blocks = NAME.last = mem_heap_alloc_block (stack_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
__memset (NAME.blocks, 0, stack_size); \
|
||||
NAME.current = NAME##_global_size; \
|
||||
NAME.length = (__typeof__ (NAME.length)) (stack_size / sizeof (TYPE)); \
|
||||
NAME.length = NAME.block_len = (NAME##_stack_data_type) ((stack_size-sizeof (NAME##_linked_list)) / sizeof (TYPE)); \
|
||||
} while (0)
|
||||
|
||||
#define STACK_FREE(NAME) \
|
||||
do { \
|
||||
mem_heap_free_block ((uint8_t *) NAME.data); \
|
||||
free_##NAME##_linked_list (NAME.blocks); \
|
||||
NAME.length = NAME.current = 0; \
|
||||
} while (0)
|
||||
|
||||
/* In most cases (for example, in parser) default size of stack is enough.
|
||||
However, in serializer, there is a need for reallocation of memory.
|
||||
Do this in several steps:
|
||||
1) Allocate already allocated memory size twice.
|
||||
2) Copy used memory to the last.
|
||||
3) Dealocate first two chuncks.
|
||||
4) Allocate new memory. (It must point to the memory before increasing).
|
||||
5) Copy data back.
|
||||
6) Free temp buffer. */
|
||||
#define DEFINE_INCREASE_STACK_SIZE(NAME, TYPE) \
|
||||
static void increase_##NAME##_stack_size (__typeof__ (NAME.length)) __unused; \
|
||||
static void increase_##NAME##_stack_size (void) __unused; \
|
||||
static void \
|
||||
increase_##NAME##_stack_size (__typeof__ (NAME.length) elements_count) { \
|
||||
if (NAME.current + elements_count >= NAME.length) \
|
||||
increase_##NAME##_stack_size (void) { \
|
||||
if (NAME.current == NAME.length && ((NAME##_linked_list *) NAME.last)->next == NULL) \
|
||||
{ \
|
||||
size_t old_size = NAME.length * sizeof (TYPE); \
|
||||
size_t temp1_size = mem_heap_recommend_allocation_size ( \
|
||||
(size_t) (elements_count * sizeof (TYPE))); \
|
||||
size_t new_size = mem_heap_recommend_allocation_size ( \
|
||||
(size_t) (temp1_size + old_size)); \
|
||||
TYPE *temp1 = (TYPE *) mem_heap_alloc_block (temp1_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
TYPE *temp2 = (TYPE *) mem_heap_alloc_block (old_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
if (temp2 == NULL) \
|
||||
size_t temp_size = mem_heap_recommend_allocation_size ((size_t) (sizeof (NAME##_linked_list))); \
|
||||
JERRY_ASSERT ((temp_size-sizeof (NAME##_linked_list)) / sizeof (TYPE) == NAME.block_len); \
|
||||
NAME##_linked_list *temp = (NAME##_linked_list *) mem_heap_alloc_block ( \
|
||||
temp_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
if (temp == NULL) \
|
||||
{ \
|
||||
mem_heap_print (true, false, true); \
|
||||
JERRY_UNREACHABLE (); \
|
||||
} \
|
||||
__memcpy (temp2, NAME.data, old_size); \
|
||||
mem_heap_free_block ((uint8_t *) NAME.data); \
|
||||
mem_heap_free_block ((uint8_t *) temp1); \
|
||||
NAME.data = (TYPE *) mem_heap_alloc_block (new_size, MEM_HEAP_ALLOC_SHORT_TERM); \
|
||||
if (NAME.data == NULL) \
|
||||
{ \
|
||||
__printf ("old_size: %d\ntemp1_size: %d\nnew_size: %d\n", old_size, temp1_size, new_size); \
|
||||
mem_heap_print (true, false, true); \
|
||||
JERRY_UNREACHABLE (); \
|
||||
} \
|
||||
__memcpy (NAME.data, temp2, old_size); \
|
||||
mem_heap_free_block ((uint8_t *) temp2); \
|
||||
NAME.length = (__typeof__ (NAME.length)) (new_size / sizeof (TYPE)); \
|
||||
__memset (temp, 0, temp_size); \
|
||||
((NAME##_linked_list *) NAME.last)->next = temp; \
|
||||
temp->prev = (NAME##_linked_list *) NAME.last; \
|
||||
NAME.last = (uint8_t *) temp; \
|
||||
NAME.length = (NAME##_stack_data_type) (NAME.length + NAME.block_len); \
|
||||
} \
|
||||
NAME.current = (__typeof__ (NAME.current)) (NAME.current + elements_count); \
|
||||
NAME.current = (NAME##_stack_data_type) (NAME.current + 1); \
|
||||
}
|
||||
|
||||
#define DEFINE_DECREASE_STACE_SIZE(NAME) \
|
||||
static void decrease_##NAME##_stack_size (__typeof__ (NAME.length)) __unused; \
|
||||
#define DEFINE_DECREASE_STACE_SIZE(NAME, TYPE) \
|
||||
static void decrease_##NAME##_stack_size (void) __unused; \
|
||||
static void \
|
||||
decrease_##NAME##_stack_size (__typeof__ (NAME.length) elements_count) { \
|
||||
JERRY_ASSERT (NAME.current - elements_count >= NAME##_global_size); \
|
||||
NAME.current = (__typeof__ (NAME.current)) (NAME.current - elements_count); \
|
||||
decrease_##NAME##_stack_size (void) { \
|
||||
JERRY_ASSERT (NAME.current - 1 >= NAME##_global_size); \
|
||||
NAME.current = (NAME##_stack_data_type) (NAME.current - 1); \
|
||||
}
|
||||
|
||||
#define DEFINE_STACK_ELEMENT(NAME, TYPE) \
|
||||
static TYPE NAME##_stack_element (NAME##_stack_data_type) __unused; \
|
||||
static TYPE NAME##_stack_element (NAME##_stack_data_type elem) { \
|
||||
JERRY_ASSERT (elem < NAME.current); \
|
||||
NAME##_linked_list *block = (NAME##_linked_list *) NAME.blocks; \
|
||||
for (NAME##_stack_data_type i = 0; i < elem / NAME.block_len; i++) { \
|
||||
JERRY_ASSERT (block->next); \
|
||||
block = block->next; \
|
||||
} \
|
||||
return NAME##_list_element ((uint8_t *) block, (uint8_t) ((elem)%NAME.block_len)); \
|
||||
}
|
||||
|
||||
#define DEFINE_SET_STACK_ELEMENT(NAME, TYPE) \
|
||||
static void set_##NAME##_stack_element (NAME##_stack_data_type, TYPE) __unused; \
|
||||
static void set_##NAME##_stack_element (NAME##_stack_data_type elem, TYPE value) { \
|
||||
JERRY_ASSERT (elem < NAME.current); \
|
||||
NAME##_linked_list *block = (NAME##_linked_list *) NAME.blocks; \
|
||||
for (NAME##_stack_data_type i = 0; i < elem / NAME.block_len; i++) { \
|
||||
JERRY_ASSERT (block->next); \
|
||||
block = block->next; \
|
||||
} \
|
||||
set_##NAME##_list_element ((uint8_t *) block, (uint8_t) ((elem)%NAME.block_len), value); \
|
||||
}
|
||||
|
||||
#define DEFINE_STACK_HEAD(NAME, TYPE) \
|
||||
static TYPE NAME##_stack_head (NAME##_stack_data_type) __unused; \
|
||||
static TYPE NAME##_stack_head (NAME##_stack_data_type elem) { \
|
||||
JERRY_ASSERT (elem <= NAME.current); \
|
||||
JERRY_ASSERT (elem <= NAME.block_len); \
|
||||
if ((NAME.current % NAME.block_len) < elem) { \
|
||||
return NAME##_list_element ((uint8_t *) ((NAME##_linked_list *) NAME.last)->prev, \
|
||||
(uint8_t) ((NAME.current % NAME.block_len) - elem + NAME.block_len)); \
|
||||
} else { \
|
||||
return NAME##_list_element (NAME.last, (uint8_t) ((NAME.current % NAME.block_len) - elem)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEFINE_SET_STACK_HEAD(NAME, DATA_TYPE, TYPE) \
|
||||
static void set_##NAME##_stack_head (DATA_TYPE, TYPE) __unused; \
|
||||
static void set_##NAME##_stack_head (DATA_TYPE elem, TYPE value) { \
|
||||
JERRY_ASSERT (elem <= NAME.current); \
|
||||
JERRY_ASSERT (elem <= NAME.block_len); \
|
||||
if ((NAME.current % NAME.block_len) < elem) { \
|
||||
set_##NAME##_list_element ((uint8_t *) ((NAME##_linked_list *) NAME.last)->prev, \
|
||||
(uint8_t) ((NAME.current % NAME.block_len) - elem + NAME.block_len), value); \
|
||||
} else { \
|
||||
set_##NAME##_list_element (NAME.last, (uint8_t) ((NAME.current % NAME.block_len) - elem), value); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEFINE_STACK_PUSH(NAME, TYPE) \
|
||||
static void NAME##_stack_push (TYPE) __unused; \
|
||||
static void NAME##_stack_push (TYPE value) { \
|
||||
if (NAME.current % NAME.block_len == 0 && NAME.current != 0) { \
|
||||
increase_##NAME##_stack_size (); \
|
||||
set_##NAME##_list_element (NAME.last, (uint8_t) ((NAME.current - 1) % NAME.block_len), value); \
|
||||
} else { \
|
||||
set_##NAME##_list_element (NAME.last, (uint8_t) ((NAME.current) % NAME.block_len), value); \
|
||||
increase_##NAME##_stack_size (); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEFINE_CONVERT_TO_RAW_DATA(NAME, TYPE) \
|
||||
static TYPE *convert_##NAME##_to_raw_data (void) __unused; \
|
||||
static TYPE *convert_##NAME##_to_raw_data (void) { \
|
||||
size_t size = mem_heap_recommend_allocation_size ( \
|
||||
((size_t) (NAME.current + 1) * sizeof (NAME##_stack_value_type))); \
|
||||
TYPE *DATA = (TYPE *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM); \
|
||||
__memset (DATA, 0, size); \
|
||||
for (NAME##_stack_data_type i = 0; i < NAME.current; i++) { \
|
||||
DATA[i] = STACK_ELEMENT (NAME, i); \
|
||||
} \
|
||||
return DATA; \
|
||||
}
|
||||
|
||||
#define STACK_PUSH(NAME, VALUE) \
|
||||
do { \
|
||||
increase_##NAME##_stack_size (1); \
|
||||
NAME.data[NAME.current - 1] = VALUE; \
|
||||
} while (0)
|
||||
do { NAME##_stack_push (VALUE); } while (0)
|
||||
|
||||
#define STACK_POP(NAME, VALUE) \
|
||||
do { \
|
||||
decrease_##NAME##_stack_size (1); \
|
||||
VALUE = NAME.data[NAME.current]; \
|
||||
decrease_##NAME##_stack_size (); \
|
||||
VALUE = NAME##_list_element (NAME.last, (uint8_t) (NAME.current % NAME.block_len)); \
|
||||
} while (0)
|
||||
|
||||
#define STACK_DROP(NAME, I) \
|
||||
do { decrease_##NAME##_stack_size ((__typeof__(NAME.current))(I)); } while (0)
|
||||
do { \
|
||||
JERRY_ASSERT ((I) >= 0); \
|
||||
for (size_t i = 0; i < (size_t) (I); i++) { \
|
||||
decrease_##NAME##_stack_size (); } } while (0)
|
||||
|
||||
#define STACK_CLEAN(NAME) \
|
||||
STACK_DROP (NAME, NAME.current - NAME##_global_size);
|
||||
|
||||
#define STACK_HEAD(NAME, I) \
|
||||
NAME.data[NAME.current - I]
|
||||
NAME##_stack_head ((NAME##_stack_data_type) (I))
|
||||
|
||||
#define STACK_SET_HEAD(NAME, I, VALUE) \
|
||||
do { set_##NAME##_stack_head ((NAME##_stack_data_type) (I), VALUE); } while (0)
|
||||
|
||||
#define STACK_INCR_HEAD(NAME, I) \
|
||||
do { STACK_SET_HEAD (NAME, I, (NAME##_stack_value_type) (STACK_HEAD (NAME, I) + 1)); } while (0)
|
||||
|
||||
#define STACK_TOP(NAME) \
|
||||
STACK_HEAD (NAME, 1)
|
||||
|
||||
#define STACK_SWAP(NAME) \
|
||||
do { \
|
||||
NAME##_stack_value_type temp = STACK_TOP(NAME); \
|
||||
STACK_SET_HEAD(NAME, 1, STACK_HEAD(NAME, 2)); \
|
||||
STACK_SET_HEAD(NAME, 2, temp); \
|
||||
} while (0)
|
||||
|
||||
#define STACK_SIZE(NAME) \
|
||||
NAME.current
|
||||
|
||||
#define STACK_ELEMENT(NAME, I) \
|
||||
NAME.data[I]
|
||||
NAME##_stack_element ((NAME##_stack_data_type) (I))
|
||||
|
||||
#define STACK_RAW_DATA(NAME) \
|
||||
NAME.data
|
||||
#define STACK_SET_ELEMENT(NAME, I, VALUE) \
|
||||
do { set_##NAME##_stack_element ((NAME##_stack_data_type) I, VALUE); } while (0);
|
||||
|
||||
#define STACK_CONVERT_TO_RAW_DATA(NAME, DATA) \
|
||||
do { DATA = convert_##NAME##_to_raw_data (); } while (0)
|
||||
|
||||
#define STACK_INCR_ELEMENT(NAME, I) \
|
||||
do { STACK_SET_ELEMENT (NAME, I, (NAME##_stack_value_type) (STACK_ELEMENT(NAME, I) + 1)); } while (0)
|
||||
|
||||
#define STACK_DECR_ELEMENT(NAME, I) \
|
||||
do { STACK_SET_ELEMENT (NAME, I, (NAME##_stack_value_type) (STACK_ELEMENT(NAME, I) - 1)); } while (0)
|
||||
|
||||
#define STACK_ITERATE_VARG(NAME, FUNC, ...) \
|
||||
do { for (NAME##_stack_data_type i = 0; i < NAME.current; i++) { \
|
||||
FUNC (STACK_ELEMENT (NAME, i), __VA_ARGS__); \
|
||||
} } while (0)
|
||||
|
||||
#define STACK(NAME, DATA_TYPE, TYPE) \
|
||||
DEFINE_STACK_TYPE(NAME, DATA_TYPE, TYPE) \
|
||||
NAME##_stack NAME; \
|
||||
DEFINE_DECREASE_STACE_SIZE (NAME) \
|
||||
DEFINE_INCREASE_STACK_SIZE (NAME, TYPE)
|
||||
DEFINE_DECREASE_STACE_SIZE (NAME, TYPE) \
|
||||
DEFINE_INCREASE_STACK_SIZE (NAME, TYPE) \
|
||||
DEFINE_STACK_ELEMENT(NAME, TYPE) \
|
||||
DEFINE_SET_STACK_ELEMENT(NAME, TYPE) \
|
||||
DEFINE_STACK_HEAD(NAME, TYPE) \
|
||||
DEFINE_CONVERT_TO_RAW_DATA(NAME, TYPE) \
|
||||
DEFINE_SET_STACK_HEAD(NAME, DATA_TYPE, TYPE) \
|
||||
DEFINE_STACK_PUSH(NAME, TYPE)
|
||||
|
||||
#define STATIC_STACK(NAME, DATA_TYPE, TYPE) \
|
||||
DEFINE_STACK_TYPE(NAME, DATA_TYPE, TYPE) \
|
||||
static NAME##_stack NAME; \
|
||||
DEFINE_DECREASE_STACE_SIZE (NAME) \
|
||||
DEFINE_INCREASE_STACK_SIZE (NAME, TYPE)
|
||||
DEFINE_DECREASE_STACE_SIZE (NAME, TYPE) \
|
||||
DEFINE_INCREASE_STACK_SIZE (NAME, TYPE) \
|
||||
DEFINE_STACK_ELEMENT(NAME, TYPE) \
|
||||
DEFINE_SET_STACK_ELEMENT(NAME, TYPE) \
|
||||
DEFINE_STACK_HEAD(NAME, TYPE) \
|
||||
DEFINE_CONVERT_TO_RAW_DATA(NAME, TYPE) \
|
||||
DEFINE_SET_STACK_HEAD(NAME, DATA_TYPE, TYPE) \
|
||||
DEFINE_STACK_PUSH(NAME, TYPE)
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
#define STACK_DECLARE_USAGE(NAME) \
|
||||
__typeof__(NAME.current) NAME##_current = NAME.current;
|
||||
NAME##_stack_data_type NAME##_current = NAME.current;
|
||||
#define STACK_CHECK_USAGE(NAME) \
|
||||
do { \
|
||||
JERRY_ASSERT (NAME.current == NAME##_current); \
|
||||
|
||||
@ -496,7 +496,7 @@ convert_current_token_to_token (token_type tt)
|
||||
|
||||
for (uint8_t i = 0; i < STACK_SIZE (strings); i++)
|
||||
{
|
||||
if (current_token_equals_to_lp (strings.data[i]))
|
||||
if (current_token_equals_to_lp (STACK_ELEMENT (strings, i)))
|
||||
{
|
||||
return (token)
|
||||
{
|
||||
@ -529,12 +529,12 @@ convert_seen_num_to_token (ecma_number_t num)
|
||||
JERRY_ASSERT (STACK_SIZE (num_ids) == STACK_SIZE (numbers));
|
||||
for (uint8_t i = 0; i < STACK_SIZE (numbers); i++)
|
||||
{
|
||||
if (numbers.data[i] == num)
|
||||
if (STACK_ELEMENT (numbers, i) == num)
|
||||
{
|
||||
return (token)
|
||||
{
|
||||
.type = TOK_NUMBER,
|
||||
.uid = num_ids.data[i]
|
||||
.uid = STACK_ELEMENT (num_ids, i)
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -553,7 +553,9 @@ convert_seen_num_to_token (ecma_number_t num)
|
||||
const lp_string *
|
||||
lexer_get_strings (void)
|
||||
{
|
||||
return STACK_RAW_DATA (strings);
|
||||
lp_string *data = NULL;
|
||||
STACK_CONVERT_TO_RAW_DATA (strings, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
@ -578,7 +580,9 @@ lexer_get_string_by_id (uint8_t id)
|
||||
const ecma_number_t *
|
||||
lexer_get_nums (void)
|
||||
{
|
||||
return STACK_RAW_DATA (numbers);
|
||||
ecma_number_t *data = NULL;
|
||||
STACK_CONVERT_TO_RAW_DATA (numbers, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
@ -593,7 +597,7 @@ lexer_adjust_num_ids (void)
|
||||
JERRY_ASSERT (STACK_SIZE (numbers) == STACK_SIZE (num_ids));
|
||||
for (uint8_t i = 0; i < STACK_SIZE (numbers); i++)
|
||||
{
|
||||
STACK_ELEMENT (num_ids, i) = (uint8_t) (STACK_ELEMENT (num_ids, i) + STACK_SIZE (strings));
|
||||
STACK_SET_ELEMENT (num_ids, i, (uint8_t) (STACK_ELEMENT (num_ids, i) + STACK_SIZE (strings)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,8 @@
|
||||
#include "deserializer.h"
|
||||
#include "bytecode-data.h"
|
||||
|
||||
static opcode_t *raw_bytecode;
|
||||
|
||||
const ecma_char_t *
|
||||
deserialize_string_by_id (uint8_t id)
|
||||
{
|
||||
@ -41,7 +43,9 @@ const void *
|
||||
deserialize_bytecode (void)
|
||||
{
|
||||
JERRY_ASSERT (STACK_SIZE (bytecode_opcodes) > 0);
|
||||
return STACK_RAW_DATA (bytecode_opcodes);
|
||||
JERRY_ASSERT (raw_bytecode == NULL);
|
||||
STACK_CONVERT_TO_RAW_DATA (bytecode_opcodes, raw_bytecode);
|
||||
return raw_bytecode;
|
||||
}
|
||||
|
||||
opcode_t
|
||||
@ -57,3 +61,22 @@ deserialize_min_temp (void)
|
||||
{
|
||||
return (uint8_t) (bytecode_data.strs_count + bytecode_data.nums_count);
|
||||
}
|
||||
|
||||
void
|
||||
deserializer_init (void)
|
||||
{
|
||||
raw_bytecode = NULL;
|
||||
STACK_INIT (opcode_t, bytecode_opcodes);
|
||||
}
|
||||
|
||||
void
|
||||
deserializer_free (void)
|
||||
{
|
||||
STACK_FREE (bytecode_opcodes);
|
||||
if (raw_bytecode)
|
||||
{
|
||||
mem_heap_free_block ((uint8_t *) raw_bytecode);
|
||||
}
|
||||
mem_heap_free_block ((uint8_t *) bytecode_data.strings);
|
||||
mem_heap_free_block ((uint8_t *) bytecode_data.nums);
|
||||
}
|
||||
|
||||
@ -20,10 +20,12 @@
|
||||
#include "ecma-globals.h"
|
||||
#include "opcodes.h"
|
||||
|
||||
void deserializer_init (void);
|
||||
const ecma_char_t *deserialize_string_by_id (uint8_t);
|
||||
ecma_number_t deserialize_num_by_id (uint8_t);
|
||||
const void *deserialize_bytecode (void);
|
||||
opcode_t deserialize_opcode (opcode_counter_t);
|
||||
uint8_t deserialize_min_temp (void);
|
||||
void deserializer_free (void);
|
||||
|
||||
#endif //DESERIALIZER_H
|
||||
|
||||
@ -61,7 +61,7 @@ void
|
||||
serializer_rewrite_opcode (const opcode_counter_t loc, opcode_t opcode)
|
||||
{
|
||||
JERRY_ASSERT (loc < STACK_SIZE (bytecode_opcodes));
|
||||
STACK_ELEMENT (bytecode_opcodes, loc) = opcode;
|
||||
STACK_SET_ELEMENT (bytecode_opcodes, loc, opcode);
|
||||
|
||||
if (print_opcodes)
|
||||
{
|
||||
@ -102,11 +102,9 @@ void
|
||||
serializer_init (bool show_opcodes)
|
||||
{
|
||||
print_opcodes = show_opcodes;
|
||||
STACK_INIT (opcode_t, bytecode_opcodes);
|
||||
}
|
||||
|
||||
void
|
||||
serializer_free (void)
|
||||
{
|
||||
STACK_FREE (bytecode_opcodes);
|
||||
}
|
||||
|
||||
@ -39,6 +39,7 @@ jerry_run (const char *script_source, size_t script_source_size,
|
||||
const opcode_t *opcodes;
|
||||
|
||||
mem_init ();
|
||||
deserializer_init ();
|
||||
|
||||
parser_init (script_source, script_source_size, is_show_opcodes);
|
||||
parser_parse_program ();
|
||||
@ -50,10 +51,11 @@ jerry_run (const char *script_source, size_t script_source_size,
|
||||
#ifdef __TARGET_HOST_x64
|
||||
serializer_print_opcodes ();
|
||||
#endif
|
||||
parser_free ();
|
||||
|
||||
if (is_parse_only)
|
||||
{
|
||||
parser_free ();
|
||||
deserializer_free ();
|
||||
mem_finalize (is_show_mem_stats);
|
||||
return true;
|
||||
}
|
||||
@ -62,8 +64,7 @@ jerry_run (const char *script_source, size_t script_source_size,
|
||||
|
||||
bool is_success = run_int ();
|
||||
|
||||
parser_free ();
|
||||
|
||||
deserializer_free ();
|
||||
mem_finalize (is_show_mem_stats);
|
||||
|
||||
return is_success;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user