Skip to content

Commit ff4f383

Browse files
committed
Implement atomics routines
JerryScript-DCO-1.0-Signed-off-by: Csaba Repasi [email protected]
1 parent 49a1a80 commit ff4f383

File tree

7 files changed

+637
-173
lines changed

7 files changed

+637
-173
lines changed

jerry-core/ecma/base/ecma-error-messages.inc.h

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,11 @@ ECMA_ERROR_DEF (ECMA_ERR_UNSUPPORTED_BINARY_OPERATION, "Unsupported binary opera
257257
#if JERRY_BUILTIN_REGEXP
258258
ECMA_ERROR_DEF (ECMA_ERR_UNTERMINATED_CHARACTER_CLASS, "Unterminated character class")
259259
#endif /* JERRY_BUILTIN_REGEXP */
260-
#if JERRY_BUILTIN_DATAVIEW || JERRY_BUILTIN_TYPEDARRAY || JERRY_ESNEXT
260+
#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_DATAVIEW || JERRY_BUILTIN_TYPEDARRAY || JERRY_ESNEXT
261261
ECMA_ERROR_DEF (ECMA_ERR_ARRAYBUFFER_IS_DETACHED, "ArrayBuffer has been detached")
262-
#endif /* JERRY_BUILTIN_DATAVIEW \
263-
|| JERRY_BUILTIN_TYPEDARRAY \
262+
#endif /* JERRY_BUILTIN_ATOMICS \
263+
|| JERRY_BUILTIN_DATAVIEW \
264+
|| JERRY_BUILTIN_TYPEDARRAY \
264265
|| JERRY_ESNEXT */
265266
#if JERRY_ESNEXT
266267
ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_NOT_AN_OBJECT, "Constructor must be an object")
@@ -290,9 +291,10 @@ ECMA_ERROR_DEF (ECMA_ERR_MODULE_CANNOT_BE_INSTANTIATED, "Module cannot be instan
290291
ECMA_ERROR_DEF (ECMA_ERR_SPECIES_MUST_BE_A_CONSTRUCTOR, "Species must be a constructor")
291292
#endif /* JERRY_ESNEXT */
292293
ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_IS_NOT_A_PROXY, "Argument is not a Proxy object")
293-
#if JERRY_BUILTIN_TYPEDARRAY
294+
#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_TYPEDARRAY
294295
ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_NOT_ARRAY_BUFFER, "Argument is not an ArrayBuffer")
295-
#endif /* JERRY_BUILTIN_TYPEDARRAY */
296+
#endif /* JERRY_BUILTIN_ATOMICS \
297+
|| JERRY_BUILTIN_TYPEDARRAY */
296298
#if JERRY_BUILTIN_CONTAINER
297299
ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_MAP_REQUIRES_NEW, "Constructor Map requires 'new'")
298300
ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_SET_REQUIRES_NEW, "Constructor Set requires 'new'")
@@ -383,9 +385,6 @@ ECMA_ERROR_DEF (ECMA_ERR_STATIC_SNAPSHOTS_ARE_NOT_ENABLED, "Static snapshots are
383385
ECMA_ERROR_DEF (ECMA_ERR_WEAKREF_TARGET_MUST_BE_AN_OBJECT, "WeakRef target must be an object")
384386
#endif /* JERRY_BUILTIN_WEAKREF */
385387
ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_FUNCTION, "Argument 'this' is not a function")
386-
#if JERRY_BUILTIN_ATOMICS
387-
ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_NOT_SHARED_ARRAY_BUFFER, "Argument is not SharedArrayBuffer")
388-
#endif /* JERRY_BUILTIN_ATOMICS */
389388
#if JERRY_BUILTIN_ARRAY || JERRY_BUILTIN_CONTAINER || JERRY_BUILTIN_TYPEDARRAY
390389
ECMA_ERROR_DEF (ECMA_ERR_CALLBACK_IS_NOT_CALLABLE, "Callback function is not callable")
391390
#endif /* JERRY_BUILTIN_ARRAY \
@@ -434,9 +433,10 @@ ECMA_ERROR_DEF (ECMA_ERR_MAXIMUM_TYPEDARRAY_SIZE_IS_REACHED, "Maximum TypedArray
434433
ECMA_ERROR_DEF (ECMA_ERR_THE_GIVEN_ARGUMENT_IS_NOT_A_SYMBOL, "The given argument is not a Symbol")
435434
ECMA_ERROR_DEF (ECMA_ERR_PARAMETER_REJECT_MUST_BE_CALLABLE, "'reject' parameter must be callable")
436435
#endif /* JERRY_ESNEXT */
437-
#if JERRY_BUILTIN_TYPEDARRAY || JERRY_ESNEXT
436+
#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_TYPEDARRAY || JERRY_ESNEXT
438437
ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY, "Argument 'this' is not a TypedArray")
439-
#endif /* JERRY_BUILTIN_TYPEDARRAY \
438+
#endif /* JERRY_BUILTIN_ATOMICS \
439+
|| JERRY_BUILTIN_TYPEDARRAY \
440440
|| JERRY_ESNEXT */
441441
#if JERRY_SNAPSHOT_SAVE
442442
ECMA_ERROR_DEF (ECMA_ERR_CANNOT_ALLOCATE_MEMORY_LITERALS, "Cannot allocate memory for literals")
@@ -547,11 +547,6 @@ ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_UINT32_ARRAY_REQUIRES_NEW, "Constructor Uin
547547
#if JERRY_ESNEXT
548548
ECMA_ERROR_DEF (ECMA_ERR_GENERATOR_IS_CURRENTLY_UNDER_EXECUTION, "Generator is currently under execution")
549549
ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_RETURN_RESULT_IS_NOT_OBJECT, "Iterator 'return' result is not object")
550-
#endif /* JERRY_ESNEXT */
551-
#if JERRY_BUILTIN_TYPEDARRAY
552-
ECMA_ERROR_DEF (ECMA_ERR_RETURNED_ARRAYBUFFER_HAS_BEEN_DETACHED, "Returned ArrayBuffer has been detached")
553-
#endif /* JERRY_BUILTIN_TYPEDARRAY */
554-
#if JERRY_ESNEXT
555550
ECMA_ERROR_DEF (ECMA_ERR_SEARCH_STRING_CANNOT_BE_OF_TYPE_REGEXP, "Search string can't be of type: RegExp")
556551
ECMA_ERROR_DEF (ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT, "Value received by yield* is not object")
557552
#endif /* JERRY_ESNEXT */
@@ -595,8 +590,11 @@ ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_GENERATOR_OBJECT, "Argument 'this' is
595590
ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_CANNOT_CONVERT_TO_OBJECT, "Argument cannot be converted to an object")
596591
#if JERRY_BUILTIN_BIGINT
597592
ECMA_ERROR_DEF (ECMA_ERR_ALLOCATE_BIGINT_VALUE, "Cannot allocate memory for a BigInt value")
598-
ECMA_ERROR_DEF (ECMA_ERR_CONVERT_BIGINT_TO_NUMBER, "Cannot convert a BigInt value to a number")
599593
#endif /* JERRY_BUILTIN_BIGINT */
594+
#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_BIGINT
595+
ECMA_ERROR_DEF (ECMA_ERR_CONVERT_BIGINT_TO_NUMBER, "Cannot convert a BigInt value to a number")
596+
#endif /* JERRY_BUILTIN_ATOMICS \
597+
|| JERRY_BUILTIN_BIGINT */
600598
#if JERRY_ESNEXT
601599
ECMA_ERROR_DEF (ECMA_ERR_CONVERT_SYMBOL_TO_NUMBER, "Cannot convert a Symbol value to a number")
602600
ECMA_ERROR_DEF (ECMA_ERR_CONVERT_SYMBOL_TO_STRING, "Cannot convert a Symbol value to a string")

