Bug 1225026 - Remove support for atomics on Uint8ClampedArray. r=nbp
authorLars T Hansen <lhansen@mozilla.com>
Wed, 02 Dec 2015 18:26:18 +0100
changeset 309574 b6eea9eddc4aeba17ec35572ce45a3a565f4ec2a
parent 309573 f1012f684bbc5d6595083229380f70fcab70f334
child 309575 b7dd3ffbf52b18e9d58c27abb7ed67c4a2208686
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1225026
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1225026 - Remove support for atomics on Uint8ClampedArray. r=nbp
js/src/builtin/AtomicsObject.cpp
js/src/jit-test/tests/atomics/basic-tests.js
js/src/jit/MCallOptimize.cpp
js/src/jit/MIR.h
js/src/jit/arm/CodeGenerator-arm.cpp
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm64/MacroAssembler-arm64.cpp
js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
js/src/jit/mips32/MacroAssembler-mips32.cpp
js/src/jit/mips64/MacroAssembler-mips64.cpp
js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
js/src/tests/js1_8_5/extensions/sharedtypedarray.js
--- a/js/src/builtin/AtomicsObject.cpp
+++ b/js/src/builtin/AtomicsObject.cpp
@@ -134,23 +134,16 @@ CompareExchange(Scalar::Type viewType, i
       }
       case Scalar::Uint8: {
         uint8_t oldval = (uint8_t)oldCandidate;
         uint8_t newval = (uint8_t)newCandidate;
         oldval = jit::AtomicOperations::compareExchangeSeqCst(viewData.cast<uint8_t*>() + offset,
                                                               oldval, newval);
         return oldval;
       }
-      case Scalar::Uint8Clamped: {
-        uint8_t oldval = ClampIntForUint8Array(oldCandidate);
-        uint8_t newval = ClampIntForUint8Array(newCandidate);
-        oldval = jit::AtomicOperations::compareExchangeSeqCst(viewData.cast<uint8_t*>() + offset,
-                                                              oldval, newval);
-        return oldval;
-      }
       case Scalar::Int16: {
         int16_t oldval = (int16_t)oldCandidate;
         int16_t newval = (int16_t)newCandidate;
         oldval = jit::AtomicOperations::compareExchangeSeqCst(viewData.cast<int16_t*>() + offset,
                                                               oldval, newval);
         return oldval;
       }
       case Scalar::Uint16: {
@@ -230,18 +223,17 @@ js::atomics_load(JSContext* cx, unsigned
     if (!GetSharedTypedArray(cx, objv, &view))
         return false;
     uint32_t offset;
     if (!GetTypedArrayIndex(cx, idxv, view, &offset))
         return false;
 
     SharedMem<void*> viewData = view->viewDataShared();
     switch (view->type()) {
-      case Scalar::Uint8:
-      case Scalar::Uint8Clamped: {
+      case Scalar::Uint8: {
         uint8_t v = jit::AtomicOperations::loadSeqCst(viewData.cast<uint8_t*>() + offset);
         r.setInt32(v);
         return true;
       }
       case Scalar::Int8: {
         int8_t v = jit::AtomicOperations::loadSeqCst(viewData.cast<uint8_t*>() + offset);
         r.setInt32(v);
         return true;
@@ -295,21 +287,16 @@ ExchangeOrStore(Scalar::Type viewType, i
         INT_OP(viewData.cast<int8_t*>() + offset, value);
         return value;
       }
       case Scalar::Uint8: {
         uint8_t value = (uint8_t)numberValue;
         INT_OP(viewData.cast<uint8_t*>() + offset, value);
         return value;
       }
-      case Scalar::Uint8Clamped: {
-        uint8_t value = ClampIntForUint8Array(numberValue);
-        INT_OP(viewData.cast<uint8_t*>() + offset, value);
-        return value;
-      }
       case Scalar::Int16: {
         int16_t value = (int16_t)numberValue;
         INT_OP(viewData.cast<int16_t*>() + offset, value);
         return value;
       }
       case Scalar::Uint16: {
         uint16_t value = (uint16_t)numberValue;
         INT_OP(viewData.cast<uint16_t*>() + offset, value);
@@ -401,36 +388,16 @@ AtomicsBinop(JSContext* cx, HandleValue 
         r.setInt32(T::operate(viewData.cast<int8_t*>() + offset, v));
         return true;
       }
       case Scalar::Uint8: {
         uint8_t v = (uint8_t)numberValue;
         r.setInt32(T::operate(viewData.cast<uint8_t*>() + offset, v));
         return true;
       }
-      case Scalar::Uint8Clamped: {
-        // Spec says:
-        //  - clamp the input value
-        //  - perform the operation
-        //  - clamp the result
-        //  - store the result
-        // This requires a CAS loop.
-        int32_t value = ClampIntForUint8Array(numberValue);
-        SharedMem<uint8_t*> loc = viewData.cast<uint8_t*>() + offset;
-        for (;;) {
-            uint8_t old = jit::AtomicOperations::loadSafeWhenRacy(loc);
-            uint8_t result = (uint8_t)ClampIntForUint8Array(T::perform(old, value));
-            uint8_t tmp = jit::AtomicOperations::compareExchangeSeqCst(loc, old, result);
-            if (tmp == old) {
-                r.setInt32(old);
-                break;
-            }
-        }
-        return true;
-      }
       case Scalar::Int16: {
         int16_t v = (int16_t)numberValue;
         r.setInt32(T::operate(viewData.cast<int16_t*>() + offset, v));
         return true;
       }
       case Scalar::Uint16: {
         uint16_t v = (uint16_t)numberValue;
         r.setInt32(T::operate(viewData.cast<uint16_t*>() + offset, v));
--- a/js/src/jit-test/tests/atomics/basic-tests.js
+++ b/js/src/jit-test/tests/atomics/basic-tests.js
@@ -404,16 +404,29 @@ function testIsLockFree() {
     assertEq(Atomics.isLockFree(7), false);
     assertEq(Atomics.isLockFree(8), saved8);
     assertEq(Atomics.isLockFree(9), false);
     assertEq(Atomics.isLockFree(10), false);
     assertEq(Atomics.isLockFree(11), false);
     assertEq(Atomics.isLockFree(12), false);
 }
 
+function testUint8Clamped(sab) {
+    var ta = new Uint8ClampedArray(sab);
+    var thrown = false;
+    try {
+	CLONE(testMethod)(ta, 0);
+    }
+    catch (e) {
+	thrown = true;
+	assertEq(e instanceof TypeError, true);
+    }
+    assertEq(thrown, true);
+}
+
 function isLittleEndian() {
     var xxx = new ArrayBuffer(2);
     var xxa = new Int16Array(xxx);
     var xxb = new Int8Array(xxx);
     xxa[0] = 37;
     var is_little = xxb[0] == 37;
     return is_little;
 }
@@ -435,17 +448,16 @@ function runTests() {
 	assertEq(t2[0], 37);
     else
 	assertEq(t2[0], 37 << 16);
     t1[0] = 0;
 
     // Test that invoking as Atomics.whatever() works, on correct arguments.
     CLONE(testMethod)(new Int8Array(sab), 0, 42, 4095);
     CLONE(testMethod)(new Uint8Array(sab), 0, 42, 4095);
-    CLONE(testMethod)(new Uint8ClampedArray(sab), 0, 42, 4095);
     CLONE(testMethod)(new Int16Array(sab), 0, 42, 2047);
     CLONE(testMethod)(new Uint16Array(sab), 0, 42, 2047);
     CLONE(testMethod)(new Int32Array(sab), 0, 42, 1023);
     CLONE(testMethod)(new Uint32Array(sab), 0, 42, 1023);
 
     // Test that invoking as v = Atomics.whatever; v() works, on correct arguments.
     gAtomics_compareExchange = Atomics.compareExchange;
     gAtomics_exchange = Atomics.exchange;
@@ -455,17 +467,16 @@ function runTests() {
     gAtomics_add = Atomics.add;
     gAtomics_sub = Atomics.sub;
     gAtomics_and = Atomics.and;
     gAtomics_or = Atomics.or;
     gAtomics_xor = Atomics.xor;
 
     CLONE(testFunction)(new Int8Array(sab), 0, 42, 4095);
     CLONE(testFunction)(new Uint8Array(sab), 0, 42, 4095);
-    CLONE(testFunction)(new Uint8ClampedArray(sab), 0, 42, 4095);
     CLONE(testFunction)(new Int16Array(sab), 0, 42, 2047);
     CLONE(testFunction)(new Uint16Array(sab), 0, 42, 2047);
     CLONE(testFunction)(new Int32Array(sab), 0, 42, 1023);
     CLONE(testFunction)(new Uint32Array(sab), 0, 42, 1023);
 
     // Test various range and type conditions
     var v8 = new Int8Array(sab);
     var v32 = new Int32Array(sab);
@@ -492,16 +503,19 @@ function runTests() {
     CLONE(testRangeCAS)(v32);
 
     // Test extreme values
     testInt8Extremes(new Int8Array(sab));
     testUint8Extremes(new Uint8Array(sab));
     testInt16Extremes(new Int16Array(sab));
     testUint32(new Uint32Array(sab));
 
+    // Test that Uint8ClampedArray is not accepted.
+    testUint8Clamped(sab);
+
     // Misc ad-hoc tests
     adHocExchange();
 
     // Misc
     testIsLockFree();
 }
 
 if (this.Atomics && this.SharedArrayBuffer)
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -2970,17 +2970,17 @@ IonBuilder::atomicsMeetsPreconditions(Ca
       case Scalar::Int32:
         return checkResult == DontCheckAtomicResult || getInlineReturnType() == MIRType_Int32;
       case Scalar::Uint32:
         // Bug 1077305: it would be attractive to allow inlining even
         // if the inline return type is Int32, which it will frequently
         // be.
         return checkResult == DontCheckAtomicResult || getInlineReturnType() == MIRType_Double;
       default:
-        // Excludes floating types and Uint8Clamped
+        // Excludes floating types and Uint8Clamped.
         return false;
     }
 }
 
 void
 IonBuilder::atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index)
 {
     // Perform bounds checking and extract the elements vector.
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -13190,18 +13190,17 @@ class MCompareExchangeTypedArrayElement
     static MCompareExchangeTypedArrayElement* New(TempAllocator& alloc, MDefinition* elements,
                                                   MDefinition* index, Scalar::Type arrayType,
                                                   MDefinition* oldval, MDefinition* newval)
     {
         return new(alloc) MCompareExchangeTypedArrayElement(elements, index, arrayType, oldval, newval);
     }
     bool isByteArray() const {
         return (arrayType_ == Scalar::Int8 ||
-                arrayType_ == Scalar::Uint8 ||
-                arrayType_ == Scalar::Uint8Clamped);
+                arrayType_ == Scalar::Uint8);
     }
     MDefinition* elements() {
         return getOperand(0);
     }
     MDefinition* index() {
         return getOperand(1);
     }
     MDefinition* oldval() {
@@ -13245,18 +13244,17 @@ class MAtomicExchangeTypedArrayElement
                                                  MDefinition* index, MDefinition* value,
                                                  Scalar::Type arrayType)
     {
         return new(alloc) MAtomicExchangeTypedArrayElement(elements, index, value, arrayType);
     }
 
     bool isByteArray() const {
         return (arrayType_ == Scalar::Int8 ||
-                arrayType_ == Scalar::Uint8 ||
-                arrayType_ == Scalar::Uint8Clamped);
+                arrayType_ == Scalar::Uint8);
     }
     MDefinition* elements() {
         return getOperand(0);
     }
     MDefinition* index() {
         return getOperand(1);
     }
     MDefinition* value() {
@@ -13297,18 +13295,17 @@ class MAtomicTypedArrayElementBinop
                                               MDefinition* elements, MDefinition* index,
                                               Scalar::Type arrayType, MDefinition* value)
     {
         return new(alloc) MAtomicTypedArrayElementBinop(op, elements, index, arrayType, value);
     }
 
     bool isByteArray() const {
         return (arrayType_ == Scalar::Int8 ||
-                arrayType_ == Scalar::Uint8 ||
-                arrayType_ == Scalar::Uint8Clamped);
+                arrayType_ == Scalar::Uint8);
     }
     AtomicOp operation() const {
         return op_;
     }
     Scalar::Type arrayType() const {
         return arrayType_;
     }
     MDefinition* elements() {
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -1737,17 +1737,16 @@ template<typename S, typename T>
 void
 CodeGeneratorARM::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType,
                                              const S& value, const T& mem, Register flagTemp,
                                              Register outTemp, AnyRegister output)
 {
     MOZ_ASSERT(flagTemp != InvalidReg);
     MOZ_ASSERT_IF(arrayType == Scalar::Uint32, outTemp != InvalidReg);
 
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicFetchAdd8SignExtend(value, mem, flagTemp, output.gpr());
             break;
           case AtomicFetchSubOp:
             masm.atomicFetchSub8SignExtend(value, mem, flagTemp, output.gpr());
@@ -1903,17 +1902,16 @@ CodeGeneratorARM::atomicBinopToTypedIntA
 // Binary operation for effect, result discarded.
 template<typename S, typename T>
 void
 CodeGeneratorARM::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S& value,
                                              const T& mem, Register flagTemp)
 {
     MOZ_ASSERT(flagTemp != InvalidReg);
 
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
       case Scalar::Uint8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicAdd8(value, mem, flagTemp);
             break;
           case AtomicFetchSubOp:
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -4823,19 +4823,16 @@ MacroAssemblerARMCompat::compareExchange
 {
     switch (arrayType) {
       case Scalar::Int8:
         compareExchange8SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint8:
         compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
-        break;
       case Scalar::Int16:
         compareExchange16SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint16:
         compareExchange16ZeroExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Int32:
         compareExchange32(mem, oldval, newval, output.gpr());
@@ -4868,19 +4865,16 @@ MacroAssemblerARMCompat::atomicExchangeT
 {
     switch (arrayType) {
       case Scalar::Int8:
         atomicExchange8SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint8:
         atomicExchange8ZeroExtend(mem, value, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        atomicExchange8ZeroExtend(mem, value, output.gpr());
-        break;
       case Scalar::Int16:
         atomicExchange16SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint16:
         atomicExchange16ZeroExtend(mem, value, output.gpr());
         break;
       case Scalar::Int32:
         atomicExchange32(mem, value, output.gpr());
--- a/js/src/jit/arm64/MacroAssembler-arm64.cpp
+++ b/js/src/jit/arm64/MacroAssembler-arm64.cpp
@@ -268,19 +268,16 @@ MacroAssemblerCompat::compareExchangeToT
 {
     switch (arrayType) {
       case Scalar::Int8:
         compareExchange8SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint8:
         compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
-        break;
       case Scalar::Int16:
         compareExchange16SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint16:
         compareExchange16ZeroExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Int32:
         compareExchange32(mem, oldval, newval, output.gpr());
@@ -313,19 +310,16 @@ MacroAssemblerCompat::atomicExchangeToTy
 {
     switch (arrayType) {
       case Scalar::Int8:
         atomicExchange8SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint8:
         atomicExchange8ZeroExtend(mem, value, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        atomicExchange8ZeroExtend(mem, value, output.gpr());
-        break;
       case Scalar::Int16:
         atomicExchange16SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint16:
         atomicExchange16ZeroExtend(mem, value, output.gpr());
         break;
       case Scalar::Int32:
         atomicExchange32(mem, value, output.gpr());
--- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
+++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
@@ -2037,17 +2037,16 @@ CodeGeneratorMIPSShared::atomicBinopToTy
                                                     const S& value, const T& mem, Register flagTemp,
                                                     Register outTemp, Register valueTemp,
                                                     Register offsetTemp, Register maskTemp,
                                                     AnyRegister output)
 {
     MOZ_ASSERT(flagTemp != InvalidReg);
     MOZ_ASSERT_IF(arrayType == Scalar::Uint32, outTemp != InvalidReg);
 
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicFetchAdd8SignExtend(value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output.gpr());
             break;
           case AtomicFetchSubOp:
             masm.atomicFetchSub8SignExtend(value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output.gpr());
@@ -2208,17 +2207,16 @@ CodeGeneratorMIPSShared::atomicBinopToTy
 template<typename S, typename T>
 void
 CodeGeneratorMIPSShared::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S& value,
                                                     const T& mem, Register flagTemp, Register valueTemp,
                                                     Register offsetTemp, Register maskTemp)
 {
     MOZ_ASSERT(flagTemp != InvalidReg);
 
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
       case Scalar::Uint8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicAdd8(value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
             break;
           case AtomicFetchSubOp:
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -2432,19 +2432,16 @@ MacroAssemblerMIPSCompat::compareExchang
 {
     switch (arrayType) {
       case Scalar::Int8:
         compareExchange8SignExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint8:
         compareExchange8ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        compareExchange8ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
-        break;
       case Scalar::Int16:
         compareExchange16SignExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint16:
         compareExchange16ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Int32:
         compareExchange32(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
@@ -2481,19 +2478,16 @@ MacroAssemblerMIPSCompat::atomicExchange
 {
     switch (arrayType) {
       case Scalar::Int8:
         atomicExchange8SignExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint8:
         atomicExchange8ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        atomicExchange8ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
-        break;
       case Scalar::Int16:
         atomicExchange16SignExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint16:
         atomicExchange16ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Int32:
         atomicExchange32(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -2535,19 +2535,16 @@ MacroAssemblerMIPS64Compat::compareExcha
 {
     switch (arrayType) {
       case Scalar::Int8:
         compareExchange8SignExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint8:
         compareExchange8ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        compareExchange8ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
-        break;
       case Scalar::Int16:
         compareExchange16SignExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint16:
         compareExchange16ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Int32:
         compareExchange32(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
@@ -2584,19 +2581,16 @@ MacroAssemblerMIPS64Compat::atomicExchan
 {
     switch (arrayType) {
       case Scalar::Int8:
         atomicExchange8SignExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint8:
         atomicExchange8ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        atomicExchange8ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
-        break;
       case Scalar::Int16:
         atomicExchange16SignExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint16:
         atomicExchange16ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Int32:
         atomicExchange32(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
--- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
@@ -3361,17 +3361,16 @@ CodeGeneratorX86Shared::visitAtomicExcha
     }
 }
 
 template<typename S, typename T>
 void
 CodeGeneratorX86Shared::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S& value,
                                                    const T& mem, Register temp1, Register temp2, AnyRegister output)
 {
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicFetchAdd8SignExtend(value, mem, temp1, output.gpr());
             break;
           case AtomicFetchSubOp:
             masm.atomicFetchSub8SignExtend(value, mem, temp1, output.gpr());
@@ -3521,17 +3520,16 @@ CodeGeneratorX86Shared::atomicBinopToTyp
                                                     Register temp1, Register temp2, AnyRegister output);
 
 // Binary operation for effect, result discarded.
 template<typename S, typename T>
 void
 CodeGeneratorX86Shared::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S& value,
                                                     const T& mem)
 {
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
       case Scalar::Uint8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicAdd8(value, mem);
             break;
           case AtomicFetchSubOp:
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
@@ -151,19 +151,16 @@ MacroAssemblerX86Shared::compareExchange
 {
     switch (arrayType) {
       case Scalar::Int8:
         compareExchange8SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint8:
         compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
-        break;
       case Scalar::Int16:
         compareExchange16SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint16:
         compareExchange16ZeroExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Int32:
         compareExchange32(mem, oldval, newval, output.gpr());
@@ -196,19 +193,16 @@ MacroAssemblerX86Shared::atomicExchangeT
 {
     switch (arrayType) {
       case Scalar::Int8:
         atomicExchange8SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint8:
         atomicExchange8ZeroExtend(mem, value, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        atomicExchange8ZeroExtend(mem, value, output.gpr());
-        break;
       case Scalar::Int16:
         atomicExchange16SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint16:
         atomicExchange16ZeroExtend(mem, value, output.gpr());
         break;
       case Scalar::Int32:
         atomicExchange32(mem, value, output.gpr());
--- a/js/src/tests/js1_8_5/extensions/sharedtypedarray.js
+++ b/js/src/tests/js1_8_5/extensions/sharedtypedarray.js
@@ -186,15 +186,49 @@ function testClone2() {
     var ia2 = deserialize(blob);
     assertEq(ia1.length, ia2.length);
     assertEq(ia1.buffer instanceof SharedArrayBuffer, true);
     assertEq(sharedAddress(ia1.buffer), sharedAddress(ia2.buffer));
     ia1[10] = 37;
     assertEq(ia2[10], 37);
 }
 
+function testApplicable() {
+    var sab = b;
+    var x;
+
+    // Just make sure we can create all the view types on shared memory.
+
+    x = new Int32Array(sab);
+    assertEq(x.length, sab.byteLength / Int32Array.BYTES_PER_ELEMENT);
+    x = new Uint32Array(sab);
+    assertEq(x.length, sab.byteLength / Uint32Array.BYTES_PER_ELEMENT);
+
+    x = new Int16Array(sab);
+    assertEq(x.length, sab.byteLength / Int16Array.BYTES_PER_ELEMENT);
+    x = new Uint16Array(sab);
+    assertEq(x.length, sab.byteLength / Uint16Array.BYTES_PER_ELEMENT);
+
+    x = new Int8Array(sab);
+    assertEq(x.length, sab.byteLength / Int8Array.BYTES_PER_ELEMENT);
+    x = new Uint8Array(sab);
+    assertEq(x.length, sab.byteLength / Uint8Array.BYTES_PER_ELEMENT);
+
+    // Though the atomic operations are illegal on Uint8ClampedArray and the
+    // float arrays, they can still be used to create views on shared memory.
+
+    x = new Uint8ClampedArray(sab);
+    assertEq(x.length, sab.byteLength / Uint8ClampedArray.BYTES_PER_ELEMENT);
+
+    x = new Float32Array(sab);
+    assertEq(x.length, sab.byteLength / Float32Array.BYTES_PER_ELEMENT);
+    x = new Float64Array(sab);
+    assertEq(x.length, sab.byteLength / Float64Array.BYTES_PER_ELEMENT);
+}
+
 testSharedArrayBuffer();
 testSharedTypedArray();
 testSharedTypedArrayMethods();
 testClone1();
 testClone2();
+testApplicable();
 
 reportCompare(0, 0, 'ok');