Implement operations of atomics (#5166)

The following methods were implemented:
 - Atomics.compareExchange
 - Atomics.store

The implementation is based on PR #4956, only resolved the conflicts.

Co-authored-by: Csaba Repasi repasics@inf.u-szeged.hu
JerryScript-DCO-1.0-Signed-off-by: Gergo Csizi gergocs@inf.u-szeged.hu
This commit is contained in:
Gergo Csizi
2024-11-26 10:56:28 +01:00
committed by GitHub
parent dfa9afbf6e
commit 7db6a9a372
12 changed files with 725 additions and 180 deletions
@@ -15,6 +15,7 @@
#include "ecma-arraybuffer-object.h"
#include "ecma-bigint.h"
#include "ecma-builtin-helpers.h"
#include "ecma-builtins.h"
#include "ecma-exceptions.h"
@@ -27,6 +28,8 @@
#include "ecma-typedarray-object.h"
#include "jcontext.h"
#include "jrt.h"
#include "opcodes.h"
#if JERRY_BUILTIN_TYPEDARRAY
@@ -553,6 +556,154 @@ free_new_arraybuffer:
return ret_value;
} /* ecma_builtin_arraybuffer_slice */
/**
* Apply atomics operation on numbers.
*
* Note: ECMA_ATOMICS_COMPAREEXCHANGE is not handled here.
*
* @return ecma value
*/
static ecma_value_t
ecma_atomics_operation_on_number (ecma_value_t stored_value, /**< stored value */
ecma_value_t val, /**< value to operate with */
ecma_atomics_op_t op) /**< operation */
{
ecma_number_t result = ecma_get_number_from_value (stored_value);
switch (op)
{
case ECMA_ATOMICS_ADD:
{
result += ecma_get_number_from_value (val);
break;
}
case ECMA_ATOMICS_EXCHANGE:
{
result = ecma_get_number_from_value (val);
break;
}
case ECMA_ATOMICS_SUBTRACT:
{
result -= ecma_get_number_from_value (val);
break;
}
default:
{
JERRY_STATIC_ASSERT (
(number_bitwise_logic_op) ECMA_ATOMICS_AND == NUMBER_BITWISE_LOGIC_AND,
logical_operations_must_be_on_the_same_index_in_ecma_atomics_op_t_and_number_bitwise_logic_op);
JERRY_STATIC_ASSERT (
(number_bitwise_logic_op) ECMA_ATOMICS_OR == NUMBER_BITWISE_LOGIC_OR,
logical_operations_must_be_on_the_same_index_in_ecma_atomics_op_t_and_number_bitwise_logic_op);
JERRY_STATIC_ASSERT (
(number_bitwise_logic_op) ECMA_ATOMICS_XOR == NUMBER_BITWISE_LOGIC_XOR,
logical_operations_must_be_on_the_same_index_in_ecma_atomics_op_t_and_number_bitwise_logic_op);
return do_number_bitwise_logic ((number_bitwise_logic_op) (op), stored_value, val);
}
}
return ecma_make_number_value (result);
} /* ecma_atomics_operation_on_number */
#if JERRY_BUILTIN_BIGINT
/**
* Apply atomics operation on numbers.
*
* Note: ECMA_ATOMICS_COMPAREEXCHANGE is not handled here.
*
* @return ecma value
*/
static ecma_value_t
ecma_atomics_operation_on_bigint (ecma_value_t stored_value, ecma_value_t val, ecma_atomics_op_t op)
{
switch (op)
{
case ECMA_ATOMICS_ADD:
{
return ecma_bigint_add_sub (stored_value, val, true);
}
case ECMA_ATOMICS_AND:
{
return ecma_bigint_and (stored_value, val);
}
case ECMA_ATOMICS_EXCHANGE:
{
return ecma_copy_value (val);
}
case ECMA_ATOMICS_OR:
{
return ecma_bigint_or (stored_value, val);
}
case ECMA_ATOMICS_SUBTRACT:
{
return ecma_bigint_add_sub (stored_value, val, false);
}
default:
{
JERRY_ASSERT (op == ECMA_ATOMICS_XOR);
return ecma_bigint_xor (stored_value, val);
}
}
} /* ecma_atomics_operation_on_bigint */
#endif /* JERRY_BUILTIN_BIGINT */
/**
* ArrayBuffer get, modify, set value in buffer
*
* See also: ES12 25.1.2.13
* @return ecma value
*/
ecma_value_t
ecma_arraybuffer_get_modify_set_value_in_buffer (
ecma_value_t buffer, /**< arrayBuffer */
uint32_t indexed_position, /**< position of the element in buffer */
ecma_value_t val, /**< parameter of op, number or bigint */
ecma_atomics_op_t op, /**< the atomics operation to execute */
ecma_typedarray_type_t element_type, /**< type of the elements stored in typedArray */
ecma_typedarray_getter_fn_t typedarray_getter_cb, /**< getter callback of typedArray */
ecma_typedarray_setter_fn_t typedarray_setter_cb) /**< setter callback of typedArray */
{
#if !JERRY_BUILTIN_BIGINT
JERRY_UNUSED (element_type);
#endif /* !JERRY_BUILTIN_BIGINT */
/* 1. */
JERRY_ASSERT (!ecma_arraybuffer_is_detached (ecma_get_object_from_value (buffer)));
/* 3. */
JERRY_ASSERT (ecma_is_value_number (val) || ecma_is_value_bigint (val));
ecma_object_t *buffer_obj_p = ecma_get_object_from_value (buffer);
lit_utf8_byte_t *pos = ecma_arraybuffer_get_buffer (buffer_obj_p) + indexed_position;
ecma_value_t stored_value = typedarray_getter_cb (pos);
ecma_value_t op_result;
#if JERRY_BUILTIN_BIGINT
if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (element_type))
{
op_result = ecma_atomics_operation_on_bigint (stored_value, val, op);
}
else
#endif /* JERRY_BUILTIN_BIGINT */
{
op_result = ecma_atomics_operation_on_number (stored_value, val, op);
}
ecma_free_value (val);
if (ECMA_IS_VALUE_ERROR (op_result))
{
return op_result;
}
// TODO: Handle shared array buffers differently.
typedarray_setter_cb (pos, op_result);
ecma_free_value (op_result);
return stored_value;
} /* ecma_arraybuffer_get_modify_set_value_in_buffer */
/**
* @}
* @}