jerry-core/ecma/base/ecma-error-messages.ini

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ ECMA_ERR_ARGUMENT_THIS_NOT_ITERATOR = "Argument 'this' is not an iterator"
4040
ECMA_ERR_ARGUMENT_THIS_NOT_OBJECT = "Argument 'this' is not an object"
4141
ECMA_ERR_ARGUMENT_THIS_NOT_SYMBOL = "Argument 'this' must be a Symbol"
4242
ECMA_ERR_ARGUMENT_CANNOT_CONVERT_TO_OBJECT = "Argument cannot be converted to an object"
43-
ECMA_ERR_ARGUMENT_NOT_SHARED_ARRAY_BUFFER = "Argument is not SharedArrayBuffer"
4443
ECMA_ERR_ARGUMENT_NOT_ARRAY_BUFFER = "Argument is not an ArrayBuffer"
4544
ECMA_ERR_ARGUMENT_NOT_SUPPORTED = "Argument is not supported"
4645
ECMA_ERR_ARRAY_BUFFER_DETACHED = "ArrayBuffer has already been detached"
@@ -213,7 +212,6 @@ ECMA_ERR_RESOLVE_MUST_BE_UNDEFINED = "Resolve must be undefined"
213212
ECMA_ERR_RESULT_OF_DEFAULTVALUE_IS_INVALID = "Result of [[DefaultValue]] is invalid"
214213
ECMA_ERR_RETURN_VALUE_IS_NOT_AN_ARRAYBUFFER_OBJECT = "Return value is not an ArrayBuffer object"
215214
ECMA_ERR_RETURN_VALUE_OF_EXEC_MUST_BE_AN_OBJECT_OR_NULL = "Return value of 'exec' must be an object or null"
216-
ECMA_ERR_RETURNED_ARRAYBUFFER_HAS_BEEN_DETACHED = "Returned ArrayBuffer has been detached"
217215
ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT = "Right value of 'in' must be an object"
218216
ECMA_ERR_RIGHT_VALUE_OF_INSTANCEOF_MUST_BE_AN_OBJECT = "Right value of 'instanceof' must be an object"
219217
ECMA_ERR_SEARCH_STRING_CANNOT_BE_OF_TYPE_REGEXP = "Search string can't be of type: RegExp"

