Skip to content

Commit c622bc1

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

11 files changed

+706
-184
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: 232 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

@@ -66,10 +73,46 @@ enum
6673
* @{
6774
*/
6875

76+
static ecma_value_t
77+
ecma_convert_number_to_typed_array_type (ecma_number_t num, ecma_typedarray_type_t element_type)
78+
{
79+
uint32_t value = ecma_typedarray_setter_number_to_uint32 (num);
80+
81+
switch (element_type)
82+
{
83+
case ECMA_INT8_ARRAY:
84+
{
85+
return ecma_make_number_value ((int8_t) value);
86+
}
87+
case ECMA_UINT8_ARRAY:
88+
{
89+
return ecma_make_number_value ((uint8_t) value);
90+
}
91+
case ECMA_INT16_ARRAY:
92+
{
93+
return ecma_make_number_value ((int16_t) value);
94+
}
95+
case ECMA_UINT16_ARRAY:
96+
{
97+
return ecma_make_number_value ((uint16_t) value);
98+
}
99+
case ECMA_INT32_ARRAY:
100+
{
101+
return ecma_make_number_value ((int32_t) value);
102+
}
103+
default:
104+
{
105+
JERRY_ASSERT (element_type == ECMA_UINT32_ARRAY);
106+
107+
return ecma_make_number_value (value);
108+
}
109+
}
110+
}
111+
69112
/**
70113
* The Atomics object's 'compareExchange' routine
71114
*
72-
* See also: ES11 24.4.4
115+
* See also: ES12 25.4.4
73116
*
74117
* @return ecma value
75118
* Returned value must be freed with ecma_free_value.
@@ -80,12 +123,122 @@ ecma_builtin_atomics_compare_exchange (ecma_value_t typedarray, /**< typedArray
80123
ecma_value_t expected_value, /**< expectedValue argument */
81124
ecma_value_t replacement_value) /**< replacementValue argument*/
82125
{
83-
JERRY_UNUSED (typedarray);
84-
JERRY_UNUSED (index);
85-
JERRY_UNUSED (expected_value);
86-
JERRY_UNUSED (replacement_value);
126+
ecma_value_t buffer = ecma_validate_integer_typedarray (typedarray, false);
87127

88-
return ecma_make_uint32_value (0);
128+
if (ECMA_IS_VALUE_ERROR (buffer))
129+
{
130+
return buffer;
131+
}
132+
133+
uint32_t idx = ecma_validate_atomic_access (typedarray, index);
134+
135+
if (idx == ECMA_STRING_NOT_ARRAY_INDEX)
136+
{
137+
return ECMA_VALUE_ERROR;
138+
}
139+
140+
ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray);
141+
ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p);
142+
143+
if (ECMA_ARRAYBUFFER_LAZY_ALLOC (target_info.array_buffer_p))
144+
{
145+
return ECMA_VALUE_ERROR;
146+
}
147+
148+
ecma_typedarray_type_t element_type = target_info.id;
149+
ecma_value_t expected;
150+
ecma_value_t replacement;
151+
152+
if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (element_type))
153+
{
154+
expected = ecma_bigint_to_bigint (expected_value, false);
155+
156+
if (ECMA_IS_VALUE_ERROR (expected))
157+
{
158+
return expected;
159+
}
160+
161+
if (element_type == ECMA_BIGUINT64_ARRAY)
162+
{
163+
uint64_t num;
164+
bool sign;
165+
166+
ecma_bigint_get_digits_and_sign (expected, &num, 1, &sign);
167+
168+
if (sign)
169+
{
170+
num = (uint64_t) (-(int64_t) num);
171+
}
172+
173+
if (expected != ECMA_BIGINT_ZERO)
174+
{
175+
ecma_deref_bigint (ecma_get_extended_primitive_from_value (expected));
176+
}
177+
178+
expected = ecma_bigint_create_from_digits (&num, 1, false);
179+
}
180+
181+
replacement = ecma_bigint_to_bigint (replacement_value, false);
182+
183+
if (ECMA_IS_VALUE_ERROR (replacement))
184+
{
185+
ecma_free_value (expected);
186+
return replacement;
187+
}
188+
}
189+
else
190+
{
191+
ecma_number_t tmp_exp;
192+
ecma_number_t tmp_rep;
193+
194+
expected = ecma_op_to_integer (expected_value, &tmp_exp);
195+
196+
if (ECMA_IS_VALUE_ERROR (expected))
197+
{
198+
return expected;
199+
}
200+
201+
expected = ecma_convert_number_to_typed_array_type (tmp_exp, element_type);
202+
203+
replacement = ecma_op_to_integer (replacement_value, &tmp_rep);
204+
205+
if (ECMA_IS_VALUE_ERROR (replacement))
206+
{
207+
ecma_free_value (expected);
208+
return replacement;
209+
}
210+
211+
replacement = ecma_make_number_value (tmp_rep);
212+
}
213+
214+
uint8_t element_size = target_info.element_size;
215+
uint32_t offset = target_info.offset;
216+
uint32_t indexed_position = idx * element_size + offset;
217+
218+
if (ecma_arraybuffer_is_detached (ecma_get_object_from_value (buffer)))
219+
{
220+
ecma_free_value (expected);
221+
ecma_free_value (replacement);
222+
return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED);
223+
}
224+
225+
ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (element_type);
226+
227+
ecma_object_t *buffer_obj_p = ecma_get_object_from_value (buffer);
228+
lit_utf8_byte_t *pos = ecma_arraybuffer_get_buffer (buffer_obj_p) + indexed_position;
229+
ecma_value_t stored_value = typedarray_getter_cb (pos);
230+
231+
// TODO: Handle shared array buffers differently.
232+
if (ecma_op_same_value (stored_value, expected))
233+
{
234+
ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (element_type);
235+
typedarray_setter_cb (ecma_arraybuffer_get_buffer (buffer_obj_p) + indexed_position, replacement);
236+
}
237+
238+
ecma_free_value (expected);
239+
ecma_free_value (replacement);
240+
241+
return stored_value;
89242
} /* ecma_builtin_atomics_compare_exchange */
90243

