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. // Shared TypedObject methods for all SIMD types.
static const JSFunctionSpec SimdTypedObjectMethods[] = { static const JSFunctionSpec SimdTypedObjectMethods[] = {
JS_SELF_HOSTED_FN("toString", "SimdToString", 0, 0), 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_SELF_HOSTED_FN("toSource", "SimdToSource", 0, 0),
JS_FS_END JS_FS_END
}; };

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

@ -690,6 +690,24 @@ function SimdTypeToLength(type) {
return undefined; 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() { function SimdToSource() {
if (!IsObject(this) || !ObjectIsTypedObject(this)) if (!IsObject(this) || !ObjectIsTypedObject(this))
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD.*", "toSource", typeof this); ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD.*", "toSource", typeof this);

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

@ -7,9 +7,10 @@ if (typeof SIMD === 'undefined' || !isSimdAvailable()) {
"use asm"; "use asm";
var frd = global.Math.fround; var frd = global.Math.fround;
var fx4 = global.SIMD.Float32x4; var fx4 = global.SIMD.Float32x4;
var fc4 = fx4.check;
var fsp = fx4.splat; var fsp = fx4.splat;
function s(){} function s(){}
function d(x){x=fx4(x);} function d(x){x=fc4(x);}
function e() { function e() {
var x = frd(0); var x = frd(0);
x = frd(x / x); x = frd(x / x);
@ -23,11 +24,12 @@ if (typeof SIMD === 'undefined' || !isSimdAvailable()) {
"use asm" "use asm"
var k = m.SIMD.Bool32x4 var k = m.SIMD.Bool32x4
var g = m.SIMD.Int32x4 var g = m.SIMD.Int32x4
var gc = g.check;
var h = g.select var h = g.select
function f() { function f() {
var x = k(0, 0, 0, 0) var x = k(0, 0, 0, 0)
var y = g(1, 2, 3, 4) var y = g(1, 2, 3, 4)
return g(h(x, y, y)) return gc(h(x, y, y))
} }
return f; return f;
})(this)(); })(this)();
@ -36,6 +38,7 @@ t = (function(global) {
"use asm" "use asm"
var toF = global.Math.fround var toF = global.Math.fround
var f4 = global.SIMD.Float32x4 var f4 = global.SIMD.Float32x4
var f4c = f4.check
function p(x, y, width, value, max_iterations) { function p(x, y, width, value, max_iterations) {
x = x | 0 x = x | 0
y = y | 0 y = y | 0
@ -50,7 +53,7 @@ t = (function(global) {
max_iterations = max_iterations | 0 max_iterations = max_iterations | 0
var _ = f4(0, 0, 0, 0), c_im4 = f4(0, 0, 0, 0) var _ = f4(0, 0, 0, 0), c_im4 = f4(0, 0, 0, 0)
c_im4 = f4(yf, yd, yd, yf) c_im4 = f4(yf, yd, yd, yf)
return f4(c_im4); return f4c(c_im4);
} }
return {p:p,m:m}; return {p:p,m:m};
})(this) })(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_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_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_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 // Typed array
MSG_DEF(JSMSG_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index") 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(5), TypeError);
assertThrowsInstanceOf(() => ts.call({}), TypeError); assertThrowsInstanceOf(() => ts.call({}), TypeError);
// Can't convert SIMD objects to numbers.
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Float64x2 = SIMD.Float64x2; var Float64x2 = SIMD.Float64x2;
var f = Float64x2(11, 22); var f = Float64x2(11, 22);
assertEq(f.toString(), "SIMD.Float64x2(11, 22)"); assertEq(f.toString(), "SIMD.Float64x2(11, 22)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
var Int8x16 = SIMD.Int8x16; var Int8x16 = SIMD.Int8x16;
var f = Int8x16(11, 22, 33, 44, -11, -22, -33, -44, 1, 2, 3, 4, -1, -2, -3, -4); 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)"); 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 Int16x8 = SIMD.Int16x8;
var f = Int16x8(11, 22, 33, 44, -11, -22, -33, -44); var f = Int16x8(11, 22, 33, 44, -11, -22, -33, -44);
assertEq(f.toString(), "SIMD.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 Int32x4 = SIMD.Int32x4;
var f = Int32x4(11, 22, 33, 44); var f = Int32x4(11, 22, 33, 44);
assertEq(f.toString(), "SIMD.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 Uint8x16 = SIMD.Uint8x16;
var f = Uint8x16(11, 22, 33, 44, 245, 234, 223, 212, 1, 2, 3, 4, 255, 254, 0, 250); 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)"); 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 Uint16x8 = SIMD.Uint16x8;
var f = Uint16x8(11, 22, 33, 44, 65535, 65534, 65533, 65532); var f = Uint16x8(11, 22, 33, 44, 65535, 65534, 65533, 65532);
assertEq(f.toString(), "SIMD.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 Uint32x4 = SIMD.Uint32x4;
var f = Uint32x4(11, 22, 4294967295, 4294967294); var f = Uint32x4(11, 22, 4294967295, 4294967294);
assertEq(f.toString(), "SIMD.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 Bool8x16 = SIMD.Bool8x16;
var f = Bool8x16(true, true, false, false, false, true, true, false, true, true, true, true, false, false, false, false); 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)"); 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 Bool16x8 = SIMD.Bool16x8;
var f = Bool16x8(true, true, false, false, true, false, false, true); var f = Bool16x8(true, true, false, false, true, false, false, true);
assertEq(f.toString(), "SIMD.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 Bool32x4 = SIMD.Bool32x4;
var f = Bool32x4(true, true, false, false); var f = Bool32x4(true, true, false, false);
assertEq(f.toString(), "SIMD.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 Bool64x2 = SIMD.Bool64x2;
var f = Bool64x2(true, false); var f = Bool64x2(true, false);
assertEq(f.toString(), "SIMD.Bool64x2(true, false)"); assertEq(f.toString(), "SIMD.Bool64x2(true, false)");
assertThrowsInstanceOf(() => +f, TypeError);
assertThrowsInstanceOf(() => f.valueOf(), TypeError);
if (typeof reportCompare === "function") if (typeof reportCompare === "function")
reportCompare(true, true); reportCompare(true, true);

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

@ -31,11 +31,11 @@ namespace js {
* *
* (If you're wondering, 0xb973c0de is used because it looks like "bytecode".) * (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 = static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND); 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 " "GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
"removed MSG_DEFs from js.msg, you should increment " "removed MSG_DEFs from js.msg, you should increment "
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's " "XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "