Bug 1252924 - SIMD.*.prototype.valueOf. r=waldo

When SIMD objects have proper value semantics, this method will just return
|this| after a type check.

Until then, do as the polyfill and override valueOf to throw a TypeError so
that ToNumber() can't convert a SIMD value to a number.

Fix wrong code in asm.js/testBug1099216.js. This code was using Float32x4(x)
instead of Float32x4.check(x) as an argument coercion.

MozReview-Commit-ID: H9zaEfoqs2J
This commit is contained in:
Jakob Olesen 2016-03-14 09:50:15 -07:00
Родитель a6cad32eee
Коммит acc528baf8
6 изменённых файлов: 54 добавлений и 5 удалений

Просмотреть файл

@ -219,6 +219,7 @@ static const JSFunctionSpec TypeDescriptorMethods[] = {
// Shared TypedObject methods for all SIMD types.
static const JSFunctionSpec SimdTypedObjectMethods[] = {
JS_SELF_HOSTED_FN("toString", "SimdToString", 0, 0),
JS_SELF_HOSTED_FN("valueOf", "SimdValueOf", 0, 0),
JS_SELF_HOSTED_FN("toSource", "SimdToSource", 0, 0),
JS_FS_END
};

Просмотреть файл

@ -690,6 +690,24 @@ function SimdTypeToLength(type) {
return undefined;
}
// This implements SIMD.*.prototype.valueOf().
// Once we have proper value semantics for SIMD types, this function should just
// perform a type check and return this.
// For now, throw a TypeError unconditionally since valueOf() was probably
// called from ToNumber() which is supposed to throw when attempting to convert
// a SIMD value to a number.
function SimdValueOf() {
if (!IsObject(this) || !ObjectIsTypedObject(this))
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD", "valueOf", typeof this);
var descr = TypedObjectTypeDescr(this);
if (DESCR_KIND(descr) != JS_TYPEREPR_SIMD_KIND)
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD", "valueOf", typeof this);
ThrowTypeError(JSMSG_SIMD_TO_NUMBER);
}
function SimdToSource() {
if (!IsObject(this) || !ObjectIsTypedObject(this))
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD.*", "toSource", typeof this);

Просмотреть файл

@ -7,9 +7,10 @@ if (typeof SIMD === 'undefined' || !isSimdAvailable()) {
"use asm";
var frd = global.Math.fround;
var fx4 = global.SIMD.Float32x4;
var fc4 = fx4.check;
var fsp = fx4.splat;
function s(){}
function d(x){x=fx4(x);}
function d(x){x=fc4(x);}
function e() {
var x = frd(0);
x = frd(x / x);
@ -23,11 +24,12 @@ if (typeof SIMD === 'undefined' || !isSimdAvailable()) {
"use asm"
var k = m.SIMD.Bool32x4
var g = m.SIMD.Int32x4
var gc = g.check;
var h = g.select
function f() {
var x = k(0, 0, 0, 0)
var y = g(1, 2, 3, 4)
return g(h(x, y, y))
return gc(h(x, y, y))
}
return f;
})(this)();
@ -36,6 +38,7 @@ t = (function(global) {
"use asm"
var toF = global.Math.fround
var f4 = global.SIMD.Float32x4
var f4c = f4.check
function p(x, y, width, value, max_iterations) {
x = x | 0
y = y | 0
@ -50,7 +53,7 @@ t = (function(global) {
max_iterations = max_iterations | 0
var _ = f4(0, 0, 0, 0), c_im4 = f4(0, 0, 0, 0)
c_im4 = f4(yf, yd, yd, yf)
return f4(c_im4);
return f4c(c_im4);
}
return {p:p,m:m};
})(this)

Просмотреть файл

@ -471,6 +471,7 @@ MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED, 0, JSEXN_TYPEERR, "handle unattache
MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_ARGS, 0, JSEXN_RANGEERR, "invalid field descriptor")
MSG_DEF(JSMSG_TYPEDOBJECT_TOO_BIG, 0, JSEXN_ERR, "Type is too large to allocate")
MSG_DEF(JSMSG_SIMD_FAILED_CONVERSION, 0, JSEXN_RANGEERR, "SIMD conversion loses precision")
MSG_DEF(JSMSG_SIMD_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert SIMD value to number")
// Typed array
MSG_DEF(JSMSG_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index")

Просмотреть файл

@ -13,49 +13,75 @@ function test() {
assertThrowsInstanceOf(() => ts.call(5), TypeError);
assertThrowsInstanceOf(() => ts.call({}), TypeError);
// Can't convert SIMD objects to numbers.
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Float64x2 = SIMD.Float64x2;
var f = Float64x2(11, 22);
assertEq(f.toString(), "SIMD.Float64x2(11, 22)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Int8x16 = SIMD.Int8x16;
var f = Int8x16(11, 22, 33, 44, -11, -22, -33, -44, 1, 2, 3, 4, -1, -2, -3, -4);
assertEq(f.toString(), "SIMD.Int8x16(11, 22, 33, 44, -11, -22, -33, -44, 1, 2, 3, 4, -1, -2, -3, -4)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Int16x8 = SIMD.Int16x8;
var f = Int16x8(11, 22, 33, 44, -11, -22, -33, -44);
assertEq(f.toString(), "SIMD.Int16x8(11, 22, 33, 44, -11, -22, -33, -44)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Int32x4 = SIMD.Int32x4;
var f = Int32x4(11, 22, 33, 44);
assertEq(f.toString(), "SIMD.Int32x4(11, 22, 33, 44)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Uint8x16 = SIMD.Uint8x16;
var f = Uint8x16(11, 22, 33, 44, 245, 234, 223, 212, 1, 2, 3, 4, 255, 254, 0, 250);
assertEq(f.toString(), "SIMD.Uint8x16(11, 22, 33, 44, 245, 234, 223, 212, 1, 2, 3, 4, 255, 254, 0, 250)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Uint16x8 = SIMD.Uint16x8;
var f = Uint16x8(11, 22, 33, 44, 65535, 65534, 65533, 65532);
assertEq(f.toString(), "SIMD.Uint16x8(11, 22, 33, 44, 65535, 65534, 65533, 65532)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Uint32x4 = SIMD.Uint32x4;
var f = Uint32x4(11, 22, 4294967295, 4294967294);
assertEq(f.toString(), "SIMD.Uint32x4(11, 22, 4294967295, 4294967294)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Bool8x16 = SIMD.Bool8x16;
var f = Bool8x16(true, true, false, false, false, true, true, false, true, true, true, true, false, false, false, false);
assertEq(f.toString(), "SIMD.Bool8x16(true, true, false, false, false, true, true, false, true, true, true, true, false, false, false, false)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Bool16x8 = SIMD.Bool16x8;
var f = Bool16x8(true, true, false, false, true, false, false, true);
assertEq(f.toString(), "SIMD.Bool16x8(true, true, false, false, true, false, false, true)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Bool32x4 = SIMD.Bool32x4;
var f = Bool32x4(true, true, false, false);
assertEq(f.toString(), "SIMD.Bool32x4(true, true, false, false)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Bool64x2 = SIMD.Bool64x2;
var f = Bool64x2(true, false);
assertEq(f.toString(), "SIMD.Bool64x2(true, false)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -31,11 +31,11 @@ namespace js {
*
* (If you're wondering, 0xb973c0de is used because it looks like "bytecode".)
*/
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 352;
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 353;
static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
static_assert(JSErr_Limit == 419,
static_assert(JSErr_Limit == 420,
"GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
"removed MSG_DEFs from js.msg, you should increment "
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "