Commit 1fb752ad authored by fpizlo@apple.com's avatar fpizlo@apple.com

FloatTypedArrayAdaptor::toJSValue should almost certainly not use jsNumber()...

FloatTypedArrayAdaptor::toJSValue should almost certainly not use jsNumber() since that attempts int conversions
https://bugs.webkit.org/show_bug.cgi?id=120228

Source/JavaScriptCore: 

Reviewed by Oliver Hunt.
        
It turns out that there were three problems:
        
- Using jsNumber() meant that we were converting doubles to integers and then
  possibly back again whenever doing a set() between floating point arrays.
        
- Slow-path accesses to double typed arrays were slower than necessary because
  of the to-int conversion attempt.
        
- The use of JSValue as an intermediate for converting between differen types
  in typedArray.set() resulted in worse code than I had previously expected.
        
This patch solves the problem by using template double-dispatch to ensure that
that C++ compiler sees the simplest possible combination of casts between any
combination of typed array types, while still preserving JS and typed array
conversion semantics. Conversions are done as follows:
        
    SourceAdaptor::convertTo<TargetAdaptor>(value)
        
Internally, convertTo() calls one of three possible methods on TargetAdaptor,
with one method for each of int32_t, uint32_t, and double. This means that the
C++ compiler will at worst see a widening cast to one of those types followed
by a narrowing conversion (not necessarily a cast - may have clamping or the
JS toInt32() function).
        
This change doesn't just affect typedArray.set(); it also affects slow-path
accesses to typed arrays as well. This patch also adds a bunch of new test
coverage.
        
This change is a ~50% speed-up on typedArray.set() involving floating point
types.

* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* runtime/GenericTypedArrayView.h:
(JSC::GenericTypedArrayView::set):
* runtime/JSDataViewPrototype.cpp:
(JSC::setData):
* runtime/JSGenericTypedArrayView.h:
(JSC::JSGenericTypedArrayView::setIndexQuicklyToDouble):
(JSC::JSGenericTypedArrayView::setIndexQuickly):
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::::setWithSpecificType):
(JSC::::set):
* runtime/ToNativeFromValue.h: Added.
(JSC::toNativeFromValue):
* runtime/TypedArrayAdaptors.h:
(JSC::IntegralTypedArrayAdaptor::toJSValue):
(JSC::IntegralTypedArrayAdaptor::toDouble):
(JSC::IntegralTypedArrayAdaptor::toNativeFromInt32):
(JSC::IntegralTypedArrayAdaptor::toNativeFromUint32):
(JSC::IntegralTypedArrayAdaptor::toNativeFromDouble):
(JSC::IntegralTypedArrayAdaptor::convertTo):
(JSC::FloatTypedArrayAdaptor::toJSValue):
(JSC::FloatTypedArrayAdaptor::toDouble):
(JSC::FloatTypedArrayAdaptor::toNativeFromInt32):
(JSC::FloatTypedArrayAdaptor::toNativeFromUint32):
(JSC::FloatTypedArrayAdaptor::toNativeFromDouble):
(JSC::FloatTypedArrayAdaptor::convertTo):
(JSC::Uint8ClampedAdaptor::toJSValue):
(JSC::Uint8ClampedAdaptor::toDouble):
(JSC::Uint8ClampedAdaptor::toNativeFromInt32):
(JSC::Uint8ClampedAdaptor::toNativeFromUint32):
(JSC::Uint8ClampedAdaptor::toNativeFromDouble):
(JSC::Uint8ClampedAdaptor::convertTo):

LayoutTests: 

Reviewed by Oliver Hunt.
        
Add coverage for three things:
        
- Typed array accesses with corner-case values.
        
- Typed array set() (i.e. copy) between arrays of different types.
        
- Performance of typedArray.set() involving different types.
        
This required some changes to our test harnesses, since they previously
couldn't consistently do numerical array comparisons in a reliable way.

