From 3b0fef6e0481a3363efe5794ef7bf30a780cd740 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Thu, 24 Jul 2014 19:27:58 +0400 Subject: [PATCH] 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 */