diff --git a/Makefile b/Makefile index 1f3a537d4..82d36fea2 100644 --- a/Makefile +++ b/Makefile @@ -15,10 +15,9 @@ # # Target naming scheme # -# Main targets: {dev,debug,release,debug_release}.{linux,stm32f{4}}[.{check,flash}] +# Main targets: {debug,release,debug_release}.{linux,stm32f{4}}[.{check,flash}] # # Target mode part (before dot): -# dev: - JERRY_NDEBUG; - optimizations; + debug symbols; - -Werror | local development build # debug: - JERRY_NDEBUG; - optimizations; + debug symbols; + -Werror | debug build # debug_release: - JERRY_NDEBUG; + optimizations; + debug symbols; + -Werror | checked release build # release: + JERRY_NDEBUG; + optimizations; - debug symbols; + -Werror | release build @@ -35,7 +34,7 @@ # Unit test target: unittests # -export TARGET_MODES = dev debug debug_release release +export TARGET_MODES = debug debug_release release export TARGET_PC_SYSTEMS = linux export TARGET_MCU_SYSTEMS = $(addprefix stm32f,4) # now only stm32f4 is supported, to add, for example, to stm32f3, change to $(addprefix stm32f,3 4) export TARGET_SYSTEMS = $(TARGET_PC_SYSTEMS) $(TARGET_MCU_SYSTEMS) diff --git a/Makefile.mak b/Makefile.mak index ec77a95d2..fdc510b62 100644 --- a/Makefile.mak +++ b/Makefile.mak @@ -59,13 +59,6 @@ else OPTION_OPTIMIZE = disable endif -# -Werror -ifeq ($(TARGET_MODE),dev) - OPTION_WERROR = disable -else - OPTION_WERROR = enable -endif - # Is MCU target? ifeq ($(filter-out $(TARGET_MCU_SYSTEMS),$(TARGET_SYSTEM)),) OPTION_MCU = enable @@ -149,7 +142,7 @@ endif # Jerry part sources, headers, includes, cflags, ldflags # -CFLAGS_JERRY = $(CFLAGS_WARNINGS) +CFLAGS_JERRY = $(CFLAGS_WARNINGS) $(CFLAGS_WERROR) DEFINES_JERRY = -DMEM_HEAP_CHUNK_SIZE=256 -DMEM_HEAP_AREA_SIZE=32768 -DMEM_STATS # FIXME: @@ -181,10 +174,6 @@ ifeq ($(OPTION_NDEBUG),enable) DEFINES_JERRY += -DJERRY_NDEBUG endif -ifeq ($(OPTION_WERROR),enable) - CFLAGS_JERRY += $(CFLAGS_WERROR) -endif - ifeq ($(OPTION_MCU),disable) DEFINES_JERRY += -D__HOST -DJERRY_SOURCE_BUFFER_SIZE=1048576 else diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index 783ab449f..edc27460a 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -14,11 +14,13 @@ */ #include "ecma-alloc.h" +#include "ecma-comparison.h" #include "ecma-conversion.h" #include "ecma-exceptions.h" #include "ecma-helpers.h" #include "ecma-number-arithmetic.h" #include "ecma-operations.h" +#include "ecma-try-catch-macro.h" #include "globals.h" #include "interpreter.h" #include "jerry-libc.h" @@ -39,52 +41,19 @@ * * 1. At the beginning of the handler there should be declared opcode handler's 'return value' variable. * - * 2. All exceptionable operations except the last should be enclosed in TRY_CATCH macro. + * 2. All exceptionable operations except the last should be enclosed in ECMA_TRY_CATCH macro. * All subsequent operations in the opcode handler should be placed into block between - * the TRY_CATCH and corresponding FINALIZE. + * the ECMA_TRY_CATCH and corresponding ECMA_FINALIZE. * * 3. The last exceptionable's operation result should be assigned directly to opcode handler's - * 'return value' variable without using TRY_CATCH macro. + * 'return value' variable without using ECMA_TRY_CATCH macro. * - * 4. After last FINALIZE statement there should be only one operator. + * 4. After last ECMA_FINALIZE statement there should be only one operator. * The operator should return from the opcode handler with it's 'return value'. * * 5. No other operations with opcode handler's 'return value' variable should be performed. */ -/** - * The macro defines try-block that initializes variable 'var' with 'op' - * and checks for exceptions that might be thrown during initialization. - * - * If no exception was thrown, then code after the try-block is executed. - * Otherwise, throw-completion value is just copied to return_value. - * - * Note: - * Each TRY_CATCH should have it's own corresponding FINALIZE - * statement with same argument as corresponding TRY_CATCH's first argument. - */ -#define TRY_CATCH(var, op, return_value) \ - ecma_completion_value_t var = op; \ - if ( unlikely( ecma_is_completion_value_throw( var) ) ) \ - { \ - return_value = ecma_copy_completion_value( var); \ - } \ - else \ - { \ - JERRY_ASSERT( ecma_is_completion_value_normal( var) ) - -/** - * The macro marks end of code block that is executed if no exception - * was catched by corresponding TRY_CATCH and frees variable, - * initialized by the TRY_CATCH. - * - * Note: - * Each TRY_CATCH should be followed by FINALIZE with same - * argument as corresponding TRY_CATCH's first argument. - */ -#define FINALIZE(var) } \ - ecma_free_completion_value( var) - /** * String literal copy descriptor. */ @@ -312,8 +281,8 @@ do_number_arithmetic(struct __int_data *int_data, /**< interpreter context */ { ecma_completion_value_t ret_value; - TRY_CATCH(num_left_value, ecma_op_to_number( left_value), ret_value); - TRY_CATCH(num_right_value, ecma_op_to_number( right_value), ret_value); + ECMA_TRY_CATCH(num_left_value, ecma_op_to_number( left_value), ret_value); + ECMA_TRY_CATCH(num_right_value, ecma_op_to_number( right_value), ret_value); ecma_number_t *left_p, *right_p, *res_p; left_p = (ecma_number_t*)ecma_get_pointer( num_left_value.value.value); @@ -346,8 +315,8 @@ do_number_arithmetic(struct __int_data *int_data, /**< interpreter context */ ecma_dealloc_number( res_p); - FINALIZE( num_right_value); - FINALIZE( num_left_value); + ECMA_FINALIZE( num_right_value); + ECMA_FINALIZE( num_left_value); return ret_value; } /* do_number_arithmetic */ @@ -372,12 +341,8 @@ do_number_arithmetic(struct __int_data *int_data, /**< interpreter context */ op(b_xor) \ op(logical_and) \ op(logical_or) \ - op(equal_value) \ - op(not_equal_value) \ op(equal_value_type) \ op(not_equal_value_type) \ - op(less_than) \ - op(greater_than) \ op(less_or_equal_than) \ op(greater_or_equal_than) \ op(nop) \ @@ -446,13 +411,13 @@ opfunc_call_1 (OPCODE opdata __unused, struct __int_data *int_data) 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); + ECMA_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); + ECMA_FINALIZE (cond_value); } free_string_literal_copy (&str_value); @@ -476,7 +441,7 @@ opfunc_is_true_jmp (OPCODE opdata, /**< operation data */ ecma_completion_value_t ret_value; - TRY_CATCH(cond_value, get_variable_value( int_data, cond_var_idx, false), ret_value); + ECMA_TRY_CATCH(cond_value, get_variable_value( int_data, cond_var_idx, false), ret_value); ecma_completion_value_t to_bool_completion = ecma_op_to_boolean( cond_value.value); JERRY_ASSERT( ecma_is_completion_value_normal( to_bool_completion) ); @@ -492,7 +457,7 @@ opfunc_is_true_jmp (OPCODE opdata, /**< operation data */ ret_value = ecma_make_empty_completion_value(); - FINALIZE(cond_value); + ECMA_FINALIZE(cond_value); return ret_value; } /* opfunc_is_true_jmp */ @@ -513,7 +478,7 @@ opfunc_is_false_jmp (OPCODE opdata, /**< operation data */ ecma_completion_value_t ret_value; - TRY_CATCH(cond_value, get_variable_value( int_data, cond_var_idx, false), ret_value); + ECMA_TRY_CATCH(cond_value, get_variable_value( int_data, cond_var_idx, false), ret_value); ecma_completion_value_t to_bool_completion = ecma_op_to_boolean( cond_value.value); JERRY_ASSERT( ecma_is_completion_value_normal( to_bool_completion) ); @@ -529,7 +494,7 @@ opfunc_is_false_jmp (OPCODE opdata, /**< operation data */ ret_value = ecma_make_empty_completion_value(); - FINALIZE(cond_value); + ECMA_FINALIZE(cond_value); return ret_value; } /* opfunc_is_false_jmp */ @@ -700,10 +665,10 @@ opfunc_addition(OPCODE opdata, /**< operation data */ ecma_completion_value_t ret_value; - TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); - TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); - TRY_CATCH(prim_left_value, ecma_op_to_primitive( left_value.value), ret_value); - TRY_CATCH(prim_right_value, ecma_op_to_primitive( right_value.value), ret_value); + ECMA_TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); + ECMA_TRY_CATCH(prim_left_value, ecma_op_to_primitive( left_value.value, ECMA_PREFERRED_TYPE_NO), ret_value); + ECMA_TRY_CATCH(prim_right_value, ecma_op_to_primitive( right_value.value, ECMA_PREFERRED_TYPE_NO), ret_value); if ( prim_left_value.value.value_type == ECMA_TYPE_STRING || prim_right_value.value.value_type == ECMA_TYPE_STRING ) @@ -719,10 +684,10 @@ opfunc_addition(OPCODE opdata, /**< operation data */ prim_right_value.value); } - FINALIZE(prim_right_value); - FINALIZE(prim_left_value); - FINALIZE(right_value); - FINALIZE(left_value); + ECMA_FINALIZE(prim_right_value); + ECMA_FINALIZE(prim_left_value); + ECMA_FINALIZE(right_value); + ECMA_FINALIZE(left_value); return ret_value; } /* opfunc_addition */ @@ -747,8 +712,8 @@ opfunc_substraction(OPCODE opdata, /**< operation data */ ecma_completion_value_t ret_value; - TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); - TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); + ECMA_TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); ret_value = do_number_arithmetic(int_data, dst_var_idx, @@ -756,8 +721,8 @@ opfunc_substraction(OPCODE opdata, /**< operation data */ left_value.value, right_value.value); - FINALIZE(right_value); - FINALIZE(left_value); + ECMA_FINALIZE(right_value); + ECMA_FINALIZE(left_value); return ret_value; } /* opfunc_substraction */ @@ -782,8 +747,8 @@ opfunc_multiplication(OPCODE opdata, /**< operation data */ ecma_completion_value_t ret_value; - TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); - TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); + ECMA_TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); ret_value = do_number_arithmetic(int_data, dst_var_idx, @@ -791,8 +756,8 @@ opfunc_multiplication(OPCODE opdata, /**< operation data */ left_value.value, right_value.value); - FINALIZE(right_value); - FINALIZE(left_value); + ECMA_FINALIZE(right_value); + ECMA_FINALIZE(left_value); return ret_value; } /* opfunc_multiplication */ @@ -817,8 +782,8 @@ opfunc_division(OPCODE opdata, /**< operation data */ ecma_completion_value_t ret_value; - TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); - TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); + ECMA_TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); ret_value = do_number_arithmetic(int_data, dst_var_idx, @@ -826,8 +791,8 @@ opfunc_division(OPCODE opdata, /**< operation data */ left_value.value, right_value.value); - FINALIZE(right_value); - FINALIZE(left_value); + ECMA_FINALIZE(right_value); + ECMA_FINALIZE(left_value); return ret_value; } /* opfunc_division */ @@ -852,8 +817,8 @@ opfunc_remainder(OPCODE opdata, /**< operation data */ ecma_completion_value_t ret_value; - TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); - TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); + ECMA_TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); ret_value = do_number_arithmetic(int_data, dst_var_idx, @@ -861,12 +826,181 @@ opfunc_remainder(OPCODE opdata, /**< operation data */ left_value.value, right_value.value); - FINALIZE(right_value); - FINALIZE(left_value); + ECMA_FINALIZE(right_value); + ECMA_FINALIZE(left_value); return ret_value; } /* opfunc_remainder */ +/** + * 'Equals' opcode handler. + * + * See also: ECMA-262 v5, 11.9.1 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_equal_value(OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.equal_value.dst; + const T_IDX left_var_idx = opdata.data.equal_value.var_left; + const T_IDX right_var_idx = opdata.data.equal_value.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); + + bool is_equal = ecma_op_abstract_equality_compare( left_value.value, right_value.value); + + ret_value = set_variable_value( int_data, dst_var_idx, ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_TRUE + : ECMA_SIMPLE_VALUE_FALSE)); + + ECMA_FINALIZE(right_value); + ECMA_FINALIZE(left_value); + + return ret_value; +} /* opfunc_equal_value */ + +/** + * 'Does-not-equals' opcode handler. + * + * See also: ECMA-262 v5, 11.9.2 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_not_equal_value(OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.not_equal_value.dst; + const T_IDX left_var_idx = opdata.data.not_equal_value.var_left; + const T_IDX right_var_idx = opdata.data.not_equal_value.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); + + bool is_equal = ecma_op_abstract_equality_compare( left_value.value, right_value.value); + + ret_value = set_variable_value( int_data, dst_var_idx, ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_FALSE + : ECMA_SIMPLE_VALUE_TRUE)); + + + ECMA_FINALIZE(right_value); + ECMA_FINALIZE(left_value); + + return ret_value; +} /* opfunc_not_equal_value */ + +/** + * 'Less-than' opcode handler. + * + * See also: ECMA-262 v5, 11.8.1 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_less_than(OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.less_than.dst; + const T_IDX left_var_idx = opdata.data.less_than.var_left; + const T_IDX right_var_idx = opdata.data.less_than.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); + ECMA_TRY_CATCH(compare_result, + ecma_op_abstract_relational_compare (left_value.value, + right_value.value, + true), + ret_value); + + ecma_simple_value_t res; + + if ( ecma_is_value_undefined( compare_result.value) ) + { + res = ECMA_SIMPLE_VALUE_FALSE; + } + else + { + JERRY_ASSERT( ecma_is_value_boolean( compare_result.value) ); + + res = compare_result.value.value; + } + + ret_value = set_variable_value( int_data, dst_var_idx, ecma_make_simple_value( res)); + + ECMA_FINALIZE(compare_result); + ECMA_FINALIZE(right_value); + ECMA_FINALIZE(left_value); + + return ret_value; +} /* opfunc_less_than */ + +/** + * 'Greater-than' opcode handler. + * + * See also: ECMA-262 v5, 11.8.2 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_greater_than(OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.greater_than.dst; + const T_IDX left_var_idx = opdata.data.greater_than.var_left; + const T_IDX right_var_idx = opdata.data.greater_than.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH(left_value, get_variable_value( int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH(right_value, get_variable_value( int_data, right_var_idx, false), ret_value); + ECMA_TRY_CATCH(compare_result, + ecma_op_abstract_relational_compare (right_value.value, + left_value.value, + false), + ret_value); + + ecma_simple_value_t res; + + if ( ecma_is_value_undefined( compare_result.value) ) + { + res = ECMA_SIMPLE_VALUE_FALSE; + } + else + { + JERRY_ASSERT( ecma_is_value_boolean( compare_result.value) ); + + res = compare_result.value.value; + } + + ret_value = set_variable_value( int_data, dst_var_idx, ecma_make_simple_value( res)); + + ECMA_FINALIZE(compare_result); + ECMA_FINALIZE(right_value); + ECMA_FINALIZE(left_value); + + return ret_value; +} /* opfunc_greater_than */ + /** * 'Register variable declaration' opcode handler. * diff --git a/src/libecmaoperations/ecma-comparison.c b/src/libecmaoperations/ecma-comparison.c index d07025431..e695d71c5 100644 --- a/src/libecmaoperations/ecma-comparison.c +++ b/src/libecmaoperations/ecma-comparison.c @@ -14,7 +14,9 @@ */ #include "ecma-comparison.h" +#include "ecma-conversion.h" #include "ecma-globals.h" +#include "ecma-try-catch-macro.h" #include "globals.h" /** \addtogroup ecma ---TODO--- @@ -33,8 +35,8 @@ * false - otherwise. */ bool -ecma_abstract_equality_compare(ecma_value_t x, /**< first operand */ - ecma_value_t y) /**< second operand */ +ecma_op_abstract_equality_compare(ecma_value_t x, /**< first operand */ + ecma_value_t y) /**< second operand */ { const bool is_x_undefined = ecma_is_value_undefined( x); const bool is_x_null = ecma_is_value_null( x); @@ -97,7 +99,75 @@ ecma_abstract_equality_compare(ecma_value_t x, /**< first operand */ { JERRY_UNIMPLEMENTED(); } -} /* ecma_abstract_equality_compare */ +} /* ecma_op_abstract_equality_compare */ + +/** + * ECMA abstract relational comparison routine. + * + * See also: ECMA-262 v5, 11.8.5 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +ecma_op_abstract_relational_compare(ecma_value_t x, /**< first operand */ + ecma_value_t y, /**< second operand */ + bool left_first) /**< 'LeftFirst' flag */ +{ + ecma_completion_value_t ret_value, px, py; + + ecma_value_t first_converted_value = left_first ? x : y; + ecma_value_t second_converted_value = left_first ? y : x; + + // 1., 2. + ECMA_TRY_CATCH( prim_first_converted_value, ecma_op_to_primitive( first_converted_value, ECMA_PREFERRED_TYPE_NUMBER), ret_value); + ECMA_TRY_CATCH( prim_second_converted_value, ecma_op_to_primitive( second_converted_value, ECMA_PREFERRED_TYPE_NUMBER), ret_value); + + px = left_first ? prim_first_converted_value : prim_second_converted_value; + py = left_first ? prim_second_converted_value : prim_first_converted_value; + + const bool is_px_string = ( px.value.value_type == ECMA_TYPE_STRING ); + const bool is_py_string = ( py.value.value_type == ECMA_TYPE_STRING ); + + if ( !( is_px_string && is_py_string ) ) + { // 3. + // a. + ECMA_TRY_CATCH( nx, ecma_op_to_number( px.value), ret_value); + + // b. + ECMA_TRY_CATCH( ny, ecma_op_to_number( py.value), ret_value); + + ecma_number_t* num_x_p = (ecma_number_t*)ecma_get_pointer( nx.value.value); + ecma_number_t* num_y_p = (ecma_number_t*)ecma_get_pointer( ny.value.value); + + TODO( /* Implement according to ECMA */ ); + + if ( *num_x_p >= *num_y_p ) + { + ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, + ecma_make_simple_value( ECMA_SIMPLE_VALUE_FALSE), + ECMA_TARGET_ID_RESERVED); + } + else + { + ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, + ecma_make_simple_value( ECMA_SIMPLE_VALUE_TRUE), + ECMA_TARGET_ID_RESERVED); + } + + ECMA_FINALIZE( ny); + ECMA_FINALIZE( nx); + } + else + { // 4. + JERRY_UNIMPLEMENTED(); + } + + ECMA_FINALIZE( prim_second_converted_value); + ECMA_FINALIZE( prim_first_converted_value); + + return ret_value; +} /* ecma_op_abstract_relational_compare */ /** * @} diff --git a/src/libecmaoperations/ecma-comparison.h b/src/libecmaoperations/ecma-comparison.h index bdb305578..50c8fc525 100644 --- a/src/libecmaoperations/ecma-comparison.h +++ b/src/libecmaoperations/ecma-comparison.h @@ -26,7 +26,8 @@ * @{ */ -extern bool ecma_abstract_equality_compare( ecma_value_t x, ecma_value_t y); +extern bool ecma_op_abstract_equality_compare( ecma_value_t x, ecma_value_t y); +extern ecma_completion_value_t ecma_op_abstract_relational_compare(ecma_value_t x, ecma_value_t y, bool left_first); /** * @} diff --git a/src/libecmaoperations/ecma-conversion.c b/src/libecmaoperations/ecma-conversion.c index df77f9b5a..b42a90f0b 100644 --- a/src/libecmaoperations/ecma-conversion.c +++ b/src/libecmaoperations/ecma-conversion.c @@ -91,7 +91,8 @@ ecma_op_check_object_coercible( ecma_value_t value) /**< ecma-value */ * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t -ecma_op_to_primitive( ecma_value_t value) /**< ecma-value */ +ecma_op_to_primitive( ecma_value_t value, /**< ecma-value */ + ecma_preferred_type_hint preferred_type) /**< preferred type hint */ { switch ( (ecma_type_t)value.value_type ) { @@ -105,7 +106,7 @@ ecma_op_to_primitive( ecma_value_t value) /**< ecma-value */ } case ECMA_TYPE_OBJECT: { - JERRY_UNIMPLEMENTED(); + JERRY_UNIMPLEMENTED_REF_UNUSED_VARS(preferred_type); } case ECMA_TYPE__COUNT: { @@ -215,7 +216,7 @@ ecma_op_to_number( ecma_value_t value) /**< ecma-value */ } case ECMA_TYPE_OBJECT: { - ecma_completion_value_t completion_to_primitive = ecma_op_to_primitive( value); + ecma_completion_value_t completion_to_primitive = ecma_op_to_primitive( value, ECMA_PREFERRED_TYPE_NUMBER); JERRY_ASSERT( ecma_is_completion_value_normal( completion_to_primitive) ); ecma_completion_value_t completion_to_number = ecma_op_to_number( completion_to_primitive.value); diff --git a/src/libecmaoperations/ecma-conversion.h b/src/libecmaoperations/ecma-conversion.h index eaa02eb39..1fbc67b01 100644 --- a/src/libecmaoperations/ecma-conversion.h +++ b/src/libecmaoperations/ecma-conversion.h @@ -26,8 +26,22 @@ * @{ */ +/** + * Second argument of 'ToPrimitive' operation that is a hint, + * specifying the preferred type of conversion result. + */ +typedef enum +{ + ECMA_PREFERRED_TYPE_NO, /**< no preferred type is specified */ + ECMA_PREFERRED_TYPE_UNDEFINED, /**< Undefined */ + ECMA_PREFERRED_TYPE_NULL, /**< Null */ + ECMA_PREFERRED_TYPE_BOOLEAN, /**< Boolean */ + ECMA_PREFERRED_TYPE_NUMBER, /**< Number */ + ECMA_PREFERRED_TYPE_STRING /**< String */ +} ecma_preferred_type_hint; + extern ecma_completion_value_t ecma_op_check_object_coercible( ecma_value_t value); -extern ecma_completion_value_t ecma_op_to_primitive( ecma_value_t value); +extern ecma_completion_value_t ecma_op_to_primitive( ecma_value_t value, ecma_preferred_type_hint preferred_type); extern ecma_completion_value_t ecma_op_to_boolean( ecma_value_t value); extern ecma_completion_value_t ecma_op_to_number( ecma_value_t value); extern ecma_completion_value_t ecma_op_to_object( ecma_value_t value); diff --git a/src/libecmaoperations/ecma-try-catch-macro.h b/src/libecmaoperations/ecma-try-catch-macro.h new file mode 100644 index 000000000..1b47559ef --- /dev/null +++ b/src/libecmaoperations/ecma-try-catch-macro.h @@ -0,0 +1,52 @@ +/* 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 ECMA_TRY_CATCH_MACRO_H +#define ECMA_TRY_CATCH_MACRO_H + +/** + * The macro defines try-block that initializes variable 'var' with 'op' + * and checks for exceptions that might be thrown during initialization. + * + * If no exception was thrown, then code after the try-block is executed. + * Otherwise, throw-completion value is just copied to return_value. + * + * Note: + * Each ECMA_TRY_CATCH should have it's own corresponding ECMA_FINALIZE + * statement with same argument as corresponding ECMA_TRY_CATCH's first argument. + */ +#define ECMA_TRY_CATCH(var, op, return_value) \ + ecma_completion_value_t var = op; \ + if ( unlikely( ecma_is_completion_value_throw( var) ) ) \ + { \ + return_value = ecma_copy_completion_value( var); \ + } \ + else \ + { \ + JERRY_ASSERT( ecma_is_completion_value_normal( var) ) + +/** + * The macro marks end of code block that is executed if no exception + * was catched by corresponding ECMA_TRY_CATCH and frees variable, + * initialized by the ECMA_TRY_CATCH. + * + * Note: + * Each ECMA_TRY_CATCH should be followed by ECMA_FINALIZE with same + * argument as corresponding ECMA_TRY_CATCH's first argument. + */ +#define ECMA_FINALIZE(var) } \ + ecma_free_completion_value( var) + +#endif /* !ECMA_TRY_CATCH_MACRO_H */ diff --git a/tests/unit/test_addition_opcode_number_operands.c b/tests/unit/test_addition_opcode_number_operands.c index 683432222..0ebeadfe4 100644 --- a/tests/unit/test_addition_opcode_number_operands.c +++ b/tests/unit/test_addition_opcode_number_operands.c @@ -17,6 +17,7 @@ #include "interpreter.h" #include "mem-allocator.h" #include "opcodes.h" +#include "serializer.h" /** * Unit test's main function. @@ -37,6 +38,12 @@ main( int __unused argc, mem_init(); + const char *strings[] = { "a", + "b" }; + int nums [] = { 2 }; + uint8_t offset = serializer_dump_strings( strings, 2); + serializer_dump_nums( nums, 1, offset, 2); + init_int( test_program); return run_int() ? 0 diff --git a/tests/unit/test_assignment_opcode.c b/tests/unit/test_assignment_opcode.c index d138cf377..ef8950da2 100644 --- a/tests/unit/test_assignment_opcode.c +++ b/tests/unit/test_assignment_opcode.c @@ -17,6 +17,7 @@ #include "interpreter.h" #include "mem-allocator.h" #include "opcodes.h" +#include "serializer.h" /** * Unit test's main function. @@ -42,6 +43,12 @@ main( int __unused argc, mem_init(); + const char *strings[] = { "a", + "b" }; + int nums [] = { 2 }; + uint8_t offset = serializer_dump_strings( strings, 2); + serializer_dump_nums( nums, 1, offset, 2); + init_int( test_program); return run_int() ? 0 diff --git a/tests/unit/test_division_opcode.c b/tests/unit/test_division_opcode.c index 5c1c121ac..32e22cf0d 100644 --- a/tests/unit/test_division_opcode.c +++ b/tests/unit/test_division_opcode.c @@ -17,6 +17,7 @@ #include "interpreter.h" #include "mem-allocator.h" #include "opcodes.h" +#include "serializer.h" /** * Unit test's main function. @@ -37,6 +38,12 @@ main( int __unused argc, mem_init(); + const char *strings[] = { "a", + "b" }; + int nums [] = { 2 }; + uint8_t offset = serializer_dump_strings( strings, 2); + serializer_dump_nums( nums, 1, offset, 2); + init_int( test_program); return run_int() ? 0 diff --git a/tests/unit/test_multiplication_opcode.c b/tests/unit/test_multiplication_opcode.c index aba7f5660..fdb31c203 100644 --- a/tests/unit/test_multiplication_opcode.c +++ b/tests/unit/test_multiplication_opcode.c @@ -17,6 +17,7 @@ #include "interpreter.h" #include "mem-allocator.h" #include "opcodes.h" +#include "serializer.h" /** * Unit test's main function. @@ -37,6 +38,12 @@ main( int __unused argc, mem_init(); + const char *strings[] = { "a", + "b" }; + int nums [] = { 2 }; + uint8_t offset = serializer_dump_strings( strings, 2); + serializer_dump_nums( nums, 1, offset, 2); + init_int( test_program); return run_int() ? 0 diff --git a/tests/unit/test_remainder_opcode.c b/tests/unit/test_remainder_opcode.c index 7e4882a5d..d9380fbc4 100644 --- a/tests/unit/test_remainder_opcode.c +++ b/tests/unit/test_remainder_opcode.c @@ -17,6 +17,7 @@ #include "interpreter.h" #include "mem-allocator.h" #include "opcodes.h" +#include "serializer.h" /** * Unit test's main function. @@ -37,6 +38,12 @@ main( int __unused argc, mem_init(); + const char *strings[] = { "a", + "b" }; + int nums [] = { 2 }; + uint8_t offset = serializer_dump_strings( strings, 2); + serializer_dump_nums( nums, 1, offset, 2); + init_int( test_program); return run_int() ? 0 diff --git a/tests/unit/test_substraction_opcode.c b/tests/unit/test_substraction_opcode.c index 392f1bfb5..f47833de7 100644 --- a/tests/unit/test_substraction_opcode.c +++ b/tests/unit/test_substraction_opcode.c @@ -17,6 +17,7 @@ #include "interpreter.h" #include "mem-allocator.h" #include "opcodes.h" +#include "serializer.h" /** * Unit test's main function. @@ -37,6 +38,12 @@ main( int __unused argc, mem_init(); + const char *strings[] = { "a", + "b" }; + int nums [] = { 2 }; + uint8_t offset = serializer_dump_strings( strings, 2); + serializer_dump_nums( nums, 1, offset, 2); + init_int( test_program); return run_int() ? 0 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 a10ab2939..274ad6f77 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 @@ -17,6 +17,7 @@ #include "interpreter.h" #include "mem-allocator.h" #include "opcodes.h" +#include "serializer.h" /** * Unit test's main function. @@ -35,6 +36,12 @@ main( int __unused argc, mem_init(); + const char *strings[] = { "a", + "b" }; + int nums [] = { 2 }; + uint8_t offset = serializer_dump_strings( strings, 2); + serializer_dump_nums( nums, 1, offset, 2); + init_int( test_program); return run_int() ? 0