blob: 94d98d4ffaf77a46e4aec1cb088bd55b36e406e4 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/runtime/runtime-utils.h"
6
7#include "src/arguments.h"
8#include "src/base/macros.h"
9#include "src/base/platform/mutex.h"
10#include "src/conversions-inl.h"
11#include "src/factory.h"
12
13// Implement Atomic accesses to SharedArrayBuffers as defined in the
14// SharedArrayBuffer draft spec, found here
15// https://github.com/lars-t-hansen/ecmascript_sharedmem
16
17namespace v8 {
18namespace internal {
19
20namespace {
21
22inline bool AtomicIsLockFree(uint32_t size) {
23 return size == 1 || size == 2 || size == 4;
24}
25
26#if V8_CC_GNU
27
28template <typename T>
29inline T CompareExchangeSeqCst(T* p, T oldval, T newval) {
30 (void)__atomic_compare_exchange_n(p, &oldval, newval, 0, __ATOMIC_SEQ_CST,
31 __ATOMIC_SEQ_CST);
32 return oldval;
33}
34
35template <typename T>
36inline T LoadSeqCst(T* p) {
37 T result;
38 __atomic_load(p, &result, __ATOMIC_SEQ_CST);
39 return result;
40}
41
42template <typename T>
43inline void StoreSeqCst(T* p, T value) {
44 __atomic_store_n(p, value, __ATOMIC_SEQ_CST);
45}
46
47template <typename T>
48inline T AddSeqCst(T* p, T value) {
49 return __atomic_fetch_add(p, value, __ATOMIC_SEQ_CST);
50}
51
52template <typename T>
53inline T SubSeqCst(T* p, T value) {
54 return __atomic_fetch_sub(p, value, __ATOMIC_SEQ_CST);
55}
56
57template <typename T>
58inline T AndSeqCst(T* p, T value) {
59 return __atomic_fetch_and(p, value, __ATOMIC_SEQ_CST);
60}
61
62template <typename T>
63inline T OrSeqCst(T* p, T value) {
64 return __atomic_fetch_or(p, value, __ATOMIC_SEQ_CST);
65}
66
67template <typename T>
68inline T XorSeqCst(T* p, T value) {
69 return __atomic_fetch_xor(p, value, __ATOMIC_SEQ_CST);
70}
71
72template <typename T>
73inline T ExchangeSeqCst(T* p, T value) {
74 return __atomic_exchange_n(p, value, __ATOMIC_SEQ_CST);
75}
76
77#elif V8_CC_MSVC
78
79#define InterlockedCompareExchange32 _InterlockedCompareExchange
80#define InterlockedExchange32 _InterlockedExchange
81#define InterlockedExchangeAdd32 _InterlockedExchangeAdd
82#define InterlockedAnd32 _InterlockedAnd
83#define InterlockedOr32 _InterlockedOr
84#define InterlockedXor32 _InterlockedXor
85#define InterlockedExchangeAdd16 _InterlockedExchangeAdd16
86#define InterlockedCompareExchange8 _InterlockedCompareExchange8
87#define InterlockedExchangeAdd8 _InterlockedExchangeAdd8
88
89#define ATOMIC_OPS(type, suffix, vctype) \
90 inline type AddSeqCst(type* p, type value) { \
91 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \
92 bit_cast<vctype>(value)); \
93 } \
94 inline type SubSeqCst(type* p, type value) { \
95 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \
96 -bit_cast<vctype>(value)); \
97 } \
98 inline type AndSeqCst(type* p, type value) { \
99 return InterlockedAnd##suffix(reinterpret_cast<vctype*>(p), \
100 bit_cast<vctype>(value)); \
101 } \
102 inline type OrSeqCst(type* p, type value) { \
103 return InterlockedOr##suffix(reinterpret_cast<vctype*>(p), \
104 bit_cast<vctype>(value)); \
105 } \
106 inline type XorSeqCst(type* p, type value) { \
107 return InterlockedXor##suffix(reinterpret_cast<vctype*>(p), \
108 bit_cast<vctype>(value)); \
109 } \
110 inline type ExchangeSeqCst(type* p, type value) { \
111 return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p), \
112 bit_cast<vctype>(value)); \
113 } \
114 \
115 inline type CompareExchangeSeqCst(type* p, type oldval, type newval) { \
116 return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \
117 bit_cast<vctype>(newval), \
118 bit_cast<vctype>(oldval)); \
119 } \
120 inline type LoadSeqCst(type* p) { return *p; } \
121 inline void StoreSeqCst(type* p, type value) { \
122 InterlockedExchange##suffix(reinterpret_cast<vctype*>(p), \
123 bit_cast<vctype>(value)); \
124 }
125
126ATOMIC_OPS(int8_t, 8, char)
127ATOMIC_OPS(uint8_t, 8, char)
128ATOMIC_OPS(int16_t, 16, short) /* NOLINT(runtime/int) */
129ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */
130ATOMIC_OPS(int32_t, 32, long) /* NOLINT(runtime/int) */
131ATOMIC_OPS(uint32_t, 32, long) /* NOLINT(runtime/int) */
132
133#undef ATOMIC_OPS_INTEGER
134#undef ATOMIC_OPS
135
136#undef InterlockedCompareExchange32
137#undef InterlockedExchange32
138#undef InterlockedExchangeAdd32
139#undef InterlockedAnd32
140#undef InterlockedOr32
141#undef InterlockedXor32
142#undef InterlockedExchangeAdd16
143#undef InterlockedCompareExchange8
144#undef InterlockedExchangeAdd8
145
146#else
147
148#error Unsupported platform!
149
150#endif
151
152template <typename T>
153T FromObject(Handle<Object> number);
154
155template <>
156inline uint8_t FromObject<uint8_t>(Handle<Object> number) {
157 return NumberToUint32(*number);
158}
159
160template <>
161inline int8_t FromObject<int8_t>(Handle<Object> number) {
162 return NumberToInt32(*number);
163}
164
165template <>
166inline uint16_t FromObject<uint16_t>(Handle<Object> number) {
167 return NumberToUint32(*number);
168}
169
170template <>
171inline int16_t FromObject<int16_t>(Handle<Object> number) {
172 return NumberToInt32(*number);
173}
174
175template <>
176inline uint32_t FromObject<uint32_t>(Handle<Object> number) {
177 return NumberToUint32(*number);
178}
179
180template <>
181inline int32_t FromObject<int32_t>(Handle<Object> number) {
182 return NumberToInt32(*number);
183}
184
185
186inline Object* ToObject(Isolate* isolate, int8_t t) { return Smi::FromInt(t); }
187
188inline Object* ToObject(Isolate* isolate, uint8_t t) { return Smi::FromInt(t); }
189
190inline Object* ToObject(Isolate* isolate, int16_t t) { return Smi::FromInt(t); }
191
192inline Object* ToObject(Isolate* isolate, uint16_t t) {
193 return Smi::FromInt(t);
194}
195
196
197inline Object* ToObject(Isolate* isolate, int32_t t) {
198 return *isolate->factory()->NewNumber(t);
199}
200
201
202inline Object* ToObject(Isolate* isolate, uint32_t t) {
203 return *isolate->factory()->NewNumber(t);
204}
205
206
207template <typename T>
208inline Object* DoCompareExchange(Isolate* isolate, void* buffer, size_t index,
209 Handle<Object> oldobj, Handle<Object> newobj) {
210 T oldval = FromObject<T>(oldobj);
211 T newval = FromObject<T>(newobj);
212 T result =
213 CompareExchangeSeqCst(static_cast<T*>(buffer) + index, oldval, newval);
214 return ToObject(isolate, result);
215}
216
217
218template <typename T>
219inline Object* DoLoad(Isolate* isolate, void* buffer, size_t index) {
220 T result = LoadSeqCst(static_cast<T*>(buffer) + index);
221 return ToObject(isolate, result);
222}
223
224
225template <typename T>
226inline Object* DoStore(Isolate* isolate, void* buffer, size_t index,
227 Handle<Object> obj) {
228 T value = FromObject<T>(obj);
229 StoreSeqCst(static_cast<T*>(buffer) + index, value);
230 return *obj;
231}
232
233
234template <typename T>
235inline Object* DoAdd(Isolate* isolate, void* buffer, size_t index,
236 Handle<Object> obj) {
237 T value = FromObject<T>(obj);
238 T result = AddSeqCst(static_cast<T*>(buffer) + index, value);
239 return ToObject(isolate, result);
240}
241
242
243template <typename T>
244inline Object* DoSub(Isolate* isolate, void* buffer, size_t index,
245 Handle<Object> obj) {
246 T value = FromObject<T>(obj);
247 T result = SubSeqCst(static_cast<T*>(buffer) + index, value);
248 return ToObject(isolate, result);
249}
250
251
252template <typename T>
253inline Object* DoAnd(Isolate* isolate, void* buffer, size_t index,
254 Handle<Object> obj) {
255 T value = FromObject<T>(obj);
256 T result = AndSeqCst(static_cast<T*>(buffer) + index, value);
257 return ToObject(isolate, result);
258}
259
260
261template <typename T>
262inline Object* DoOr(Isolate* isolate, void* buffer, size_t index,
263 Handle<Object> obj) {
264 T value = FromObject<T>(obj);
265 T result = OrSeqCst(static_cast<T*>(buffer) + index, value);
266 return ToObject(isolate, result);
267}
268
269
270template <typename T>
271inline Object* DoXor(Isolate* isolate, void* buffer, size_t index,
272 Handle<Object> obj) {
273 T value = FromObject<T>(obj);
274 T result = XorSeqCst(static_cast<T*>(buffer) + index, value);
275 return ToObject(isolate, result);
276}
277
278
279template <typename T>
280inline Object* DoExchange(Isolate* isolate, void* buffer, size_t index,
281 Handle<Object> obj) {
282 T value = FromObject<T>(obj);
283 T result = ExchangeSeqCst(static_cast<T*>(buffer) + index, value);
284 return ToObject(isolate, result);
285}
286
287
288// Uint8Clamped functions
289
290uint8_t ClampToUint8(int32_t value) {
291 if (value < 0) return 0;
292 if (value > 255) return 255;
293 return value;
294}
295
296
297inline Object* DoCompareExchangeUint8Clamped(Isolate* isolate, void* buffer,
298 size_t index,
299 Handle<Object> oldobj,
300 Handle<Object> newobj) {
301 typedef int32_t convert_type;
302 uint8_t oldval = ClampToUint8(FromObject<convert_type>(oldobj));
303 uint8_t newval = ClampToUint8(FromObject<convert_type>(newobj));
304 uint8_t result = CompareExchangeSeqCst(static_cast<uint8_t*>(buffer) + index,
305 oldval, newval);
306 return ToObject(isolate, result);
307}
308
309
310inline Object* DoStoreUint8Clamped(Isolate* isolate, void* buffer, size_t index,
311 Handle<Object> obj) {
312 typedef int32_t convert_type;
313 uint8_t value = ClampToUint8(FromObject<convert_type>(obj));
314 StoreSeqCst(static_cast<uint8_t*>(buffer) + index, value);
315 return *obj;
316}
317
318
319#define DO_UINT8_CLAMPED_OP(name, op) \
320 inline Object* Do##name##Uint8Clamped(Isolate* isolate, void* buffer, \
321 size_t index, Handle<Object> obj) { \
322 typedef int32_t convert_type; \
323 uint8_t* p = static_cast<uint8_t*>(buffer) + index; \
324 convert_type operand = FromObject<convert_type>(obj); \
325 uint8_t expected; \
326 uint8_t result; \
327 do { \
328 expected = *p; \
329 result = ClampToUint8(static_cast<convert_type>(expected) op operand); \
330 } while (CompareExchangeSeqCst(p, expected, result) != expected); \
331 return ToObject(isolate, expected); \
332 }
333
334DO_UINT8_CLAMPED_OP(Add, +)
335DO_UINT8_CLAMPED_OP(Sub, -)
336DO_UINT8_CLAMPED_OP(And, &)
337DO_UINT8_CLAMPED_OP(Or, | )
338DO_UINT8_CLAMPED_OP(Xor, ^)
339
340#undef DO_UINT8_CLAMPED_OP
341
342
343inline Object* DoExchangeUint8Clamped(Isolate* isolate, void* buffer,
344 size_t index, Handle<Object> obj) {
345 typedef int32_t convert_type;
346 uint8_t* p = static_cast<uint8_t*>(buffer) + index;
347 uint8_t result = ClampToUint8(FromObject<convert_type>(obj));
348 uint8_t expected;
349 do {
350 expected = *p;
351 } while (CompareExchangeSeqCst(p, expected, result) != expected);
352 return ToObject(isolate, expected);
353}
354
355
356} // anonymous namespace
357
358// Duplicated from objects.h
359// V has parameters (Type, type, TYPE, C type, element_size)
360#define INTEGER_TYPED_ARRAYS(V) \
361 V(Uint8, uint8, UINT8, uint8_t, 1) \
362 V(Int8, int8, INT8, int8_t, 1) \
363 V(Uint16, uint16, UINT16, uint16_t, 2) \
364 V(Int16, int16, INT16, int16_t, 2) \
365 V(Uint32, uint32, UINT32, uint32_t, 4) \
366 V(Int32, int32, INT32, int32_t, 4)
367
368
369RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) {
370 HandleScope scope(isolate);
371 DCHECK(args.length() == 4);
372 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
373 CONVERT_SIZE_ARG_CHECKED(index, 1);
374 CONVERT_NUMBER_ARG_HANDLE_CHECKED(oldobj, 2);
375 CONVERT_NUMBER_ARG_HANDLE_CHECKED(newobj, 3);
376 RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
377 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
378
379 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
380 NumberToSize(isolate, sta->byte_offset());
381
382 switch (sta->type()) {
383#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
384 case kExternal##Type##Array: \
385 return DoCompareExchange<ctype>(isolate, source, index, oldobj, newobj);
386
387 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
388#undef TYPED_ARRAY_CASE
389
390 case kExternalUint8ClampedArray:
391 return DoCompareExchangeUint8Clamped(isolate, source, index, oldobj,
392 newobj);
393
394 default:
395 break;
396 }
397
398 UNREACHABLE();
399 return isolate->heap()->undefined_value();
400}
401
402
403RUNTIME_FUNCTION(Runtime_AtomicsLoad) {
404 HandleScope scope(isolate);
405 DCHECK(args.length() == 2);
406 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
407 CONVERT_SIZE_ARG_CHECKED(index, 1);
408 RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
409 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
410
411 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
412 NumberToSize(isolate, sta->byte_offset());
413
414 switch (sta->type()) {
415#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
416 case kExternal##Type##Array: \
417 return DoLoad<ctype>(isolate, source, index);
418
419 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
420#undef TYPED_ARRAY_CASE
421
422 case kExternalUint8ClampedArray:
423 return DoLoad<uint8_t>(isolate, source, index);
424
425 default:
426 break;
427 }
428
429 UNREACHABLE();
430 return isolate->heap()->undefined_value();
431}
432
433
434RUNTIME_FUNCTION(Runtime_AtomicsStore) {
435 HandleScope scope(isolate);
436 DCHECK(args.length() == 3);
437 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
438 CONVERT_SIZE_ARG_CHECKED(index, 1);
439 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
440 RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
441 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
442
443 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
444 NumberToSize(isolate, sta->byte_offset());
445
446 switch (sta->type()) {
447#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
448 case kExternal##Type##Array: \
449 return DoStore<ctype>(isolate, source, index, value);
450
451 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
452#undef TYPED_ARRAY_CASE
453
454 case kExternalUint8ClampedArray:
455 return DoStoreUint8Clamped(isolate, source, index, value);
456
457 default:
458 break;
459 }
460
461 UNREACHABLE();
462 return isolate->heap()->undefined_value();
463}
464
465
466RUNTIME_FUNCTION(Runtime_AtomicsAdd) {
467 HandleScope scope(isolate);
468 DCHECK(args.length() == 3);
469 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
470 CONVERT_SIZE_ARG_CHECKED(index, 1);
471 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
472 RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
473 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
474
475 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
476 NumberToSize(isolate, sta->byte_offset());
477
478 switch (sta->type()) {
479#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
480 case kExternal##Type##Array: \
481 return DoAdd<ctype>(isolate, source, index, value);
482
483 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
484#undef TYPED_ARRAY_CASE
485
486 case kExternalUint8ClampedArray:
487 return DoAddUint8Clamped(isolate, source, index, value);
488
489 default:
490 break;
491 }
492
493 UNREACHABLE();
494 return isolate->heap()->undefined_value();
495}
496
497
498RUNTIME_FUNCTION(Runtime_AtomicsSub) {
499 HandleScope scope(isolate);
500 DCHECK(args.length() == 3);
501 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
502 CONVERT_SIZE_ARG_CHECKED(index, 1);
503 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
504 RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
505 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
506
507 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
508 NumberToSize(isolate, sta->byte_offset());
509
510 switch (sta->type()) {
511#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
512 case kExternal##Type##Array: \
513 return DoSub<ctype>(isolate, source, index, value);
514
515 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
516#undef TYPED_ARRAY_CASE
517
518 case kExternalUint8ClampedArray:
519 return DoSubUint8Clamped(isolate, source, index, value);
520
521 default:
522 break;
523 }
524
525 UNREACHABLE();
526 return isolate->heap()->undefined_value();
527}
528
529
530RUNTIME_FUNCTION(Runtime_AtomicsAnd) {
531 HandleScope scope(isolate);
532 DCHECK(args.length() == 3);
533 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
534 CONVERT_SIZE_ARG_CHECKED(index, 1);
535 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
536 RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
537 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
538
539 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
540 NumberToSize(isolate, sta->byte_offset());
541
542 switch (sta->type()) {
543#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
544 case kExternal##Type##Array: \
545 return DoAnd<ctype>(isolate, source, index, value);
546
547 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
548#undef TYPED_ARRAY_CASE
549
550 case kExternalUint8ClampedArray:
551 return DoAndUint8Clamped(isolate, source, index, value);
552
553 default:
554 break;
555 }
556
557 UNREACHABLE();
558 return isolate->heap()->undefined_value();
559}
560
561
562RUNTIME_FUNCTION(Runtime_AtomicsOr) {
563 HandleScope scope(isolate);
564 DCHECK(args.length() == 3);
565 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
566 CONVERT_SIZE_ARG_CHECKED(index, 1);
567 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
568 RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
569 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
570
571 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
572 NumberToSize(isolate, sta->byte_offset());
573
574 switch (sta->type()) {
575#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
576 case kExternal##Type##Array: \
577 return DoOr<ctype>(isolate, source, index, value);
578
579 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
580#undef TYPED_ARRAY_CASE
581
582 case kExternalUint8ClampedArray:
583 return DoOrUint8Clamped(isolate, source, index, value);
584
585 default:
586 break;
587 }
588
589 UNREACHABLE();
590 return isolate->heap()->undefined_value();
591}
592
593
594RUNTIME_FUNCTION(Runtime_AtomicsXor) {
595 HandleScope scope(isolate);
596 DCHECK(args.length() == 3);
597 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
598 CONVERT_SIZE_ARG_CHECKED(index, 1);
599 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
600 RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
601 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
602
603 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
604 NumberToSize(isolate, sta->byte_offset());
605
606 switch (sta->type()) {
607#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
608 case kExternal##Type##Array: \
609 return DoXor<ctype>(isolate, source, index, value);
610
611 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
612#undef TYPED_ARRAY_CASE
613
614 case kExternalUint8ClampedArray:
615 return DoXorUint8Clamped(isolate, source, index, value);
616
617 default:
618 break;
619 }
620
621 UNREACHABLE();
622 return isolate->heap()->undefined_value();
623}
624
625
626RUNTIME_FUNCTION(Runtime_AtomicsExchange) {
627 HandleScope scope(isolate);
628 DCHECK(args.length() == 3);
629 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
630 CONVERT_SIZE_ARG_CHECKED(index, 1);
631 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
632 RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
633 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
634
635 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
636 NumberToSize(isolate, sta->byte_offset());
637
638 switch (sta->type()) {
639#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
640 case kExternal##Type##Array: \
641 return DoExchange<ctype>(isolate, source, index, value);
642
643 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
644#undef TYPED_ARRAY_CASE
645
646 case kExternalUint8ClampedArray:
647 return DoExchangeUint8Clamped(isolate, source, index, value);
648
649 default:
650 break;
651 }
652
653 UNREACHABLE();
654 return isolate->heap()->undefined_value();
655}
656
657
658RUNTIME_FUNCTION(Runtime_AtomicsIsLockFree) {
659 HandleScope scope(isolate);
660 DCHECK(args.length() == 1);
661 CONVERT_NUMBER_ARG_HANDLE_CHECKED(size, 0);
662 uint32_t usize = NumberToUint32(*size);
663 return isolate->heap()->ToBoolean(AtomicIsLockFree(usize));
664}
665} // namespace internal
666} // namespace v8