diff --git a/jerry-core/ecma/operations/ecma-arraybuffer-object.c b/jerry-core/ecma/operations/ecma-arraybuffer-object.c index 3e796fb25..cf44a5983 100644 --- a/jerry-core/ecma/operations/ecma-arraybuffer-object.c +++ b/jerry-core/ecma/operations/ecma-arraybuffer-object.c @@ -32,53 +32,6 @@ * @{ */ -/** - * ArrayBuffer object creation operation. - * - * See also: ES2015 24.1.1.1 - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_create_arraybuffer_object (const ecma_value_t *arguments_list_p, /**< list of arguments that - * are passed to String constructor */ - ecma_length_t arguments_list_len) /**< length of the arguments' list */ -{ - JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); - - uint32_t length = 0; - - if (arguments_list_len > 0) - { - ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (num, arguments_list_p[0], ret); - length = ecma_number_to_uint32 (num); - - if (num != ((ecma_number_t) length)) - { - return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid ArrayBuffer length.")); - } - - ECMA_OP_TO_NUMBER_FINALIZE (num); - - if (!ecma_is_value_empty (ret)) - { - return ret; - } - } - - if (length > UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1) - { - return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid ArrayBuffer length.")); - } - - ecma_object_t *object_p = ecma_arraybuffer_new_object (length); - - return ecma_make_object_value (object_p); -} /* ecma_op_create_arraybuffer_object */ - /** * Helper function: create arraybuffer object based on the array length * @@ -108,27 +61,55 @@ ecma_arraybuffer_new_object (ecma_length_t length) /**< length of the arraybuffe } /* ecma_arraybuffer_new_object */ /** - * Helper function: create arraybuffer object by cloning another arraybuffer + * ArrayBuffer object creation operation. * - * See also: ES2015 24.1.1.4 + * See also: ES2015 24.1.1.1 * - * @return cloned array buffer + * @return ecma value + * Returned value must be freed with ecma_free_value */ -ecma_object_t * -ecma_arraybuffer_clone_arraybuffer (ecma_object_t *array_buf_p, /**< the cloned array buffer */ - ecma_length_t offset) /**< start offset */ +ecma_value_t +ecma_op_create_arraybuffer_object (const ecma_value_t *arguments_list_p, /**< list of arguments that + * are passed to String constructor */ + ecma_length_t arguments_list_len) /**< length of the arguments' list */ { + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); - JERRY_ASSERT (offset <= ecma_arraybuffer_get_length (array_buf_p)); + uint32_t length = 0; - ecma_length_t length = ecma_arraybuffer_get_length (array_buf_p) - offset; - ecma_object_t *new_array_buf_p = ecma_arraybuffer_new_object (length); - lit_utf8_byte_t *src_buf_p = ecma_arraybuffer_get_buffer (array_buf_p); - lit_utf8_byte_t *dst_buf_p = ecma_arraybuffer_get_buffer (new_array_buf_p); - memcpy (dst_buf_p, src_buf_p + offset, length); + if (arguments_list_len > 0) + { + ecma_number_t num; - return new_array_buf_p; -} /* ecma_arraybuffer_clone_arraybuffer */ + if (ecma_is_value_number (arguments_list_p[0])) + { + num = ecma_get_number_from_value (arguments_list_p[0]); + } + else + { + ecma_value_t to_number_value = ecma_op_to_number (arguments_list_p[0]); + + if (ECMA_IS_VALUE_ERROR (to_number_value)) + { + return to_number_value; + } + + num = ecma_get_number_from_value (to_number_value); + + ecma_free_value (to_number_value); + } + + length = ecma_number_to_uint32 (num); + + if (num != ((ecma_number_t) length) + || length > (UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1)) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid ArrayBuffer length.")); + } + } + + return ecma_make_object_value (ecma_arraybuffer_new_object (length)); +} /* ecma_op_create_arraybuffer_object */ /** * Helper function: check if the target is ArrayBuffer @@ -142,15 +123,9 @@ ecma_arraybuffer_clone_arraybuffer (ecma_object_t *array_buf_p, /**< the cloned bool ecma_is_arraybuffer (ecma_value_t target) /**< the target value */ { - if (!ecma_is_value_object (target)) - { - return false; - } - - ecma_object_t *obj_p = ecma_get_object_from_value (target); - lit_magic_string_id_t class_id = ecma_object_get_class_name (obj_p); - - return class_id == LIT_MAGIC_STRING_ARRAY_BUFFER_UL; + return (ecma_is_value_object (target) + && ecma_object_class_is (ecma_get_object_from_value (target), + LIT_MAGIC_STRING_ARRAY_BUFFER_UL)); } /* ecma_is_arraybuffer */ /** diff --git a/jerry-core/ecma/operations/ecma-arraybuffer-object.h b/jerry-core/ecma/operations/ecma-arraybuffer-object.h index e3d7418d4..f363f4c38 100644 --- a/jerry-core/ecma/operations/ecma-arraybuffer-object.h +++ b/jerry-core/ecma/operations/ecma-arraybuffer-object.h @@ -34,8 +34,6 @@ ecma_op_create_arraybuffer_object (const ecma_value_t *, ecma_length_t); */ ecma_object_t * ecma_arraybuffer_new_object (ecma_length_t lengh); -ecma_object_t * -ecma_arraybuffer_clone_arraybuffer (ecma_object_t *src_p, ecma_length_t offset); lit_utf8_byte_t * ecma_arraybuffer_get_buffer (ecma_object_t *obj_p) __attr_pure___; ecma_length_t diff --git a/jerry-core/ecma/operations/ecma-typedarray-object.c b/jerry-core/ecma/operations/ecma-typedarray-object.c index 84d27bd58..8890b4832 100644 --- a/jerry-core/ecma/operations/ecma-typedarray-object.c +++ b/jerry-core/ecma/operations/ecma-typedarray-object.c @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "ecma-typedarray-object.h" #include "ecma-arraybuffer-object.h" #include "ecma-function-object.h" @@ -39,17 +41,8 @@ * cast it from type to ecma_number_t * then assign to variale number */ -#define GET_ELEMENT(type, location, number) \ - type v = *((type *) location); \ - number = (ecma_number_t) v; - -/** - * Cast the number from ecma_numbet_t into type, - * and store the number in the location - */ -#define SET_ELEMENT(type, location, number) \ - int64_t v = (int64_t) number; \ - *((type *) location) = (type) v; +#define GET_ELEMENT(type, location) \ + ((ecma_number_t) (*((type *) location))); /** * set typedarray's element value @@ -60,82 +53,63 @@ static ecma_number_t get_typedarray_element (lit_utf8_byte_t *src, /**< the location in the internal arraybuffer */ lit_magic_string_id_t class_id) /**< class name of the typedarray */ { - ecma_number_t ret_num; - switch (class_id) { case LIT_MAGIC_STRING_INT8_ARRAY_UL: { - GET_ELEMENT (int8_t, src, ret_num); - break; + return GET_ELEMENT (int8_t, src); } case LIT_MAGIC_STRING_UINT8_ARRAY_UL: case LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL: { - GET_ELEMENT (uint8_t, src, ret_num); - break; + return GET_ELEMENT (uint8_t, src); } case LIT_MAGIC_STRING_INT16_ARRAY_UL: { - GET_ELEMENT (int16_t, src, ret_num); - break; + return GET_ELEMENT (int16_t, src); } case LIT_MAGIC_STRING_UINT16_ARRAY_UL: { - GET_ELEMENT (uint16_t, src, ret_num); - break; + return GET_ELEMENT (uint16_t, src); } case LIT_MAGIC_STRING_INT32_ARRAY_UL: { - GET_ELEMENT (int32_t, src, ret_num); - break; + return GET_ELEMENT (int32_t, src); } case LIT_MAGIC_STRING_UINT32_ARRAY_UL: { - GET_ELEMENT (uint32_t, src, ret_num); - break; + return GET_ELEMENT (uint32_t, src); } case LIT_MAGIC_STRING_FLOAT32_ARRAY_UL: { - GET_ELEMENT (float, src, ret_num); - break; + return GET_ELEMENT (float, src); } #if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 case LIT_MAGIC_STRING_FLOAT64_ARRAY_UL: { - GET_ELEMENT (double, src, ret_num); - break; + return GET_ELEMENT (double, src); } #endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 */ default: { JERRY_UNREACHABLE (); + return 0; } } - - return ret_num; } /* get_typedarray_element */ +#undef GET_ELEMENT + /** * set typedarray's element value */ static void -set_typedarray_element (lit_utf8_byte_t *dst, /**< the location in the internal arraybuffer */ +set_typedarray_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ ecma_number_t value, /**< the number value to set */ lit_magic_string_id_t class_id) /**< class name of the typedarray */ { switch (class_id) { - case LIT_MAGIC_STRING_INT8_ARRAY_UL: - { - SET_ELEMENT (int8_t, dst, value); - break; - } - case LIT_MAGIC_STRING_UINT8_ARRAY_UL: - { - SET_ELEMENT (uint8_t, dst, value); - break; - } case LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL: { uint8_t clamped; @@ -144,7 +118,7 @@ set_typedarray_element (lit_utf8_byte_t *dst, /**< the location in the internal { clamped = 255; } - else if (value < 0) + else if (value <= 0) { clamped = 0; } @@ -153,46 +127,89 @@ set_typedarray_element (lit_utf8_byte_t *dst, /**< the location in the internal clamped = (uint8_t) value; if (clamped + 0.5 < value - || (clamped + 0.5 == value && clamped % 2 == 1)) + || (clamped + 0.5 == value && (clamped % 2) == 1)) { clamped ++; } } - *((uint8_t *) dst) = clamped; - break; - } - case LIT_MAGIC_STRING_INT16_ARRAY_UL: - { - SET_ELEMENT (int16_t, dst, value); - break; - } - case LIT_MAGIC_STRING_UINT16_ARRAY_UL: - { - SET_ELEMENT (uint16_t, dst, value); - break; - } - case LIT_MAGIC_STRING_INT32_ARRAY_UL: - { - SET_ELEMENT (int32_t, dst, value); - break; - } - case LIT_MAGIC_STRING_UINT32_ARRAY_UL: - { - SET_ELEMENT (uint32_t, dst, value); - break; + *((uint8_t *) dst_p) = clamped; + return; } case LIT_MAGIC_STRING_FLOAT32_ARRAY_UL: { - *((float *) dst) = (float) value; - break; + *((float *) dst_p) = (float) value; + return; } #if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 case LIT_MAGIC_STRING_FLOAT64_ARRAY_UL: { - *((double *) dst) = (double) value; - break; + *((double *) dst_p) = (double) value; + return; } #endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 */ + default: + { + break; + } + } + + uint32_t uint32_value = 0; + + if (!ecma_number_is_nan (value) && !ecma_number_is_infinity (value)) + { + bool is_negative = false; + + if (value < 0) + { + is_negative = true; + value = -value; + } + + if (value > ((ecma_number_t) 0xffffffff)) + { + value = (ecma_number_t) (fmod (value, (ecma_number_t) 0x100000000)); + } + + uint32_value = (uint32_t) value; + + if (is_negative) + { + uint32_value = (uint32_t) (-(int32_t) uint32_value); + } + } + + switch (class_id) + { + case LIT_MAGIC_STRING_INT8_ARRAY_UL: + { + *((int8_t *) dst_p) = (int8_t) uint32_value; + break; + } + case LIT_MAGIC_STRING_UINT8_ARRAY_UL: + { + *((uint8_t *) dst_p) = (uint8_t) uint32_value; + break; + } + case LIT_MAGIC_STRING_INT16_ARRAY_UL: + { + *((int16_t *) dst_p) = (int16_t) uint32_value; + break; + } + case LIT_MAGIC_STRING_UINT16_ARRAY_UL: + { + *((uint16_t *) dst_p) = (uint16_t) uint32_value; + break; + } + case LIT_MAGIC_STRING_INT32_ARRAY_UL: + { + *((int32_t *) dst_p) = (int32_t) uint32_value; + break; + } + case LIT_MAGIC_STRING_UINT32_ARRAY_UL: + { + *((uint32_t *) dst_p) = uint32_value; + break; + } default: { JERRY_UNREACHABLE (); @@ -258,36 +275,29 @@ ecma_typedarray_create_object_with_buffer (ecma_object_t *arraybuffer_p, /**< th uint8_t element_size_shift, /**< the size shift of the element length */ lit_magic_string_id_t class_id) /**< class name of the typedarray */ { - ecma_object_t *object_p; + ecma_length_t expected_length = (ecma_arraybuffer_get_length (arraybuffer_p) >> element_size_shift); - if (byte_offset == 0 && array_length == ecma_arraybuffer_get_length (arraybuffer_p) >> element_size_shift) - { - object_p = ecma_create_object (proto_p, - sizeof (ecma_extended_object_t), - ECMA_OBJECT_TYPE_PSEUDO_ARRAY); + bool needs_ext_typedarray_obj = (byte_offset != 0 || array_length != expected_length); - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - ext_object_p->u.pseudo_array.u1.class_id = class_id; - ext_object_p->u.pseudo_array.type = ECMA_PSEUDO_ARRAY_TYPEDARRAY; - ext_object_p->u.pseudo_array.extra_info = element_size_shift; - ext_object_p->u.pseudo_array.u2.arraybuffer = ecma_make_object_value (arraybuffer_p); + size_t object_size = (needs_ext_typedarray_obj ? sizeof (ecma_extended_typedarray_object_t) + : sizeof (ecma_extended_object_t)); - return ecma_make_object_value (object_p); - } - - object_p = ecma_create_object (proto_p, - sizeof (ecma_extended_typedarray_object_t), - ECMA_OBJECT_TYPE_PSEUDO_ARRAY); + ecma_object_t *object_p = ecma_create_object (proto_p, object_size, ECMA_OBJECT_TYPE_PSEUDO_ARRAY); ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; ext_object_p->u.pseudo_array.u1.class_id = class_id; - ext_object_p->u.pseudo_array.type = ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO; + ext_object_p->u.pseudo_array.type = ECMA_PSEUDO_ARRAY_TYPEDARRAY; ext_object_p->u.pseudo_array.extra_info = element_size_shift; ext_object_p->u.pseudo_array.u2.arraybuffer = ecma_make_object_value (arraybuffer_p); - ecma_extended_typedarray_object_t *typedarray_info_p = (ecma_extended_typedarray_object_t *) ext_object_p; - typedarray_info_p->array_length = array_length; - typedarray_info_p->byte_offset = byte_offset; + if (needs_ext_typedarray_obj) + { + ext_object_p->u.pseudo_array.type = ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO; + + ecma_extended_typedarray_object_t *typedarray_info_p = (ecma_extended_typedarray_object_t *) object_p; + typedarray_info_p->array_length = array_length; + typedarray_info_p->byte_offset = byte_offset; + } return ecma_make_object_value (object_p); } /* ecma_typedarray_create_object_with_buffer */ @@ -307,57 +317,50 @@ ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**< lit_magic_string_id_t class_id) /**< class name of the typedarray */ { ecma_length_t array_length = ecma_typedarray_get_length (typedarray_p); - ecma_length_t byte_offset = ecma_typedarray_get_offset (typedarray_p); + + ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (array_length, + proto_p, + element_size_shift, + class_id); + + if (ECMA_IS_VALUE_ERROR (new_typedarray)) + { + return new_typedarray; + } + + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); + ecma_object_t *src_arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p); + lit_utf8_byte_t *src_buf_p = ecma_arraybuffer_get_buffer (src_arraybuffer_p); + + ecma_object_t *dst_arraybuffer_p = ecma_typedarray_get_arraybuffer (new_typedarray_p); + lit_utf8_byte_t *dst_buf_p = ecma_arraybuffer_get_buffer (dst_arraybuffer_p); + + src_buf_p += ecma_typedarray_get_offset (typedarray_p); + lit_magic_string_id_t src_class_id = ecma_object_get_class_name (typedarray_p); - ecma_object_t *arraybuffer_p = NULL; if (src_class_id == class_id) { - arraybuffer_p = ecma_arraybuffer_clone_arraybuffer (src_arraybuffer_p, - byte_offset); + memcpy (dst_buf_p, src_buf_p, array_length << element_size_shift); } else { - if (array_length > (UINT32_MAX >> element_size_shift)) - { - return ecma_raise_range_error (ECMA_ERR_MSG ("Maximum typedarray size is reached.")); - } - - ecma_length_t byte_length = array_length << element_size_shift; - - if (byte_length > UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1) - { - return ecma_raise_range_error (ECMA_ERR_MSG ("Maximum typedarray size is reached.")); - } - - arraybuffer_p = ecma_arraybuffer_new_object (byte_length); - lit_utf8_byte_t *src_buf = ecma_arraybuffer_get_buffer (src_arraybuffer_p); - lit_utf8_byte_t *dst_buf = ecma_arraybuffer_get_buffer (arraybuffer_p); - uint8_t src_element_size_shift = ecma_typedarray_get_element_size_shift (typedarray_p); + uint32_t src_element_size = 1u << ecma_typedarray_get_element_size_shift (typedarray_p); + uint32_t dst_element_size = 1u << element_size_shift; for (uint32_t i = 0; i < array_length; i++) { - ecma_number_t tmp = get_typedarray_element (src_buf, - ecma_object_get_class_name (typedarray_p)); - /** check dst type and set value to dst typedarray */ - set_typedarray_element (dst_buf, tmp, class_id); + /* Convert values from source to destination format. */ + ecma_number_t tmp = get_typedarray_element (src_buf_p, src_class_id); + set_typedarray_element (dst_buf_p, tmp, class_id); - src_buf = src_buf + (1 << src_element_size_shift); - dst_buf = dst_buf + (1 << element_size_shift); + src_buf_p += src_element_size; + dst_buf_p += dst_element_size; } } - ecma_value_t obj = ecma_typedarray_create_object_with_buffer (arraybuffer_p, - 0, - array_length, - proto_p, - element_size_shift, - class_id); - - ecma_deref_object (arraybuffer_p); - - return obj; + return new_typedarray; } /* ecma_typedarray_create_object_with_typedarray */ /** @@ -388,17 +391,18 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje } /* 10 */ - ECMA_TRY_CATCH (arraylike, + ECMA_TRY_CATCH (arraylike_object_val, ecma_op_to_object (items_val), ret_value); - ecma_object_t *arraylike_p = ecma_get_object_from_value (arraylike); + ecma_object_t *arraylike_object_p = ecma_get_object_from_value (arraylike_object_val); /* 12 */ - ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); + ecma_string_t magic_string_length; + ecma_init_ecma_length_string (&magic_string_length); ECMA_TRY_CATCH (len_value, - ecma_op_object_get (arraylike_p, magic_string_length_p), + ecma_op_object_get (arraylike_object_p, &magic_string_length), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); @@ -427,7 +431,7 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); /* 17.b */ - ECMA_TRY_CATCH (current_value, ecma_op_object_find (arraylike_p, index_str_p), ret_value); + ECMA_TRY_CATCH (current_value, ecma_op_object_find (arraylike_object_p, index_str_p), ret_value); if (ecma_is_value_found (current_value)) { @@ -476,8 +480,7 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje ECMA_OP_TO_NUMBER_FINALIZE (len_number); ECMA_FINALIZE (len_value); - ecma_deref_ecma_string (magic_string_length_p); - ECMA_FINALIZE (arraylike); + ECMA_FINALIZE (arraylike_object_val); return ret_value; } /* ecma_op_typedarray_from */ diff --git a/tests/jerry-test-suite/es2015/22/22.02/22.02.01/22.02.01-015.js b/tests/jerry-test-suite/es2015/22/22.02/22.02.01/22.02.01-015.js index 3a9d5009c..5fb7709f3 100644 --- a/tests/jerry-test-suite/es2015/22/22.02/22.02.01/22.02.01-015.js +++ b/tests/jerry-test-suite/es2015/22/22.02/22.02.01/22.02.01-015.js @@ -13,12 +13,22 @@ * limitations under the License. */ -var a = new Int32Array(3); +var a = new Int32Array(8); a[0] = 0xffffffff; a[1] = 0xff00000001; -a[2] = -2.3; +a[2] = 0xff80000001; +a[3] = -2.3; +a[4] = Number.NEGATIVE_INFINITY; +a[5] = NaN; +a[6] = 10e17; +a[7] = -10e17; assert(a[0] === -1); assert(a[1] === 1); -assert(a[2] === -2); +assert(a[2] === -2147483647); +assert(a[3] === -2); +assert(a[4] === 0); +assert(a[5] === 0); +assert(a[6] === -1486618624); +assert(a[7] === 1486618624);