5 #include "src/base/macros.h" 6 #include "src/base/platform/mutex.h" 7 #include "src/base/platform/time.h" 8 #include "src/builtins/builtins-utils-inl.h" 9 #include "src/builtins/builtins.h" 10 #include "src/code-factory.h" 11 #include "src/conversions-inl.h" 12 #include "src/counters.h" 13 #include "src/futex-emulation.h" 14 #include "src/globals.h" 15 #include "src/heap/factory.h" 16 #include "src/objects-inl.h" 17 #include "src/objects/js-array-buffer-inl.h" 25 inline bool AtomicIsLockFree(
uint32_t size) {
26 return size == 1 || size == 2 || size == 4;
30 BUILTIN(AtomicsIsLockFree) {
31 HandleScope scope(isolate);
32 Handle<Object> size = args.atOrUndefined(isolate, 1);
33 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, size,
34 Object::ToNumber(isolate, size));
35 return *isolate->factory()->ToBoolean(AtomicIsLockFree(size->Number()));
39 V8_WARN_UNUSED_RESULT MaybeHandle<JSTypedArray> ValidateSharedIntegerTypedArray(
40 Isolate* isolate, Handle<Object>
object,
bool only_int32 =
false) {
41 if (object->IsJSTypedArray()) {
42 Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(
object);
43 if (typed_array->GetBuffer()->is_shared()) {
45 if (typed_array->type() == kExternalInt32Array)
return typed_array;
47 if (typed_array->type() != kExternalFloat32Array &&
48 typed_array->type() != kExternalFloat64Array &&
49 typed_array->type() != kExternalUint8ClampedArray)
57 NewTypeError(only_int32 ? MessageTemplate::kNotInt32SharedTypedArray
58 : MessageTemplate::kNotIntegerSharedTypedArray,
65 V8_WARN_UNUSED_RESULT Maybe<size_t> ValidateAtomicAccess(
66 Isolate* isolate, Handle<JSTypedArray> typed_array,
67 Handle<Object> request_index) {
68 Handle<Object> access_index_obj;
69 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
70 isolate, access_index_obj,
71 Object::ToIndex(isolate, request_index,
72 MessageTemplate::kInvalidAtomicAccessIndex),
76 if (!TryNumberToSize(*access_index_obj, &access_index) ||
77 typed_array->WasNeutered() ||
78 access_index >= typed_array->length_value()) {
79 isolate->Throw(*isolate->factory()->NewRangeError(
80 MessageTemplate::kInvalidAtomicAccessIndex));
81 return Nothing<size_t>();
83 return Just<size_t>(access_index);
87 MaybeHandle<Object> AtomicsWake(Isolate* isolate, Handle<Object> array,
88 Handle<Object> index, Handle<Object> count) {
89 Handle<JSTypedArray> sta;
90 ASSIGN_RETURN_ON_EXCEPTION(
91 isolate, sta, ValidateSharedIntegerTypedArray(isolate, array,
true),
94 Maybe<size_t> maybe_index = ValidateAtomicAccess(isolate, sta, index);
95 MAYBE_RETURN_NULL(maybe_index);
96 size_t i = maybe_index.FromJust();
99 if (count->IsUndefined(isolate)) {
102 ASSIGN_RETURN_ON_EXCEPTION(isolate, count,
103 Object::ToInteger(isolate, count), Object);
104 double count_double = count->Number();
105 if (count_double < 0)
107 else if (count_double > kMaxUInt32)
108 count_double = kMaxUInt32;
109 c =
static_cast<uint32_t>(count_double);
112 Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
113 size_t addr = (
i << 2) + sta->byte_offset();
115 return Handle<Object>(FutexEmulation::Wake(array_buffer, addr, c), isolate);
122 BUILTIN(AtomicsWake) {
123 HandleScope scope(isolate);
124 Handle<Object> array = args.atOrUndefined(isolate, 1);
125 Handle<Object> index = args.atOrUndefined(isolate, 2);
126 Handle<Object> count = args.atOrUndefined(isolate, 3);
128 isolate->CountUsage(v8::Isolate::UseCounterFeature::kAtomicsWake);
129 RETURN_RESULT_OR_FAILURE(isolate, AtomicsWake(isolate, array, index, count));
134 BUILTIN(AtomicsNotify) {
135 HandleScope scope(isolate);
136 Handle<Object> array = args.atOrUndefined(isolate, 1);
137 Handle<Object> index = args.atOrUndefined(isolate, 2);
138 Handle<Object> count = args.atOrUndefined(isolate, 3);
140 isolate->CountUsage(v8::Isolate::UseCounterFeature::kAtomicsNotify);
141 RETURN_RESULT_OR_FAILURE(isolate, AtomicsWake(isolate, array, index, count));
146 BUILTIN(AtomicsWait) {
147 HandleScope scope(isolate);
148 Handle<Object> array = args.atOrUndefined(isolate, 1);
149 Handle<Object> index = args.atOrUndefined(isolate, 2);
150 Handle<Object> value = args.atOrUndefined(isolate, 3);
151 Handle<Object> timeout = args.atOrUndefined(isolate, 4);
153 Handle<JSTypedArray> sta;
154 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
155 isolate, sta, ValidateSharedIntegerTypedArray(isolate, array,
true));
157 Maybe<size_t> maybe_index = ValidateAtomicAccess(isolate, sta, index);
158 if (maybe_index.IsNothing())
return ReadOnlyRoots(isolate).exception();
159 size_t i = maybe_index.FromJust();
161 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
162 Object::ToInt32(isolate, value));
163 int32_t value_int32 = NumberToInt32(*value);
165 double timeout_number;
166 if (timeout->IsUndefined(isolate)) {
167 timeout_number = ReadOnlyRoots(isolate).infinity_value()->Number();
169 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, timeout,
170 Object::ToNumber(isolate, timeout));
171 timeout_number = timeout->Number();
172 if (std::isnan(timeout_number))
173 timeout_number = ReadOnlyRoots(isolate).infinity_value()->Number();
174 else if (timeout_number < 0)
178 if (!isolate->allow_atomics_wait()) {
179 THROW_NEW_ERROR_RETURN_FAILURE(
180 isolate, NewTypeError(MessageTemplate::kAtomicsWaitNotAllowed));
183 Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
184 size_t addr = (
i << 2) + sta->byte_offset();
186 return FutexEmulation::WaitJs(isolate, array_buffer, addr, value_int32,