OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // 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 | 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/base/macros.h" | 8 #include "src/base/macros.h" |
9 #include "src/base/platform/mutex.h" | 9 #include "src/base/platform/mutex.h" |
10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
417 inline Object* DoExchange(Isolate* isolate, void* buffer, size_t index, | 417 inline Object* DoExchange(Isolate* isolate, void* buffer, size_t index, |
418 Handle<Object> obj) { | 418 Handle<Object> obj) { |
419 typedef typename FromObjectTraits<T>::atomic_type atomic_type; | 419 typedef typename FromObjectTraits<T>::atomic_type atomic_type; |
420 typedef typename FromObjectTraits<T>::convert_type convert_type; | 420 typedef typename FromObjectTraits<T>::convert_type convert_type; |
421 atomic_type value = ToAtomic<atomic_type>(FromObject<convert_type>(obj)); | 421 atomic_type value = ToAtomic<atomic_type>(FromObject<convert_type>(obj)); |
422 atomic_type result = | 422 atomic_type result = |
423 ExchangeSeqCst(static_cast<atomic_type*>(buffer) + index, value); | 423 ExchangeSeqCst(static_cast<atomic_type*>(buffer) + index, value); |
424 return ToObject<T>(isolate, FromAtomic<T>(result)); | 424 return ToObject<T>(isolate, FromAtomic<T>(result)); |
425 } | 425 } |
426 | 426 |
427 | |
428 // Uint8Clamped functions | |
429 | |
430 uint8_t ClampToUint8(int32_t value) { | |
431 if (value < 0) return 0; | |
432 if (value > 255) return 255; | |
433 return value; | |
Jarin
2015/06/22 07:04:03
Hmm, I am really surprised this does not need any
binji
2015/06/22 18:21:04
I didn't notice it until you mentioned it. I check
| |
434 } | |
435 | |
436 | |
437 inline Object* DoCompareExchangeUint8Clamped(Isolate* isolate, void* buffer, | |
438 size_t index, | |
439 Handle<Object> oldobj, | |
440 Handle<Object> newobj) { | |
441 typedef int32_t convert_type; | |
442 typedef uint8_t atomic_type; | |
443 atomic_type oldval = ClampToUint8(FromObject<convert_type>(oldobj)); | |
444 atomic_type newval = ClampToUint8(FromObject<convert_type>(newobj)); | |
445 atomic_type result = CompareExchangeSeqCst( | |
446 static_cast<atomic_type*>(buffer) + index, oldval, newval); | |
447 return ToObject<uint8_t>(isolate, FromAtomic<uint8_t>(result)); | |
448 } | |
449 | |
450 | |
451 inline Object* DoStoreUint8Clamped(Isolate* isolate, void* buffer, size_t index, | |
452 Handle<Object> obj) { | |
453 typedef int32_t convert_type; | |
454 typedef uint8_t atomic_type; | |
455 atomic_type value = ClampToUint8(FromObject<convert_type>(obj)); | |
456 StoreSeqCst(static_cast<atomic_type*>(buffer) + index, value); | |
457 return *obj; | |
458 } | |
459 | |
460 | |
461 #define DO_UINT8_CLAMPED_OP(name, op) \ | |
462 inline Object* Do##name##Uint8Clamped(Isolate* isolate, void* buffer, \ | |
463 size_t index, Handle<Object> obj) { \ | |
464 typedef int32_t convert_type; \ | |
465 typedef uint8_t atomic_type; \ | |
466 atomic_type* p = static_cast<atomic_type*>(buffer) + index; \ | |
467 convert_type operand = FromObject<convert_type>(obj); \ | |
468 atomic_type expected; \ | |
469 atomic_type result; \ | |
470 do { \ | |
471 expected = *p; \ | |
472 result = ClampToUint8(static_cast<convert_type>(expected) op operand); \ | |
473 } while (CompareExchangeSeqCst(p, expected, result) != expected); \ | |
474 return ToObject<uint8_t>(isolate, expected); \ | |
475 } | |
476 | |
477 DO_UINT8_CLAMPED_OP(Add, +) | |
478 DO_UINT8_CLAMPED_OP(Sub, -) | |
479 DO_UINT8_CLAMPED_OP(And, &) | |
480 DO_UINT8_CLAMPED_OP(Or, | ) | |
481 DO_UINT8_CLAMPED_OP(Xor, ^) | |
482 | |
483 #undef DO_UINT8_CLAMPED_OP | |
484 | |
485 | |
486 inline Object* DoExchangeUint8Clamped(Isolate* isolate, void* buffer, | |
487 size_t index, Handle<Object> obj) { | |
488 typedef int32_t convert_type; | |
489 typedef uint8_t atomic_type; | |
490 atomic_type* p = static_cast<atomic_type*>(buffer) + index; | |
491 atomic_type result = ClampToUint8(FromObject<convert_type>(obj)); | |
492 atomic_type expected; | |
493 do { | |
494 expected = *p; | |
495 } while (CompareExchangeSeqCst(p, expected, result) != expected); | |
496 return ToObject<uint8_t>(isolate, expected); | |
497 } | |
498 | |
499 | |
427 } // anonymous namespace | 500 } // anonymous namespace |
428 | 501 |
429 // Duplicated from objects.h | 502 // Duplicated from objects.h |
430 // V has parameters (Type, type, TYPE, C type, element_size) | 503 // V has parameters (Type, type, TYPE, C type, element_size) |
431 #define INTEGER_TYPED_ARRAYS(V) \ | 504 #define INTEGER_TYPED_ARRAYS(V) \ |
432 V(Uint8, uint8, UINT8, uint8_t, 1) \ | 505 V(Uint8, uint8, UINT8, uint8_t, 1) \ |
433 V(Int8, int8, INT8, int8_t, 1) \ | 506 V(Int8, int8, INT8, int8_t, 1) \ |
434 V(Uint16, uint16, UINT16, uint16_t, 2) \ | 507 V(Uint16, uint16, UINT16, uint16_t, 2) \ |
435 V(Int16, int16, INT16, int16_t, 2) \ | 508 V(Int16, int16, INT16, int16_t, 2) \ |
436 V(Uint32, uint32, UINT32, uint32_t, 4) \ | 509 V(Uint32, uint32, UINT32, uint32_t, 4) \ |
437 V(Int32, int32, INT32, int32_t, 4) \ | 510 V(Int32, int32, INT32, int32_t, 4) |
438 V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t, 1) | |
439 | 511 |
440 | 512 |
441 RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) { | 513 RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) { |
442 HandleScope scope(isolate); | 514 HandleScope scope(isolate); |
443 DCHECK(args.length() == 4); | 515 DCHECK(args.length() == 4); |
444 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); | 516 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |
445 CONVERT_SIZE_ARG_CHECKED(index, 1); | 517 CONVERT_SIZE_ARG_CHECKED(index, 1); |
446 CONVERT_NUMBER_ARG_HANDLE_CHECKED(oldobj, 2); | 518 CONVERT_NUMBER_ARG_HANDLE_CHECKED(oldobj, 2); |
447 CONVERT_NUMBER_ARG_HANDLE_CHECKED(newobj, 3); | 519 CONVERT_NUMBER_ARG_HANDLE_CHECKED(newobj, 3); |
448 RUNTIME_ASSERT(sta->GetBuffer()->is_shared()); | 520 RUNTIME_ASSERT(sta->GetBuffer()->is_shared()); |
449 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length())); | 521 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length())); |
450 | 522 |
451 void* buffer = sta->GetBuffer()->backing_store(); | 523 void* buffer = sta->GetBuffer()->backing_store(); |
452 | 524 |
453 switch (sta->type()) { | 525 switch (sta->type()) { |
454 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ | 526 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
455 case kExternal##Type##Array: \ | 527 case kExternal##Type##Array: \ |
456 return DoCompareExchange<ctype>(isolate, buffer, index, oldobj, newobj); | 528 return DoCompareExchange<ctype>(isolate, buffer, index, oldobj, newobj); |
457 | 529 |
458 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 530 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
459 #undef TYPED_ARRAY_CASE | 531 #undef TYPED_ARRAY_CASE |
460 | 532 |
533 case kExternalFloat32Array: | |
534 return DoCompareExchange<float>(isolate, buffer, index, oldobj, newobj); | |
535 | |
536 case kExternalFloat64Array: | |
537 return DoCompareExchange<double>(isolate, buffer, index, oldobj, newobj); | |
538 | |
539 case kExternalUint8ClampedArray: | |
540 return DoCompareExchangeUint8Clamped(isolate, buffer, index, oldobj, | |
541 newobj); | |
542 | |
461 default: | 543 default: |
462 break; | 544 break; |
463 } | 545 } |
464 | 546 |
465 UNREACHABLE(); | 547 UNREACHABLE(); |
466 return isolate->heap()->undefined_value(); | 548 return isolate->heap()->undefined_value(); |
467 } | 549 } |
468 | 550 |
469 | 551 |
470 RUNTIME_FUNCTION(Runtime_AtomicsLoad) { | 552 RUNTIME_FUNCTION(Runtime_AtomicsLoad) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
503 RUNTIME_ASSERT(sta->GetBuffer()->is_shared()); | 585 RUNTIME_ASSERT(sta->GetBuffer()->is_shared()); |
504 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length())); | 586 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length())); |
505 | 587 |
506 void* buffer = sta->GetBuffer()->backing_store(); | 588 void* buffer = sta->GetBuffer()->backing_store(); |
507 | 589 |
508 switch (sta->type()) { | 590 switch (sta->type()) { |
509 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ | 591 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
510 case kExternal##Type##Array: \ | 592 case kExternal##Type##Array: \ |
511 return DoStore<ctype>(isolate, buffer, index, value); | 593 return DoStore<ctype>(isolate, buffer, index, value); |
512 | 594 |
513 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 595 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
514 #undef TYPED_ARRAY_CASE | 596 #undef TYPED_ARRAY_CASE |
515 | 597 |
598 case kExternalFloat32Array: | |
599 return DoStore<float>(isolate, buffer, index, value); | |
600 | |
601 case kExternalFloat64Array: | |
602 return DoStore<double>(isolate, buffer, index, value); | |
603 | |
604 case kExternalUint8ClampedArray: | |
605 return DoStoreUint8Clamped(isolate, buffer, index, value); | |
606 | |
516 default: | 607 default: |
517 break; | 608 break; |
518 } | 609 } |
519 | 610 |
520 UNREACHABLE(); | 611 UNREACHABLE(); |
521 return isolate->heap()->undefined_value(); | 612 return isolate->heap()->undefined_value(); |
522 } | 613 } |
523 | 614 |
524 | 615 |
525 RUNTIME_FUNCTION(Runtime_AtomicsAdd) { | 616 RUNTIME_FUNCTION(Runtime_AtomicsAdd) { |
526 HandleScope scope(isolate); | 617 HandleScope scope(isolate); |
527 DCHECK(args.length() == 3); | 618 DCHECK(args.length() == 3); |
528 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); | 619 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); |
529 CONVERT_SIZE_ARG_CHECKED(index, 1); | 620 CONVERT_SIZE_ARG_CHECKED(index, 1); |
530 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); | 621 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); |
531 RUNTIME_ASSERT(sta->GetBuffer()->is_shared()); | 622 RUNTIME_ASSERT(sta->GetBuffer()->is_shared()); |
532 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length())); | 623 RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length())); |
533 | 624 |
534 void* buffer = sta->GetBuffer()->backing_store(); | 625 void* buffer = sta->GetBuffer()->backing_store(); |
535 | 626 |
536 switch (sta->type()) { | 627 switch (sta->type()) { |
537 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ | 628 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
538 case kExternal##Type##Array: \ | 629 case kExternal##Type##Array: \ |
539 return DoAdd<ctype>(isolate, buffer, index, value); | 630 return DoAdd<ctype>(isolate, buffer, index, value); |
540 | 631 |
541 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) | 632 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
542 #undef TYPED_ARRAY_CASE | 633 #undef TYPED_ARRAY_CASE |
543 | 634 |
635 case kExternalUint8ClampedArray: | |
636 return DoAddUint8Clamped(isolate, buffer, index, value); | |
637 | |
544 case kExternalFloat32Array: | 638 case kExternalFloat32Array: |
545 case kExternalFloat64Array: | 639 case kExternalFloat64Array: |
546 default: | 640 default: |
547 break; | 641 break; |
548 } | 642 } |
549 | 643 |
550 UNREACHABLE(); | 644 UNREACHABLE(); |
551 return isolate->heap()->undefined_value(); | 645 return isolate->heap()->undefined_value(); |
552 } | 646 } |
553 | 647 |
(...skipping 10 matching lines...) Expand all Loading... | |
564 void* buffer = sta->GetBuffer()->backing_store(); | 658 void* buffer = sta->GetBuffer()->backing_store(); |
565 | 659 |
566 switch (sta->type()) { | 660 switch (sta->type()) { |
567 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ | 661 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
568 case kExternal##Type##Array: \ | 662 case kExternal##Type##Array: \ |
569 return DoSub<ctype>(isolate, buffer, index, value); | 663 return DoSub<ctype>(isolate, buffer, index, value); |
570 | 664 |
571 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) | 665 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
572 #undef TYPED_ARRAY_CASE | 666 #undef TYPED_ARRAY_CASE |
573 | 667 |
668 case kExternalUint8ClampedArray: | |
669 return DoSubUint8Clamped(isolate, buffer, index, value); | |
670 | |
574 case kExternalFloat32Array: | 671 case kExternalFloat32Array: |
575 case kExternalFloat64Array: | 672 case kExternalFloat64Array: |
576 default: | 673 default: |
577 break; | 674 break; |
578 } | 675 } |
579 | 676 |
580 UNREACHABLE(); | 677 UNREACHABLE(); |
581 return isolate->heap()->undefined_value(); | 678 return isolate->heap()->undefined_value(); |
582 } | 679 } |
583 | 680 |
(...skipping 10 matching lines...) Expand all Loading... | |
594 void* buffer = sta->GetBuffer()->backing_store(); | 691 void* buffer = sta->GetBuffer()->backing_store(); |
595 | 692 |
596 switch (sta->type()) { | 693 switch (sta->type()) { |
597 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ | 694 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
598 case kExternal##Type##Array: \ | 695 case kExternal##Type##Array: \ |
599 return DoAnd<ctype>(isolate, buffer, index, value); | 696 return DoAnd<ctype>(isolate, buffer, index, value); |
600 | 697 |
601 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) | 698 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
602 #undef TYPED_ARRAY_CASE | 699 #undef TYPED_ARRAY_CASE |
603 | 700 |
701 case kExternalUint8ClampedArray: | |
702 return DoAndUint8Clamped(isolate, buffer, index, value); | |
703 | |
604 case kExternalFloat32Array: | 704 case kExternalFloat32Array: |
605 case kExternalFloat64Array: | 705 case kExternalFloat64Array: |
606 default: | 706 default: |
607 break; | 707 break; |
608 } | 708 } |
609 | 709 |
610 UNREACHABLE(); | 710 UNREACHABLE(); |
611 return isolate->heap()->undefined_value(); | 711 return isolate->heap()->undefined_value(); |
612 } | 712 } |
613 | 713 |
(...skipping 10 matching lines...) Expand all Loading... | |
624 void* buffer = sta->GetBuffer()->backing_store(); | 724 void* buffer = sta->GetBuffer()->backing_store(); |
625 | 725 |
626 switch (sta->type()) { | 726 switch (sta->type()) { |
627 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ | 727 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
628 case kExternal##Type##Array: \ | 728 case kExternal##Type##Array: \ |
629 return DoOr<ctype>(isolate, buffer, index, value); | 729 return DoOr<ctype>(isolate, buffer, index, value); |
630 | 730 |
631 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) | 731 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
632 #undef TYPED_ARRAY_CASE | 732 #undef TYPED_ARRAY_CASE |
633 | 733 |
734 case kExternalUint8ClampedArray: | |
735 return DoOrUint8Clamped(isolate, buffer, index, value); | |
736 | |
634 case kExternalFloat32Array: | 737 case kExternalFloat32Array: |
635 case kExternalFloat64Array: | 738 case kExternalFloat64Array: |
636 default: | 739 default: |
637 break; | 740 break; |
638 } | 741 } |
639 | 742 |
640 UNREACHABLE(); | 743 UNREACHABLE(); |
641 return isolate->heap()->undefined_value(); | 744 return isolate->heap()->undefined_value(); |
642 } | 745 } |
643 | 746 |
(...skipping 10 matching lines...) Expand all Loading... | |
654 void* buffer = sta->GetBuffer()->backing_store(); | 757 void* buffer = sta->GetBuffer()->backing_store(); |
655 | 758 |
656 switch (sta->type()) { | 759 switch (sta->type()) { |
657 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ | 760 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
658 case kExternal##Type##Array: \ | 761 case kExternal##Type##Array: \ |
659 return DoXor<ctype>(isolate, buffer, index, value); | 762 return DoXor<ctype>(isolate, buffer, index, value); |
660 | 763 |
661 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) | 764 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
662 #undef TYPED_ARRAY_CASE | 765 #undef TYPED_ARRAY_CASE |
663 | 766 |
767 case kExternalUint8ClampedArray: | |
768 return DoXorUint8Clamped(isolate, buffer, index, value); | |
769 | |
664 case kExternalFloat32Array: | 770 case kExternalFloat32Array: |
665 case kExternalFloat64Array: | 771 case kExternalFloat64Array: |
666 default: | 772 default: |
667 break; | 773 break; |
668 } | 774 } |
669 | 775 |
670 UNREACHABLE(); | 776 UNREACHABLE(); |
671 return isolate->heap()->undefined_value(); | 777 return isolate->heap()->undefined_value(); |
672 } | 778 } |
673 | 779 |
(...skipping 10 matching lines...) Expand all Loading... | |
684 void* buffer = sta->GetBuffer()->backing_store(); | 790 void* buffer = sta->GetBuffer()->backing_store(); |
685 | 791 |
686 switch (sta->type()) { | 792 switch (sta->type()) { |
687 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ | 793 #define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \ |
688 case kExternal##Type##Array: \ | 794 case kExternal##Type##Array: \ |
689 return DoExchange<ctype>(isolate, buffer, index, value); | 795 return DoExchange<ctype>(isolate, buffer, index, value); |
690 | 796 |
691 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) | 797 INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE) |
692 #undef TYPED_ARRAY_CASE | 798 #undef TYPED_ARRAY_CASE |
693 | 799 |
800 case kExternalUint8ClampedArray: | |
801 return DoExchangeUint8Clamped(isolate, buffer, index, value); | |
802 | |
694 case kExternalFloat32Array: | 803 case kExternalFloat32Array: |
695 case kExternalFloat64Array: | 804 case kExternalFloat64Array: |
696 default: | 805 default: |
697 break; | 806 break; |
698 } | 807 } |
699 | 808 |
700 UNREACHABLE(); | 809 UNREACHABLE(); |
701 return isolate->heap()->undefined_value(); | 810 return isolate->heap()->undefined_value(); |
702 } | 811 } |
703 | 812 |
704 | 813 |
705 RUNTIME_FUNCTION(Runtime_AtomicsIsLockFree) { | 814 RUNTIME_FUNCTION(Runtime_AtomicsIsLockFree) { |
706 HandleScope scope(isolate); | 815 HandleScope scope(isolate); |
707 DCHECK(args.length() == 1); | 816 DCHECK(args.length() == 1); |
708 CONVERT_NUMBER_ARG_HANDLE_CHECKED(size, 0); | 817 CONVERT_NUMBER_ARG_HANDLE_CHECKED(size, 0); |
709 uint32_t usize = NumberToUint32(*size); | 818 uint32_t usize = NumberToUint32(*size); |
710 | 819 |
711 return Runtime::AtomicIsLockFree(usize) ? isolate->heap()->true_value() | 820 return Runtime::AtomicIsLockFree(usize) ? isolate->heap()->true_value() |
712 : isolate->heap()->false_value(); | 821 : isolate->heap()->false_value(); |
713 } | 822 } |
714 } | 823 } |
715 } // namespace v8::internal | 824 } // namespace v8::internal |
OLD | NEW |