91244
/**
@@ -117,11 +270,80 @@ ecma_builtin_atomics_store (ecma_value_t typedarray, /**< typedArray argument */
117270
ecma_value_t index, /**< index argument */
118271
ecma_value_t value) /**< value argument */
119272
{
120-
JERRY_UNUSED (typedarray);
121-
JERRY_UNUSED (index);
122-
JERRY_UNUSED (value);
273+
/* 1. */
274+
ecma_value_t buffer = ecma_validate_integer_typedarray (typedarray, false);
123275

124-
return ecma_make_uint32_value (0);
276+
if (ECMA_IS_VALUE_ERROR (buffer))
277+
{
278+
return buffer;
279+
}
280+
281+
/* 2. */
282+
uint32_t idx = ecma_validate_atomic_access (typedarray, index);
283+
284+
if (idx == ECMA_STRING_NOT_ARRAY_INDEX)
285+
{
286+
return ECMA_VALUE_ERROR;
287+
}
288+
289+
ecma_object_t *typedarray_p = ecma_get_object_from_value (typedarray);
290+
ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p);
291+
292+
if (ECMA_ARRAYBUFFER_LAZY_ALLOC (target_info.array_buffer_p))
293+
{
294+
return ECMA_VALUE_ERROR;
295+
}
296+
297+
uint8_t element_size = target_info.element_size;
298+
299+
ecma_typedarray_type_t element_type = target_info.id;
300+
301+
uint32_t offset = target_info.offset;
302+
303+
uint32_t indexed_position = idx * element_size + offset;
304+
305+
ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (element_type);
306+
ecma_object_t *buffer_obj_p = ecma_get_object_from_value (buffer);
307+
308+
ecma_value_t v;
309+
if (element_type == ECMA_BIGINT64_ARRAY || element_type == ECMA_BIGUINT64_ARRAY)
310+
{
311+
v = ecma_bigint_to_bigint (value, false);
312+
}
313+
else
314+
{
315+
ecma_number_t num_int;
316+
317+
v = ecma_op_to_integer (value, &num_int);
318+
319+
if (ECMA_IS_VALUE_ERROR (v))
320+
{
321+
return v;
322+
}
323+
324+
if (ecma_number_is_zero (num_int) && ecma_number_is_negative (num_int))
325+
{
326+
num_int = (ecma_number_t) 0;
327+
}
328+
329+
v = ecma_make_number_value (num_int);
330+
}
331+
332+
if (ECMA_IS_VALUE_ERROR (v))
333+
{
334+
return v;
335+
}
336+
337+
if (ecma_arraybuffer_is_detached (ecma_get_object_from_value (buffer)))
338+
{
339+
ecma_free_value (v);
340+
return ecma_raise_type_error (ECMA_ERR_ARRAYBUFFER_IS_DETACHED);
341+
}
342+
343+
// TODO: Handle shared array buffers differently.
344+
typedarray_setter_cb (ecma_arraybuffer_get_buffer (buffer_obj_p) + indexed_position, v);
345+
346+
return v;
125347
} /* ecma_builtin_atomics_store */
126348

127349
/**

0 commit comments

Comments
 (0)