From b7a3a13bc9d18319fc54ac2310d3cdea9a12aec8 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Thu, 24 Jul 2014 18:13:32 +0400 Subject: [PATCH 1/5] Implementing register variables. --- src/libcoreint/interpreter.c | 59 ++++++++-- src/libcoreint/interpreter.h | 8 +- src/libcoreint/opcodes.c | 109 +++++++++++++----- src/libecmaobjects/ecma-globals.h | 2 +- src/libecmaobjects/ecma-helpers-value.c | 12 ++ src/libecmaobjects/ecma-helpers.h | 1 + .../test_addition_opcode_number_operands.c | 1 + tests/unit/test_assignment_opcode.c | 23 ++-- tests/unit/test_division_opcode.c | 1 + tests/unit/test_multiplication_opcode.c | 1 + tests/unit/test_remainder_opcode.c | 1 + tests/unit/test_substraction_opcode.c | 1 + .../test_var_decl_opcode_in_decl_lex_env.c | 9 +- 13 files changed, 169 insertions(+), 59 deletions(-) diff --git a/src/libcoreint/interpreter.c b/src/libcoreint/interpreter.c index 821cb9328..2264cc4de 100644 --- a/src/libcoreint/interpreter.c +++ b/src/libcoreint/interpreter.c @@ -13,8 +13,11 @@ * limitations under the License. */ +#include "ecma-globals.h" #include "ecma-helpers.h" +#include "globals.h" #include "interpreter.h" +#include "jerry-libc.h" #define INIT_OP_FUNC(name) [ __op__idx_##name ] = opfunc_##name, static const opfunc __opfuncs[LAST_OP] = { @@ -42,15 +45,17 @@ run_int (void) { JERRY_ASSERT( __program != NULL ); - struct __int_data int_data; - int_data.pos = 0; - int_data.this_binding_p = NULL; - int_data.lex_env_p = ecma_create_lexical_environment( NULL, - ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + const int start_pos = 0; + ecma_object_t *this_binding_p = NULL; + ecma_object_t *lex_env_p = ecma_create_lexical_environment (NULL, + ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); FIXME( Strict mode ); - int_data.is_strict = false; + const bool is_strict = false; - ecma_completion_value_t completion = run_int_from_pos( &int_data); + ecma_completion_value_t completion = run_int_from_pos (start_pos, + this_binding_p, + lex_env_p, + is_strict); switch ( (ecma_completion_type_t)completion.type ) { @@ -82,16 +87,43 @@ run_int (void) } ecma_completion_value_t -run_int_from_pos (struct __int_data *int_data) +run_int_from_pos (int start_pos, + ecma_object_t *this_binding_p, + ecma_object_t *lex_env_p, + bool is_strict) { ecma_completion_value_t completion; + const OPCODE *curr = &__program[start_pos]; + JERRY_ASSERT( curr->op_idx == __op__idx_reg_var_decl ); + + const T_IDX min_reg_num = curr->data.reg_var_decl.min; + const T_IDX max_reg_num = curr->data.reg_var_decl.max; + JERRY_ASSERT( max_reg_num >= min_reg_num ); + + const uint32_t regs_num = (uint32_t) (max_reg_num - min_reg_num + 1); + + ecma_value_t regs[ regs_num ]; + + /* memseting with zero initializes each 'register' to empty value */ + __memset (regs, 0, sizeof(regs)); + JERRY_ASSERT( ecma_is_value_empty( regs[0]) ); + + struct __int_data int_data; + int_data.pos = start_pos + 1; + int_data.this_binding_p = this_binding_p; + int_data.lex_env_p = lex_env_p; + int_data.is_strict = is_strict; + int_data.min_reg_num = min_reg_num; + int_data.max_reg_num = max_reg_num; + int_data.regs_p = regs; + while ( true ) { do { - const OPCODE *curr = &__program[int_data->pos]; - completion = __opfuncs[curr->op_idx](*curr, int_data); + const OPCODE *curr = &__program[int_data.pos]; + completion = __opfuncs[curr->op_idx](*curr, &int_data); JERRY_ASSERT( !ecma_is_completion_value_normal( completion) || ecma_is_completion_value_normal_simple_value(completion, @@ -111,6 +143,13 @@ run_int_from_pos (struct __int_data *int_data) continue; } + for ( uint32_t reg_index = 0; + reg_index < regs_num; + reg_index++ ) + { + ecma_free_value( regs[ reg_index ] ); + } + return completion; } } diff --git a/src/libcoreint/interpreter.h b/src/libcoreint/interpreter.h index 5825b25eb..253b77565 100644 --- a/src/libcoreint/interpreter.h +++ b/src/libcoreint/interpreter.h @@ -26,11 +26,17 @@ struct __int_data ecma_object_t *this_binding_p; /**< this binding for current context */ ecma_object_t *lex_env_p; /**< current lexical environment */ bool is_strict; /**< is current code execution mode strict? */ + T_IDX min_reg_num; /**< minimum idx used for register identification */ + T_IDX max_reg_num; /**< maximum idx used for register identification */ + ecma_value_t *regs_p; /**< register variables */ }; void init_int (const OPCODE* program_p); bool run_int (void); -ecma_completion_value_t run_int_from_pos (struct __int_data *); +ecma_completion_value_t run_int_from_pos (int start_pos, + ecma_object_t *this_binding_p, + ecma_object_t *lex_env_p, + bool is_strict); ssize_t try_get_string_by_idx( T_IDX idx, ecma_char_t *buffer_p, ssize_t buffer_size); ecma_number_t get_number_by_idx(T_IDX idx); diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index cc8c8782e..07a31d1f0 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -183,27 +183,42 @@ get_variable_value(struct __int_data *int_data, /**< interpreter context */ bool do_eval_or_arguments_check) /** run 'strict eval or arguments reference' check See also: do_strict_eval_arguments_check */ { - string_literal_copy var_name; - ecma_reference_t ref; ecma_completion_value_t ret_value; - init_string_literal_copy( var_idx, &var_name); - ref = ecma_op_get_identifier_reference( int_data->lex_env_p, - var_name.str_p, - int_data->is_strict); + if ( var_idx >= int_data->min_reg_num + && var_idx <= int_data->max_reg_num ) + { + ecma_value_t reg_value = int_data->regs_p[ var_idx - int_data->min_reg_num ]; - if ( unlikely( do_eval_or_arguments_check - && do_strict_eval_arguments_check( ref) ) ) + JERRY_ASSERT( !ecma_is_value_empty( reg_value) ); + + ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, + ecma_copy_value( reg_value), + ECMA_TARGET_ID_RESERVED); + } + else + { + string_literal_copy var_name; + ecma_reference_t ref; + + init_string_literal_copy( var_idx, &var_name); + ref = ecma_op_get_identifier_reference( int_data->lex_env_p, + var_name.str_p, + int_data->is_strict); + + if ( unlikely( do_eval_or_arguments_check + && do_strict_eval_arguments_check( ref) ) ) { ret_value = ecma_make_throw_value( ecma_new_standard_error( ECMA_ERROR_SYNTAX)); } - else + else { ret_value = ecma_op_get_value( ref); } - ecma_free_reference( ref); - free_string_literal_copy( &var_name); + ecma_free_reference( ref); + free_string_literal_copy( &var_name); + } return ret_value; } /* get_variable_value */ @@ -219,26 +234,44 @@ set_variable_value(struct __int_data *int_data, /**< interpreter context */ T_IDX var_idx, /**< variable identifier */ ecma_value_t value) /**< value to set */ { - string_literal_copy var_name; - ecma_reference_t ref; ecma_completion_value_t ret_value; - init_string_literal_copy( var_idx, &var_name); - ref = ecma_op_get_identifier_reference( int_data->lex_env_p, - var_name.str_p, - int_data->is_strict); + if ( var_idx >= int_data->min_reg_num + && var_idx <= int_data->max_reg_num ) + { + ecma_value_t reg_value = int_data->regs_p[ var_idx - int_data->min_reg_num ]; - if ( unlikely( do_strict_eval_arguments_check( ref) ) ) + if ( !ecma_is_value_empty( reg_value) ) + { + ecma_free_value( reg_value); + } + + int_data->regs_p[ var_idx - int_data->min_reg_num ] = ecma_copy_value( value); + + ret_value = ecma_make_empty_completion_value(); + } + else + { + string_literal_copy var_name; + ecma_reference_t ref; + + init_string_literal_copy( var_idx, &var_name); + ref = ecma_op_get_identifier_reference( int_data->lex_env_p, + var_name.str_p, + int_data->is_strict); + + if ( unlikely( do_strict_eval_arguments_check( ref) ) ) { ret_value = ecma_make_throw_value( ecma_new_standard_error( ECMA_ERROR_SYNTAX)); } - else + else { ret_value = ecma_op_put_value( ref, value); } - ecma_free_reference( ref); - free_string_literal_copy( &var_name); + ecma_free_reference( ref); + free_string_literal_copy( &var_name); + } return ret_value; } /* set_variable_value */ @@ -372,13 +405,13 @@ do_number_arithmetic(struct __int_data *int_data, /**< interpreter context */ op(b_not) \ op(instanceof) \ op(in) \ - op(reg_var_decl) + static char __unused unimplemented_list_end #define DEFINE_UNIMPLEMENTED_OP(op) \ ecma_completion_value_t opfunc_ ## op(OPCODE opdata, struct __int_data *int_data) { \ JERRY_UNIMPLEMENTED_REF_UNUSED_VARS( opdata, int_data); \ } -OP_UNIMPLEMENTED_LIST(DEFINE_UNIMPLEMENTED_OP) +OP_UNIMPLEMENTED_LIST(DEFINE_UNIMPLEMENTED_OP); #undef DEFINE_UNIMPLEMENTED_OP ecma_completion_value_t @@ -804,6 +837,18 @@ opfunc_remainder(OPCODE opdata, /**< operation data */ return ret_value; } /* opfunc_remainder */ +/** + * 'Register variable declaration' opcode handler. + * + * The opcode is meta-opcode that is not supposed to be executed. + */ +ecma_completion_value_t +opfunc_reg_var_decl(OPCODE opdata __unused, /**< operation data */ + struct __int_data *int_data __unused) /**< interpreter context */ +{ + JERRY_UNREACHABLE(); +} /* opfunc_reg_var_decl */ + /** * 'Variable declaration' opcode handler. * @@ -815,25 +860,25 @@ opfunc_remainder(OPCODE opdata, /**< operation data */ */ ecma_completion_value_t opfunc_var_decl(OPCODE opdata, /**< operation data */ - struct __int_data *int_data __unused) /**< interpreter context */ + struct __int_data *int_data) /**< interpreter context */ { string_literal_copy variable_name; init_string_literal_copy( opdata.data.var_decl.variable_name, &variable_name); - if ( ecma_is_completion_value_normal_false( ecma_op_has_binding( int_data->lex_env_p, - variable_name.str_p)) ) + if ( ecma_is_completion_value_normal_false( ecma_op_has_binding (int_data->lex_env_p, + variable_name.str_p)) ) { FIXME( Pass configurableBindings that is true if and only if current code is eval code ); - ecma_op_create_mutable_binding( int_data->lex_env_p, - variable_name.str_p, - false); + ecma_op_create_mutable_binding (int_data->lex_env_p, + variable_name.str_p, + false); /* Skipping SetMutableBinding as we have already checked that there were not * any binding with specified name in current lexical environment * and CreateMutableBinding sets the created binding's value to undefined */ - JERRY_ASSERT( ecma_is_completion_value_normal_simple_value( ecma_op_get_binding_value( int_data->lex_env_p, - variable_name.str_p, - true), + JERRY_ASSERT( ecma_is_completion_value_normal_simple_value( ecma_op_get_binding_value (int_data->lex_env_p, + variable_name.str_p, + true), ECMA_SIMPLE_VALUE_UNDEFINED) ); } diff --git a/src/libecmaobjects/ecma-globals.h b/src/libecmaobjects/ecma-globals.h index 61a58f586..39611a2e3 100644 --- a/src/libecmaobjects/ecma-globals.h +++ b/src/libecmaobjects/ecma-globals.h @@ -63,11 +63,11 @@ typedef enum { * Simple ecma-values */ typedef enum { + ECMA_SIMPLE_VALUE_EMPTY, /**< empty value (see also: ECMA-262 v5, 8.9 Completion specification type) */ ECMA_SIMPLE_VALUE_UNDEFINED, /**< undefined value */ ECMA_SIMPLE_VALUE_NULL, /**< null value */ ECMA_SIMPLE_VALUE_FALSE, /**< boolean false */ ECMA_SIMPLE_VALUE_TRUE, /**< boolean true */ - ECMA_SIMPLE_VALUE_EMPTY, /**< empty value (see also: ECMA-262 v5, 8.9 Completion specification type) */ ECMA_SIMPLE_VALUE_ARRAY_REDIRECT, /**< special value for an array's elements that exists, but is stored directly in the array's property list (used for array elements with non-default attribute values) */ diff --git a/src/libecmaobjects/ecma-helpers-value.c b/src/libecmaobjects/ecma-helpers-value.c index bb66c33a9..efa0a1155 100644 --- a/src/libecmaobjects/ecma-helpers-value.c +++ b/src/libecmaobjects/ecma-helpers-value.c @@ -26,6 +26,18 @@ #include "ecma-helpers.h" #include "globals.h" +/** + * Check if the value is empty. + * + * @return true - if the value contains implementation-defined empty simple value, + * false - otherwise. + */ +bool +ecma_is_value_empty( ecma_value_t value) /**< ecma-value */ +{ + return ( value.value_type == ECMA_TYPE_SIMPLE && value.value == ECMA_SIMPLE_VALUE_EMPTY ); +} /* ecma_is_value_empty */ + /** * Check if the value is undefined. * diff --git a/src/libecmaobjects/ecma-helpers.h b/src/libecmaobjects/ecma-helpers.h index db8e3e0ab..a72e84bec 100644 --- a/src/libecmaobjects/ecma-helpers.h +++ b/src/libecmaobjects/ecma-helpers.h @@ -42,6 +42,7 @@ extern void* ecma_decompress_pointer(uintptr_t compressed_pointer); (field) = ecma_compress_pointer( non_compressed_pointer) & ( ( 1u << ECMA_POINTER_FIELD_WIDTH ) - 1) /* ecma-helpers-value.c */ +extern bool ecma_is_value_empty( ecma_value_t value); extern bool ecma_is_value_undefined( ecma_value_t value); extern bool ecma_is_value_null( ecma_value_t value); extern bool ecma_is_value_boolean( ecma_value_t value); diff --git a/tests/unit/test_addition_opcode_number_operands.c b/tests/unit/test_addition_opcode_number_operands.c index 1c840fde1..683432222 100644 --- a/tests/unit/test_addition_opcode_number_operands.c +++ b/tests/unit/test_addition_opcode_number_operands.c @@ -26,6 +26,7 @@ main( int __unused argc, char __unused **argv) { const OPCODE test_program[] = { + getop_reg_var_decl( 255, 255), getop_var_decl( 0), getop_var_decl( 1), getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253), diff --git a/tests/unit/test_assignment_opcode.c b/tests/unit/test_assignment_opcode.c index 8b4ef8292..d138cf377 100644 --- a/tests/unit/test_assignment_opcode.c +++ b/tests/unit/test_assignment_opcode.c @@ -26,17 +26,18 @@ main( int __unused argc, char __unused **argv) { const OPCODE test_program[] = { - /* 0: */ getop_var_decl( 0), - /* 1: */ getop_var_decl( 1), - /* 2: */ getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1), - /* 3: */ getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0), - /* 4: */ getop_is_true_jmp( 1, 6), - /* 5: */ getop_jmp_down( 5), - /* 6: */ getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253), - /* 7: */ getop_assignment( 1, OPCODE_ARG_TYPE_NUMBER, 2), - /* 8: */ getop_is_false_jmp( 1, 10), - /* 9: */ getop_exitval( 0), - /* 10: */ getop_exitval( 1) + /* 0: */ getop_reg_var_decl( 255, 255), + /* 1: */ getop_var_decl( 0), + /* 2: */ getop_var_decl( 1), + /* 3: */ getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1), + /* 4: */ getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0), + /* 5: */ getop_is_true_jmp( 1, 7), + /* 6: */ getop_jmp_down( 5), + /* 7: */ getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253), + /* 8: */ getop_assignment( 1, OPCODE_ARG_TYPE_NUMBER, 2), + /* 9: */ getop_is_false_jmp( 1, 11), + /* 10: */ getop_exitval( 0), + /* 11: */ getop_exitval( 1) }; mem_init(); diff --git a/tests/unit/test_division_opcode.c b/tests/unit/test_division_opcode.c index e14084bbc..5c1c121ac 100644 --- a/tests/unit/test_division_opcode.c +++ b/tests/unit/test_division_opcode.c @@ -26,6 +26,7 @@ main( int __unused argc, char __unused **argv) { const OPCODE test_program[] = { + getop_reg_var_decl( 255, 255), getop_var_decl( 0), getop_var_decl( 1), getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253), diff --git a/tests/unit/test_multiplication_opcode.c b/tests/unit/test_multiplication_opcode.c index 1bbd2bb29..aba7f5660 100644 --- a/tests/unit/test_multiplication_opcode.c +++ b/tests/unit/test_multiplication_opcode.c @@ -26,6 +26,7 @@ main( int __unused argc, char __unused **argv) { const OPCODE test_program[] = { + getop_reg_var_decl( 255, 255), getop_var_decl( 0), getop_var_decl( 1), getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253), diff --git a/tests/unit/test_remainder_opcode.c b/tests/unit/test_remainder_opcode.c index a4b7328ce..7e4882a5d 100644 --- a/tests/unit/test_remainder_opcode.c +++ b/tests/unit/test_remainder_opcode.c @@ -26,6 +26,7 @@ main( int __unused argc, char __unused **argv) { const OPCODE test_program[] = { + getop_reg_var_decl( 255, 255), getop_var_decl( 0), getop_var_decl( 1), getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253), diff --git a/tests/unit/test_substraction_opcode.c b/tests/unit/test_substraction_opcode.c index f8c8d64ab..392f1bfb5 100644 --- a/tests/unit/test_substraction_opcode.c +++ b/tests/unit/test_substraction_opcode.c @@ -26,6 +26,7 @@ main( int __unused argc, char __unused **argv) { const OPCODE test_program[] = { + getop_reg_var_decl( 255, 255), getop_var_decl( 0), getop_var_decl( 1), getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253), diff --git a/tests/unit/test_var_decl_opcode_in_decl_lex_env.c b/tests/unit/test_var_decl_opcode_in_decl_lex_env.c index d6164c131..a10ab2939 100644 --- a/tests/unit/test_var_decl_opcode_in_decl_lex_env.c +++ b/tests/unit/test_var_decl_opcode_in_decl_lex_env.c @@ -26,10 +26,11 @@ main( int __unused argc, char __unused **argv) { const OPCODE test_program[] = { - getop_var_decl( 0), - getop_is_true_jmp( 0, 3), - getop_exitval( 0), - getop_exitval( 1) + /* 0: */ getop_reg_var_decl( 255, 255), + /* 1: */ getop_var_decl( 0), + /* 2: */ getop_is_true_jmp( 0, 4), + /* 3: */ getop_exitval( 0), + /* 4: */ getop_exitval( 1) }; mem_init(); From 63a757a5a732f9f8c3426bd0903ce30e72284291 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Thu, 24 Jul 2014 18:28:46 +0400 Subject: [PATCH 2/5] Connecting try_get_str_by_idx with deserialize_string_by_id and get_number_by_idx with deserialize_num_by_id. --- src/libcoreint/interpreter.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/libcoreint/interpreter.c b/src/libcoreint/interpreter.c index 2264cc4de..dfc9a8b3b 100644 --- a/src/libcoreint/interpreter.c +++ b/src/libcoreint/interpreter.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "deserializer.h" #include "ecma-globals.h" #include "ecma-helpers.h" #include "globals.h" @@ -167,18 +168,19 @@ try_get_string_by_idx(T_IDX idx, /**< literal id */ { TODO( Actual string literal retrievement ); - ssize_t req_length = 2; // TODO - - JERRY_ASSERT( idx < 'z' - 'a' + 1 ); + const ecma_char_t *str_p = deserialize_string_by_id( idx); + JERRY_ASSERT( str_p != NULL ); + + FIXME( strlen for ecma_char_t ); + ssize_t req_length = (ssize_t)__strlen( (const char*)str_p) + 1; if ( buffer_size < req_length ) { return -req_length; } - // TODO - buffer_p[0] = (ecma_char_t) ('a' + idx); - buffer_p[1] = 0; + FIXME( strncpy for ecma_char_t ); + __strncpy( (char*)buffer_p, (const char*)str_p, (size_t)req_length); return req_length; } /* try_get_string_by_idx */ @@ -193,5 +195,8 @@ get_number_by_idx(T_IDX idx) /**< literal id */ { TODO( Actual number literal retrievement ); - return (ecma_number_t)idx; + FIXME( /* conversion of value returned from deserialize_num_by_id to ecma_number_t */ ); + ecma_number_t num = (ecma_number_t) deserialize_num_by_id( idx); + + return num; } /* get_number_by_idx */ From 89834cd61609ae1c1f65149bac92462fd117c8b2 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Thu, 24 Jul 2014 18:30:49 +0400 Subject: [PATCH 3/5] Printing of called function's name in 'call_1' opcode handler. --- src/libcoreint/opcodes.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index 07a31d1f0..5b97ab233 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -418,7 +418,7 @@ ecma_completion_value_t opfunc_call_1 (OPCODE opdata __unused, struct __int_data *int_data) { #ifdef __HOST - __printf ("%d::op_call_1:idx:%d:%d\n", + __printf ("%d::op_call_1:idx:%d:%d\t", int_data->pos, opdata.data.call_1.name_lit_idx, opdata.data.call_1.arg1_lit_idx); @@ -426,6 +426,15 @@ opfunc_call_1 (OPCODE opdata __unused, struct __int_data *int_data) int_data->pos++; + string_literal_copy str_value; + init_string_literal_copy( opdata.data.call_1.name_lit_idx, &str_value); + +#ifdef __HOST + __printf("%s\n", str_value.str_p); +#endif + + free_string_literal_copy( &str_value); + // FIXME return ecma_make_empty_completion_value(); } From c2f82eefc0afe9cd826b0779c6feec4da9704e01 Mon Sep 17 00:00:00 2001 From: "e.gavrin" Date: Thu, 24 Jul 2014 19:27:19 +0400 Subject: [PATCH 4/5] add blink_toggle_once --- Makefile.mak | 2 +- src/generated.h | 15 +------ src/libcoreint/opcodes.c | 25 ++++++++++-- src/libperipherals/actuators.c | 75 +++++++++++++++++++++++++++++++--- src/libperipherals/actuators.h | 10 +++-- src/main.c | 7 +++- 6 files changed, 105 insertions(+), 29 deletions(-) diff --git a/Makefile.mak b/Makefile.mak index 551d18c55..a491df449 100644 --- a/Makefile.mak +++ b/Makefile.mak @@ -110,7 +110,7 @@ CFLAGS_CORTEXM4 ?= -mlittle-endian -mcpu=cortex-m4 -march=armv7e-m -mthumb \ # Common # -CFLAGS_COMMON ?= $(INCLUDES) -std=c99 -fsanitize=address -fdiagnostics-color=always +CFLAGS_COMMON ?= $(INCLUDES) -std=c99 #-fsanitize=address -fdiagnostics-color=always LDFLAGS ?= diff --git a/src/generated.h b/src/generated.h index fae8816bc..68e831091 100644 --- a/src/generated.h +++ b/src/generated.h @@ -15,17 +15,6 @@ #include "globals.h" -static const char* generated_source __unused = "" -"while (true) {\n" -"LEDToggle (LED3);\n" -"LEDToggle (LED6);\n" -"LEDToggle (LED7);\n" -"LEDToggle (LED4);\n" -"LEDToggle (LED10);\n" -"LEDToggle (LED8);\n" -"LEDToggle (LED9);\n" -"LEDToggle (LED5);\n" -"\n" -"wait(500);\n" -"}\n" +static const char* generated_source = "" +"LEDToggle (14);\n" ; diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index 5b97ab233..3e4460a73 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -25,6 +25,10 @@ #include "mem-heap.h" #include "opcodes.h" +#include "actuators.h" +#include "common-io.h" +#include "sensors.h" + /** * Note: * The note describes exception handling in opcode handlers that perform operations, @@ -416,7 +420,10 @@ OP_UNIMPLEMENTED_LIST(DEFINE_UNIMPLEMENTED_OP); ecma_completion_value_t opfunc_call_1 (OPCODE opdata __unused, struct __int_data *int_data) -{ +{ + ecma_completion_value_t ret_value; + ret_value = ecma_make_empty_completion_value (); + #ifdef __HOST __printf ("%d::op_call_1:idx:%d:%d\t", int_data->pos, @@ -432,11 +439,21 @@ opfunc_call_1 (OPCODE opdata __unused, struct __int_data *int_data) #ifdef __HOST __printf("%s\n", str_value.str_p); #endif + + if (!__strcmp ((const char*)str_value.str_p, "LEDToggle")) + { + TRY_CATCH (cond_value, get_variable_value (int_data, opdata.data.call_1.arg1_lit_idx, false), ret_value); + JERRY_ASSERT(cond_value.value.value_type == ECMA_TYPE_NUMBER ); + ecma_number_t * num_p = (ecma_number_t*)ecma_get_pointer(cond_value.value.value); + uint32_t int_num = (uint32_t)*num_p; + led_blink_once (int_num); + ret_value = ecma_make_empty_completion_value (); + FINALIZE (cond_value); + } - free_string_literal_copy( &str_value); + free_string_literal_copy (&str_value); - // FIXME - return ecma_make_empty_completion_value(); + return ret_value; } /** diff --git a/src/libperipherals/actuators.c b/src/libperipherals/actuators.c index 1fa50043a..0c37242ff 100644 --- a/src/libperipherals/actuators.c +++ b/src/libperipherals/actuators.c @@ -13,20 +13,83 @@ * limitations under the License. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#pragma GCC diagnostic ignored "-Wsign-conversion" +#include "stm32f4xx.h" +#include "stm32f4xx_gpio.h" +#include "stm32f4xx_rcc.h" +#pragma GCC diagnostic pop + #include "actuators.h" #include "jerry-libc.h" -void led_toggle(int led_id) +#ifdef __TARGET_MCU + +void +blink_once (uint32_t led) { - __printf("led_toogle: %d", led_id); + uint32_t pin = led; + uint32_t mode = (uint32_t)GPIO_Mode_OUT << (pin * 2); + uint32_t speed = (uint32_t)GPIO_Speed_100MHz << (pin * 2); + uint32_t type = (uint32_t)GPIO_OType_PP << pin; + uint32_t pullup = (uint32_t)GPIO_PuPd_NOPULL << (pin * 2); + + TODO (INITIALIZE ONCE); + // + // Initialise the peripheral clock. + // + RCC->AHB1ENR |= RCC_AHB1Periph_GPIOD; + // + // Initilaise the GPIO port. + // + volatile GPIO_TypeDef* gpio = GPIOD; + + gpio->MODER |= mode; + gpio->OSPEEDR |= speed; + gpio->OTYPER |= type; + gpio->PUPDR |= pullup; + // + // Toggle the selected LED indefinitely. + // + int index; + + int dot = 600000; + int dash = dot * 3; + + while (1) + { + gpio->BSRRL = (uint16_t) (1 << pin); for (index = 0; index < dot; index++); gpio->BSRRH = (uint16_t) (1 << pin); for (index = 0; index < dash; index++); + gpio->BSRRL = (uint16_t) (1 << pin); for (index = 0; index < dot; index++); gpio->BSRRH = (uint16_t) (1 << pin); for (index = 0; index < dash; index++); + gpio->BSRRL = (uint16_t) (1 << pin); for (index = 0; index < dot; index++); gpio->BSRRH = (uint16_t) (1 << pin); for (index = 0; index < dash; index++); + + for (index = 0; index < dash * 7; index++); + } +} +#endif + +void led_toggle(uint32_t led_id) +{ + __printf("led_toggle: %d\n", led_id); } -void led_on(int led_id) +void led_on(uint32_t led_id) { - __printf("led_on: %d", led_id); + __printf("led_on: %d\n", led_id); } -void led_off(int led_id) +void led_off(uint32_t led_id) { - __printf("led_off: %d", led_id); + __printf("led_off: %d\n", led_id); +} + +void led_blink_once(uint32_t led_id) +{ +#ifdef __HOST + __printf("led_blink_once: %d\n", led_id); +#endif + +#ifdef __TARGET_MCU + blink_once(led_id); +#endif } diff --git a/src/libperipherals/actuators.h b/src/libperipherals/actuators.h index 40114e69f..5700e00d6 100644 --- a/src/libperipherals/actuators.h +++ b/src/libperipherals/actuators.h @@ -16,15 +16,19 @@ #ifndef ACTUATORS_H #define ACTUATORS_H +#include "globals.h" + // STM32 F4 #define LED_GREEN 12 #define LED_ORANGE 13 #define LED_RED 14 #define LED_BLUE 15 -void led_toggle(int); -void led_on(int); -void led_off(int); +void led_toggle(uint32_t); +void led_on(uint32_t); +void led_off(uint32_t); +void led_blink_once(uint32_t); +void blink_once (uint32_t); #endif /* ACTUATORS_H */ diff --git a/src/main.c b/src/main.c index 8d4b46a9b..67b39c10c 100644 --- a/src/main.c +++ b/src/main.c @@ -154,7 +154,7 @@ void fake_exit(void); void fake_exit (void) { - uint32_t pin = LED_RED; + uint32_t pin = LED_ORANGE; uint32_t mode = (uint32_t)GPIO_Mode_OUT << (pin * 2); uint32_t speed = (uint32_t)GPIO_Speed_100MHz << (pin * 2); uint32_t type = (uint32_t)GPIO_OType_PP << pin; @@ -175,7 +175,7 @@ fake_exit (void) // // Toggle the selected LED indefinitely. // - int index; + volatile int index; // SOS @@ -203,6 +203,9 @@ fake_exit (void) int main(void) { + + //fake_exit(); + const char *source_p = generated_source; const size_t source_size = sizeof(generated_source); From 1f3b5a4c2986fbbd0875e029557d9750fb6c47c7 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Thu, 24 Jul 2014 19:50:37 +0400 Subject: [PATCH 5/5] Merge --- .gitignore | 1 + 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/libperipherals/actuators.c | 2 + src/libruntime/serializer.h | 2 + src/libruntime/target/linux/deserializer.c | 9 +++- src/libruntime/target/linux/serializer.c | 24 +++++++++ src/libruntime/target/stm32f4/serializer.c | 5 ++ src/main.c | 14 +++++- 14 files changed, 182 insertions(+), 34 deletions(-) create mode 100644 src/liboptimizer/optimizer-passes.c create mode 100644 src/liboptimizer/optimizer-passes.h diff --git a/.gitignore b/.gitignore index bab9c0778..def6aaec1 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ nbproject *~ js.files core +**.orig # ctags and ID database tags diff --git a/Makefile.mak b/Makefile.mak index a491df449..ec77a95d2 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 3e4460a73..783ab449f 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -409,6 +409,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) \ static char __unused unimplemented_list_end #define DEFINE_UNIMPLEMENTED_OP(op) \ @@ -950,6 +954,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/libperipherals/actuators.c b/src/libperipherals/actuators.c index 0c37242ff..bd66af889 100644 --- a/src/libperipherals/actuators.c +++ b/src/libperipherals/actuators.c @@ -16,9 +16,11 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" #pragma GCC diagnostic ignored "-Wsign-conversion" +#ifdef __TARGET_MCU #include "stm32f4xx.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_rcc.h" +#endif #pragma GCC diagnostic pop #include "actuators.h" 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/deserializer.c b/src/libruntime/target/linux/deserializer.c index fb09c43b4..eaa50a2ce 100644 --- a/src/libruntime/target/linux/deserializer.c +++ b/src/libruntime/target/linux/deserializer.c @@ -22,11 +22,18 @@ uint8_t num_size = 0; const ecma_char_t * deserialize_string_by_id (uint8_t id) { - uint8_t size = *bytecode_data, *data = bytecode_data, offset; + 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; 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 67b39c10c..4fc3c6b52 100644 --- a/src/main.c +++ b/src/main.c @@ -27,9 +27,9 @@ #define LED_ORANGE 13 #define LED_RED 14 #define LED_BLUE 15 +#include "generated.h" #endif -#include "generated.h" #include "globals.h" #include "interpreter.h" #include "jerry-libc.h" @@ -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 */