* fast/js/regress/Float32Array-to-Float64Array-set-expected.txt: Added.
* fast/js/regress/Float32Array-to-Float64Array-set.html: Added.
* fast/js/regress/Float64Array-to-Int16Array-set-expected.txt: Added.
* fast/js/regress/Float64Array-to-Int16Array-set.html: Added.
* fast/js/regress/Int16Array-to-Int32Array-set-expected.txt: Added.
* fast/js/regress/Int16Array-to-Int32Array-set.html: Added.
* fast/js/regress/script-tests/Float32Array-to-Float64Array-set.js: Added.
* fast/js/regress/script-tests/Float64Array-to-Int16Array-set.js: Added.
* fast/js/regress/script-tests/Int16Array-to-Int32Array-set.js: Added.
* fast/js/resources/js-test-pre.js:
(areNumbersEqual):
(areArraysEqual):
(isResultCorrect):
* fast/js/resources/standalone-pre.js:
(areNumbersEqual):
(areArraysEqual):
(isTypedArray):
(isResultCorrect):
(stringify):
(shouldBe):
* fast/js/script-tests/typed-array-access.js: Added.
(bitsToString):
(bitsToValue):
(valueToBits):
(roundTrip):
* fast/js/script-tests/typed-array-set-different-types.js: Added.
(MyRandom):
(.reference):
(.usingConstruct):
* fast/js/typed-array-access-expected.txt: Added.
* fast/js/typed-array-access.html: Added.
* fast/js/typed-array-set-different-types-expected.txt: Added.
* fast/js/typed-array-set-different-types.html: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@154569 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 57ac83d3
2013-08-24 Filip Pizlo <fpizlo@apple.com>
FloatTypedArrayAdaptor::toJSValue should almost certainly not use jsNumber() since that attempts int conversions
https://bugs.webkit.org/show_bug.cgi?id=120228
Reviewed by Oliver Hunt.
Add coverage for three things:
- Typed array accesses with corner-case values.
- Typed array set() (i.e. copy) between arrays of different types.
- Performance of typedArray.set() involving different types.
This required some changes to our test harnesses, since they previously
couldn't consistently do numerical array comparisons in a reliable way.
* fast/js/regress/Float32Array-to-Float64Array-set-expected.txt: Added.
* fast/js/regress/Float32Array-to-Float64Array-set.html: Added.
* fast/js/regress/Float64Array-to-Int16Array-set-expected.txt: Added.
* fast/js/regress/Float64Array-to-Int16Array-set.html: Added.
* fast/js/regress/Int16Array-to-Int32Array-set-expected.txt: Added.
* fast/js/regress/Int16Array-to-Int32Array-set.html: Added.
* fast/js/regress/script-tests/Float32Array-to-Float64Array-set.js: Added.
* fast/js/regress/script-tests/Float64Array-to-Int16Array-set.js: Added.
* fast/js/regress/script-tests/Int16Array-to-Int32Array-set.js: Added.
* fast/js/resources/js-test-pre.js:
(areNumbersEqual):
(areArraysEqual):
(isResultCorrect):
* fast/js/resources/standalone-pre.js:
(areNumbersEqual):
(areArraysEqual):
(isTypedArray):
(isResultCorrect):
(stringify):
(shouldBe):
* fast/js/script-tests/typed-array-access.js: Added.
(bitsToString):
(bitsToValue):
(valueToBits):
(roundTrip):
* fast/js/script-tests/typed-array-set-different-types.js: Added.
(MyRandom):
(.reference):
(.usingConstruct):
* fast/js/typed-array-access-expected.txt: Added.
* fast/js/typed-array-access.html: Added.
* fast/js/typed-array-set-different-types-expected.txt: Added.
* fast/js/typed-array-set-different-types.html: Added.
2013-08-25 Ryuan Choi <ryuan.choi@samsung.com>
Unreviewed EFL gardening.
JSRegress/Float32Array-to-Float64Array-set
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS no exception thrown
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/js-test-pre.js"></script>
</head>
<body>
<script src="resources/regress-pre.js"></script>
<script src="script-tests/Float32Array-to-Float64Array-set.js"></script>
<script src="resources/regress-post.js"></script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
JSRegress/Float64Array-to-Int16Array-set
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS no exception thrown
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/js-test-pre.js"></script>
</head>
<body>
<script src="resources/regress-pre.js"></script>
<script src="script-tests/Float64Array-to-Int16Array-set.js"></script>
<script src="resources/regress-post.js"></script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
JSRegress/Int16Array-to-Int32Array-set
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS no exception thrown
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/js-test-pre.js"></script>
</head>
<body>
<script src="resources/regress-pre.js"></script>
<script src="script-tests/Int16Array-to-Int32Array-set.js"></script>
<script src="resources/regress-post.js"></script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
(function() {
var result = 0;
for (var i = 0; i < 100000; ++i) {
var array1 = new Float32Array(15);
for (var j = 0; j < array1.length; ++j)
array1[j] = i - j;
var array2 = new Float64Array(15);
for (var j = 0; j < 10; ++j)
array2.set(array1);
for (var j = 0; j < array2.length; ++j)
result += array2[j];
}
if (result != 74988750000)
throw "Error: bad result: " + result;
})();
(function() {
var result = 0;
for (var i = 0; i < 100000; ++i) {
var array1 = new Float64Array(15);
for (var j = 0; j < array1.length; ++j)
array1[j] = i - j;
var array2 = new Int16Array(15);
for (var j = 0; j < 10; ++j)
array2.set(array1);
for (var j = 0; j < array2.length; ++j)
result += array2[j];
}
if (result != 7243531440)
throw "Error: bad result: " + result;
})();
(function() {
var result = 0;
for (var i = 0; i < 100000; ++i) {
var array1 = new Int16Array(15);
for (var j = 0; j < array1.length; ++j)
array1[j] = i - j;
var array2 = new Int32Array(15);
for (var j = 0; j < 10; ++j)
array2.set(array1);
for (var j = 0; j < array2.length; ++j)
result += array2[j];
}
if (result != 7243531440)
throw "Error: bad result: " + result;
})();
......@@ -112,13 +112,24 @@ function testFailed(msg)
debug('<span><span class="fail">FAIL</span> ' + escapeHTML(msg) + '</span>');
}
function areNumbersEqual(_actual, _expected)
{
if (_expected === 0)
return _actual === _expected && (1/_actual) === (1/_expected);
if (_actual === _expected)
return true;
if (typeof(_expected) == "number" && isNaN(_expected))
return typeof(_actual) == "number" && isNaN(_actual);
return false;
}
function areArraysEqual(_a, _b)
{
try {
if (_a.length !== _b.length)
return false;
for (var i = 0; i < _a.length; i++)
if (_a[i] !== _b[i])
if (!areNumbersEqual(_a[i], _b[i]))
return false;
} catch (ex) {
return false;
......@@ -148,12 +159,8 @@ function isTypedArray(array)
function isResultCorrect(_actual, _expected)
{
if (_expected === 0)
return _actual === _expected && (1/_actual) === (1/_expected);
if (_actual === _expected)
if (areNumbersEqual(_actual, _expected))
return true;
if (typeof(_expected) == "number" && isNaN(_expected))
return typeof(_actual) == "number" && isNaN(_actual);
if (_expected
&& (Object.prototype.toString.call(_expected) ==
Object.prototype.toString.call([])
......
......@@ -30,15 +30,28 @@ function testFailed(msg)
print("FAIL", escapeString(msg));
}
function areNumbersEqual(_actual, _expected)
{
if (_expected === 0)
return _actual === _expected && (1/_actual) === (1/_expected);
if (_actual === _expected)
return true;
if (typeof(_expected) == "number" && isNaN(_expected))
return typeof(_actual) == "number" && isNaN(_actual);
return false;
}
function areArraysEqual(_a, _b)
{
if (Object.prototype.toString.call(_a) != Object.prototype.toString.call([]))
return false;
if (_a.length !== _b.length)
return false;
for (var i = 0; i < _a.length; i++)
if (_a[i] !== _b[i])
try {
if (_a.length !== _b.length)
return false;
for (var i = 0; i < _a.length; i++)
if (!areNumbersEqual(_a[i], _b[i]))
return false;
} catch (ex) {
return false;
}
return true;
}
......@@ -49,15 +62,27 @@ function isMinusZero(n)
return n === 0 && 1/n < 0;
}
function isTypedArray(array)
{
return array instanceof Int8Array
|| array instanceof Int16Array
|| array instanceof Int32Array
|| array instanceof Uint8Array
|| array instanceof Uint8ClampedArray
|| array instanceof Uint16Array
|| array instanceof Uint32Array
|| array instanceof Float32Array
|| array instanceof Float64Array;
}
function isResultCorrect(_actual, _expected)
{
if (_expected === 0)
return _actual === _expected && (1/_actual) === (1/_expected);
if (_actual === _expected)
if (areNumbersEqual(_actual, _expected))
return true;
if (typeof(_expected) == "number" && isNaN(_expected))
return typeof(_actual) == "number" && isNaN(_actual);
if (Object.prototype.toString.call(_expected) == Object.prototype.toString.call([]))
if (_expected
&& (Object.prototype.toString.call(_expected) ==
Object.prototype.toString.call([])
|| isTypedArray(_expected)))
return areArraysEqual(_actual, _expected);
return false;
}
......@@ -66,7 +91,10 @@ function stringify(v)
{
if (v === 0 && 1/v < 0)
return "-0";
else return "" + v;
else if (isTypedArray(v))
return v.__proto__.constructor.name + ":[" + Array.prototype.join.call(v, ",") + "]";
else
return "" + v;
}
function shouldBe(_a, _b)
......@@ -83,13 +111,13 @@ function shouldBe(_a, _b)
var _bv = eval(_b);
if (exception)
testFailed(_a + " should be " + _bv + ". Threw exception " + exception);
testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + exception);
else if (isResultCorrect(_av, _bv))
testPassed(_a + " is " + _b);
else if (typeof(_av) == typeof(_bv))
testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + ".");
testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
else
testFailed(_a + " should be " + _bv + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
}
function shouldBeTrue(_a) { shouldBe(_a, "true"); }
......
description(
"Tests that accesses to typed arrays handle value conversions correctly."
);
// FIXME: This test assumes little-endian. It would take some hackage to convert
// it to a big-endian test.
function bitsToString(array) {
return Array.prototype.join.call(array, ":");
}
// Call this like so:
//
// bitsToValue(type, expectedJavascriptValue, first32Bits, second32Bits)
//
// Note that the second32Bits are optional.
//
// Where 'type' is for example "Int32".
function bitsToValue(type, expected) {
var baseArray = new Int32Array(arguments.length - 2);
for (var i = 0; i < arguments.length - 2; ++i)
baseArray[i] = arguments[i + 2];
var actual = (new this[type + "Array"](baseArray.buffer, 0, 1))[0];
if (isResultCorrect(actual, expected))
testPassed("Reading bit pattern " + bitsToString(baseArray) + " with " + type + " resulted in " + stringify(actual));
else
testFailed("Reading bit pattern " + bitsToString(baseArray) + " with " + type + " should result in " + stringify(expected) + " but instead was " + stringify(actual));
}
// Same signature as bitsToValue, except that the meaning is reversed.
function valueToBits(type, input) {
var buffer = new ArrayBuffer((arguments.length - 2) * 4);
var baseArray = new this[type + "Array"](buffer);
baseArray[0] = input;
var expectedArray = new Int32Array(arguments.length - 2);
for (var i = 0; i < arguments.length - 2; ++i)
expectedArray[i] = arguments[i + 2];
var actualArray = new Int32Array(buffer);
if (isResultCorrect(actualArray, expectedArray))
testPassed("Writing the value " + stringify(input) + " with type " + type + " results in bit pattern " + bitsToString(actualArray));
else
testFailed("Writing the value " + stringify(input) + " with type " + type + " should result in bit pattern " + bitsToString(expectedArray) + " but instead was " + bitsToString(actualArray));
}
// Test that both directions work.
function roundTrip() {
bitsToValue.apply(this, arguments);
valueToBits.apply(this, arguments);
}
roundTrip("Int8", 0, 0);
roundTrip("Int8", 42, 42);
roundTrip("Int8", -1, 255);
bitsToValue("Int8", 112, -400);
bitsToValue("Int8", -112, 400);
valueToBits("Int8", 1000, 232);
valueToBits("Int8", -1000, 24);
valueToBits("Int8", 0.5, 0);
valueToBits("Int8", -0.5, 0);
valueToBits("Int8", -1.5, 255);
valueToBits("Int8", 6326266464264213, 21);
valueToBits("Int8", -6326266464264213, 235);
roundTrip("Uint8", 0, 0);
roundTrip("Uint8", 42, 42);
roundTrip("Uint8", 255, 255);
bitsToValue("Uint8", 144, 400);
bitsToValue("Uint8", 112, -400);
valueToBits("Uint8", 1000, 232);
valueToBits("Uint8", -1000, 24);
valueToBits("Uint8", 0.5, 0);
valueToBits("Uint8", -0.5, 0);
valueToBits("Uint8", -1.5, 255);
valueToBits("Uint8", 6326266464264213, 21);
valueToBits("Uint8", -6326266464264213, 235);
roundTrip("Uint8Clamped", 0, 0);
roundTrip("Uint8Clamped", 42, 42);
roundTrip("Uint8Clamped", 255, 255);
bitsToValue("Uint8Clamped", 144, 400);
bitsToValue("Uint8Clamped", 112, -400);
valueToBits("Uint8Clamped", 1000, 255);
valueToBits("Uint8Clamped", -1000, 0);
valueToBits("Uint8Clamped", 0.5, 0);
valueToBits("Uint8Clamped", -0.5, 0);
valueToBits("Uint8Clamped", -1.5, 0);
valueToBits("Uint8Clamped", 6326266464264213, 255);
valueToBits("Uint8Clamped", -6326266464264213, 0);
roundTrip("Int16", 0, 0);
roundTrip("Int16", 42, 42);
roundTrip("Int16", 400, 400);
roundTrip("Int16", -1, 65535);
roundTrip("Int16", -400, 65136);
roundTrip("Int16", 30901, 30901);
bitsToValue("Int16", 6784, 400000);
bitsToValue("Int16", -6784, -400000);
valueToBits("Int16", 100000, 34464);
valueToBits("Int16", -100000, 31072);
valueToBits("Int16", 0.5, 0);
valueToBits("Int16", -0.5, 0);
valueToBits("Int16", -1.5, 65535);
valueToBits("Int16", 6326266464264213, 24597);
valueToBits("Int16", -6326266464264213, 40939);
roundTrip("Uint16", 0, 0);
roundTrip("Uint16", 42, 42);
roundTrip("Uint16", 400, 400);
roundTrip("Uint16", 30901, 30901);
bitsToValue("Uint16", 6784, 400000);
bitsToValue("Uint16", 58752, -400000);
valueToBits("Int16", 100000, 34464);
valueToBits("Int16", -100000, 31072);
valueToBits("Uint16", -1, 65535);
valueToBits("Uint16", -400, 65136);
valueToBits("Uint16", 0.5, 0);
valueToBits("Uint16", 6326266464264213, 24597);
valueToBits("Uint16", -6326266464264213, 40939);
roundTrip("Int32", 0, 0);
roundTrip("Int32", 42, 42);
roundTrip("Int32", 1000000000, 1000000000);
roundTrip("Int32", -42, -42);
roundTrip("Int32", -1000000000, -1000000000);
valueToBits("Int32", 0.5, 0);
valueToBits("Int32", -0.5, 0);
valueToBits("Int32", -1.5, -1);
valueToBits("Int32", 6326266464264213, -1319411691);
valueToBits("Int32", -6326266464264213, 1319411691);
roundTrip("Uint32", 0, 0);
roundTrip("Uint32", 42, 42);
roundTrip("Uint32", 1000000000, 1000000000);
valueToBits("Uint32", -42, -42);
bitsToValue("Uint32", (-42)>>>0, -42);
valueToBits("Uint32", -1000000000, -1000000000);
bitsToValue("Uint32", (-1000000000)>>>0, -1000000000);
valueToBits("Uint32", 0.5, 0);
valueToBits("Uint32", -0.5, 0);
valueToBits("Uint32", -1.5, -1);
valueToBits("Uint32", 6326266464264213, -1319411691);
valueToBits("Uint32", -6326266464264213, 1319411691);
roundTrip("Float32", 0, 0);
roundTrip("Float32", 1.5, 1069547520);
valueToBits("Float32", 1000000000, 1315859240);
roundTrip("Float64", 0, 0, 0);
roundTrip("Float64", 1.5, 0, 1073217536);
roundTrip("Float64", 1000000000, 0, 1104006501);
description(
"Tests that typedArray.set(otherTypedArray) does the right conversions when dealing with different types."
);
function MyRandom(z, w) {
this.z = (z == null ? 42 : z);
this.w = (w == null ? 23 : w);
}
MyRandom.prototype.get = function() {
this.z = (36969 * (this.z & 65535) + (this.z >> 16)) | 0;
this.w = (18000 * (this.w & 65535) + (this.w >> 16)) | 0;
return ((this.z << 16) + this.w) | 0;
};
function testArraySet(fromType, toType) {
// This function tests type conversions of set() by asserting that they are
// equivalent to converting via JSValue.
var rand = new MyRandom();
function createIntArray() {
var numSequences = 3;
var numPerSequence = 4;
var masks = [255, 65535, -1];
var array = new fromType(numSequences * numPerSequence);
for (var i = 0; i < numSequences; ++i) {
for (var j = 0; j < numPerSequence; ++j)
array[i * numPerSequence + j] = rand.get() & masks[i];
}
return array;
}
function createFloatArray() {
var array = [0, 0/-1, 1, 42, 1.5, -2.5, 1/0, -1/0, 0/0];
for (var i = 3; i--;)
array.push(rand.get());
return new fromType(array);
}
var sourceArray;
if (fromType == Float32Array || fromType == Float64Array)
sourceArray = createFloatArray();
else
sourceArray = createIntArray();
function reference() {
var array = new toType(sourceArray.length);
for (var i = 0; i < sourceArray.length; ++i)
array[i] = sourceArray[i];
return array;
}
function usingConstruct() {
return new toType(sourceArray);
}
function usingSet() {
var array = new toType(sourceArray.length);
array.set(sourceArray);
return array;
}
var referenceArray = reference();
var actualConstructArray = usingConstruct();
if (isResultCorrect(referenceArray, actualConstructArray))
testPassed("Copying " + stringify(sourceArray) + " to an array of type " + toType.name + " using the constructor resulted in " + stringify(actualConstructArray));
else
testFailed("Copying " + stringify(sourceArray) + " to an array of type " + toType.name + " using the constructor should have resulted in " + stringify(referenceArray) + " but instead resulted in " + stringify(actualConstructArray));
var actualSetArray = usingSet();
if (isResultCorrect(referenceArray, actualSetArray))
testPassed("Copying " + stringify(sourceArray) + " to an array of type " + toType.name + " using typedArray.set() resulted in " + stringify(actualSetArray));
else
testFailed("Copying " + stringify(sourceArray) + " to an array of type " + toType.name + " using typedArray.set() should have resulted in " + stringify(referenceArray) + " but instead resulted in " + stringify(actualSetArray));
}
var types = [Int8Array, Int16Array, Int32Array, Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array, Float32Array, Float64Array];
for (var i = 0; i < types.length; ++i) {
for (var j = 0; j < types.length; ++j)
testArraySet(types[i], types[j]);
}
Tests that accesses to typed arrays handle value conversions correctly.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS Reading bit pattern 0 with Int8 resulted in 0
PASS Writing the value 0 with type Int8 results in bit pattern 0
PASS Reading bit pattern 42 with Int8 resulted in 42
PASS Writing the value 42 with type Int8 results in bit pattern 42
PASS Reading bit pattern 255 with Int8 resulted in -1
PASS Writing the value -1 with type Int8 results in bit pattern 255
PASS Reading bit pattern -400 with Int8 resulted in 112
PASS Reading bit pattern 400 with Int8 resulted in -112
PASS Writing the value 1000 with type Int8 results in bit pattern 232
PASS Writing the value -1000 with type Int8 results in bit pattern 24
PASS Writing the value 0.5 with type Int8 results in bit pattern 0
PASS Writing the value -0.5 with type Int8 results in bit pattern 0