| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/base/macros.h" | 5 #include "src/base/macros.h" |
| 6 #include "src/base/platform/mutex.h" | 6 #include "src/base/platform/mutex.h" |
| 7 #include "src/base/platform/time.h" | 7 #include "src/base/platform/time.h" |
| 8 #include "src/builtins/builtins-utils.h" | 8 #include "src/builtins/builtins-utils.h" |
| 9 #include "src/builtins/builtins.h" | 9 #include "src/builtins/builtins.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 | 334 |
| 335 a.Bind(&u32); | 335 a.Bind(&u32); |
| 336 a.Return(a.ChangeUint32ToTagged( | 336 a.Return(a.ChangeUint32ToTagged( |
| 337 a.AtomicExchange(MachineType::Uint32(), backing_store, | 337 a.AtomicExchange(MachineType::Uint32(), backing_store, |
| 338 a.WordShl(index_word, 2), value_word32))); | 338 a.WordShl(index_word, 2), value_word32))); |
| 339 | 339 |
| 340 // This shouldn't happen, we've already validated the type. | 340 // This shouldn't happen, we've already validated the type. |
| 341 a.Bind(&other); | 341 a.Bind(&other); |
| 342 a.Return(a.SmiConstant(0)); | 342 a.Return(a.SmiConstant(0)); |
| 343 } | 343 } |
| 344 |
| 345 void Builtins::Generate_AtomicsCompareExchange( |
| 346 compiler::CodeAssemblerState* state) { |
| 347 using compiler::Node; |
| 348 CodeStubAssembler a(state); |
| 349 Node* array = a.Parameter(1); |
| 350 Node* index = a.Parameter(2); |
| 351 Node* old_value = a.Parameter(3); |
| 352 Node* new_value = a.Parameter(4); |
| 353 Node* context = a.Parameter(5 + 2); |
| 354 |
| 355 Node* instance_type; |
| 356 Node* backing_store; |
| 357 ValidateSharedTypedArray(&a, array, context, &instance_type, &backing_store); |
| 358 |
| 359 Node* index_word32 = ConvertTaggedAtomicIndexToWord32(&a, index, context); |
| 360 Node* array_length_word32 = a.TruncateTaggedToWord32( |
| 361 context, a.LoadObjectField(array, JSTypedArray::kLengthOffset)); |
| 362 ValidateAtomicIndex(&a, index_word32, array_length_word32, context); |
| 363 Node* index_word = a.ChangeUint32ToWord(index_word32); |
| 364 |
| 365 Node* old_value_integer = a.ToInteger(context, old_value); |
| 366 Node* old_value_word32 = a.TruncateTaggedToWord32(context, old_value_integer); |
| 367 |
| 368 Node* new_value_integer = a.ToInteger(context, new_value); |
| 369 Node* new_value_word32 = a.TruncateTaggedToWord32(context, new_value_integer); |
| 370 |
| 371 CodeStubAssembler::Label i8(&a), u8(&a), i16(&a), u16(&a), i32(&a), u32(&a), |
| 372 other(&a); |
| 373 int32_t case_values[] = { |
| 374 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE, |
| 375 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE, |
| 376 }; |
| 377 CodeStubAssembler::Label* case_labels[] = { |
| 378 &i8, &u8, &i16, &u16, &i32, &u32, |
| 379 }; |
| 380 a.Switch(instance_type, &other, case_values, case_labels, |
| 381 arraysize(case_labels)); |
| 382 |
| 383 a.Bind(&i8); |
| 384 a.Return(a.SmiFromWord32( |
| 385 a.AtomicCompareExchange(MachineType::Int8(), backing_store, index_word, |
| 386 old_value_word32, new_value_word32))); |
| 387 |
| 388 a.Bind(&u8); |
| 389 a.Return(a.SmiFromWord32( |
| 390 a.AtomicCompareExchange(MachineType::Uint8(), backing_store, index_word, |
| 391 old_value_word32, new_value_word32))); |
| 392 |
| 393 a.Bind(&i16); |
| 394 a.Return(a.SmiFromWord32(a.AtomicCompareExchange( |
| 395 MachineType::Int16(), backing_store, a.WordShl(index_word, 1), |
| 396 old_value_word32, new_value_word32))); |
| 397 |
| 398 a.Bind(&u16); |
| 399 a.Return(a.SmiFromWord32(a.AtomicCompareExchange( |
| 400 MachineType::Uint16(), backing_store, a.WordShl(index_word, 1), |
| 401 old_value_word32, new_value_word32))); |
| 402 |
| 403 a.Bind(&i32); |
| 404 a.Return(a.ChangeInt32ToTagged(a.AtomicCompareExchange( |
| 405 MachineType::Int32(), backing_store, a.WordShl(index_word, 2), |
| 406 old_value_word32, new_value_word32))); |
| 407 |
| 408 a.Bind(&u32); |
| 409 a.Return(a.ChangeUint32ToTagged(a.AtomicCompareExchange( |
| 410 MachineType::Uint32(), backing_store, a.WordShl(index_word, 2), |
| 411 old_value_word32, new_value_word32))); |
| 412 |
| 413 // This shouldn't happen, we've already validated the type. |
| 414 a.Bind(&other); |
| 415 a.Return(a.SmiConstant(0)); |
| 416 } |
| 344 #endif | 417 #endif |
| 345 | 418 |
| 346 inline bool AtomicIsLockFree(uint32_t size) { | 419 inline bool AtomicIsLockFree(uint32_t size) { |
| 347 return size == 1 || size == 2 || size == 4; | 420 return size == 1 || size == 2 || size == 4; |
| 348 } | 421 } |
| 349 | 422 |
| 350 // ES #sec-atomics.islockfree | 423 // ES #sec-atomics.islockfree |
| 351 BUILTIN(AtomicsIsLockFree) { | 424 BUILTIN(AtomicsIsLockFree) { |
| 352 HandleScope scope(isolate); | 425 HandleScope scope(isolate); |
| 353 Handle<Object> size = args.atOrUndefined(isolate, 1); | 426 Handle<Object> size = args.atOrUndefined(isolate, 1); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 | 562 |
| 490 return FutexEmulation::Wait(isolate, array_buffer, addr, value_int32, | 563 return FutexEmulation::Wait(isolate, array_buffer, addr, value_int32, |
| 491 timeout_number); | 564 timeout_number); |
| 492 } | 565 } |
| 493 | 566 |
| 494 namespace { | 567 namespace { |
| 495 | 568 |
| 496 #if V8_CC_GNU | 569 #if V8_CC_GNU |
| 497 | 570 |
| 498 template <typename T> | 571 template <typename T> |
| 499 inline T CompareExchangeSeqCst(T* p, T oldval, T newval) { | |
| 500 (void)__atomic_compare_exchange_n(p, &oldval, newval, 0, __ATOMIC_SEQ_CST, | |
| 501 __ATOMIC_SEQ_CST); | |
| 502 return oldval; | |
| 503 } | |
| 504 | |
| 505 template <typename T> | |
| 506 inline T AddSeqCst(T* p, T value) { | 572 inline T AddSeqCst(T* p, T value) { |
| 507 return __atomic_fetch_add(p, value, __ATOMIC_SEQ_CST); | 573 return __atomic_fetch_add(p, value, __ATOMIC_SEQ_CST); |
| 508 } | 574 } |
| 509 | 575 |
| 510 template <typename T> | 576 template <typename T> |
| 511 inline T SubSeqCst(T* p, T value) { | 577 inline T SubSeqCst(T* p, T value) { |
| 512 return __atomic_fetch_sub(p, value, __ATOMIC_SEQ_CST); | 578 return __atomic_fetch_sub(p, value, __ATOMIC_SEQ_CST); |
| 513 } | 579 } |
| 514 | 580 |
| 515 template <typename T> | 581 template <typename T> |
| 516 inline T AndSeqCst(T* p, T value) { | 582 inline T AndSeqCst(T* p, T value) { |
| 517 return __atomic_fetch_and(p, value, __ATOMIC_SEQ_CST); | 583 return __atomic_fetch_and(p, value, __ATOMIC_SEQ_CST); |
| 518 } | 584 } |
| 519 | 585 |
| 520 template <typename T> | 586 template <typename T> |
| 521 inline T OrSeqCst(T* p, T value) { | 587 inline T OrSeqCst(T* p, T value) { |
| 522 return __atomic_fetch_or(p, value, __ATOMIC_SEQ_CST); | 588 return __atomic_fetch_or(p, value, __ATOMIC_SEQ_CST); |
| 523 } | 589 } |
| 524 | 590 |
| 525 template <typename T> | 591 template <typename T> |
| 526 inline T XorSeqCst(T* p, T value) { | 592 inline T XorSeqCst(T* p, T value) { |
| 527 return __atomic_fetch_xor(p, value, __ATOMIC_SEQ_CST); | 593 return __atomic_fetch_xor(p, value, __ATOMIC_SEQ_CST); |
| 528 } | 594 } |
| 529 | 595 |
| 530 | 596 |
| 531 #elif V8_CC_MSVC | 597 #elif V8_CC_MSVC |
| 532 | 598 |
| 533 #define InterlockedCompareExchange32 _InterlockedCompareExchange | |
| 534 #define InterlockedExchangeAdd32 _InterlockedExchangeAdd | 599 #define InterlockedExchangeAdd32 _InterlockedExchangeAdd |
| 535 #define InterlockedAnd32 _InterlockedAnd | 600 #define InterlockedAnd32 _InterlockedAnd |
| 536 #define InterlockedOr32 _InterlockedOr | 601 #define InterlockedOr32 _InterlockedOr |
| 537 #define InterlockedXor32 _InterlockedXor | 602 #define InterlockedXor32 _InterlockedXor |
| 538 #define InterlockedExchangeAdd16 _InterlockedExchangeAdd16 | 603 #define InterlockedExchangeAdd16 _InterlockedExchangeAdd16 |
| 539 #define InterlockedCompareExchange8 _InterlockedCompareExchange8 | |
| 540 #define InterlockedExchangeAdd8 _InterlockedExchangeAdd8 | 604 #define InterlockedExchangeAdd8 _InterlockedExchangeAdd8 |
| 541 | 605 |
| 542 #define ATOMIC_OPS(type, suffix, vctype) \ | 606 #define ATOMIC_OPS(type, suffix, vctype) \ |
| 543 inline type AddSeqCst(type* p, type value) { \ | 607 inline type AddSeqCst(type* p, type value) { \ |
| 544 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \ | 608 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \ |
| 545 bit_cast<vctype>(value)); \ | 609 bit_cast<vctype>(value)); \ |
| 546 } \ | 610 } \ |
| 547 inline type SubSeqCst(type* p, type value) { \ | 611 inline type SubSeqCst(type* p, type value) { \ |
| 548 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \ | 612 return InterlockedExchangeAdd##suffix(reinterpret_cast<vctype*>(p), \ |
| 549 -bit_cast<vctype>(value)); \ | 613 -bit_cast<vctype>(value)); \ |
| 550 } \ | 614 } \ |
| 551 inline type AndSeqCst(type* p, type value) { \ | 615 inline type AndSeqCst(type* p, type value) { \ |
| 552 return InterlockedAnd##suffix(reinterpret_cast<vctype*>(p), \ | 616 return InterlockedAnd##suffix(reinterpret_cast<vctype*>(p), \ |
| 553 bit_cast<vctype>(value)); \ | 617 bit_cast<vctype>(value)); \ |
| 554 } \ | 618 } \ |
| 555 inline type OrSeqCst(type* p, type value) { \ | 619 inline type OrSeqCst(type* p, type value) { \ |
| 556 return InterlockedOr##suffix(reinterpret_cast<vctype*>(p), \ | 620 return InterlockedOr##suffix(reinterpret_cast<vctype*>(p), \ |
| 557 bit_cast<vctype>(value)); \ | 621 bit_cast<vctype>(value)); \ |
| 558 } \ | 622 } \ |
| 559 inline type XorSeqCst(type* p, type value) { \ | 623 inline type XorSeqCst(type* p, type value) { \ |
| 560 return InterlockedXor##suffix(reinterpret_cast<vctype*>(p), \ | 624 return InterlockedXor##suffix(reinterpret_cast<vctype*>(p), \ |
| 561 bit_cast<vctype>(value)); \ | 625 bit_cast<vctype>(value)); \ |
| 562 } \ | |
| 563 \ | |
| 564 inline type CompareExchangeSeqCst(type* p, type oldval, type newval) { \ | |
| 565 return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \ | |
| 566 bit_cast<vctype>(newval), \ | |
| 567 bit_cast<vctype>(oldval)); \ | |
| 568 } | 626 } |
| 569 | 627 |
| 570 ATOMIC_OPS(int8_t, 8, char) | 628 ATOMIC_OPS(int8_t, 8, char) |
| 571 ATOMIC_OPS(uint8_t, 8, char) | 629 ATOMIC_OPS(uint8_t, 8, char) |
| 572 ATOMIC_OPS(int16_t, 16, short) /* NOLINT(runtime/int) */ | 630 ATOMIC_OPS(int16_t, 16, short) /* NOLINT(runtime/int) */ |
| 573 ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */ | 631 ATOMIC_OPS(uint16_t, 16, short) /* NOLINT(runtime/int) */ |
| 574 ATOMIC_OPS(int32_t, 32, long) /* NOLINT(runtime/int) */ | 632 ATOMIC_OPS(int32_t, 32, long) /* NOLINT(runtime/int) */ |
| 575 ATOMIC_OPS(uint32_t, 32, long) /* NOLINT(runtime/int) */ | 633 ATOMIC_OPS(uint32_t, 32, long) /* NOLINT(runtime/int) */ |
| 576 | 634 |
| 577 #undef ATOMIC_OPS_INTEGER | 635 #undef ATOMIC_OPS_INTEGER |
| 578 #undef ATOMIC_OPS | 636 #undef ATOMIC_OPS |
| 579 | 637 |
| 580 #undef InterlockedCompareExchange32 | |
| 581 #undef InterlockedExchangeAdd32 | 638 #undef InterlockedExchangeAdd32 |
| 582 #undef InterlockedAnd32 | 639 #undef InterlockedAnd32 |
| 583 #undef InterlockedOr32 | 640 #undef InterlockedOr32 |
| 584 #undef InterlockedXor32 | 641 #undef InterlockedXor32 |
| 585 #undef InterlockedExchangeAdd16 | 642 #undef InterlockedExchangeAdd16 |
| 586 #undef InterlockedCompareExchange8 | |
| 587 #undef InterlockedExchangeAdd8 | 643 #undef InterlockedExchangeAdd8 |
| 588 | 644 |
| 589 #else | 645 #else |
| 590 | 646 |
| 591 #error Unsupported platform! | 647 #error Unsupported platform! |
| 592 | 648 |
| 593 #endif | 649 #endif |
| 594 | 650 |
| 595 template <typename T> | 651 template <typename T> |
| 596 T FromObject(Handle<Object> number); | 652 T FromObject(Handle<Object> number); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 | 693 |
| 638 inline Object* ToObject(Isolate* isolate, int32_t t) { | 694 inline Object* ToObject(Isolate* isolate, int32_t t) { |
| 639 return *isolate->factory()->NewNumber(t); | 695 return *isolate->factory()->NewNumber(t); |
| 640 } | 696 } |
| 641 | 697 |
| 642 inline Object* ToObject(Isolate* isolate, uint32_t t) { | 698 inline Object* ToObject(Isolate* isolate, uint32_t t) { |
| 643 return *isolate->factory()->NewNumber(t); | 699 return *isolate->factory()->NewNumber(t); |
| 644 } | 700 } |
| 645 | 701 |
| 646 template <typename T> | 702 template <typename T> |
| 647 inline Object* DoCompareExchange(Isolate* isolate, void* buffer, size_t index, | |
| 648 Handle<Object> oldobj, Handle<Object> newobj) { | |
| 649 T oldval = FromObject<T>(oldobj); | |
| 650 T newval = FromObject<T>(newobj); | |
| 651 T result = | |
| 652 CompareExchangeSeqCst(static_cast<T*>(buffer) + index, oldval, newval); | |
| 653 return ToObject(isolate, result); | |
| 654 } | |
| 655 | |
| 656 template <typename T> | |
| 657 inline Object* DoAdd(Isolate* isolate, void* buffer, size_t index, | 703 inline Object* DoAdd(Isolate* isolate, void* buffer, size_t index, |
| 658 Handle<Object> obj) { | 704 Handle<Object> obj) { |
| 659 T value = FromObject<T>(obj); | 705 T value = FromObject<T>(obj); |
| 660 T result = AddSeqCst(static_cast<T*>(buffer) + index, value); | 706 T result = AddSeqCst(static_cast<T*>(buffer) + index, value); |
| 661 return ToObject(isolate, result); | 707 return ToObject(isolate, result); |
| 662 } | 708 } |
| 663 | 709 |
| 664 template <typename T> | 710 template <typename T> |
| 665 inline Object* DoSub(Isolate* isolate, void* buffer, size_t index, | 711 inline Object* DoSub(Isolate* isolate, void* buffer, size_t index, |
| 666 Handle<Object> obj) { | 712 Handle<Object> obj) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 // Duplicated from objects.h | 745 // Duplicated from objects.h |
| 700 // V has parameters (Type, type, TYPE, C type, element_size) | 746 // V has parameters (Type, type, TYPE, C type, element_size) |
| 701 #define INTEGER_TYPED_ARRAYS(V) \ | 747 #define INTEGER_TYPED_ARRAYS(V) \ |
| 702 V(Uint8, uint8, UINT8, uint8_t, 1) \ | 748 V(Uint8, uint8, UINT8, uint8_t, 1) \ |
| 703 V(Int8, int8, INT8, int8_t, 1) \ | 749 V(Int8, int8, INT8, int8_t, 1) \ |
| 704 V(Uint16, uint16, UINT16, uint16_t, 2) \ | 750 V(Uint16, uint16, UINT16, uint16_t, 2) \ |
| 705 V(Int16, int16, INT16, int16_t, 2) \ | 751 V(Int16, int16, INT16, int16_t, 2) \ |
| 706 V(Uint32, uint32, UINT32, uint32_t, 4) \ | 752 V(Uint32, uint32, UINT32, uint32_t, 4) \ |
| 707 V(Int32, int32, INT32, int32_t, 4) | 753 V(Int32, int32, INT32, int32_t, 4) |
| 708 | 754 |
| 709 // ES #sec-atomics.wait | |
| 710 // Atomics.compareExchange( typedArray, index, expectedValue, replacementValue ) | |
| 711 BUILTIN(AtomicsCompareExchange) { | |
| 712 HandleScope scope(isolate); | |
| 713 Handle<Object> array = args.atOrUndefined(isolate, 1); | |
| 714 Handle<Object> index = args.atOrUndefined(isolate, 2); | |
| 715 Handle<Object> expected_value = args.atOrUndefined(isolate, 3); | |
| 716 Handle<Object> replacement_value = args.atOrUndefined(isolate, 4); | |
| 717 | |
| 718 Handle<JSTypedArray> sta; | |
| 719 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 720 isolate, sta, ValidateSharedIntegerTypedArray(isolate, array)); | |
| 721 | |
| 722 Maybe<size_t> maybe_index = ValidateAtomicAccess(isolate, sta, index); | |
| 723 if (maybe_index.IsNothing()) return isolate->heap()->exception(); | |
| 724 size_t i = maybe_index.FromJust(); | |
| 725 | |
| 726 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 727 isolate, expected_value, Object::ToInteger(isolate, expected_value)); | |
| 728 | |
| 729 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 730 isolate, replacement_value, | |
| 731 Object::ToInteger(isolate, replacement_value)); | |
| 732 | |
| 733 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + | |
| 734 NumberToSize(sta->byte_offset()); | |
| 735 | |
| 736 switch (sta->type()) { | |
| 737 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ | |
| 738 case kExternal##Type##Array: \ | |
| 739 return DoCompareExchange<ctype>(isolate, source, i, expected_value, \ | |
| 740 replacement_value); | |
| 741 | |
| 742 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) | |
| 743 #undef TYPED_ARRAY_CASE | |
| 744 | |
| 745 default: | |
| 746 break; | |
| 747 } | |
| 748 | |
| 749 UNREACHABLE(); | |
| 750 return isolate->heap()->undefined_value(); | |
| 751 } | |
| 752 | |
| 753 // ES #sec-atomics.add | 755 // ES #sec-atomics.add |
| 754 // Atomics.add( typedArray, index, value ) | 756 // Atomics.add( typedArray, index, value ) |
| 755 BUILTIN(AtomicsAdd) { | 757 BUILTIN(AtomicsAdd) { |
| 756 HandleScope scope(isolate); | 758 HandleScope scope(isolate); |
| 757 Handle<Object> array = args.atOrUndefined(isolate, 1); | 759 Handle<Object> array = args.atOrUndefined(isolate, 1); |
| 758 Handle<Object> index = args.atOrUndefined(isolate, 2); | 760 Handle<Object> index = args.atOrUndefined(isolate, 2); |
| 759 Handle<Object> value = args.atOrUndefined(isolate, 3); | 761 Handle<Object> value = args.atOrUndefined(isolate, 3); |
| 760 | 762 |
| 761 Handle<JSTypedArray> sta; | 763 Handle<JSTypedArray> sta; |
| 762 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 764 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 984 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) | 986 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 985 #undef TYPED_ARRAY_CASE | 987 #undef TYPED_ARRAY_CASE |
| 986 | 988 |
| 987 default: | 989 default: |
| 988 break; | 990 break; |
| 989 } | 991 } |
| 990 | 992 |
| 991 UNREACHABLE(); | 993 UNREACHABLE(); |
| 992 return isolate->heap()->undefined_value(); | 994 return isolate->heap()->undefined_value(); |
| 993 } | 995 } |
| 996 |
| 997 template <typename T> |
| 998 inline T CompareExchangeSeqCst(T* p, T oldval, T newval) { |
| 999 (void)__atomic_compare_exchange_n(p, &oldval, newval, 0, __ATOMIC_SEQ_CST, |
| 1000 __ATOMIC_SEQ_CST); |
| 1001 return oldval; |
| 1002 } |
| 1003 |
| 1004 template <typename T> |
| 1005 inline Object* DoCompareExchange(Isolate* isolate, void* buffer, size_t index, |
| 1006 Handle<Object> oldobj, Handle<Object> newobj) { |
| 1007 T oldval = FromObject<T>(oldobj); |
| 1008 T newval = FromObject<T>(newobj); |
| 1009 T result = |
| 1010 CompareExchangeSeqCst(static_cast<T*>(buffer) + index, oldval, newval); |
| 1011 return ToObject(isolate, result); |
| 1012 } |
| 1013 |
| 1014 // ES #sec-atomics.wait |
| 1015 // Atomics.compareExchange( typedArray, index, expectedValue, replacementValue ) |
| 1016 BUILTIN(AtomicsCompareExchange) { |
| 1017 HandleScope scope(isolate); |
| 1018 Handle<Object> array = args.atOrUndefined(isolate, 1); |
| 1019 Handle<Object> index = args.atOrUndefined(isolate, 2); |
| 1020 Handle<Object> expected_value = args.atOrUndefined(isolate, 3); |
| 1021 Handle<Object> replacement_value = args.atOrUndefined(isolate, 4); |
| 1022 |
| 1023 Handle<JSTypedArray> sta; |
| 1024 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1025 isolate, sta, ValidateSharedIntegerTypedArray(isolate, array)); |
| 1026 |
| 1027 Maybe<size_t> maybe_index = ValidateAtomicAccess(isolate, sta, index); |
| 1028 if (maybe_index.IsNothing()) return isolate->heap()->exception(); |
| 1029 size_t i = maybe_index.FromJust(); |
| 1030 |
| 1031 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1032 isolate, expected_value, Object::ToInteger(isolate, expected_value)); |
| 1033 |
| 1034 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1035 isolate, replacement_value, |
| 1036 Object::ToInteger(isolate, replacement_value)); |
| 1037 |
| 1038 uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) + |
| 1039 NumberToSize(sta->byte_offset()); |
| 1040 |
| 1041 switch (sta->type()) { |
| 1042 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
| 1043 case kExternal##Type##Array: \ |
| 1044 return DoCompareExchange<ctype>(isolate, source, i, expected_value, \ |
| 1045 replacement_value); |
| 1046 |
| 1047 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 1048 #undef TYPED_ARRAY_CASE |
| 1049 |
| 1050 default: |
| 1051 break; |
| 1052 } |
| 1053 |
| 1054 UNREACHABLE(); |
| 1055 return isolate->heap()->undefined_value(); |
| 1056 } |
| 994 #endif | 1057 #endif |
| 995 | 1058 |
| 996 } // namespace internal | 1059 } // namespace internal |
| 997 } // namespace v8 | 1060 } // namespace v8 |
| OLD | NEW |