jerry-core/ecma/builtin-objects/ecma-builtin-atomics.c

Lines changed: 167 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,17 @@
1313
* limitations under the License.
1414
*/
1515

16+
#include "ecma-arraybuffer-object.h"
1617
#include "ecma-atomics-object.h"
18+
#include "ecma-bigint.h"
1719
#include "ecma-builtins.h"
20+
#include "ecma-errors.h"
21+
#include "ecma-exceptions.h"
22+
#include "ecma-gc.h"
1823
#include "ecma-globals.h"
1924
#include "ecma-helpers.h"
25+
#include "ecma-shared-arraybuffer-object.h"
26+
#include "ecma-typedarray-object.h"
2027

2128
#include "jrt.h"
2229

@@ -69,7 +76,7 @@ enum
6976
/**
7077
* The Atomics object's 'compareExchange' routine
7178
*
72-
* See also: ES11 24.4.4
79+
* See also: ES12 25.4.4
7380
*
7481
* @return ecma value
7582
* Returned value must be freed with ecma_free_value.
@@ -80,12 +87,90 @@ ecma_builtin_atomics_compare_exchange (ecma_value_t typedarray, /**< typedArray
8087
ecma_value_t expected_value, /**< expectedValue argument */
8188
ecma_value_t replacement_value) /**< replacementValue argument*/
8289
{
83-
JERRY_UNUSED (typedarray);
84-
JERRY_UNUSED (index);
85-
JERRY_UNUSED (expected_value);
86-
JERRY_UNUSED (replacement_value);
90+
ecma_value_t buffer = ecma_validate_integer_typedarray (typedarray, false);
8791

88-
return ecma_make_uint32_value (0);
92+
if (ECMA_IS_VALUE_ERROR (buffer))
93+
{
94+
return buffer;
95+
}
96+
97+
uint32_t idx = ecma_validate_atomic_access (typedarray, index);
98+
99+
if (idx == ECMA_STRING_NOT_ARRAY_INDEX)
100+
{
101+
return ECMA_VALUE_ERROR;
102+
}
103+
104+
ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray);
105+
ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p);
106+
107+
if (ECMA_ARRAYBUFFER_LAZY_ALLOC (target_info.array_buffer_p))
108+
{
109+
return ECMA_VALUE_ERROR;
110+
}
111+
112+
ecma_typedarray_type_t element_type = target_info.id;
113+
ecma_value_t expected;
114+
ecma_value_t replacement;
115+
ecma_number_t tmp_exp;
116+
ecma_number_t tmp_rep;
117+
118+
if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (element_type))
119+
{
120+
expected = ecma_bigint_to_bigint (expected_value, false);
121+
122+
if (ECMA_IS_VALUE_ERROR (expected))
123+
{
124+
return expected;
125+
}
126+
127+
replacement = ecma_bigint_to_bigint (replacement_value, false);
128+
129+
if (ECMA_IS_VALUE_ERROR (replacement))
130+
{
131+
ecma_free_value (expected);
132+
return replacement;
133+
}
134+
}
135+
else if (!ECMA_IS_VALUE_ERROR (ecma_op_to_integer (expected_value, &tmp_exp))
136+
&& !ECMA_IS_VALUE_ERROR (ecma_op_to_integer (replacement_value, &tmp_rep)))
137+
{
138+
expected = ecma_make_number_value (tmp_exp);
139+
replacement = ecma_make_number_value (tmp_rep);
140+
}
141+
else
142+
{
143+
return ECMA_VALUE_ERROR;
144+
}
145+
146+
uint8_t element_size = target_info.element_size;
147+
uint32_t offset = target_info.offset;
148+
uint32_t indexed_position = idx * element_size + offset;
149+
150+
if (ecma_arraybuffer_is_detached (ecma_get_object_from_value (buffer)))
151+
{
152+
ecma_free_value (expected);
153+
ecma_free_value (replacement);
154+
return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED);
155+
}
156+
157+
ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (element_type);
158+
159+
ecma_object_t *buffer_obj_p = ecma_get_object_from_value (buffer);
160+
lit_utf8_byte_t *pos = ecma_arraybuffer_get_buffer (buffer_obj_p) + indexed_position;
161+
ecma_value_t stored_value = typedarray_getter_cb (pos);
162+
163+
// TODO: Handle shared array buffers differently.
164+
if (ecma_op_same_value (stored_value, expected))
165+
{
166+
ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (element_type);
167+
typedarray_setter_cb (ecma_arraybuffer_get_buffer (buffer_obj_p) + indexed_position, replacement);
168+
}
169+
170+
ecma_free_value (expected);
171+
ecma_free_value (replacement);
172+
173+
return stored_value;
89174
} /* ecma_builtin_atomics_compare_exchange */
90175

