From 3b0fef6e0481a3363efe5794ef7bf30a780cd740 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Thu, 24 Jul 2014 19:27:58 +0400 Subject: [PATCH 1/2] Add opcodes for increment and decrement; add optimizer --- Makefile.mak | 4 +- src/libcoreint/opcode-structures.h | 20 ++++++++ src/libcoreint/opcodes.c | 8 +++ src/libcoreint/opcodes.h | 4 ++ src/libjsparser/parser.c | 42 +++++----------- src/liboptimizer/optimizer-passes.c | 57 ++++++++++++++++++++++ src/liboptimizer/optimizer-passes.h | 24 +++++++++ src/libruntime/serializer.h | 2 + src/libruntime/target/linux/serializer.c | 24 +++++++++ src/libruntime/target/stm32f4/serializer.c | 5 ++ src/main.c | 12 ++++- 11 files changed, 170 insertions(+), 32 deletions(-) create mode 100644 src/liboptimizer/optimizer-passes.c create mode 100644 src/liboptimizer/optimizer-passes.h diff --git a/Makefile.mak b/Makefile.mak index 551d18c55..6bdfbe040 100644 --- a/Makefile.mak +++ b/Makefile.mak @@ -162,7 +162,8 @@ SOURCES_JERRY = \ $(wildcard ./src/libecmaobjects/*.c) \ $(wildcard ./src/libecmaoperations/*.c) \ $(wildcard ./src/liballocator/*.c) \ - $(wildcard ./src/libcoreint/*.c) ) \ + $(wildcard ./src/libcoreint/*.c) \ + $(wildcard ./src/liboptimizer/*.c) ) \ $(wildcard src/libruntime/target/$(TARGET_SYSTEM)/*.c) INCLUDES_JERRY = \ @@ -173,6 +174,7 @@ INCLUDES_JERRY = \ -I src/libecmaobjects \ -I src/libecmaoperations \ -I src/liballocator \ + -I src/liboptimizer \ -I src/libcoreint ifeq ($(OPTION_NDEBUG),enable) diff --git a/src/libcoreint/opcode-structures.h b/src/libcoreint/opcode-structures.h index 3af031739..603149b2e 100644 --- a/src/libcoreint/opcode-structures.h +++ b/src/libcoreint/opcode-structures.h @@ -256,6 +256,26 @@ OP_CODE_DECL (in, T_IDX_IDX_IDX, var_left, var_right) +/** dst = var_right++. */ +OP_CODE_DECL (post_incr, T_IDX_IDX, + dst, + var_right) + +/** dst = var_right--. */ +OP_CODE_DECL (post_decr, T_IDX_IDX, + dst, + var_right) + +/** dst = ++var_right. */ +OP_CODE_DECL (pre_incr, T_IDX_IDX, + dst, + var_right) + +/** dst = --var_right. */ +OP_CODE_DECL (pre_decr, T_IDX_IDX, + dst, + var_right) + // Assignment operators. // Assign value to LEFT operand based on value of RIGHT operand. diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index cc8c8782e..af9357c26 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -372,6 +372,10 @@ do_number_arithmetic(struct __int_data *int_data, /**< interpreter context */ op(b_not) \ op(instanceof) \ op(in) \ + op(post_incr) \ + op(post_decr) \ + op(pre_incr) \ + op(pre_decr) \ op(reg_var_decl) #define DEFINE_UNIMPLEMENTED_OP(op) \ @@ -879,6 +883,10 @@ GETOP_IMPL_1 (jmp, opcode_idx) GETOP_IMPL_1 (jmp_up, opcode_count) GETOP_IMPL_1 (jmp_down, opcode_count) GETOP_IMPL_3 (addition, dst, var_left, var_right) +GETOP_IMPL_2 (post_incr, dst, var_right) +GETOP_IMPL_2 (post_decr, dst, var_right) +GETOP_IMPL_2 (pre_incr, dst, var_right) +GETOP_IMPL_2 (pre_decr, dst, var_right) GETOP_IMPL_3 (substraction, dst, var_left, var_right) GETOP_IMPL_3 (division, dst, var_left, var_right) GETOP_IMPL_3 (multiplication, dst, var_left, var_right) diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index 9dfeeb7f7..7fee3c370 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -110,6 +110,10 @@ typedef ecma_completion_value_t (*opfunc)(OPCODE, struct __int_data *); op(in) #define OP_ARITHMETIC(op) \ + op(post_incr) \ + op(post_decr) \ + op(pre_incr) \ + op(pre_decr) \ op(addition) \ op(substraction) \ op(division) \ diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index e562fdbad..10f625ca5 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -23,9 +23,8 @@ #define INVALID_VALUE 255 static token tok; -static OPCODE opcode, opcodes_buffer[MAX_OPCODES]; -static uint8_t current_opcode_in_buffer = 0; -static uint8_t opcode_counter = 0; +static OPCODE opcode; +static T_IDX opcode_counter = 0; static T_IDX temp_name_stack[MAX_OPCODES], temp_name_stack_head = 0, max_temp_name; #ifdef __HOST @@ -172,23 +171,6 @@ integer_one (void) return lhs; } -static void -save_opcode (void) -{ - JERRY_ASSERT (current_opcode_in_buffer < MAX_OPCODES); - - opcodes_buffer[current_opcode_in_buffer++] = opcode; -} - -static void -dump_saved_opcodes (void) -{ - uint8_t i; - for (i = 0; i < current_opcode_in_buffer; i++) - serializer_dump_opcode (&opcodes_buffer[i]); - current_opcode_in_buffer = 0; -} - /* property_name : Identifier | StringLiteral @@ -859,18 +841,18 @@ parse_left_hand_side_expression (void) static T_IDX parse_postfix_expression (void) { - T_IDX expr = parse_left_hand_side_expression (); + T_IDX expr = parse_left_hand_side_expression (), lhs; tok = lexer_next_token (); if (tok.type == TOK_DOUBLE_PLUS) { - opcode = getop_addition (expr, expr, integer_one ()); - save_opcode (); + lhs = next_temp_name (); + DUMP_OPCODE (post_incr, lhs, expr); } else if (tok.type == TOK_DOUBLE_MINUS) { - opcode = getop_substraction (expr, expr, integer_one ()); - save_opcode (); + lhs = next_temp_name (); + DUMP_OPCODE (post_decr, lhs, expr); } else lexer_save_token (tok); @@ -890,13 +872,15 @@ parse_unary_expression (void) switch (tok.type) { case TOK_DOUBLE_PLUS: + lhs = next_temp_name (); NEXT (expr, unary_expression); - DUMP_OPCODE (addition, expr, expr, integer_one ()); + DUMP_OPCODE (pre_incr, lhs, expr); return expr; case TOK_DOUBLE_MINUS: + lhs = next_temp_name (); NEXT (expr, unary_expression); - DUMP_OPCODE (substraction, expr, expr, integer_one ()); + DUMP_OPCODE (pre_decr, lhs, expr); return expr; case TOK_PLUS: @@ -1198,7 +1182,7 @@ parse_assignment_expression (void) lhs = parse_conditional_expression (&was_conditional); if (was_conditional) { - goto end; + return lhs; } skip_newlines (); @@ -1268,8 +1252,6 @@ parse_assignment_expression (void) lexer_save_token (tok); } -end: - dump_saved_opcodes (); return lhs; } diff --git a/src/liboptimizer/optimizer-passes.c b/src/liboptimizer/optimizer-passes.c new file mode 100644 index 000000000..cde2aaaeb --- /dev/null +++ b/src/liboptimizer/optimizer-passes.c @@ -0,0 +1,57 @@ +/* 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 "optimizer-passes.h" +#include "opcodes.h" +#include "deserializer.h" + +#define NAME_TO_ID(op) (__op__idx_##op) + +/* Reorder bytecode like + + call_n ... + assignment ... + + var_?_end + + to + + assignment ... + + call_n ... + var_?_end +*/ +static void +optimize_calls (OPCODE *opcodes) +{ + OPCODE *current_opcode; + + for (current_opcode = opcodes; + current_opcode->op_idx != NAME_TO_ID (exitval); + current_opcode++) + { + if (current_opcode->op_idx == NAME_TO_ID (call_n) + && (current_opcode + 1)->op_idx == NAME_TO_ID (assignment)) + { + OPCODE temp = *current_opcode; + *current_opcode = *(current_opcode + 1); + *(current_opcode + 1) = temp; + } + } +} + +void +optimizer_run_passes (OPCODE* opcodes) +{ + optimize_calls (opcodes); +} \ No newline at end of file diff --git a/src/liboptimizer/optimizer-passes.h b/src/liboptimizer/optimizer-passes.h new file mode 100644 index 000000000..86f498abe --- /dev/null +++ b/src/liboptimizer/optimizer-passes.h @@ -0,0 +1,24 @@ +/* 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 OPTIMIZER_PASSES_H +#define OPTIMIZER_PASSES_H + +#include "globals.h" +#include "opcodes.h" + +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 d6449b112..02a2d46d1 100644 --- a/src/libruntime/serializer.h +++ b/src/libruntime/serializer.h @@ -28,4 +28,6 @@ void serializer_dump_opcode (const void *); void serializer_rewrite_opcode (const uint8_t, const void *); +void serializer_print_opcodes (void); + #endif // SERIALIZER_H diff --git a/src/libruntime/target/linux/serializer.c b/src/libruntime/target/linux/serializer.c index dfe4bf399..ddbf87d19 100644 --- a/src/libruntime/target/linux/serializer.c +++ b/src/libruntime/target/linux/serializer.c @@ -146,3 +146,27 @@ serializer_rewrite_opcode (const uint8_t loc, const void *opcode) __printf ("// REWRITE\n"); } + +void +serializer_print_opcodes (void) +{ + int loc = -1, i; + OPCODE* opcode; + int opcode_num; + + __printf ("AFTER OPTIMIZER:\n"); + + do + { + loc++; + + opcode = bytecode_opcodes + loc; + opcode_num = (int)((char*)opcode)[0]; + + __printf ("%03d: %20s ", loc, opcode_names[opcode_num]); + for (i = 1; i < opcode_sizes[opcode_num]; i++) + __printf ("%4d ", ((char*)opcode)[i]); + __printf ("\n"); + } + while (opcode->op_idx != __op__idx_exitval); +} diff --git a/src/libruntime/target/stm32f4/serializer.c b/src/libruntime/target/stm32f4/serializer.c index eb08884db..e3872bcea 100644 --- a/src/libruntime/target/stm32f4/serializer.c +++ b/src/libruntime/target/stm32f4/serializer.c @@ -46,5 +46,10 @@ serializer_rewrite_opcode (const uint8_t offset, const void *opcode) JERRY_UNIMPLEMENTED_REF_UNUSED_VARS( offset, opcode); } +void +serializer_print_opcodes (void) +{ + JERRY_UNREACHABLE (); +} TODO (Dump memory) diff --git a/src/main.c b/src/main.c index 8d4b46a9b..ea8ae9e4d 100644 --- a/src/main.c +++ b/src/main.c @@ -37,6 +37,7 @@ #include "parser.h" #include "serializer.h" #include "deserializer.h" +#include "optimizer-passes.h" #define MAX_STRINGS 100 #define MAX_NUMS 25 @@ -49,6 +50,7 @@ jerry_run( const char *script_source, int nums[MAX_NUMS]; uint8_t strings_num, nums_count; uint8_t offset; + const OPCODE *opcodes; mem_init(); @@ -68,7 +70,15 @@ jerry_run( const char *script_source, parser_init (); parser_parse_program (); - init_int (deserialize_bytecode ()); + opcodes = deserialize_bytecode (); + + optimizer_run_passes ((OPCODE *) opcodes); + +#ifdef __HOST + serializer_print_opcodes (); +#endif + + init_int (opcodes); run_int (); } /* jerry_run */ From c9c26251a4f0d53cbb9cc627abcad592e9b097c5 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Fri, 25 Jul 2014 12:37:29 +0400 Subject: [PATCH 2/2] Add savings bytecode in memory on target --- src/libjsparser/lexer.c | 6 +- src/libjsparser/lexer.h | 2 +- src/libruntime/serializer.h | 2 +- src/libruntime/target/linux/serializer.c | 3 +- src/libruntime/target/stm32f4/bytecode-stm.h | 37 ++++++++++ src/libruntime/target/stm32f4/deserializer.c | 64 +++++++++++++++-- src/libruntime/target/stm32f4/serializer.c | 75 +++++++++++++++++--- src/main.c | 2 +- 8 files changed, 168 insertions(+), 23 deletions(-) create mode 100644 src/libruntime/target/stm32f4/bytecode-stm.h diff --git a/src/libjsparser/lexer.c b/src/libjsparser/lexer.c index ab0211215..9ea3d73f2 100644 --- a/src/libjsparser/lexer.c +++ b/src/libjsparser/lexer.c @@ -227,7 +227,7 @@ lexer_get_string_by_id (uint8_t id) } uint8_t -lexer_get_nums (int *nums) +lexer_get_nums (int32_t *nums) { int i; @@ -368,7 +368,7 @@ parse_name (void) return known_token; } -static int +static int32_t hex_to_int (char hex) { switch (hex) @@ -409,7 +409,7 @@ parse_number (void) bool is_fp = false; bool is_exp = false; size_t tok_length = 0, i; - int res = 0; + int32_t res = 0; token known_token; JERRY_ASSERT (__isdigit (c) || c == '.'); diff --git a/src/libjsparser/lexer.h b/src/libjsparser/lexer.h index 3d9988299..de528a94e 100644 --- a/src/libjsparser/lexer.h +++ b/src/libjsparser/lexer.h @@ -155,7 +155,7 @@ void lexer_dump_buffer_state (void); uint8_t lexer_get_strings (const char **); uint8_t lexer_get_reserved_ids_count (void); const char *lexer_get_string_by_id (uint8_t); -uint8_t lexer_get_nums (int *); +uint8_t lexer_get_nums (int32_t *); void lexer_adjust_num_ids (void); #endif diff --git a/src/libruntime/serializer.h b/src/libruntime/serializer.h index 02a2d46d1..ac21f992c 100644 --- a/src/libruntime/serializer.h +++ b/src/libruntime/serializer.h @@ -22,7 +22,7 @@ void serializer_init (void); uint8_t serializer_dump_strings (const char **, uint8_t); -void serializer_dump_nums (const int *, uint8_t, uint8_t, uint8_t); +void serializer_dump_nums (const int32_t *, uint8_t, uint8_t, uint8_t); void serializer_dump_opcode (const void *); diff --git a/src/libruntime/target/linux/serializer.c b/src/libruntime/target/linux/serializer.c index ddbf87d19..7f997e136 100644 --- a/src/libruntime/target/linux/serializer.c +++ b/src/libruntime/target/linux/serializer.c @@ -79,10 +79,9 @@ serializer_dump_strings (const char *strings[], uint8_t size) } void -serializer_dump_nums (const int nums[], uint8_t size, uint8_t offset, uint8_t strings_num) +serializer_dump_nums (const int32_t nums[], uint8_t size, uint8_t offset, uint8_t strings_num) { uint8_t i, *data, num_offset; - JERRY_STATIC_ASSERT (sizeof (int) == 4); num_offset = (uint8_t) (offset + size + 1); __printf ("NUMS %d:\n", size); diff --git a/src/libruntime/target/stm32f4/bytecode-stm.h b/src/libruntime/target/stm32f4/bytecode-stm.h new file mode 100644 index 000000000..7e7fcda2e --- /dev/null +++ b/src/libruntime/target/stm32f4/bytecode-stm.h @@ -0,0 +1,37 @@ +/* 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 BYTECODE_STM_H +#define BYTECODE_STM_H + +#include "opcodes.h" + +#define MAX_OPCODES 255 + +/* bytecode_data contains identifiers, string and num literals. + Memory map if the following. + + bytecode_data { + U8 strs_count; + U8 string_offsets[str_count]; + U8* strings[str_count]; + + U8 nums_count; + U32 nums[nums_count]; + } */ +uint8_t *bytecode_data; +OPCODE bytecode_opcodes[MAX_OPCODES]; + +#endif // BYTECODE_STM_H \ No newline at end of file diff --git a/src/libruntime/target/stm32f4/deserializer.c b/src/libruntime/target/stm32f4/deserializer.c index e77ae97af..192d3d2e4 100644 --- a/src/libruntime/target/stm32f4/deserializer.c +++ b/src/libruntime/target/stm32f4/deserializer.c @@ -14,29 +14,81 @@ */ #include "deserializer.h" +#include "bytecode-stm.h" -TODO (Implement) +TODO (Read from flash) + +int *num_data = NULL; +uint8_t num_size = 0; const ecma_char_t * deserialize_string_by_id (uint8_t id) { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (id); + uint8_t size, *data, offset; + + if (bytecode_data == NULL) + return NULL; + + size = *bytecode_data; + + if (id >= size) + return NULL; + + data = bytecode_data; + + data += id + 1; + + offset = *data; + + return bytecode_data + offset; } int deserialize_num_by_id (uint8_t id) { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (id); + uint8_t str_size, str_offset, *data; + + str_size = *bytecode_data; + if (id < str_size) + { + return 0; + } + id = (uint8_t) (id - str_size); + + if (num_data == NULL) + { + data = bytecode_data + str_size; + str_offset = *data; + data = bytecode_data + str_offset; + + while (*data) + data++; + + num_size = *(++data); + num_data = (int *) ++data; + } + + if (id >= num_size) + return 0; + + return num_data[id]; } const void * deserialize_bytecode (void) { - JERRY_UNIMPLEMENTED (); + return bytecode_opcodes; } uint8_t deserialize_min_temp (void) { - JERRY_UNIMPLEMENTED (); -} \ No newline at end of file + uint8_t str_size = *bytecode_data; + + if (num_size == 0) + { + deserialize_num_by_id (str_size); // Init num_data and num_size + } + + return (uint8_t) (str_size + num_size); +} diff --git a/src/libruntime/target/stm32f4/serializer.c b/src/libruntime/target/stm32f4/serializer.c index e3872bcea..33986ab3f 100644 --- a/src/libruntime/target/stm32f4/serializer.c +++ b/src/libruntime/target/stm32f4/serializer.c @@ -15,35 +15,94 @@ #include "serializer.h" #include "globals.h" +#include "serializer.h" +#include "jerry-libc.h" +#include "bytecode-stm.h" +#include "deserializer.h" + +TODO (Dump to flash) void serializer_init (void) { - JERRY_UNIMPLEMENTED(); } uint8_t serializer_dump_strings (const char *strings[], uint8_t size) { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS( strings, size); + uint8_t i; + uint8_t offset = (uint8_t) (size + 1), res; + + for (i = 0; i < size; i++) + { + offset = (uint8_t) (offset + __strlen (strings[i]) + 1); + } + + bytecode_data = mem_heap_alloc_block (offset, MEM_HEAP_ALLOC_SHORT_TERM); + res = offset; + + bytecode_data[0] = size; + offset = (uint8_t) (size + 1); + for (i = 0; i < size; i++) + { + bytecode_data[i + 1] = offset; + offset = (uint8_t) (offset + __strlen (strings[i]) + 1); + } + + for (i = 0; i < size; i++) + __strncpy ((void *) (bytecode_data + bytecode_data[i + 1]), strings[i], __strlen (strings[i]) + 1); + +#ifndef JERRY_NDEBUG + for (i = 0; i < size; i++) + { + JERRY_ASSERT (!__strcmp (strings[i], (const char *) deserialize_string_by_id (i))); + } +#endif + + return res; } void -serializer_dump_nums (const int nums[], uint8_t size, uint8_t offset, uint8_t strings_num) +serializer_dump_nums (const int32_t nums[], uint8_t size, uint8_t offset, uint8_t strings_num __unused) { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS( nums, size, offset, strings_num); + uint8_t i, *data; + + data = mem_heap_alloc_block ((size_t) (offset + size * 4 + 1), MEM_HEAP_ALLOC_LONG_TERM); + __memcpy (data, bytecode_data, offset); + mem_heap_free_block (bytecode_data); + + bytecode_data = data; + data += offset; + data[0] = size; + data++; + for (i = 0; i < size; i++) + { + __memcpy (data, nums + i, 4); + data += 4; + } + +#ifndef JERRY_NDEBUG + for (i = 0; i < size; i++) + { + JERRY_ASSERT (nums[i] == deserialize_num_by_id ((uint8_t) (i + strings_num))); + } + + JERRY_ASSERT (deserialize_min_temp () == (uint8_t) (size + strings_num)); +#endif } +static int opcode_counter = 0; + void serializer_dump_opcode (const void *opcode) { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS( opcode); + bytecode_opcodes[opcode_counter++] = *((OPCODE*)opcode); } void -serializer_rewrite_opcode (const uint8_t offset, const void *opcode) +serializer_rewrite_opcode (const uint8_t loc, const void *opcode) { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS( offset, opcode); + bytecode_opcodes[loc] = *((OPCODE*)opcode); } void @@ -51,5 +110,3 @@ serializer_print_opcodes (void) { JERRY_UNREACHABLE (); } - -TODO (Dump memory) diff --git a/src/main.c b/src/main.c index 4fc3c6b52..7aa923541 100644 --- a/src/main.c +++ b/src/main.c @@ -47,7 +47,7 @@ jerry_run( const char *script_source, size_t script_source_size __unused) { const char *strings[MAX_STRINGS]; - int nums[MAX_NUMS]; + int32_t nums[MAX_NUMS]; uint8_t strings_num, nums_count; uint8_t offset; const OPCODE *opcodes;