From 2809ffb36d7b3153fb71cc6ae7256deb04c89864 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Thu, 31 Jul 2014 19:30:27 +0400 Subject: [PATCH] Add scope reordering ("use strict" -> func_decl -> var_decl -> other opcodes); Add --show-opcodes console parameter --- src/libjsparser/parser.c | 2 + src/liboptimizer/optimizer-passes.c | 337 ++++++++++++++++++++- src/liboptimizer/optimizer-passes.h | 3 + src/libruntime/serializer.h | 2 +- src/libruntime/target/linux/serializer.c | 47 ++- src/libruntime/target/stm32f4/serializer.c | 2 +- src/main.c | 15 +- tests/unit/common.h | 47 +++ tests/unit/test_optimizer_adjust_jumps.c | 94 ++++++ tests/unit/test_optimizer_reorder_scope.c | 75 +++++ 10 files changed, 602 insertions(+), 22 deletions(-) create mode 100644 tests/unit/common.h create mode 100644 tests/unit/test_optimizer_adjust_jumps.c create mode 100644 tests/unit/test_optimizer_reorder_scope.c diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index 0d05bb77b..292da0d19 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "optimizer-passes.h" #include "jerry-libc.h" #include "lexer.h" #include "parser.h" @@ -1819,6 +1820,7 @@ parse_source_element_list (void) lexer_save_token (tok); REWRITE_OPCODE (reg_var_decl_loc, reg_var_decl, min_temp_name, (uint8_t) (max_temp_name - 1)); finish_scope (); + optimizer_reorder_scope ((uint16_t) (reg_var_decl_loc + 1), opcode_counter); } /* program diff --git a/src/liboptimizer/optimizer-passes.c b/src/liboptimizer/optimizer-passes.c index cde2aaaeb..7472805d5 100644 --- a/src/liboptimizer/optimizer-passes.c +++ b/src/liboptimizer/optimizer-passes.c @@ -16,8 +16,10 @@ #include "optimizer-passes.h" #include "opcodes.h" #include "deserializer.h" +#include "serializer.h" +#include "jerry-libc.h" -#define NAME_TO_ID(op) (__op__idx_##op) +#define NAME_TO_ID(op) (__op__idx_##op) /* Reorder bytecode like @@ -50,6 +52,339 @@ optimize_calls (OPCODE *opcodes) } } +/* Move NUMBER opcodes from FROM to TO and adjust opcodes beetwen FROM and TO. */ +void +optimizer_move_opcodes (OPCODE *from, OPCODE *to, uint16_t number) +{ + OPCODE temp[number], *current_opcode; + uint16_t i; + + if (to == from) + return; + + for (i = 0; i < number; i++) + temp[i] = from[i]; + + if (to > from) + { + if (number <= to - from) + { + // Adjust opcodes up + for (current_opcode = from; current_opcode != to; current_opcode++) + { + *current_opcode = *(current_opcode + number); + } + } + else + { + optimizer_move_opcodes (from + number, from, (uint16_t) (to - from)); + } + } + else + { + if (number <= from - to) + { + // Adjust opcodes down + for (current_opcode = from; current_opcode != to; current_opcode--) + { + *current_opcode = *(current_opcode - number); + } + } + else + { + optimizer_move_opcodes (to, to + number, (uint16_t) (from - to)); + } + } + + for (i = 0; i < number; i++) + to[i] = temp[i]; +} + +static uint16_t +opcode_to_counter (OPCODE *opcode) +{ + JERRY_ASSERT (opcode > (OPCODE *) deserialize_bytecode ()); + return (uint16_t) (opcode - (OPCODE *) deserialize_bytecode ()); +} + +void +optimizer_adjust_jumps (OPCODE *first_opcode, OPCODE *last_opcode, int16_t value) +{ + OPCODE *current_opcode; + + JERRY_ASSERT (first_opcode <= last_opcode); + + for (current_opcode = first_opcode; current_opcode != last_opcode; current_opcode++) + { + if (current_opcode->op_idx == NAME_TO_ID (is_true_jmp)) + { + /* 19: is_true_jmp 2 + 20: var_decl ... + + becomes + + 19: var_decl ... + 20: is_true_jmp 2 + */ + if (current_opcode->data.is_true_jmp.opcode >= opcode_to_counter (last_opcode) + || current_opcode->data.is_true_jmp.opcode < opcode_to_counter (first_opcode) - value) + continue; + + /* 19: is_true_jmp 20 + 20: assignment + 21: var_decl + + becomes + + 19: var_decl + 20: is_true_jmp 21 + 21: assignment + */ + if (current_opcode->data.is_true_jmp.opcode >= opcode_to_counter (first_opcode) + && current_opcode->data.is_true_jmp.opcode <= opcode_to_counter (last_opcode) - value) + { + current_opcode->data.is_true_jmp.opcode = (T_IDX) (current_opcode->data.is_true_jmp.opcode + value); + continue; + } + + /* 19: is_true_jmp 22 + 20: assignment + 21: var_decl + 22: var_decl + + becomes + + 19: var_decl + 20: var_decl + 21: is_true_jmp 23 + 22: assignment + */ + if (current_opcode->data.is_true_jmp.opcode < opcode_to_counter (last_opcode)) + { + current_opcode->data.is_true_jmp.opcode = (T_IDX) opcode_to_counter (last_opcode); + continue; + } + + JERRY_UNREACHABLE (); + } + + if (current_opcode->op_idx == NAME_TO_ID (is_false_jmp)) + { + /* 19: is_false_jmp 2 + 20: var_decl ... + + becomes + + 19: var_decl ... + 20: is_false_jmp 2 + */ + if (current_opcode->data.is_false_jmp.opcode >= opcode_to_counter (last_opcode) + || current_opcode->data.is_false_jmp.opcode < opcode_to_counter (first_opcode) - value) + continue; + + /* 19: is_false_jmp 20 + 20: assignment + 21: var_decl + + becomes + + 19: var_decl + 20: is_false_jmp 21 + 21: assignment + */ + if (current_opcode->data.is_true_jmp.opcode <= opcode_to_counter (first_opcode) + && current_opcode->data.is_false_jmp.opcode < opcode_to_counter (last_opcode) - value) + { + current_opcode->data.is_false_jmp.opcode = (T_IDX) (current_opcode->data.is_false_jmp.opcode + value); + continue; + } + + /* 19: is_false_jmp 22 + 20: assignment + 21: var_decl + 22: var_decl + + becomes + + 19: var_decl + 20: var_decl + 21: is_false_jmp 23 + 22: assignment + */ + if (current_opcode->data.is_false_jmp.opcode < opcode_to_counter (last_opcode)) + { + current_opcode->data.is_false_jmp.opcode = (T_IDX) opcode_to_counter (last_opcode); + continue; + } + + JERRY_UNREACHABLE (); + } + + if (current_opcode->op_idx == NAME_TO_ID (jmp_down)) + { + /* 19: jmp_down 1 + 20: assignment + 21: var_decl ... + + becomes + + 19: var_decl ... + 20: jmp_down 1 + 21: assignment + */ + if (current_opcode->data.jmp_down.opcode_count < last_opcode - current_opcode) + continue; + + /* 19: jmp_down 3 + 20: assignment + 21: var_decl + + becomes + + 19: var_decl + 20: jmp_down 2 + 21: assignment + */ + if (current_opcode->data.jmp_down.opcode_count >= last_opcode - current_opcode + value) + { + current_opcode->data.jmp_down.opcode_count = (T_IDX) (current_opcode->data.jmp_down.opcode_count - value); + continue; + } + + /* 19: jmp_down 3 + 20: assignment + 21: var_decl + 22: var_decl + + becomes + + 19: var_decl + 20: var_decl + 21: jmp_down 2 + 22: assignment + */ + if (current_opcode->data.jmp_down.opcode_count >= last_opcode - current_opcode + && current_opcode->data.jmp_down.opcode_count < last_opcode - current_opcode + value) + { + current_opcode->data.jmp_down.opcode_count = (T_IDX) (last_opcode - current_opcode); + continue; + } + + JERRY_UNREACHABLE (); + } + + if (current_opcode->op_idx == NAME_TO_ID (jmp_up)) + { + /* 19: assignment + 20: jmp_up 1 + 21: var_decl ... + + becomes + + 19: var_decl ... + 20: assignment + 21: jmp_up 1 + */ + if (current_opcode->data.jmp_up.opcode_count < current_opcode - first_opcode) + continue; + + /* 19: jmp_up 1 + 20: assignment + 21: var_decl + + becomes + + 19: var_decl + 20: jmp_up 2 + 21: assignment + */ + if (current_opcode->data.jmp_up.opcode_count >= current_opcode - first_opcode) + { + current_opcode->data.jmp_up.opcode_count = (T_IDX) (current_opcode->data.jmp_up.opcode_count + value); + continue; + } + + JERRY_UNREACHABLE (); + } + } +} + +/* Reorder scope like + "use strict" + func_decl + var_decl + other opcodes +*/ +void +optimizer_reorder_scope (uint16_t scope_start, uint16_t scope_end) +{ + OPCODE *opcodes = (OPCODE *) deserialize_bytecode (); + OPCODE *first_opcode = opcodes + scope_start; + OPCODE *last_opcode = opcodes + scope_end; + OPCODE *current_opcode, *processed_opcode = first_opcode; + + for (current_opcode = processed_opcode; current_opcode != last_opcode; current_opcode++) + { + if (current_opcode->op_idx == NAME_TO_ID (assignment) + && current_opcode->data.assignment.type_value_right == OPCODE_ARG_TYPE_STRING + && !__strcmp ("use strict", (char *) deserialize_string_by_id (current_opcode->data.assignment.value_right))) + { + optimizer_move_opcodes (current_opcode, processed_opcode, 1); + optimizer_adjust_jumps (processed_opcode + 1, current_opcode + 1, 1); + processed_opcode++; + break; + } + } + + for (current_opcode = processed_opcode; current_opcode != last_opcode;) + { + if (current_opcode->op_idx == NAME_TO_ID (func_decl_0) + || current_opcode->op_idx == NAME_TO_ID (func_decl_1) + || current_opcode->op_idx == NAME_TO_ID (func_decl_2) + || current_opcode->op_idx == NAME_TO_ID (func_decl_n)) + { + __printf ("%p\n", processed_opcode); + OPCODE *fun_opcode; + int16_t value, jmp_offset; + for (fun_opcode = current_opcode + 1; fun_opcode != last_opcode; fun_opcode++) + { + if (fun_opcode->op_idx == NAME_TO_ID (jmp_down)) + { + jmp_offset = (int16_t) (fun_opcode - current_opcode); + fun_opcode += fun_opcode->data.jmp_down.opcode_count; + break; + } + } + JERRY_ASSERT (fun_opcode <= last_opcode); + + value = (int16_t) (fun_opcode - current_opcode); + optimizer_move_opcodes (current_opcode, processed_opcode, (uint16_t) value); + // Adjust jumps inside func_decl except end's jmp_down + optimizer_adjust_jumps (processed_opcode + jmp_offset + 1, + processed_opcode + value, + (int16_t) (processed_opcode - current_opcode)); + optimizer_adjust_jumps (processed_opcode + value, + fun_opcode, + value); + processed_opcode += value; + current_opcode = fun_opcode; + continue; + } + else + current_opcode++; + } + + for (current_opcode = processed_opcode; current_opcode != last_opcode; current_opcode++) + { + if (current_opcode->op_idx == NAME_TO_ID (var_decl)) + { + optimizer_move_opcodes (current_opcode, processed_opcode, 1); + optimizer_adjust_jumps (processed_opcode + 1, current_opcode + 1, 1); + processed_opcode++; + } + } +} + void optimizer_run_passes (OPCODE* opcodes) { diff --git a/src/liboptimizer/optimizer-passes.h b/src/liboptimizer/optimizer-passes.h index 86f498abe..fc839dc86 100644 --- a/src/liboptimizer/optimizer-passes.h +++ b/src/liboptimizer/optimizer-passes.h @@ -19,6 +19,9 @@ #include "globals.h" #include "opcodes.h" +void optimizer_move_opcodes (OPCODE *, OPCODE *, uint16_t); +void optimizer_adjust_jumps (OPCODE *, OPCODE *, int16_t); +void optimizer_reorder_scope (uint16_t, uint16_t); void optimizer_run_passes (OPCODE *); #endif // OPTIMIZER_PASSES_H \ No newline at end of file diff --git a/src/libruntime/serializer.h b/src/libruntime/serializer.h index e47008a84..ba8759df0 100644 --- a/src/libruntime/serializer.h +++ b/src/libruntime/serializer.h @@ -19,7 +19,7 @@ #include "globals.h" #include "opcodes.h" -void serializer_init (void); +void serializer_init (bool show_opcodes); uint16_t serializer_dump_strings (const char **, uint8_t); diff --git a/src/libruntime/target/linux/serializer.c b/src/libruntime/target/linux/serializer.c index a5b983249..260211bc6 100644 --- a/src/libruntime/target/linux/serializer.c +++ b/src/libruntime/target/linux/serializer.c @@ -37,9 +37,12 @@ static uint8_t opcode_sizes[] = { 0 }; +static bool print_opcodes; + void -serializer_init (void) +serializer_init (bool show_opcodes) { + print_opcodes = show_opcodes; } uint16_t @@ -48,10 +51,12 @@ serializer_dump_strings (const char *strings[], uint8_t size) uint8_t i; uint16_t offset = (uint16_t) (size * 2 + 1), res; - __printf ("STRINGS %d:\n", size); + if (print_opcodes) + __printf ("STRINGS %d:\n", size); for (i = 0; i < size; i++) { - __printf ("%3d %5d %20s\n", i, offset, strings[i]); + if (print_opcodes) + __printf ("%3d %5d %20s\n", i, offset, strings[i]); offset = (uint16_t) (offset + __strlen (strings[i]) + 1); } @@ -87,10 +92,13 @@ serializer_dump_nums (const int32_t nums[], uint8_t size, uint16_t offset, uint8 { uint8_t i, *data; - __printf ("NUMS %d:\n", size); - for (i = 0; i < size; i++) + if (print_opcodes) { - __printf ("%3d %7d\n", i + strings_num, nums[i]); + __printf ("NUMS %d:\n", size); + for (i = 0; i < size; i++) + { + __printf ("%3d %7d\n", i + strings_num, nums[i]); + } } __printf ("\n"); @@ -132,11 +140,14 @@ serializer_dump_opcode (OPCODE opcode) JERRY_ASSERT( opcode_counter < MAX_OPCODES ); bytecode_opcodes[opcode_counter] = opcode; - __printf ("%03d: %20s ", opcode_counter++, opcode_names[opcode_num]); - for (i = 1; i < opcode_sizes[opcode_num]; i++) - __printf ("%4d ", ((uint8_t*)&opcode)[i]); + if (print_opcodes) + { + __printf ("%03d: %20s ", opcode_counter++, opcode_names[opcode_num]); + for (i = 1; i < opcode_sizes[opcode_num]; i++) + __printf ("%4d ", ((uint8_t*)&opcode)[i]); - __printf ("\n"); + __printf ("\n"); + } } void @@ -148,11 +159,14 @@ serializer_rewrite_opcode (const uint8_t loc, OPCODE opcode) JERRY_ASSERT( loc < MAX_OPCODES ); bytecode_opcodes[loc] = opcode; - __printf ("%03d: %20s ", loc, opcode_names[opcode_num]); - for (i = 1; i < opcode_sizes[opcode_num]; i++) - __printf ("%4d ", ((uint8_t*)&opcode)[i]); + if (print_opcodes) + { + __printf ("%03d: %20s ", loc, opcode_names[opcode_num]); + for (i = 1; i < opcode_sizes[opcode_num]; i++) + __printf ("%4d ", ((uint8_t*)&opcode)[i]); - __printf ("// REWRITE\n"); + __printf ("// REWRITE\n"); + } } void @@ -162,6 +176,9 @@ serializer_print_opcodes (void) OPCODE* opcode; uint8_t opcode_num; + if (!print_opcodes) + return; + __printf ("AFTER OPTIMIZER:\n"); do @@ -176,5 +193,5 @@ serializer_print_opcodes (void) __printf ("%4d ", ((uint8_t*)opcode)[i]); __printf ("\n"); } - while (opcode->op_idx != __op__idx_exitval); + while (opcode->op_idx != __op__idx_exitval && (*(uint16_t *) opcode != 0x0)); } diff --git a/src/libruntime/target/stm32f4/serializer.c b/src/libruntime/target/stm32f4/serializer.c index 41ee302d3..97051ce76 100644 --- a/src/libruntime/target/stm32f4/serializer.c +++ b/src/libruntime/target/stm32f4/serializer.c @@ -24,7 +24,7 @@ TODO (Dump to flash) void -serializer_init (void) +serializer_init (bool show_opcodes __unused) { } diff --git a/src/main.c b/src/main.c index 52ccd1f2f..a55ada35f 100644 --- a/src/main.c +++ b/src/main.c @@ -69,12 +69,15 @@ parser_run (const char *script_source, size_t script_source_size __unused) } static void -jerry_run (const char *script_source, size_t script_source_size, bool is_parse_only) +jerry_run (const char *script_source, size_t script_source_size, bool is_parse_only, + bool is_show_opcodes) { const OPCODE *opcodes; mem_init(); + serializer_init (is_show_opcodes); + opcodes = parser_run (script_source, script_source_size); if (is_parse_only) @@ -140,7 +143,7 @@ main (int argc __unused, char **argv __unused) { const char *file_name = NULL; - bool parse_only = false; + bool parse_only = false, show_opcodes = false; int i; for (i = 1; i < argc; i++) @@ -149,6 +152,10 @@ main (int argc __unused, { parse_only = true; } + else if (!__strcmp ("--show-opcodes", argv[i])) + { + show_opcodes = true; + } else if (file_name) { jerry_exit (ERR_SEVERAL_FILES); @@ -167,7 +174,7 @@ main (int argc __unused, size_t source_size; const char *source_p = read_source( file_name, &source_size); - jerry_run (source_p, source_size, parse_only); + jerry_run (source_p, source_size, parse_only, show_opcodes); mem_heap_print( false, false, true); @@ -183,6 +190,6 @@ main(void) const size_t source_size = sizeof(generated_source); jerry_run( source_p, - source_size, false); + source_size, false, false); } #endif diff --git a/tests/unit/common.h b/tests/unit/common.h new file mode 100644 index 000000000..cee109295 --- /dev/null +++ b/tests/unit/common.h @@ -0,0 +1,47 @@ +/* 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 COMMON_H +#define COMMON_H + +#define OPCODE_SIZE(op) \ + sizeof (struct __op_##op) + 1, + +static uint8_t opcode_sizes[] = { + OP_LIST (OPCODE_SIZE) + 0 +}; + +static bool +opcodes_equal (OPCODE *opcodes1, OPCODE *opcodes2, uint16_t size) +{ + uint16_t i; + for (i = 0; i < size; i++) + { + uint8_t opcode_num1 = opcodes1[i].op_idx, opcode_num2 = opcodes2[i].op_idx; + uint8_t j; + + if (opcode_num1 != opcode_num2) + return false; + + for (j = 1; j < opcode_sizes[opcode_num1]; j++) + if (((uint8_t*)&opcodes1[i])[j] != ((uint8_t*)&opcodes2[i])[j]) + return false; + } + + return true; +} + +#endif // COMMON_H \ No newline at end of file diff --git a/tests/unit/test_optimizer_adjust_jumps.c b/tests/unit/test_optimizer_adjust_jumps.c new file mode 100644 index 000000000..901713913 --- /dev/null +++ b/tests/unit/test_optimizer_adjust_jumps.c @@ -0,0 +1,94 @@ +/* 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. + */ + +#include "globals.h" +#include "interpreter.h" +#include "mem-allocator.h" +#include "opcodes.h" +#include "serializer.h" +#include "optimizer-passes.h" +#include "jerry-libc.h" +#include "deserializer.h" +#include "common.h" + +/** + * Unit test's main function. + */ +int +main( int __unused argc, + char __unused **argv) +{ + OPCODE test_program[] = { + [0] = getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1), + [1] = getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0), + [2] = getop_is_false_jmp (0, 10), + [3] = getop_is_true_jmp (0, 6), + [4] = getop_jmp_up (1), + [5] = getop_jmp_up (4), + [6] = getop_jmp_down (1), + [7] = getop_jmp_down (2), + [8] = getop_jmp_down (2), + [9] = getop_assignment (0, OPCODE_ARG_TYPE_SMALLINT, 253), + [10] = getop_exitval (0) + }; + + mem_init(); + + const char *strings[] = { "a", + "b" }; + int nums [] = { 2 }; + serializer_init (true); + uint16_t offset = serializer_dump_strings (strings, 2); + serializer_dump_nums (nums, 1, offset, 2); + + for (int i = 0; i < 11; i++) + serializer_dump_opcode (test_program[i]); + + OPCODE * opcodes = (OPCODE *) deserialize_bytecode (); + + optimizer_move_opcodes (opcodes + 9, opcodes + 2, 1); + if (!opcodes_equal (opcodes, (OPCODE[]) { + [0] = getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1), + [1] = getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0), + [2] = getop_assignment (0, OPCODE_ARG_TYPE_SMALLINT, 253), + [3] = getop_is_false_jmp (0, 10), + [4] = getop_is_true_jmp (0, 6), + [5] = getop_jmp_up (1), + [6] = getop_jmp_up (4), + [7] = getop_jmp_down (1), + [8] = getop_jmp_down (2), + [9] = getop_jmp_down (2), + [10] = getop_exitval (0) + }, 11)) + return 1; + + optimizer_adjust_jumps (opcodes + 3, opcodes + 10, 1); + if (!opcodes_equal (opcodes, (OPCODE[]) { + [0] = getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1), + [1] = getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0), + [2] = getop_assignment (0, OPCODE_ARG_TYPE_SMALLINT, 253), + [3] = getop_is_false_jmp (0, 10), + [4] = getop_is_true_jmp (0, 7), + [5] = getop_jmp_up (1), + [6] = getop_jmp_up (5), + [7] = getop_jmp_down (1), + [8] = getop_jmp_down (2), + [9] = getop_jmp_down (1), + [10] = getop_exitval (0) + }, 11)) + return 1; + + return 0; +} diff --git a/tests/unit/test_optimizer_reorder_scope.c b/tests/unit/test_optimizer_reorder_scope.c new file mode 100644 index 000000000..32d6ccdc5 --- /dev/null +++ b/tests/unit/test_optimizer_reorder_scope.c @@ -0,0 +1,75 @@ +/* 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. + */ + +#include "globals.h" +#include "interpreter.h" +#include "mem-allocator.h" +#include "opcodes.h" +#include "serializer.h" +#include "optimizer-passes.h" +#include "jerry-libc.h" +#include "deserializer.h" +#include "common.h" + +/** + * Unit test's main function. + */ +int +main( int __unused argc, + char __unused **argv) +{ + // Honestly, after RETVAL there must be RET + OPCODE test_program[] = { + [0] = getop_reg_var_decl (5, 5), // tmp6 + [1] = getop_assignment (0, OPCODE_ARG_TYPE_STRING, 1), // a = "b" + [2] = getop_var_decl (1), // var b + [3] = getop_func_decl_0 (2), // function c() + [4] = getop_jmp_down (3), // { + [5] = getop_var_decl (1), // var b + [6] = getop_retval (1), // return b; } + [7] = getop_assignment (5, OPCODE_ARG_TYPE_STRING, 3), // "use strict" + [8] = getop_exitval (0) + }; + + mem_init(); + + const char *strings[] = { "a", "b", "c", "use strict" }; + int nums [] = { 2 }; + serializer_init (true); + uint16_t offset = serializer_dump_strings (strings, 4); + serializer_dump_nums (nums, 1, offset, 4); + + for (int i = 0; i < 9; i++) + serializer_dump_opcode (test_program[i]); + + OPCODE * opcodes = (OPCODE *) deserialize_bytecode (); + + optimizer_reorder_scope (1, 8); + if (!opcodes_equal (opcodes, (OPCODE[]) { + [0] = getop_reg_var_decl (5, 5), // tmp6 + [1] = getop_assignment (5, OPCODE_ARG_TYPE_STRING, 3), // "use strict" + [2] = getop_func_decl_0 (2), // function c() + [3] = getop_jmp_down (3), // { + [4] = getop_var_decl (1), // var b + [5] = getop_retval (1), // return b; } + [6] = getop_var_decl (1), // var b + [7] = getop_assignment (0, OPCODE_ARG_TYPE_STRING, 1), // a = "b" + [8] = getop_exitval (0) + }, 9)) + return 1; + + + return 0; +}