91176
/**
@@ -117,11 +202,83 @@ ecma_builtin_atomics_store (ecma_value_t typedarray, /**< typedArray argument */
117202
ecma_value_t index, /**< index argument */
118203
ecma_value_t value) /**< value argument */
119204
{
120-
JERRY_UNUSED (typedarray);
121-
JERRY_UNUSED (index);
122-
JERRY_UNUSED (value);
205+
/* 1. */
206+
ecma_value_t buffer = ecma_validate_integer_typedarray (typedarray, false);
123207

124-
return ecma_make_uint32_value (0);
208+
if (ECMA_IS_VALUE_ERROR (buffer))
209+
{
210+
return buffer;
211+
}
212+
213+
/* 2. */
214+
uint32_t idx = ecma_validate_atomic_access (typedarray, index);
215+
216+
if (idx == ECMA_STRING_NOT_ARRAY_INDEX)
217+
{
218+
return ECMA_VALUE_ERROR;
219+
}
220+
221+
ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray);
222+
ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p);
223+
224+
if (ECMA_ARRAYBUFFER_LAZY_ALLOC (target_info.array_buffer_p))
225+
{
226+
return ECMA_VALUE_ERROR;
227+
}
228+
229+
uint8_t element_size = target_info.element_size;
230+
231+
ecma_typedarray_type_t element_type = target_info.id;
232+
233+
uint32_t offset = target_info.offset;
234+
235+
uint32_t indexed_position = idx * element_size + offset;
236+
237+
ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (element_type);
238+
ecma_object_t *buffer_obj_p = ecma_get_object_from_value (buffer);
239+
240+
ecma_value_t v;
241+
if (element_type == ECMA_BIGINT64_ARRAY || element_type == ECMA_BIGUINT64_ARRAY)
242+
{
243+
v = ecma_bigint_to_bigint (value, false);
244+
}
245+
else
246+
{
247+
ecma_number_t num_int;
248+
249+
v = ecma_op_to_integer (value, &num_int);
250+
251+
if (ECMA_IS_VALUE_ERROR (v))
252+
{
253+
return v;
254+
}
255+
256+
if (ecma_number_is_zero (num_int) && ecma_number_is_negative (num_int))
257+
{
258+
num_int = (ecma_number_t) 0;
259+
value = ecma_make_number_value ((ecma_number_t) 0);
260+
}
261+
262+
v = ecma_make_number_value (num_int);
263+
}
264+
265+
if (ECMA_IS_VALUE_ERROR (v))
266+
{
267+
return v;
268+
}
269+
270+
if (ecma_arraybuffer_is_detached (ecma_get_object_from_value (buffer)))
271+
{
272+
ecma_free_value (v);
273+
return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED);
274+
}
275+
276+
// TODO: Handle shared array buffers differently.
277+
typedarray_setter_cb (ecma_arraybuffer_get_buffer (buffer_obj_p) + indexed_position, v);
278+
279+
ecma_free_value (v);
280+
281+
return ecma_copy_value (value);
125282
} /* ecma_builtin_atomics_store */
126283

127284
/**

0 commit comments

Comments
 (0)