/src/serenity/Userland/Libraries/LibJS/Runtime/AtomicsObject.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Tim Flynn <trflynn89@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | // This file explicitly implements support for JS Atomics API, which can |
8 | | // involve slow (non-lock-free) atomic ops. |
9 | | #include <AK/Platform.h> |
10 | | |
11 | | #ifdef AK_COMPILER_CLANG |
12 | | # pragma clang diagnostic ignored "-Watomic-alignment" |
13 | | #endif |
14 | | |
15 | | #include <AK/Atomic.h> |
16 | | #include <AK/ByteBuffer.h> |
17 | | #include <AK/Endian.h> |
18 | | #include <AK/TypeCasts.h> |
19 | | #include <LibJS/Runtime/Agent.h> |
20 | | #include <LibJS/Runtime/AtomicsObject.h> |
21 | | #include <LibJS/Runtime/GlobalObject.h> |
22 | | #include <LibJS/Runtime/TypedArray.h> |
23 | | #include <LibJS/Runtime/Value.h> |
24 | | #include <LibJS/Runtime/ValueInlines.h> |
25 | | |
26 | | namespace JS { |
27 | | |
28 | | JS_DEFINE_ALLOCATOR(AtomicsObject); |
29 | | |
30 | | // 25.4.2.1 ValidateIntegerTypedArray ( typedArray, waitable ), https://tc39.es/ecma262/#sec-validateintegertypedarray |
31 | | static ThrowCompletionOr<TypedArrayWithBufferWitness> validate_integer_typed_array(VM& vm, TypedArrayBase const& typed_array, bool waitable) |
32 | 0 | { |
33 | | // 1. Let taRecord be ? ValidateTypedArray(typedArray, unordered). |
34 | 0 | auto typed_array_record = TRY(validate_typed_array(vm, typed_array, ArrayBuffer::Order::Unordered)); |
35 | | |
36 | | // 2. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer. |
37 | |
|
38 | 0 | auto const& type_name = typed_array.element_name(); |
39 | | |
40 | | // 3. If waitable is true, then |
41 | 0 | if (waitable) { |
42 | | // a. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception. |
43 | 0 | if ((type_name != vm.names.Int32Array.as_string()) && (type_name != vm.names.BigInt64Array.as_string())) |
44 | 0 | return vm.throw_completion<TypeError>(ErrorType::TypedArrayTypeIsNot, type_name, "Int32 or BigInt64"sv); |
45 | 0 | } |
46 | | // 4. Else, |
47 | 0 | else { |
48 | | // a. Let type be TypedArrayElementType(typedArray). |
49 | | |
50 | | // b. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception. |
51 | 0 | if (!typed_array.is_unclamped_integer_element_type() && !typed_array.is_bigint_element_type()) |
52 | 0 | return vm.throw_completion<TypeError>(ErrorType::TypedArrayTypeIsNot, type_name, "an unclamped integer or BigInt"sv); |
53 | 0 | } |
54 | | |
55 | | // 5. Return taRecord. |
56 | 0 | return typed_array_record; |
57 | 0 | } |
58 | | |
59 | | // 25.4.2.2 ValidateAtomicAccess ( taRecord, requestIndex ), https://tc39.es/ecma262/#sec-validateatomicaccess |
60 | | static ThrowCompletionOr<size_t> validate_atomic_access(VM& vm, TypedArrayWithBufferWitness const& typed_array_record, Value request_index) |
61 | 0 | { |
62 | | // 1. Let length be TypedArrayLength(taRecord). |
63 | 0 | auto length = typed_array_length(typed_array_record); |
64 | | |
65 | | // 2. Let accessIndex be ? ToIndex(requestIndex). |
66 | | // 3. Assert: accessIndex ≥ 0. |
67 | 0 | auto access_index = TRY(request_index.to_index(vm)); |
68 | | |
69 | | // 4. If accessIndex ≥ length, throw a RangeError exception. |
70 | 0 | if (access_index >= length) |
71 | 0 | return vm.throw_completion<RangeError>(ErrorType::IndexOutOfRange, access_index, length); |
72 | | |
73 | | // 5. Let typedArray be taRecord.[[Object]]. |
74 | 0 | auto const& typed_array = *typed_array_record.object; |
75 | | |
76 | | // 6. Let elementSize be TypedArrayElementSize(typedArray). |
77 | 0 | auto element_size = typed_array.element_size(); |
78 | | |
79 | | // 7. Let offset be typedArray.[[ByteOffset]]. |
80 | 0 | auto offset = typed_array.byte_offset(); |
81 | | |
82 | | // 8. Return (accessIndex × elementSize) + offset. |
83 | 0 | return (access_index * element_size) + offset; |
84 | 0 | } |
85 | | |
86 | | // 25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable ] ), https://tc39.es/ecma262/#sec-validateatomicaccessonintegertypedarray |
87 | | static ThrowCompletionOr<size_t> validate_atomic_access_on_integer_typed_array(VM& vm, TypedArrayBase const& typed_array, Value request_index, bool waitable = false) |
88 | 0 | { |
89 | | // 1. If waitable is not present, set waitable to false. |
90 | | |
91 | | // 2. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable). |
92 | 0 | auto typed_array_record = TRY(validate_integer_typed_array(vm, typed_array, waitable)); |
93 | | |
94 | | // 3. Return ? ValidateAtomicAccess(taRecord, requestIndex). |
95 | 0 | return TRY(validate_atomic_access(vm, typed_array_record, request_index)); |
96 | 0 | } |
97 | | |
98 | | // 25.4.3.4 RevalidateAtomicAccess ( typedArray, byteIndexInBuffer ), https://tc39.es/ecma262/#sec-revalidateatomicaccess |
99 | | static ThrowCompletionOr<void> revalidate_atomic_access(VM& vm, TypedArrayBase const& typed_array, size_t byte_index_in_buffer) |
100 | 0 | { |
101 | | // 1. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(typedArray, unordered). |
102 | 0 | auto typed_array_record = make_typed_array_with_buffer_witness_record(typed_array, ArrayBuffer::Order::Unordered); |
103 | | |
104 | | // 2. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer. |
105 | | // 3. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception. |
106 | 0 | if (is_typed_array_out_of_bounds(typed_array_record)) |
107 | 0 | return vm.throw_completion<TypeError>(ErrorType::BufferOutOfBounds, "TypedArray"sv); |
108 | | |
109 | | // 4. Assert: byteIndexInBuffer ≥ typedArray.[[ByteOffset]]. |
110 | 0 | VERIFY(byte_index_in_buffer >= typed_array.byte_offset()); |
111 | | |
112 | | // 5. If byteIndexInBuffer ≥ taRecord.[[CachedBufferByteLength]], throw a RangeError exception. |
113 | 0 | if (byte_index_in_buffer >= typed_array_record.cached_buffer_byte_length.length()) |
114 | 0 | return vm.throw_completion<RangeError>(ErrorType::IndexOutOfRange, byte_index_in_buffer, typed_array_record.cached_buffer_byte_length.length()); |
115 | | |
116 | | // 6. Return unused. |
117 | 0 | return {}; |
118 | 0 | } |
119 | | |
120 | | // 25.4.2.17 AtomicReadModifyWrite ( typedArray, index, value, op ), https://tc39.es/ecma262/#sec-atomicreadmodifywrite |
121 | | static ThrowCompletionOr<Value> atomic_read_modify_write(VM& vm, TypedArrayBase& typed_array, Value index, Value value, ReadWriteModifyFunction operation) |
122 | 0 | { |
123 | | // 1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index). |
124 | 0 | auto byte_index_in_buffer = TRY(validate_atomic_access_on_integer_typed_array(vm, typed_array, index)); |
125 | |
|
126 | 0 | Value value_to_set; |
127 | | |
128 | | // 2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value). |
129 | 0 | if (typed_array.content_type() == TypedArrayBase::ContentType::BigInt) |
130 | 0 | value_to_set = TRY(value.to_bigint(vm)); |
131 | | // 3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)). |
132 | 0 | else |
133 | 0 | value_to_set = Value(TRY(value.to_integer_or_infinity(vm))); |
134 | | |
135 | | // 4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer). |
136 | 0 | TRY(revalidate_atomic_access(vm, typed_array, byte_index_in_buffer)); |
137 | | |
138 | | // 5. Let buffer be typedArray.[[ViewedArrayBuffer]]. |
139 | | // 6. Let elementType be TypedArrayElementType(typedArray). |
140 | | // 7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op). |
141 | 0 | return typed_array.get_modify_set_value_in_buffer(byte_index_in_buffer, value_to_set, move(operation)); |
142 | 0 | } |
143 | | |
144 | | enum class WaitMode { |
145 | | Sync, |
146 | | Async, |
147 | | }; |
148 | | |
149 | | // 25.4.3.14 DoWait ( mode, typedArray, index, value, timeout ), https://tc39.es/ecma262/#sec-dowait |
150 | | static ThrowCompletionOr<Value> do_wait(VM& vm, WaitMode mode, TypedArrayBase& typed_array, Value index_value, Value expected_value, Value timeout_value) |
151 | 0 | { |
152 | | // 1. Let taRecord be ? ValidateIntegerTypedArray(typedArray, true). |
153 | 0 | auto typed_array_record = TRY(validate_integer_typed_array(vm, typed_array, true)); |
154 | | |
155 | | // 2. Let buffer be taRecord.[[Object]].[[ViewedArrayBuffer]]. |
156 | 0 | auto* buffer = typed_array_record.object->viewed_array_buffer(); |
157 | | |
158 | | // 3. If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. |
159 | 0 | if (!buffer->is_shared_array_buffer()) |
160 | 0 | return vm.throw_completion<TypeError>(ErrorType::NotASharedArrayBuffer); |
161 | | |
162 | | // 4. Let i be ? ValidateAtomicAccess(taRecord, index). |
163 | 0 | auto index = TRY(validate_atomic_access(vm, typed_array_record, index_value)); |
164 | | |
165 | | // 5. Let arrayTypeName be typedArray.[[TypedArrayName]]. |
166 | 0 | auto const& array_type_name = typed_array.element_name(); |
167 | | |
168 | | // 6. If arrayTypeName is "BigInt64Array", let v be ? ToBigInt64(value). |
169 | 0 | i64 value = 0; |
170 | 0 | if (array_type_name == vm.names.BigInt64Array.as_string()) |
171 | 0 | value = TRY(expected_value.to_bigint_int64(vm)); |
172 | | // 7. Else, let v be ? ToInt32(value). |
173 | 0 | else |
174 | 0 | value = TRY(expected_value.to_i32(vm)); |
175 | | |
176 | | // 8. Let q be ? ToNumber(timeout). |
177 | 0 | auto timeout_number = TRY(timeout_value.to_number(vm)); |
178 | | |
179 | | // 9. If q is either NaN or +∞𝔽, let t be +∞; else if q is -∞𝔽, let t be 0; else let t be max(ℝ(q), 0). |
180 | 0 | double timeout = 0; |
181 | 0 | if (timeout_number.is_nan() || timeout_number.is_positive_infinity()) |
182 | 0 | timeout = js_infinity().as_double(); |
183 | 0 | else if (timeout_number.is_negative_infinity()) |
184 | 0 | timeout = 0.0; |
185 | 0 | else |
186 | 0 | timeout = max(timeout_number.as_double(), 0.0); |
187 | | |
188 | | // 10. If mode is sync and AgentCanSuspend() is false, throw a TypeError exception. |
189 | 0 | if (mode == WaitMode::Sync && !agent_can_suspend()) |
190 | 0 | return vm.throw_completion<TypeError>(ErrorType::AgentCannotSuspend); |
191 | | |
192 | | // FIXME: Implement the remaining steps when we support SharedArrayBuffer. |
193 | 0 | (void)index; |
194 | 0 | (void)value; |
195 | 0 | (void)timeout; |
196 | |
|
197 | 0 | return vm.throw_completion<InternalError>(ErrorType::NotImplemented, "SharedArrayBuffer"sv); |
198 | 0 | } |
199 | | |
200 | | template<typename T, typename AtomicFunction> |
201 | | static ThrowCompletionOr<Value> perform_atomic_operation(VM& vm, TypedArrayBase& typed_array, AtomicFunction&& operation) |
202 | 0 | { |
203 | 0 | auto index = vm.argument(1); |
204 | 0 | auto value = vm.argument(2); |
205 | |
|
206 | 0 | auto operation_wrapper = [&, operation = forward<AtomicFunction>(operation)](ByteBuffer x_bytes, ByteBuffer y_bytes) -> ByteBuffer { |
207 | 0 | if constexpr (IsFloatingPoint<T>) { |
208 | 0 | (void)operation; |
209 | 0 | VERIFY_NOT_REACHED(); |
210 | 0 | } else { |
211 | 0 | using U = Conditional<IsSame<ClampedU8, T>, u8, T>; |
212 | |
|
213 | 0 | auto* x = reinterpret_cast<U*>(x_bytes.data()); |
214 | 0 | auto* y = reinterpret_cast<U*>(y_bytes.data()); |
215 | 0 | operation(x, *y); |
216 | |
|
217 | 0 | return x_bytes; |
218 | 0 | } |
219 | 0 | }; Unexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<signed char, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<short, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<int, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<long, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<float, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<double, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<signed char, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<short, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<int, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<long, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<float, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<double, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<signed char, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<short, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<int, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<long, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<float, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<double, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<signed char, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<short, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<int, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<long, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<float, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<double, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<signed char, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<short, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<int, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<long, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<float, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<double, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<signed char, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<short, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<int, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<long, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<float, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) constUnexecuted instantiation: AtomicsObject.cpp:JS::perform_atomic_operation<double, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&)::{lambda(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)#1}::operator()(AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>) const |
220 | |
|
221 | 0 | return atomic_read_modify_write(vm, typed_array, index, value, move(operation_wrapper)); |
222 | 0 | } Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<signed char, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<short, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<int, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<long, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<float, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<double, JS::AtomicsObject::add(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::add(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<signed char, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<short, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<int, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<long, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<float, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<double, JS::AtomicsObject::and_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::and_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<signed char, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<short, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<int, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<long, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<float, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<double, JS::AtomicsObject::exchange(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::exchange(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<signed char, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<short, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<int, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<long, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<float, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<double, JS::AtomicsObject::or_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::or_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<signed char, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<short, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<int, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<long, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<float, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<double, JS::AtomicsObject::sub(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::sub(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned char, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<JS::ClampedU8, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned short, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned int, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<unsigned long, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<signed char, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<short, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<int, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<long, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<float, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::perform_atomic_operation<double, JS::AtomicsObject::xor_(JS::VM&)::$_0>(JS::VM&, JS::TypedArrayBase&, JS::AtomicsObject::xor_(JS::VM&)::$_0&&) |
223 | | |
224 | | AtomicsObject::AtomicsObject(Realm& realm) |
225 | 0 | : Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().object_prototype()) |
226 | 0 | { |
227 | 0 | } |
228 | | |
229 | | void AtomicsObject::initialize(Realm& realm) |
230 | 0 | { |
231 | 0 | Base::initialize(realm); |
232 | 0 | auto& vm = this->vm(); |
233 | |
|
234 | 0 | u8 attr = Attribute::Writable | Attribute::Configurable; |
235 | 0 | define_native_function(realm, vm.names.add, add, 3, attr); |
236 | 0 | define_native_function(realm, vm.names.and_, and_, 3, attr); |
237 | 0 | define_native_function(realm, vm.names.compareExchange, compare_exchange, 4, attr); |
238 | 0 | define_native_function(realm, vm.names.exchange, exchange, 3, attr); |
239 | 0 | define_native_function(realm, vm.names.isLockFree, is_lock_free, 1, attr); |
240 | 0 | define_native_function(realm, vm.names.load, load, 2, attr); |
241 | 0 | define_native_function(realm, vm.names.or_, or_, 3, attr); |
242 | 0 | define_native_function(realm, vm.names.store, store, 3, attr); |
243 | 0 | define_native_function(realm, vm.names.sub, sub, 3, attr); |
244 | 0 | define_native_function(realm, vm.names.wait, wait, 4, attr); |
245 | 0 | define_native_function(realm, vm.names.waitAsync, wait_async, 4, attr); |
246 | 0 | define_native_function(realm, vm.names.notify, notify, 3, attr); |
247 | 0 | define_native_function(realm, vm.names.xor_, xor_, 3, attr); |
248 | | |
249 | | // 25.4.17 Atomics [ @@toStringTag ], https://tc39.es/ecma262/#sec-atomics-@@tostringtag |
250 | 0 | define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Atomics"_string), Attribute::Configurable); |
251 | 0 | } |
252 | | |
253 | | // 25.4.4 Atomics.add ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.add |
254 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::add) |
255 | 0 | { |
256 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
257 | |
|
258 | 0 | auto atomic_add = [](auto* storage, auto value) { return AK::atomic_fetch_add(storage, value); };Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::add(JS::VM&)::$_0::operator()<unsigned char, unsigned char>(unsigned char*, unsigned char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::add(JS::VM&)::$_0::operator()<unsigned short, unsigned short>(unsigned short*, unsigned short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::add(JS::VM&)::$_0::operator()<unsigned int, unsigned int>(unsigned int*, unsigned int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::add(JS::VM&)::$_0::operator()<unsigned long, unsigned long>(unsigned long*, unsigned long) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::add(JS::VM&)::$_0::operator()<signed char, signed char>(signed char*, signed char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::add(JS::VM&)::$_0::operator()<short, short>(short*, short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::add(JS::VM&)::$_0::operator()<int, int>(int*, int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::add(JS::VM&)::$_0::operator()<long, long>(long*, long) const |
259 | |
|
260 | 0 | #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ |
261 | 0 | if (is<ClassName>(typed_array)) \ |
262 | 0 | return TRY(perform_atomic_operation<Type>(vm, *typed_array, move(atomic_add))); |
263 | 0 | JS_ENUMERATE_TYPED_ARRAYS |
264 | 0 | #undef __JS_ENUMERATE |
265 | | |
266 | 0 | VERIFY_NOT_REACHED(); |
267 | 0 | } |
268 | | |
269 | | // 25.4.5 Atomics.and ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.and |
270 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::and_) |
271 | 0 | { |
272 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
273 | |
|
274 | 0 | auto atomic_and = [](auto* storage, auto value) { return AK::atomic_fetch_and(storage, value); };Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::and_(JS::VM&)::$_0::operator()<unsigned char, unsigned char>(unsigned char*, unsigned char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::and_(JS::VM&)::$_0::operator()<unsigned short, unsigned short>(unsigned short*, unsigned short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::and_(JS::VM&)::$_0::operator()<unsigned int, unsigned int>(unsigned int*, unsigned int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::and_(JS::VM&)::$_0::operator()<unsigned long, unsigned long>(unsigned long*, unsigned long) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::and_(JS::VM&)::$_0::operator()<signed char, signed char>(signed char*, signed char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::and_(JS::VM&)::$_0::operator()<short, short>(short*, short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::and_(JS::VM&)::$_0::operator()<int, int>(int*, int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::and_(JS::VM&)::$_0::operator()<long, long>(long*, long) const |
275 | |
|
276 | 0 | #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ |
277 | 0 | if (is<ClassName>(typed_array)) \ |
278 | 0 | return TRY(perform_atomic_operation<Type>(vm, *typed_array, move(atomic_and))); |
279 | 0 | JS_ENUMERATE_TYPED_ARRAYS |
280 | 0 | #undef __JS_ENUMERATE |
281 | | |
282 | 0 | VERIFY_NOT_REACHED(); |
283 | 0 | } |
284 | | |
285 | | // 25.4.6 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue ), https://tc39.es/ecma262/#sec-atomics.compareexchange |
286 | | template<typename T> |
287 | | static ThrowCompletionOr<Value> atomic_compare_exchange_impl(VM& vm, TypedArrayBase& typed_array, Value index, Value expected_value, Value replacement_value) |
288 | 0 | { |
289 | | // 1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index). |
290 | 0 | auto byte_index_in_buffer = TRY(validate_atomic_access_on_integer_typed_array(vm, typed_array, index)); |
291 | |
|
292 | 0 | Value expected; |
293 | 0 | Value replacement; |
294 | | |
295 | | // 4. If typedArray.[[ContentType]] is bigint, then |
296 | 0 | if (typed_array.content_type() == TypedArrayBase::ContentType::BigInt) { |
297 | | // a. Let expected be ? ToBigInt(expectedValue). |
298 | 0 | expected = TRY(expected_value.to_bigint(vm)); |
299 | | |
300 | | // b. Let replacement be ? ToBigInt(replacementValue). |
301 | 0 | replacement = TRY(replacement_value.to_bigint(vm)); |
302 | 0 | } |
303 | | // 5. Else, |
304 | 0 | else { |
305 | | // a. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)). |
306 | 0 | expected = Value(TRY(expected_value.to_integer_or_infinity(vm))); |
307 | | |
308 | | // b. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)). |
309 | 0 | replacement = Value(TRY(replacement_value.to_integer_or_infinity(vm))); |
310 | 0 | } |
311 | | |
312 | | // 6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer). |
313 | 0 | TRY(revalidate_atomic_access(vm, typed_array, byte_index_in_buffer)); |
314 | | |
315 | | // NOTE: We defer steps 2 and 3 to ensure we have revalidated the TA before accessing these internal slots. |
316 | | // In our implementation, accessing [[ArrayBufferData]] on a detached buffer will fail assertions. |
317 | | |
318 | | // 2. Let buffer be typedArray.[[ViewedArrayBuffer]]. |
319 | 0 | auto* buffer = typed_array.viewed_array_buffer(); |
320 | | |
321 | | // 3. Let block be buffer.[[ArrayBufferData]]. |
322 | 0 | auto& block = buffer->buffer(); |
323 | | |
324 | | // 7. Let elementType be TypedArrayElementType(typedArray). |
325 | | // 8. Let elementSize be TypedArrayElementSize(typedArray). |
326 | | |
327 | | // 9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. |
328 | 0 | static constexpr bool is_little_endian = AK::HostIsLittleEndian; |
329 | | |
330 | | // 10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian). |
331 | 0 | auto expected_bytes = MUST(ByteBuffer::create_uninitialized(sizeof(T))); |
332 | 0 | numeric_to_raw_bytes<T>(vm, expected, is_little_endian, expected_bytes); |
333 | | |
334 | | // 11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian). |
335 | 0 | auto replacement_bytes = MUST(ByteBuffer::create_uninitialized(sizeof(T))); |
336 | 0 | numeric_to_raw_bytes<T>(vm, replacement, is_little_endian, replacement_bytes); |
337 | | |
338 | | // FIXME: Implement SharedArrayBuffer case. |
339 | | // 12. If IsSharedArrayBuffer(buffer) is true, then |
340 | | // a. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes). |
341 | | // 13. Else, |
342 | | |
343 | | // a. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer]. |
344 | | // FIXME: Propagate errors. |
345 | 0 | auto raw_bytes_read = MUST(block.slice(byte_index_in_buffer, sizeof(T))); |
346 | | |
347 | | // b. If ByteListEqual(rawBytesRead, expectedBytes) is true, then |
348 | | // i. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer]. |
349 | 0 | if constexpr (IsFloatingPoint<T>) { |
350 | 0 | VERIFY_NOT_REACHED(); |
351 | 0 | } else { |
352 | 0 | using U = Conditional<IsSame<ClampedU8, T>, u8, T>; |
353 | |
|
354 | 0 | auto* v = reinterpret_cast<U*>(block.span().slice(byte_index_in_buffer).data()); |
355 | 0 | auto* e = reinterpret_cast<U*>(expected_bytes.data()); |
356 | 0 | auto* r = reinterpret_cast<U*>(replacement_bytes.data()); |
357 | 0 | (void)AK::atomic_compare_exchange_strong(v, *e, *r); |
358 | 0 | } |
359 | | |
360 | | // 14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian). |
361 | 0 | return raw_bytes_to_numeric<T>(vm, raw_bytes_read, is_little_endian); |
362 | 0 | } Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<unsigned char>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<JS::ClampedU8>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<unsigned short>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<unsigned int>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<unsigned long>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<signed char>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<short>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<int>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<long>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<float>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) Unexecuted instantiation: AtomicsObject.cpp:JS::ThrowCompletionOr<JS::Value> JS::atomic_compare_exchange_impl<double>(JS::VM&, JS::TypedArrayBase&, JS::Value, JS::Value, JS::Value) |
363 | | |
364 | | // 25.4.6 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue ), https://tc39.es/ecma262/#sec-atomics.compareexchange |
365 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::compare_exchange) |
366 | 0 | { |
367 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
368 | 0 | auto index = vm.argument(1); |
369 | 0 | auto expected_value = vm.argument(2); |
370 | 0 | auto replacement_value = vm.argument(3); |
371 | |
|
372 | 0 | #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ |
373 | 0 | if (is<ClassName>(typed_array)) \ |
374 | 0 | return TRY(atomic_compare_exchange_impl<Type>(vm, *typed_array, index, expected_value, replacement_value)); |
375 | 0 | JS_ENUMERATE_TYPED_ARRAYS |
376 | 0 | #undef __JS_ENUMERATE |
377 | | |
378 | 0 | VERIFY_NOT_REACHED(); |
379 | 0 | } |
380 | | |
381 | | // 25.4.7 Atomics.exchange ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.exchange |
382 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::exchange) |
383 | 0 | { |
384 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
385 | |
|
386 | 0 | auto atomic_exchange = [](auto* storage, auto value) { return AK::atomic_exchange(storage, value); };Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::exchange(JS::VM&)::$_0::operator()<unsigned char, unsigned char>(unsigned char*, unsigned char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::exchange(JS::VM&)::$_0::operator()<unsigned short, unsigned short>(unsigned short*, unsigned short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::exchange(JS::VM&)::$_0::operator()<unsigned int, unsigned int>(unsigned int*, unsigned int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::exchange(JS::VM&)::$_0::operator()<unsigned long, unsigned long>(unsigned long*, unsigned long) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::exchange(JS::VM&)::$_0::operator()<signed char, signed char>(signed char*, signed char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::exchange(JS::VM&)::$_0::operator()<short, short>(short*, short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::exchange(JS::VM&)::$_0::operator()<int, int>(int*, int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::exchange(JS::VM&)::$_0::operator()<long, long>(long*, long) const |
387 | |
|
388 | 0 | #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ |
389 | 0 | if (is<ClassName>(typed_array)) \ |
390 | 0 | return TRY(perform_atomic_operation<Type>(vm, *typed_array, move(atomic_exchange))); |
391 | 0 | JS_ENUMERATE_TYPED_ARRAYS |
392 | 0 | #undef __JS_ENUMERATE |
393 | | |
394 | 0 | VERIFY_NOT_REACHED(); |
395 | 0 | } |
396 | | |
397 | | // 25.4.8 Atomics.isLockFree ( size ), https://tc39.es/ecma262/#sec-atomics.islockfree |
398 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::is_lock_free) |
399 | 0 | { |
400 | 0 | auto size = TRY(vm.argument(0).to_integer_or_infinity(vm)); |
401 | 0 | if (size == 1) |
402 | 0 | return Value(AK::atomic_is_lock_free<u8>()); |
403 | 0 | if (size == 2) |
404 | 0 | return Value(AK::atomic_is_lock_free<u16>()); |
405 | 0 | if (size == 4) |
406 | 0 | return Value(true); |
407 | 0 | if (size == 8) |
408 | 0 | return Value(AK::atomic_is_lock_free<u64>()); |
409 | 0 | return Value(false); |
410 | 0 | } |
411 | | |
412 | | // 25.4.9 Atomics.load ( typedArray, index ), https://tc39.es/ecma262/#sec-atomics.load |
413 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::load) |
414 | 0 | { |
415 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
416 | 0 | auto index = vm.argument(1); |
417 | | |
418 | | // 1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index). |
419 | 0 | auto byte_index_in_buffer = TRY(validate_atomic_access_on_integer_typed_array(vm, *typed_array, index)); |
420 | | |
421 | | // 2. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer). |
422 | 0 | TRY(revalidate_atomic_access(vm, *typed_array, byte_index_in_buffer)); |
423 | | |
424 | | // 3. Let buffer be typedArray.[[ViewedArrayBuffer]]. |
425 | | // 4. Let elementType be TypedArrayElementType(typedArray). |
426 | | // 5. Return GetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst). |
427 | 0 | return typed_array->get_value_from_buffer(byte_index_in_buffer, ArrayBuffer::Order::SeqCst, true); |
428 | 0 | } |
429 | | |
430 | | // 25.4.10 Atomics.or ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.or |
431 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::or_) |
432 | 0 | { |
433 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
434 | |
|
435 | 0 | auto atomic_or = [](auto* storage, auto value) { return AK::atomic_fetch_or(storage, value); };Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::or_(JS::VM&)::$_0::operator()<unsigned char, unsigned char>(unsigned char*, unsigned char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::or_(JS::VM&)::$_0::operator()<unsigned short, unsigned short>(unsigned short*, unsigned short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::or_(JS::VM&)::$_0::operator()<unsigned int, unsigned int>(unsigned int*, unsigned int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::or_(JS::VM&)::$_0::operator()<unsigned long, unsigned long>(unsigned long*, unsigned long) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::or_(JS::VM&)::$_0::operator()<signed char, signed char>(signed char*, signed char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::or_(JS::VM&)::$_0::operator()<short, short>(short*, short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::or_(JS::VM&)::$_0::operator()<int, int>(int*, int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::or_(JS::VM&)::$_0::operator()<long, long>(long*, long) const |
436 | |
|
437 | 0 | #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ |
438 | 0 | if (is<ClassName>(typed_array)) \ |
439 | 0 | return TRY(perform_atomic_operation<Type>(vm, *typed_array, move(atomic_or))); |
440 | 0 | JS_ENUMERATE_TYPED_ARRAYS |
441 | 0 | #undef __JS_ENUMERATE |
442 | | |
443 | 0 | VERIFY_NOT_REACHED(); |
444 | 0 | } |
445 | | |
446 | | // 25.4.11 Atomics.store ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.store |
447 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::store) |
448 | 0 | { |
449 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
450 | 0 | auto index = vm.argument(1); |
451 | 0 | auto value = vm.argument(2); |
452 | | |
453 | | // 1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index). |
454 | 0 | auto byte_index_in_buffer = TRY(validate_atomic_access_on_integer_typed_array(vm, *typed_array, index)); |
455 | | |
456 | | // 2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value). |
457 | 0 | if (typed_array->content_type() == TypedArrayBase::ContentType::BigInt) |
458 | 0 | value = TRY(value.to_bigint(vm)); |
459 | | // 3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)). |
460 | 0 | else |
461 | 0 | value = Value(TRY(value.to_integer_or_infinity(vm))); |
462 | | |
463 | | // 4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer). |
464 | 0 | TRY(revalidate_atomic_access(vm, *typed_array, byte_index_in_buffer)); |
465 | | |
466 | | // 5. Let buffer be typedArray.[[ViewedArrayBuffer]]. |
467 | | // 6. Let elementType be TypedArrayElementType(typedArray). |
468 | | // 7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst). |
469 | 0 | typed_array->set_value_in_buffer(byte_index_in_buffer, value, ArrayBuffer::Order::SeqCst, true); |
470 | | |
471 | | // 8. Return v. |
472 | 0 | return value; |
473 | 0 | } |
474 | | |
475 | | // 25.4.12 Atomics.sub ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.sub |
476 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::sub) |
477 | 0 | { |
478 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
479 | |
|
480 | 0 | auto atomic_sub = [](auto* storage, auto value) { return AK::atomic_fetch_sub(storage, value); };Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::sub(JS::VM&)::$_0::operator()<unsigned char, unsigned char>(unsigned char*, unsigned char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::sub(JS::VM&)::$_0::operator()<unsigned short, unsigned short>(unsigned short*, unsigned short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::sub(JS::VM&)::$_0::operator()<unsigned int, unsigned int>(unsigned int*, unsigned int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::sub(JS::VM&)::$_0::operator()<unsigned long, unsigned long>(unsigned long*, unsigned long) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::sub(JS::VM&)::$_0::operator()<signed char, signed char>(signed char*, signed char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::sub(JS::VM&)::$_0::operator()<short, short>(short*, short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::sub(JS::VM&)::$_0::operator()<int, int>(int*, int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::sub(JS::VM&)::$_0::operator()<long, long>(long*, long) const |
481 | |
|
482 | 0 | #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ |
483 | 0 | if (is<ClassName>(typed_array)) \ |
484 | 0 | return TRY(perform_atomic_operation<Type>(vm, *typed_array, move(atomic_sub))); |
485 | 0 | JS_ENUMERATE_TYPED_ARRAYS |
486 | 0 | #undef __JS_ENUMERATE |
487 | | |
488 | 0 | VERIFY_NOT_REACHED(); |
489 | 0 | } |
490 | | |
491 | | // 25.4.13 Atomics.wait ( typedArray, index, value, timeout ), https://tc39.es/ecma262/#sec-atomics.wait |
492 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::wait) |
493 | 0 | { |
494 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
495 | 0 | auto index = vm.argument(1); |
496 | 0 | auto value = vm.argument(2); |
497 | 0 | auto timeout = vm.argument(3); |
498 | | |
499 | | // 1. Return ? DoWait(sync, typedArray, index, value, timeout). |
500 | 0 | return TRY(do_wait(vm, WaitMode::Sync, *typed_array, index, value, timeout)); |
501 | 0 | } |
502 | | |
503 | | // 25.4.14 Atomics.waitAsync ( typedArray, index, value, timeout ), https://tc39.es/ecma262/#sec-atomics.waitasync |
504 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::wait_async) |
505 | 0 | { |
506 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
507 | 0 | auto index = vm.argument(1); |
508 | 0 | auto value = vm.argument(2); |
509 | 0 | auto timeout = vm.argument(3); |
510 | | |
511 | | // 1. Return ? DoWait(async, typedArray, index, value, timeout). |
512 | 0 | return TRY(do_wait(vm, WaitMode::Async, *typed_array, index, value, timeout)); |
513 | 0 | } |
514 | | |
515 | | // 25.4.15 Atomics.notify ( typedArray, index, count ), https://tc39.es/ecma262/#sec-atomics.notify |
516 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::notify) |
517 | 0 | { |
518 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
519 | 0 | auto index = vm.argument(1); |
520 | 0 | auto count_value = vm.argument(2); |
521 | | |
522 | | // 1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, true). |
523 | 0 | auto byte_index_in_buffer = TRY(validate_atomic_access_on_integer_typed_array(vm, *typed_array, index, true)); |
524 | | |
525 | | // 2. If count is undefined, then |
526 | 0 | double count = 0.0; |
527 | 0 | if (count_value.is_undefined()) { |
528 | | // a. Let c be +∞. |
529 | 0 | count = js_infinity().as_double(); |
530 | 0 | } |
531 | | // 3. Else, |
532 | 0 | else { |
533 | | // a. Let intCount be ? ToIntegerOrInfinity(count). |
534 | 0 | auto int_count = TRY(count_value.to_integer_or_infinity(vm)); |
535 | | |
536 | | // b. Let c be max(intCount, 0). |
537 | 0 | count = max(int_count, 0.0); |
538 | 0 | } |
539 | | |
540 | | // 4. Let buffer be typedArray.[[ViewedArrayBuffer]]. |
541 | 0 | auto* buffer = typed_array->viewed_array_buffer(); |
542 | | |
543 | | // 5. Let block be buffer.[[ArrayBufferData]]. |
544 | 0 | auto& block = buffer->buffer(); |
545 | | |
546 | | // 6. If IsSharedArrayBuffer(buffer) is false, return +0𝔽. |
547 | 0 | if (!buffer->is_shared_array_buffer()) |
548 | 0 | return Value { 0 }; |
549 | | |
550 | | // FIXME: Implement the remaining steps when we support SharedArrayBuffer. |
551 | 0 | (void)byte_index_in_buffer; |
552 | 0 | (void)count; |
553 | 0 | (void)block; |
554 | |
|
555 | 0 | return vm.throw_completion<InternalError>(ErrorType::NotImplemented, "SharedArrayBuffer"sv); |
556 | 0 | } |
557 | | |
558 | | // 25.4.16 Atomics.xor ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.xor |
559 | | JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::xor_) |
560 | 0 | { |
561 | 0 | auto* typed_array = TRY(typed_array_from(vm, vm.argument(0))); |
562 | |
|
563 | 0 | auto atomic_xor = [](auto* storage, auto value) { return AK::atomic_fetch_xor(storage, value); };Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::xor_(JS::VM&)::$_0::operator()<unsigned char, unsigned char>(unsigned char*, unsigned char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::xor_(JS::VM&)::$_0::operator()<unsigned short, unsigned short>(unsigned short*, unsigned short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::xor_(JS::VM&)::$_0::operator()<unsigned int, unsigned int>(unsigned int*, unsigned int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::xor_(JS::VM&)::$_0::operator()<unsigned long, unsigned long>(unsigned long*, unsigned long) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::xor_(JS::VM&)::$_0::operator()<signed char, signed char>(signed char*, signed char) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::xor_(JS::VM&)::$_0::operator()<short, short>(short*, short) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::xor_(JS::VM&)::$_0::operator()<int, int>(int*, int) const Unexecuted instantiation: AtomicsObject.cpp:auto JS::AtomicsObject::xor_(JS::VM&)::$_0::operator()<long, long>(long*, long) const |
564 | |
|
565 | 0 | #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ |
566 | 0 | if (is<ClassName>(typed_array)) \ |
567 | 0 | return TRY(perform_atomic_operation<Type>(vm, *typed_array, move(atomic_xor))); |
568 | 0 | JS_ENUMERATE_TYPED_ARRAYS |
569 | 0 | #undef __JS_ENUMERATE |
570 | | |
571 | 0 | VERIFY_NOT_REACHED(); |
572 | 0 | } |
573 | | |
574 | | } |