diff --git a/.gitignore b/.gitignore index 0a33559ef..ef0ba35df 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ out/ # IDE related files nbproject +**.sublime-project +**.sublime-workspace # Compiled Object files *.slo diff --git a/src/libintstructs/hash-table.h b/src/libintstructs/hash-table.h index b112d95c4..5fd2c2e4e 100644 --- a/src/libintstructs/hash-table.h +++ b/src/libintstructs/hash-table.h @@ -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) \ diff --git a/src/libintstructs/linked-list.h b/src/libintstructs/linked-list.h new file mode 100644 index 000000000..528e5bf88 --- /dev/null +++ b/src/libintstructs/linked-list.h @@ -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 */ diff --git a/src/libintstructs/stack.h b/src/libintstructs/stack.h index 3ea4d934b..f00c103c5 100644 --- a/src/libintstructs/stack.h +++ b/src/libintstructs/stack.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); \ diff --git a/src/libjsparser/lexer.c b/src/libjsparser/lexer.c index c388a2638..a056278f9 100644 --- a/src/libjsparser/lexer.c +++ b/src/libjsparser/lexer.c @@ -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))); } } diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index 272e9209a..2069673a3 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -66,6 +66,8 @@ enum }; STATIC_STACK (IDX, uint8_t, uint8_t) +#define ID(I) STACK_HEAD(IDX, I) + enum { nestings_global_size @@ -84,12 +86,21 @@ STATIC_STACK (temp_names, uint8_t, uint8_t) #define MAX_TEMP_NAME() \ GLOBAL(temp_names, max_temp_name) +#define SET_MAX_TEMP_NAME(S) \ +do { STACK_SET_ELEMENT (temp_names, max_temp_name, S); } while (0) + #define MIN_TEMP_NAME() \ GLOBAL(temp_names, min_temp_name) +#define SET_MIN_TEMP_NAME(S) \ +do { STACK_SET_ELEMENT (temp_names, min_temp_name, S); } while (0) + #define TEMP_NAME() \ GLOBAL(temp_names, temp_name) +#define SET_TEMP_NAME(S) \ +do { STACK_SET_ELEMENT (temp_names, temp_name, S); } while (0) + enum { tok = 0, @@ -100,16 +111,15 @@ STATIC_STACK (toks, uint8_t, token) #define TOK() \ GLOBAL(toks, tok) +#define SET_TOK(S) \ +do { STACK_SET_ELEMENT (toks, tok, S); } while (0) + enum { - opcode = 0, ops_global_size }; STATIC_STACK (ops, uint8_t, opcode_t) -#define OPCODE() \ -GLOBAL(ops, opcode) - enum { opcode_counter = 0, @@ -120,6 +130,15 @@ STATIC_STACK (U16, uint8_t, uint16_t) #define OPCODE_COUNTER() \ GLOBAL(U16, opcode_counter) +#define SET_OPCODE_COUNTER(S) \ +do { STACK_SET_ELEMENT (U16, opcode_counter, S); } while (0) + +#define INCR_OPCODE_COUNTER() \ +do { STACK_INCR_ELEMENT(U16, opcode_counter); } while (0) + +#define DECR_OPCODE_COUNTER() \ +do { STACK_DECR_ELEMENT(U16, opcode_counter); } while (0) + enum { rewritable_continue_global_size @@ -154,26 +173,23 @@ do { skip_newlines (); parse_##TYPE (); } while (0) #define DUMP_VOID_OPCODE(GETOP) \ do { \ - OPCODE()=getop_##GETOP (); \ - serializer_dump_opcode (OPCODE()); \ - OPCODE_COUNTER()++; \ + serializer_dump_opcode (getop_##GETOP ()); \ + INCR_OPCODE_COUNTER(); \ } while (0) #define DUMP_OPCODE_1(GETOP, OP1) \ do { \ JERRY_ASSERT (0+OP1 <= 255); \ - OPCODE()=getop_##GETOP ((idx_t) (OP1)); \ - serializer_dump_opcode (OPCODE()); \ - OPCODE_COUNTER()++; \ + serializer_dump_opcode (getop_##GETOP ((idx_t) (OP1))); \ + INCR_OPCODE_COUNTER(); \ } while (0) #define DUMP_OPCODE_2(GETOP, OP1, OP2) \ do { \ JERRY_ASSERT (0+OP1 <= 255); \ JERRY_ASSERT (0+OP2 <= 255); \ - OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2)); \ - serializer_dump_opcode (OPCODE()); \ - OPCODE_COUNTER()++; \ + serializer_dump_opcode (getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2))); \ + INCR_OPCODE_COUNTER(); \ } while (0) #define DUMP_OPCODE_3(GETOP, OP1, OP2, OP3) \ @@ -181,30 +197,26 @@ do { \ JERRY_ASSERT (0+OP1 <= 255); \ JERRY_ASSERT (0+OP2 <= 255); \ JERRY_ASSERT (0+OP3 <= 255); \ - OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2), (idx_t) (OP3)); \ - serializer_dump_opcode (OPCODE()); \ - OPCODE_COUNTER()++; \ + serializer_dump_opcode (getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2), (idx_t) (OP3))); \ + INCR_OPCODE_COUNTER(); \ } while (0) #define REWRITE_VOID_OPCODE(OC, GETOP) \ do { \ - OPCODE()=getop_##GETOP (); \ - serializer_rewrite_opcode (OC, OPCODE()); \ + serializer_rewrite_opcode (OC, getop_##GETOP ()); \ } while (0) #define REWRITE_OPCODE_1(OC, GETOP, OP1) \ do { \ JERRY_ASSERT (0+OP1 <= 255); \ - OPCODE()=getop_##GETOP ((idx_t) (OP1)); \ - serializer_rewrite_opcode (OC, OPCODE()); \ + serializer_rewrite_opcode (OC, getop_##GETOP ((idx_t) (OP1))); \ } while (0) #define REWRITE_OPCODE_2(OC, GETOP, OP1, OP2) \ do { \ JERRY_ASSERT (0+OP1 <= 255); \ JERRY_ASSERT (0+OP2 <= 255); \ - OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2)); \ - serializer_rewrite_opcode (OC, OPCODE()); \ + serializer_rewrite_opcode (OC, getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2))); \ } while (0) #define REWRITE_OPCODE_3(OC, GETOP, OP1, OP2, OP3) \ @@ -212,8 +224,7 @@ do { \ JERRY_ASSERT (0+OP1 <= 255); \ JERRY_ASSERT (0+OP2 <= 255); \ JERRY_ASSERT (0+OP3 <= 255); \ - OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2), (idx_t) (OP3)); \ - serializer_rewrite_opcode (OC, OPCODE()); \ + serializer_rewrite_opcode (OC, getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2), (idx_t) (OP3))); \ } while (0) #define REWRITE_COND_JMP(OC, GETOP, DIFF) \ @@ -223,9 +234,8 @@ do { \ JERRY_STATIC_ASSERT (sizeof (idx_t) == 1); \ STACK_PUSH (IDX, (idx_t) ((DIFF) >> JERRY_BITSINBYTE)); \ STACK_PUSH (IDX, (idx_t) ((DIFF) & ((1 << JERRY_BITSINBYTE) - 1))); \ - JERRY_ASSERT ((DIFF) == calc_opcode_counter_from_idx_idx (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1))); \ - OPCODE()=getop_##GETOP (STACK_HEAD (IDX, 3), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); \ - serializer_rewrite_opcode (OC, OPCODE()); \ + JERRY_ASSERT ((DIFF) == calc_opcode_counter_from_idx_idx (ID(2), ID(1))); \ + serializer_rewrite_opcode (OC, getop_##GETOP (ID(3), ID(2), ID(1))); \ STACK_DROP (IDX, 2); \ STACK_CHECK_USAGE (IDX); \ } while (0) @@ -237,9 +247,8 @@ do { \ JERRY_STATIC_ASSERT (sizeof (idx_t) == 1); \ STACK_PUSH (IDX, (idx_t) ((DIFF) >> JERRY_BITSINBYTE)); \ STACK_PUSH (IDX, (idx_t) ((DIFF) & ((1 << JERRY_BITSINBYTE) - 1))); \ - JERRY_ASSERT ((DIFF) == calc_opcode_counter_from_idx_idx (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1))); \ - OPCODE()=getop_##GETOP (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); \ - serializer_rewrite_opcode (OC, OPCODE()); \ + JERRY_ASSERT ((DIFF) == calc_opcode_counter_from_idx_idx (ID(2), ID(1))); \ + serializer_rewrite_opcode (OC, getop_##GETOP (ID(2), ID(1))); \ STACK_DROP (IDX, 2); \ STACK_CHECK_USAGE (IDX); \ } while (0) @@ -251,9 +260,8 @@ do { \ STACK_PUSH (IDX, (idx_t) ((OPCODE_COUNTER ()) >> JERRY_BITSINBYTE)); \ STACK_PUSH (IDX, (idx_t) ((OPCODE_COUNTER ()) & ((1 << JERRY_BITSINBYTE) - 1))); \ JERRY_ASSERT ((OPCODE_COUNTER ()) \ - == calc_opcode_counter_from_idx_idx (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1))); \ - OPCODE()=getop_try (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); \ - serializer_rewrite_opcode ((OC), OPCODE()); \ + == calc_opcode_counter_from_idx_idx (ID(2), ID(1))); \ + serializer_rewrite_opcode ((OC), getop_try (ID(2), ID(1))); \ STACK_DROP (IDX, 2); \ STACK_CHECK_USAGE (IDX); \ } while (0) @@ -284,32 +292,34 @@ lp_string_hash (lp_string str) static idx_t next_temp_name (void) { - TEMP_NAME ()++; + idx_t res = TEMP_NAME (); + STACK_INCR_ELEMENT (temp_names, temp_name); if (MAX_TEMP_NAME () < TEMP_NAME ()) { - MAX_TEMP_NAME () = TEMP_NAME (); + SET_MAX_TEMP_NAME (TEMP_NAME ()); } - return TEMP_NAME (); + return res; } static void start_new_scope (void) { STACK_PUSH (temp_names, MAX_TEMP_NAME()); - MAX_TEMP_NAME() = MIN_TEMP_NAME(); + SET_MAX_TEMP_NAME (MIN_TEMP_NAME ()); } static void finish_scope (void) { - STACK_POP (temp_names, TEMP_NAME()); - MAX_TEMP_NAME() = TEMP_NAME(); + SET_TEMP_NAME (STACK_HEAD (temp_names, 1)); + STACK_DROP (temp_names, 1); + SET_MAX_TEMP_NAME (TEMP_NAME ()); } static void reset_temp_name (void) { - TEMP_NAME() = MIN_TEMP_NAME(); + SET_TEMP_NAME (MIN_TEMP_NAME ()); } static void @@ -332,27 +342,33 @@ must_be_inside_but_not_in (uint8_t *inside, uint8_t insides_count, uint8_t not_i STACK_PUSH (U8, 0); STACK_PUSH (U8, 0); #define I() STACK_HEAD (U8, 2) -#define J() STACK_HEAD (U8, 1) +#define J() STACK_TOP (U8) +#define SET_I(S) STACK_SET_HEAD (U8, 2, (uint8_t) (S)) +#define SET_J(S) STACK_SET_HEAD (U8, 1, (uint8_t) (S)) if (STACK_SIZE(nestings) == 0) { parser_fatal (ERR_PARSER); } - for (I() = (uint8_t) (STACK_SIZE(nestings)); I() != 0; I()--) + SET_I(STACK_SIZE(nestings)); + while (I() != 0) { - if (nestings.data[I() - 1] == not_in) + if (STACK_ELEMENT (nestings, I() - 1) == not_in) { parser_fatal (ERR_PARSER); } - for (J() = 0; J() < insides_count; J()++) + SET_J(0); + while (J() < insides_count) { - if (nestings.data[I() - 1] == inside[J()]) + if (STACK_ELEMENT (nestings, I() - 1) == inside[J()]) { goto cleanup; } + SET_J(J()+1); } + SET_I(I()-1); } parser_fatal (ERR_PARSER); @@ -361,6 +377,8 @@ cleanup: STACK_DROP (U8, 2); #undef I #undef J +#undef SET_I +#undef SET_J STACK_CHECK_USAGE (U8); } @@ -379,7 +397,7 @@ token_data (void) static void skip_token (void) { - TOK() = lexer_next_token (); + SET_TOK(lexer_next_token ()); } static void @@ -461,7 +479,7 @@ integer_zero (void) STACK_DECLARE_USAGE (IDX) STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 1), OPCODE_ARG_TYPE_SMALLINT, 0); + DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_SMALLINT, 0); STACK_CHECK_USAGE_LHS (); } @@ -472,7 +490,7 @@ boolean_true (void) STACK_DECLARE_USAGE (IDX) STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 1), OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_TRUE); + DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_TRUE); STACK_CHECK_USAGE_LHS (); } @@ -488,6 +506,18 @@ add_to_rewritable_opcodes (rewritable_opcode_type type, opcode_counter_t oc) } } +static void +rewrite_breaks (opcode_counter_t break_oc, opcode_counter_t dest_oc) +{ + REWRITE_JMP (break_oc, jmp_down, dest_oc - break_oc); +} + +static void +rewrite_continues (opcode_counter_t cont_oc, opcode_counter_t dest_oc) +{ + REWRITE_JMP (cont_oc, jmp_up, cont_oc - dest_oc); +} + static void rewrite_rewritable_opcodes (rewritable_opcode_type type, opcode_counter_t oc) { @@ -499,21 +529,13 @@ rewrite_rewritable_opcodes (rewritable_opcode_type type, opcode_counter_t oc) { case REWRITABLE_BREAK: { - for (STACK_HEAD (U8, 1) = 0; STACK_HEAD (U8, 1) < STACK_SIZE (rewritable_break); STACK_HEAD (U8, 1)++) - { - REWRITE_JMP (STACK_ELEMENT (rewritable_break, STACK_HEAD (U8, 1)), jmp_down, - oc - STACK_ELEMENT (rewritable_break, STACK_HEAD (U8, 1))); - } + STACK_ITERATE_VARG (rewritable_break, rewrite_breaks, oc); STACK_CLEAN (rewritable_break); break; } case REWRITABLE_CONTINUE: { - for (STACK_HEAD (U8, 1) = 0; STACK_HEAD (U8, 1) < STACK_SIZE (rewritable_continue); STACK_HEAD (U8, 1)++) - { - REWRITE_JMP (STACK_ELEMENT (rewritable_continue, STACK_HEAD (U8, 1)), jmp_up, - STACK_ELEMENT (rewritable_continue, STACK_HEAD (U8, 1)) - oc); - } + STACK_ITERATE_VARG (rewritable_continue, rewrite_continues, oc); STACK_CLEAN (rewritable_continue); break; } @@ -560,7 +582,7 @@ is_intrinsic (idx_t obj) STACK_DECLARE_USAGE (U8) STACK_PUSH (U8, lexer_get_strings_count ()); - if (obj < STACK_HEAD (U8, 1)) + if (obj < STACK_TOP (U8)) { if (HASH_LOOKUP (intrinsics, lexer_get_string_by_id (obj)) != NULL) { @@ -651,7 +673,7 @@ parse_property_name (void) case TOK_SMALL_INT: { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 1), OPCODE_ARG_TYPE_SMALLINT, token_data ()); + DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_SMALLINT, token_data ()); break; } default: @@ -694,9 +716,9 @@ rewrite_meta_opcode_counter (opcode_counter_t meta_oc, opcode_meta_type type) STACK_PUSH (IDX, (idx_t) (OPCODE_COUNTER () >> JERRY_BITSINBYTE)); STACK_PUSH (IDX, (idx_t) (OPCODE_COUNTER () & ((1 << JERRY_BITSINBYTE) - 1))); - JERRY_ASSERT (OPCODE_COUNTER () == calc_opcode_counter_from_idx_idx (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1))); + JERRY_ASSERT (OPCODE_COUNTER () == calc_opcode_counter_from_idx_idx (ID(2), ID(1))); - REWRITE_OPCODE_3 (meta_oc, meta, type, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); + REWRITE_OPCODE_3 (meta_oc, meta, type, ID(2), ID(1)); STACK_DROP (IDX, 2); @@ -733,8 +755,8 @@ parse_property_assignment (void) token_after_newlines_must_be (TOK_CLOSE_BRACE); DUMP_VOID_OPCODE (ret); - rewrite_meta_opcode_counter (STACK_HEAD (U16, 1), OPCODE_META_TYPE_FUNCTION_END); - DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_VARG_PROP_GETTER, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); + rewrite_meta_opcode_counter (STACK_TOP (U16), OPCODE_META_TYPE_FUNCTION_END); + DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_VARG_PROP_GETTER, ID(2), ID(1)); STACK_DROP (IDX, 2); STACK_DROP (U16, 1); @@ -756,8 +778,8 @@ parse_property_assignment (void) token_after_newlines_must_be (TOK_CLOSE_BRACE); DUMP_VOID_OPCODE (ret); - rewrite_meta_opcode_counter (STACK_HEAD (U16, 1), OPCODE_META_TYPE_FUNCTION_END); - DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_VARG_PROP_SETTER, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); + rewrite_meta_opcode_counter (STACK_TOP (U16), OPCODE_META_TYPE_FUNCTION_END); + DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_VARG_PROP_SETTER, ID(2), ID(1)); STACK_DROP (IDX, 2); STACK_DROP (U16, 1); @@ -799,7 +821,7 @@ parse_argument_list (argument_list_type alt, idx_t obj) STACK_PUSH (U8, TOK_OPEN_PAREN); STACK_PUSH (U8, TOK_CLOSE_PAREN); STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (func_expr_n, STACK_HEAD (IDX, 1), obj, INVALID_VALUE); + DUMP_OPCODE_3 (func_expr_n, ID(1), obj, INVALID_VALUE); break; } case AL_CONSTRUCT_EXPR: @@ -807,7 +829,7 @@ parse_argument_list (argument_list_type alt, idx_t obj) STACK_PUSH (U8, TOK_OPEN_PAREN); STACK_PUSH (U8, TOK_CLOSE_PAREN); STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (construct_n, STACK_HEAD (IDX, 1), obj, INVALID_VALUE); + DUMP_OPCODE_3 (construct_n, ID(1), obj, INVALID_VALUE); break; } case AL_CALL_EXPR: @@ -821,13 +843,13 @@ parse_argument_list (argument_list_type alt, idx_t obj) else if (is_native_call (obj)) { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (native_call, STACK_HEAD (IDX, 1), + DUMP_OPCODE_3 (native_call, ID(1), name_to_native_call_id (obj), INVALID_VALUE); } else { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (call_n, STACK_HEAD (IDX, 1), obj, INVALID_VALUE); + DUMP_OPCODE_3 (call_n, ID(1), obj, INVALID_VALUE); } break; } @@ -836,7 +858,7 @@ parse_argument_list (argument_list_type alt, idx_t obj) STACK_PUSH (U8, TOK_OPEN_SQUARE); STACK_PUSH (U8, TOK_CLOSE_SQUARE); STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_2 (array_decl, STACK_HEAD (IDX, 1), INVALID_VALUE); + DUMP_OPCODE_2 (array_decl, ID(1), INVALID_VALUE); break; } case AL_OBJ_DECL: @@ -844,7 +866,7 @@ parse_argument_list (argument_list_type alt, idx_t obj) STACK_PUSH (U8, TOK_OPEN_BRACE); STACK_PUSH (U8, TOK_CLOSE_BRACE); STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_2 (obj_decl, STACK_HEAD (IDX, 1), INVALID_VALUE); + DUMP_OPCODE_2 (obj_decl, ID(1), INVALID_VALUE); break; } default: @@ -880,7 +902,7 @@ parse_argument_list (argument_list_type alt, idx_t obj) parse_assignment_expression (); if (is_intrinsic (obj)) { - dump_intrinsic (obj, STACK_HEAD (IDX, 1)); + dump_intrinsic (obj, ID(1)); goto next; } break; @@ -898,10 +920,10 @@ parse_argument_list (argument_list_type alt, idx_t obj) if (alt != AL_OBJ_DECL) { - DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_VARG, STACK_HEAD (IDX, 1), INVALID_VALUE); + DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_VARG, ID(1), INVALID_VALUE); STACK_DROP (IDX, 1); } - STACK_HEAD(U8, 1)++; + STACK_INCR_HEAD(U8, 1); next: skip_newlines (); @@ -918,17 +940,17 @@ next: { case AL_FUNC_DECL: { - REWRITE_OPCODE_2 (STACK_HEAD (U16, 1), func_decl_n, obj, STACK_HEAD (U8, 1)); + REWRITE_OPCODE_2 (STACK_TOP (U16), func_decl_n, obj, STACK_TOP (U8)); break; } case AL_FUNC_EXPR: { - REWRITE_OPCODE_3 (STACK_HEAD (U16, 1), func_expr_n, STACK_HEAD (IDX, 1), obj, STACK_HEAD (U8, 1)); + REWRITE_OPCODE_3 (STACK_TOP (U16), func_expr_n, ID(1), obj, STACK_TOP (U8)); break; } case AL_CONSTRUCT_EXPR: { - REWRITE_OPCODE_3 (STACK_HEAD (U16, 1), construct_n, STACK_HEAD (IDX, 1), obj, STACK_HEAD (U8, 1)); + REWRITE_OPCODE_3 (STACK_TOP (U16), construct_n, ID(1), obj, STACK_TOP (U8)); break; } case AL_CALL_EXPR: @@ -939,24 +961,24 @@ next: } else if (is_native_call (obj)) { - REWRITE_OPCODE_3 (STACK_HEAD (U16, 1), native_call, STACK_HEAD (IDX, 1), - name_to_native_call_id (obj), STACK_HEAD (U8, 1)); + REWRITE_OPCODE_3 (STACK_TOP (U16), native_call, ID(1), + name_to_native_call_id (obj), STACK_TOP (U8)); } else { - REWRITE_OPCODE_3 (STACK_HEAD (U16, 1), call_n, STACK_HEAD (IDX, 1), obj, - STACK_HEAD (U8, 1)); + REWRITE_OPCODE_3 (STACK_TOP (U16), call_n, ID(1), obj, + STACK_TOP (U8)); } break; } case AL_ARRAY_DECL: { - REWRITE_OPCODE_2 (STACK_HEAD (U16, 1), array_decl, STACK_HEAD (IDX, 1), STACK_HEAD (U8, 1)); + REWRITE_OPCODE_2 (STACK_TOP (U16), array_decl, ID(1), STACK_TOP (U8)); break; } case AL_OBJ_DECL: { - REWRITE_OPCODE_2 (STACK_HEAD (U16, 1), obj_decl, STACK_HEAD (IDX, 1), STACK_HEAD (U8, 1)); + REWRITE_OPCODE_2 (STACK_TOP (U16), obj_decl, ID(1), STACK_TOP (U8)); break; } default: @@ -1006,7 +1028,7 @@ parse_function_declaration (void) STACK_PUSH (IDX, token_data ()); skip_newlines (); - parse_argument_list (AL_FUNC_DECL, STACK_HEAD (IDX, 1)); + parse_argument_list (AL_FUNC_DECL, ID(1)); STACK_PUSH (U16, OPCODE_COUNTER ()); DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_UNDEFINED, INVALID_VALUE, INVALID_VALUE); @@ -1022,7 +1044,7 @@ parse_function_declaration (void) DUMP_VOID_OPCODE (ret); - rewrite_meta_opcode_counter (STACK_HEAD (U16, 1), OPCODE_META_TYPE_FUNCTION_END); + rewrite_meta_opcode_counter (STACK_TOP (U16), OPCODE_META_TYPE_FUNCTION_END); STACK_DROP (U16, 1); STACK_DROP (IDX, 1); @@ -1058,7 +1080,7 @@ parse_function_expression (void) } skip_newlines (); - parse_argument_list (AL_FUNC_EXPR, STACK_HEAD (IDX, 1)); // push lhs + parse_argument_list (AL_FUNC_EXPR, ID(1)); // push lhs STACK_PUSH (U16, OPCODE_COUNTER ()); DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_UNDEFINED, INVALID_VALUE, INVALID_VALUE); @@ -1073,9 +1095,9 @@ parse_function_expression (void) token_after_newlines_must_be (TOK_CLOSE_BRACE); DUMP_VOID_OPCODE (ret); - rewrite_meta_opcode_counter (STACK_HEAD (U16, 1), OPCODE_META_TYPE_FUNCTION_END); + rewrite_meta_opcode_counter (STACK_TOP (U16), OPCODE_META_TYPE_FUNCTION_END); - STACK_HEAD (IDX, 2) = STACK_HEAD (IDX, 1); + STACK_SWAP (IDX); STACK_DROP (IDX, 1); STACK_DROP (U16, 1); @@ -1121,32 +1143,32 @@ parse_literal (void) case TOK_NULL: { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 1), OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_NULL); + DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_NULL); break; } case TOK_BOOL: { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 1), OPCODE_ARG_TYPE_SIMPLE, + DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_SIMPLE, token_data () ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); break; } case TOK_NUMBER: { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 1), OPCODE_ARG_TYPE_NUMBER, token_data ()); + DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_NUMBER, token_data ()); break; } case TOK_SMALL_INT: { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 1), OPCODE_ARG_TYPE_SMALLINT, token_data ()); + DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_SMALLINT, token_data ()); break; } case TOK_STRING: { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 1), OPCODE_ARG_TYPE_STRING, token_data ()); + DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_STRING, token_data ()); break; } default: @@ -1175,7 +1197,7 @@ parse_primary_expression (void) if (is_keyword (KW_THIS)) { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_1 (this, STACK_HEAD (IDX, 1)); + DUMP_OPCODE_1 (this, ID(1)); goto cleanup; } @@ -1262,9 +1284,9 @@ parse_member_expression (void) NEXT (member_expression); // push member skip_newlines (); - parse_argument_list (AL_CONSTRUCT_EXPR, STACK_HEAD (IDX, 1)); // push obj + parse_argument_list (AL_CONSTRUCT_EXPR, ID(1)); // push obj - STACK_HEAD (IDX, 2) = STACK_HEAD (IDX, 1); + STACK_SWAP (IDX); STACK_DROP (IDX, 1); } else @@ -1290,18 +1312,20 @@ parse_member_expression (void) parser_fatal (ERR_PARSER); } STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 1), OPCODE_ARG_TYPE_STRING, token_data ()); + DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_STRING, token_data ()); } else { JERRY_UNREACHABLE (); } - DUMP_OPCODE_3 (prop_getter, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 3), STACK_HEAD (IDX, 1)); - STACK_HEAD (IDX, 3) = STACK_HEAD (IDX, 2); + DUMP_OPCODE_3 (prop_getter, ID(2), ID(3), ID(1)); + STACK_DROP (IDX, 1); + STACK_SWAP (IDX); + skip_newlines (); - STACK_DROP (IDX, 2); + STACK_DROP (IDX, 1); } lexer_save_token (TOK ()); @@ -1337,8 +1361,8 @@ parse_call_expression (void) goto cleanup; } - parse_argument_list (AL_CALL_EXPR, STACK_HEAD (IDX, 1)); // push lhs - STACK_HEAD (IDX, 2) = STACK_HEAD (IDX, 1); + parse_argument_list (AL_CALL_EXPR, ID(1)); // push lhs + STACK_SWAP (IDX); skip_newlines (); while (token_is (TOK_OPEN_PAREN) || token_is (TOK_OPEN_SQUARE) @@ -1349,7 +1373,7 @@ parse_call_expression (void) case TOK_OPEN_PAREN: { STACK_DROP (IDX, 1); - parse_argument_list (AL_CALL_EXPR, STACK_HEAD (IDX, 1)); // push lhs + parse_argument_list (AL_CALL_EXPR, ID(1)); // push lhs skip_newlines (); break; } @@ -1358,9 +1382,9 @@ parse_call_expression (void) NEXT (expression); // push prop next_token_must_be (TOK_CLOSE_SQUARE); - DUMP_OPCODE_3 (prop_getter, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 3), STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (prop_getter, ID(2), ID(3), ID(1)); STACK_DROP (IDX, 1); - STACK_HEAD (IDX, 2) = STACK_HEAD (IDX, 1); + STACK_SWAP (IDX); skip_newlines (); break; } @@ -1369,9 +1393,9 @@ parse_call_expression (void) token_after_newlines_must_be (TOK_NAME); STACK_PUSH (IDX, token_data ()); - DUMP_OPCODE_3 (prop_getter, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 3), STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (prop_getter, ID(2), ID(3), ID(1)); STACK_DROP (IDX, 1); - STACK_HEAD (IDX, 2) = STACK_HEAD (IDX, 1); + STACK_SWAP (IDX); skip_newlines (); break; } @@ -1418,15 +1442,15 @@ parse_postfix_expression (void) if (token_is (TOK_DOUBLE_PLUS)) { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_2 (post_incr, STACK_HEAD (IDX, 1), STACK_HEAD (IDX, 2)); - STACK_HEAD (IDX, 2) = STACK_HEAD (IDX, 1); + DUMP_OPCODE_2 (post_incr, ID(1), ID(2)); + STACK_SWAP (IDX); STACK_DROP (IDX, 1); } else if (token_is (TOK_DOUBLE_MINUS)) { STACK_PUSH (IDX, next_temp_name ()); - DUMP_OPCODE_2 (post_decr, STACK_HEAD (IDX, 1), STACK_HEAD (IDX, 2)); - STACK_HEAD (IDX, 2) = STACK_HEAD (IDX, 1); + DUMP_OPCODE_2 (post_decr, ID(1), ID(2)); + STACK_SWAP (IDX); STACK_DROP (IDX, 1); } else @@ -1452,13 +1476,13 @@ parse_unary_expression (void) case TOK_DOUBLE_PLUS: { NEXT (unary_expression); - DUMP_OPCODE_2 (pre_incr, next_temp_name (), STACK_HEAD (IDX, 1)); + DUMP_OPCODE_2 (pre_incr, next_temp_name (), ID(1)); break; } case TOK_DOUBLE_MINUS: { NEXT (unary_expression); - DUMP_OPCODE_2 (pre_decr, next_temp_name (), STACK_HEAD (IDX, 1)); + DUMP_OPCODE_2 (pre_decr, next_temp_name (), ID(1)); break; } case TOK_PLUS: @@ -1466,7 +1490,7 @@ parse_unary_expression (void) STACK_PUSH (IDX, next_temp_name ()); NEXT (unary_expression); integer_zero (); - DUMP_OPCODE_3 (addition, STACK_HEAD (IDX, 3), STACK_HEAD (IDX, 1), STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (addition, ID(3), ID(1), ID(2)); STACK_DROP (IDX, 2); break; } @@ -1475,7 +1499,7 @@ parse_unary_expression (void) STACK_PUSH (IDX, next_temp_name ()); NEXT (unary_expression); integer_zero (); - DUMP_OPCODE_3 (substraction, STACK_HEAD (IDX, 3), STACK_HEAD (IDX, 1), STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (substraction, ID(3), ID(1), ID(2)); STACK_DROP (IDX, 2); break; } @@ -1483,7 +1507,7 @@ parse_unary_expression (void) { STACK_PUSH (IDX, next_temp_name ()); NEXT (unary_expression); - DUMP_OPCODE_2 (b_not, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); + DUMP_OPCODE_2 (b_not, ID(2), ID(1)); STACK_DROP (IDX, 1); break; } @@ -1491,7 +1515,7 @@ parse_unary_expression (void) { STACK_PUSH (IDX, next_temp_name ()); NEXT (unary_expression); - DUMP_OPCODE_2 (logical_not, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); + DUMP_OPCODE_2 (logical_not, ID(2), ID(1)); STACK_DROP (IDX, 1); break; } @@ -1513,7 +1537,7 @@ parse_unary_expression (void) { STACK_PUSH (IDX, next_temp_name ()); NEXT (unary_expression); - DUMP_OPCODE_2 (typeof, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); + DUMP_OPCODE_2 (typeof, ID(2), ID(1)); STACK_DROP (IDX, 1); break; } @@ -1532,9 +1556,10 @@ parse_unary_expression (void) do { \ STACK_PUSH (IDX, next_temp_name ()); \ NEXT (EXPR);\ - DUMP_OPCODE_3 (GETOP, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 3), STACK_HEAD (IDX, 1)); \ - STACK_HEAD (IDX, 3) = STACK_HEAD (IDX, 2); \ - STACK_DROP (IDX, 2); \ + DUMP_OPCODE_3 (GETOP, ID(2), ID(3), ID(1)); \ + STACK_DROP (IDX, 1); \ + STACK_SWAP (IDX); \ + STACK_DROP (IDX, 1); \ } while (0) /* multiplicative_expression @@ -1764,27 +1789,30 @@ parse_conditional_expression (void) skip_newlines (); if (token_is (TOK_QUERY)) { - DUMP_OPCODE_3 (is_true_jmp_down, STACK_HEAD (IDX, 1), 0, 2); + DUMP_OPCODE_3 (is_true_jmp_down, ID(1), 0, 2); STACK_PUSH (IDX, next_temp_name ()); STACK_PUSH (U16, OPCODE_COUNTER ()); DUMP_OPCODE_2 (jmp_down, INVALID_VALUE, INVALID_VALUE); NEXT (assignment_expression); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 2), OPCODE_ARG_TYPE_VARIABLE, STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (assignment, ID(2), OPCODE_ARG_TYPE_VARIABLE, ID(1)); token_after_newlines_must_be (TOK_COLON); - REWRITE_JMP (STACK_HEAD (U16, 1), jmp_down, OPCODE_COUNTER () - STACK_HEAD (U16, 1)); - STACK_HEAD (U16, 1) = OPCODE_COUNTER (); + REWRITE_JMP (STACK_TOP (U16), jmp_down, OPCODE_COUNTER () - STACK_TOP (U16)); + STACK_DROP (U16, 1); + STACK_PUSH (U16, OPCODE_COUNTER ()); DUMP_OPCODE_2 (jmp_down, INVALID_VALUE, INVALID_VALUE); STACK_DROP (IDX, 1); NEXT (assignment_expression); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 2), OPCODE_ARG_TYPE_VARIABLE, STACK_HEAD (IDX, 1)); - REWRITE_JMP (STACK_HEAD (U16, 1), jmp_down, OPCODE_COUNTER () - STACK_HEAD (U16, 1)); + DUMP_OPCODE_3 (assignment, ID(2), OPCODE_ARG_TYPE_VARIABLE, ID(1)); + REWRITE_JMP (STACK_TOP (U16), jmp_down, OPCODE_COUNTER () - STACK_TOP (U16)); - STACK_HEAD (U8, 1) = 1; - STACK_HEAD (IDX, 3) = STACK_HEAD (IDX, 2); - STACK_DROP (IDX, 2); + STACK_DROP (U8, 1); + STACK_PUSH (U8, 1); + STACK_DROP (IDX, 1); + STACK_SWAP (IDX); + STACK_DROP (IDX, 1); } else { @@ -1812,7 +1840,7 @@ parse_assignment_expression (void) STACK_PUSH (U8, 0); parse_conditional_expression (); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_DROP (U8, 1); goto cleanup; @@ -1823,7 +1851,8 @@ parse_assignment_expression (void) if (LAST_OPCODE_IS (prop_getter)) { STACK_PUSH (U16, (opcode_counter_t) (OPCODE_COUNTER () - 1)); - STACK_HEAD (U8, 1) = 1; + STACK_DROP (U8, 1); + STACK_PUSH (U8, 1); } skip_newlines (); @@ -1831,248 +1860,249 @@ parse_assignment_expression (void) { case TOK_EQ: { - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { - STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 1))); - JERRY_ASSERT (STACK_HEAD (ops, 1).op_idx == __op__idx_prop_getter); - serializer_set_writing_position (--OPCODE_COUNTER ()); + STACK_PUSH (ops, deserialize_opcode (STACK_TOP (U16))); + JERRY_ASSERT (STACK_TOP (ops).op_idx == __op__idx_prop_getter); + DECR_OPCODE_COUNTER (); + serializer_set_writing_position (OPCODE_COUNTER ()); NEXT (assignment_expression); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(1)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { NEXT (assignment_expression); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 2), OPCODE_ARG_TYPE_VARIABLE, - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (assignment, ID(2), OPCODE_ARG_TYPE_VARIABLE, + ID(1)); } break; } case TOK_MULT_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (multiplication, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (multiplication, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (multiplication, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (multiplication, ID(2), ID(2), + ID(1)); } break; } case TOK_DIV_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (division, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (division, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (division, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (division, ID(2), ID(2), + ID(1)); } break; } case TOK_MOD_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (remainder, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (remainder, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (remainder, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (remainder, ID(2), ID(2), + ID(1)); } break; } case TOK_PLUS_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (addition, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (addition, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (addition, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (addition, ID(2), ID(2), + ID(1)); } break; } case TOK_MINUS_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (substraction, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (substraction, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (substraction, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (substraction, ID(2), ID(2), + ID(1)); } break; } case TOK_LSHIFT_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (b_shift_left, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (b_shift_left, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (b_shift_left, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (b_shift_left, ID(2), ID(2), + ID(1)); } break; } case TOK_RSHIFT_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (b_shift_right, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (b_shift_right, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (b_shift_right, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (b_shift_right, ID(2), ID(2), + ID(1)); } break; } case TOK_RSHIFT_EX_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (b_shift_uright, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (b_shift_uright, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (b_shift_uright, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (b_shift_uright, ID(2), ID(2), + ID(1)); } break; } case TOK_AND_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (b_and, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (b_and, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (b_and, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (b_and, ID(2), ID(2), + ID(1)); } break; } case TOK_XOR_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (b_xor, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (b_xor, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (b_xor, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (b_xor, ID(2), ID(2), + ID(1)); } break; } case TOK_OR_EQ: { NEXT (assignment_expression); - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0))); - DUMP_OPCODE_3 (b_or, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); - DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj, - STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2)); + DUMP_OPCODE_3 (b_or, ID(2), ID(2), + ID(1)); + DUMP_OPCODE_3 (prop_setter, STACK_TOP (ops).data.prop_getter.obj, + STACK_TOP (ops).data.prop_getter.prop, ID(2)); STACK_DROP (ops, 1); STACK_DROP (U16, 1); } else { - DUMP_OPCODE_3 (b_or, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), - STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (b_or, ID(2), ID(2), + ID(1)); } break; } default: { - if (STACK_HEAD (U8, 1)) + if (STACK_TOP (U8)) { STACK_DROP (U16, 1); } @@ -2110,7 +2140,7 @@ parse_expression (void) if (token_is (TOK_COMMA)) { NEXT (assignment_expression); - STACK_HEAD (IDX, 2) = STACK_HEAD (IDX, 1); + STACK_SWAP (IDX); STACK_DROP (IDX, 1); } else @@ -2138,13 +2168,13 @@ parse_variable_declaration (void) current_token_must_be (TOK_NAME); STACK_PUSH (IDX, token_data ()); - DUMP_OPCODE_1 (var_decl, STACK_HEAD (IDX, 1)); + DUMP_OPCODE_1 (var_decl, ID(1)); skip_newlines (); if (token_is (TOK_EQ)) { NEXT (assignment_expression); - DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 2), OPCODE_ARG_TYPE_VARIABLE, STACK_HEAD (IDX, 1)); + DUMP_OPCODE_3 (assignment, ID(2), OPCODE_ARG_TYPE_VARIABLE, ID(1)); STACK_DROP (IDX, 1); } else @@ -2336,10 +2366,10 @@ plain_for: parse_statement (); pop_nesting (NESTING_ITERATIONAL); - DUMP_OPCODE_2 (jmp_up, 0, OPCODE_COUNTER () - STACK_HEAD (U16, 1)); + DUMP_OPCODE_2 (jmp_up, 0, OPCODE_COUNTER () - STACK_TOP (U16)); REWRITE_COND_JMP (STACK_HEAD (U16, 3), is_false_jmp_down, OPCODE_COUNTER () - STACK_HEAD (U16, 3)); - rewrite_rewritable_opcodes (REWRITABLE_CONTINUE, STACK_HEAD (U16, 1)); + rewrite_rewritable_opcodes (REWRITABLE_CONTINUE, STACK_TOP (U16)); rewrite_rewritable_opcodes (REWRITABLE_BREAK, OPCODE_COUNTER ()); STACK_DROP (IDX, 1); @@ -2427,13 +2457,13 @@ parse_if_statement (void) skip_newlines (); parse_statement (); - REWRITE_JMP (STACK_HEAD (U16, 1), jmp_down, OPCODE_COUNTER () - STACK_HEAD (U16, 1)); + REWRITE_JMP (STACK_TOP (U16), jmp_down, OPCODE_COUNTER () - STACK_TOP (U16)); STACK_DROP (U16, 1); } else { - REWRITE_COND_JMP (STACK_HEAD (U16, 1), is_false_jmp_down, OPCODE_COUNTER () - STACK_HEAD (U16, 1)); + REWRITE_COND_JMP (STACK_TOP (U16), is_false_jmp_down, OPCODE_COUNTER () - STACK_TOP (U16)); lexer_save_token (TOK ()); } @@ -2508,7 +2538,7 @@ parse_while_statement (void) STACK_PUSH (U16, OPCODE_COUNTER ()); DUMP_OPCODE_2 (jmp_up, INVALID_VALUE, INVALID_VALUE); - REWRITE_JMP (STACK_HEAD (U16, 1), jmp_up, OPCODE_COUNTER () - STACK_HEAD (U16, 3)); + REWRITE_JMP (STACK_TOP (U16), jmp_up, OPCODE_COUNTER () - STACK_HEAD (U16, 3)); REWRITE_COND_JMP (STACK_HEAD (U16, 2), is_false_jmp_down, OPCODE_COUNTER () - STACK_HEAD (U16, 2)); rewrite_rewritable_opcodes (REWRITABLE_CONTINUE, STACK_HEAD (U16, 3)); @@ -2534,7 +2564,7 @@ parse_with_statement (void) assert_keyword (KW_WITH); parse_expression_inside_parens (); - DUMP_OPCODE_1 (with, STACK_HEAD (IDX, 1)); + DUMP_OPCODE_1 (with, ID(1)); skip_newlines (); parse_statement (); @@ -2585,14 +2615,14 @@ parse_catch_clause (void) STACK_PUSH (U16, OPCODE_COUNTER ()); DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_CATCH, INVALID_VALUE, INVALID_VALUE); - DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER, STACK_HEAD (IDX, 1), INVALID_VALUE); + DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER, ID(1), INVALID_VALUE); token_after_newlines_must_be (TOK_OPEN_BRACE); skip_newlines (); parse_statement_list (); next_token_must_be (TOK_CLOSE_BRACE); - rewrite_meta_opcode_counter (STACK_HEAD (U16, 1), OPCODE_META_TYPE_CATCH); + rewrite_meta_opcode_counter (STACK_TOP (U16), OPCODE_META_TYPE_CATCH); STACK_DROP (U16, 1); STACK_DROP (IDX, 1); @@ -2620,7 +2650,7 @@ parse_finally_clause (void) parse_statement_list (); next_token_must_be (TOK_CLOSE_BRACE); - rewrite_meta_opcode_counter (STACK_HEAD (U16, 1), OPCODE_META_TYPE_FINALLY); + rewrite_meta_opcode_counter (STACK_TOP (U16), OPCODE_META_TYPE_FINALLY); STACK_DROP (U16, 1); @@ -2646,7 +2676,7 @@ parse_try_statement (void) parse_statement_list (); next_token_must_be (TOK_CLOSE_BRACE); - REWRITE_TRY (STACK_HEAD (U16, 1)); + REWRITE_TRY (STACK_TOP (U16)); token_after_newlines_must_be (TOK_KEYWORD); if (is_keyword (KW_CATCH)) @@ -2682,8 +2712,9 @@ parse_try_statement (void) static void insert_semicolon (void) { - skip_token (); - JERRY_ASSERT (token_is (TOK_SEMICOLON) || token_is (TOK_NEWLINE)); + TODO (/*Uncomment when skip_newlines will be fixed. */) + // skip_token (); + // JERRY_ASSERT (token_is (TOK_SEMICOLON) || token_is (TOK_NEWLINE)); } /* statement @@ -2829,7 +2860,7 @@ parse_statement (void) if (!token_is (TOK_SEMICOLON) && !token_is (TOK_NEWLINE)) { parse_expression (); - DUMP_OPCODE_1 (retval, STACK_HEAD (IDX, 1)); + DUMP_OPCODE_1 (retval, ID(1)); STACK_DROP (IDX, 1); insert_semicolon (); goto cleanup; @@ -2856,7 +2887,7 @@ parse_statement (void) parse_expression (); insert_semicolon (); - DUMP_OPCODE_1 (throw, STACK_HEAD (IDX, 1)); + DUMP_OPCODE_1 (throw, ID(1)); STACK_DROP (IDX, 1); goto cleanup; } @@ -2877,7 +2908,8 @@ parse_statement (void) else { lexer_save_token (TOK ()); - STACK_POP (toks, TOK()); + SET_TOK (STACK_TOP (toks)); + STACK_DROP (toks, 1); parse_expression (); STACK_DROP (IDX, 1); goto cleanup; @@ -2937,7 +2969,7 @@ parse_source_element_list (void) skip_newlines (); } lexer_save_token (TOK ()); - REWRITE_OPCODE_2 (STACK_HEAD (U16, 1), reg_var_decl, MIN_TEMP_NAME (), MAX_TEMP_NAME ()); + REWRITE_OPCODE_2 (STACK_TOP (U16), reg_var_decl, MIN_TEMP_NAME (), MAX_TEMP_NAME ()); finish_scope (); STACK_DROP (U16, 1); @@ -2996,40 +3028,42 @@ parser_init (const char *source, size_t source_size, bool show_opcodes) fill_intrinsics (); - MAX_TEMP_NAME () = TEMP_NAME () = MIN_TEMP_NAME () = lexer_get_reserved_ids_count (); - OPCODE_COUNTER () = 0; + SET_MAX_TEMP_NAME (lexer_get_reserved_ids_count ()); + SET_TEMP_NAME (lexer_get_reserved_ids_count ()); + SET_MIN_TEMP_NAME (lexer_get_reserved_ids_count ()); + SET_OPCODE_COUNTER (0); TODO (/* Rewrite using hash when number of natives reaches 20 */) for (uint8_t i = 0; i < OPCODE_NATIVE_CALL__COUNT; i++) { - STACK_ELEMENT (IDX, i) = INVALID_VALUE; + STACK_SET_ELEMENT (IDX, i, INVALID_VALUE); } for (uint8_t i = 0, strs_count = lexer_get_strings_count (); i < strs_count; i++) { if (lp_string_equal_s (identifiers[i], "LEDToggle")) { - STACK_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_TOGGLE) = i; + STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_TOGGLE, i); } else if (lp_string_equal_s (identifiers[i], "LEDOn")) { - STACK_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_ON) = i; + STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_ON, i); } else if (lp_string_equal_s (identifiers[i], "LEDOff")) { - STACK_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_OFF) = i; + STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_OFF, i); } else if (lp_string_equal_s (identifiers[i], "LEDOnce")) { - STACK_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_ONCE) = i; + STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_LED_ONCE, i); } else if (lp_string_equal_s (identifiers[i], "wait")) { - STACK_ELEMENT (IDX, OPCODE_NATIVE_CALL_WAIT) = i; + STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_WAIT, i); } else if (lp_string_equal_s (identifiers[i], "print")) { - STACK_ELEMENT (IDX, OPCODE_NATIVE_CALL_PRINT) = i; + STACK_SET_ELEMENT (IDX, OPCODE_NATIVE_CALL_PRINT, i); } } } diff --git a/src/liboptimizer/deserializer.c b/src/liboptimizer/deserializer.c index 2293b9260..1bb19fa16 100644 --- a/src/liboptimizer/deserializer.c +++ b/src/liboptimizer/deserializer.c @@ -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); +} diff --git a/src/liboptimizer/deserializer.h b/src/liboptimizer/deserializer.h index 2ed304c5a..df13307a8 100644 --- a/src/liboptimizer/deserializer.h +++ b/src/liboptimizer/deserializer.h @@ -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 diff --git a/src/liboptimizer/serializer.c b/src/liboptimizer/serializer.c index 412ac5387..e21a75b5b 100644 --- a/src/liboptimizer/serializer.c +++ b/src/liboptimizer/serializer.c @@ -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); } diff --git a/src/main.c b/src/main.c index 7b33f65df..7dae33b7b 100644 --- a/src/main.c +++ b/src/main.c @@ -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;