diff --git a/js/src/asmjs/AsmJSValidate.cpp b/js/src/asmjs/AsmJSValidate.cpp index bbdca789581..5514d19d0dd 100644 --- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -4773,33 +4773,12 @@ CheckSimdCallArgs(FunctionCompiler &f, ParseNode *call, unsigned expectedArity, return true; } -class CheckSimdScalarArgs +class CheckArgIsSubtypeOf { Type formalType_; public: - explicit CheckSimdScalarArgs(Type t) : formalType_(t.simdToCoercedScalarType()) {} - - bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType, - MDefinition **argDef) const - { - if (formalType_ == Type::Floatish) - return CheckFloatCoercionArg(f, arg, actualType, *argDef, argDef); - - if (!(actualType <= formalType_)) { - return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(), - formalType_.toChars()); - } - return true; - } -}; - -class CheckSimdVectorArgs -{ - Type formalType_; - - public: - explicit CheckSimdVectorArgs(Type t) : formalType_(t) {} + explicit CheckArgIsSubtypeOf(Type t) : formalType_(t) {} bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType, MDefinition **argDef) const @@ -4845,7 +4824,7 @@ CheckSimdBinary(FunctionCompiler &f, ParseNode *call, Type retType, OpEnum op, M Type *type) { DefinitionVector argDefs; - if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorArgs(retType), &argDefs)) + if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(retType), &argDefs)) return false; *def = f.binarySimd(argDefs[0], argDefs[1], op, retType.toMIRType()); *type = retType; @@ -4859,7 +4838,7 @@ CheckSimdBinary(FunctionCompiler &f, ParseNode *call Type *type) { DefinitionVector argDefs; - if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorArgs(retType), &argDefs)) + if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(retType), &argDefs)) return false; *def = f.binarySimd(argDefs[0], argDefs[1], op); *type = Type::Int32x4; @@ -4906,7 +4885,8 @@ CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompile case AsmJSSimdOperation_splat: { DefinitionVector defs; - if (!CheckSimdCallArgs(f, call, 1, CheckSimdScalarArgs(retType), &defs)) + Type formalType = retType.simdToCoercedScalarType(); + if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(formalType), &defs)) return false; *def = f.splatSimd(defs[0], retType.toMIRType()); *type = retType; @@ -4938,11 +4918,11 @@ CheckSimdCtorCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Gl return CheckCoercionArg(f, argNode, coercion, def, type); AsmJSSimdType simdType = global->simdCtorType(); - unsigned length = SimdTypeToLength(simdType); Type retType = simdType; - + unsigned length = SimdTypeToLength(simdType); + Type formalType = retType.simdToCoercedScalarType(); DefinitionVector defs; - if (!CheckSimdCallArgs(f, call, length, CheckSimdScalarArgs(retType), &defs)) + if (!CheckSimdCallArgs(f, call, length, CheckArgIsSubtypeOf(formalType), &defs)) return false; // This code will need to be generalized when we handle float64x2 @@ -5099,6 +5079,9 @@ CheckCoercedCall(FunctionCompiler &f, ParseNode *call, RetType retType, MDefinit { JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed()); + if (IsNumericLiteral(f.m(), call)) + return CheckNumericLiteral(f, call, def, type); + ParseNode *callee = CallCallee(call); if (callee->isKind(PNK_ELEM)) diff --git a/js/src/jit-test/tests/asm.js/testSIMD.js b/js/src/jit-test/tests/asm.js/testSIMD.js index 88f029ac732..9e131539e5e 100644 --- a/js/src/jit-test/tests/asm.js/testSIMD.js +++ b/js/src/jit-test/tests/asm.js/testSIMD.js @@ -137,8 +137,8 @@ assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {return f4(f // Int32x4 ctor should accept int? assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + "var i32=new glob.Int32Array(heap); function f(i) {i=i|0; return i4(i4(i32[i>>2], 2, 3, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [0, 2, 3, 4]); // Float32x4 ctor should accept floatish, i.e. float || float? || floatish -assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + "var f32=new glob.Float32Array(heap); function f(i) {i=i|0; return f4(f4(f32[i>>2], 2, 3, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [NaN, 2, 3, 4]); -assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "var f32=glob.Math.fround; function f(i) {i=i|0; return f4(f4(f32(1) + f32(2), 2, 3, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + FROUND + "var h=new glob.Float32Array(heap); function f(i) {i=i|0; return f4(f4(h[i>>2], f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [NaN, 2, 3, 4]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + "function f(i) {i=i|0; return f4(f4(f32(1) + f32(2), f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]); // 1.3.2 Reading values out of lanes assertAsmTypeFail('glob', USE_ASM + "function f() {var x=1; return x.y | 0;} return f"); @@ -172,9 +172,9 @@ assertAsmTypeFail('glob', USE_ASM + FROUND + "function f() {var x=f32(42.); retu assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f() { var x=i4(1,2,3,4); return x.signMask | 0 } return f'), this)(), 0b0000); assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f() { var x=i4(0,-1, ' + INT32_MAX + ',' + INT32_MIN + '); return x.signMask | 0 } return f'), this)(), 0b1010); -assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(1, -13.37, 42, -Infinity); return x.signMask | 0 } return f'), this)(), 0b1010); -assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(-1, 0, -0.000001, Infinity); return x.signMask | 0 } return f'), this)(), 0b0101); -assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + 'var NaN = glob.NaN; function f() { var x=f4(0,0,0,0); x=f4(-1, NaN, 3., 4.); return x.signMask | 0 } return f'), this)(), 0b0001); +assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(f32(1), f32(-13.37), f32(42), f32(-Infinity)); return x.signMask | 0 } return f'), this)(), 0b1010); +assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(f32(-1), f32(0), f32(-0.000001), f32(Infinity)); return x.signMask | 0 } return f'), this)(), 0b0101); +assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + 'var NaN = glob.NaN; function f() { var x=f4(0,0,0,0); x=f4(f32(-1), f32(NaN), f32(3.), f32(4.)); return x.signMask | 0 } return f'), this)(), 0b0001); // 1.3.3. Variable assignments assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4();} return f"); @@ -197,9 +197,13 @@ CheckI4('', 'var x=i4(1,2,3,4); x=i4(5,6,7,8)', [5, 6, 7, 8]); CheckI4('', 'var x=i4(1,2,3,4); var c=6; x=i4(5,c|0,7,8)', [5, 6, 7, 8]); CheckI4('', 'var x=i4(8,7,6,5); x=i4(x.w|0,x.z|0,x.y|0,x.x|0)', [5, 6, 7, 8]); -CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(7.); x=f4(5,6,y,8)', [5, 6, 7, 8]); -CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5.),6.,7.,8.)', [5, 6, 7, 8]); -CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5),6,7,8)', [5, 6, 7, 8]); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=f4(1,2,3,c);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=f4(1.,2.,3.,c);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4.; x=f4(1,2,3,c);} return f"); +assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4.; x=f4(1.,2.,3.,c);} return f"); + +CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(7.); x=f4(f32(5),f32(6),y,f32(8))', [5, 6, 7, 8]); +CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5),f32(6),f32(7),f32(8))', [5, 6, 7, 8]); CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5.),f32(6.),f32(7.),f32(8.))', [5, 6, 7, 8]); CheckF4('', 'var x=f4(1.,2.,3.,4.); x=f4(5.,6.,7.,8.)', [5, 6, 7, 8]); CheckF4('', 'var x=f4(1.,2.,3.,4.); x=f4(1,2,3,4)', [1, 2, 3, 4]); @@ -561,7 +565,7 @@ assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f const I32SPLAT = 'var splat=i4.splat;' const F32SPLAT = 'var splat=f4.splat;' -assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); var p=f4(1.,2.,3.,4.); p=splat(1);} return f"); +assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); var p=f4(1.,2.,3.,4.); p=splat(f32(1));} return f"); assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(1, 2)} return f"); assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat()} return f"); @@ -572,9 +576,8 @@ assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + FROUND + "function f() {var assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SPLAT + 'function f(){return i4(splat(42));} return f'), this)(), [42, 42, 42, 42]); const l33t = Math.fround(13.37); -assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(1));} return f'), this)(), [1, 1, 1, 1]); -assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(1 >>> 0));} return f'), this)(), [1, 1, 1, 1]); -assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(13.37));} return f'), this)(), [l33t, l33t, l33t, l33t]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(1)));} return f'), this)(), [1, 1, 1, 1]); +assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(1 >>> 0)));} return f'), this)(), [1, 1, 1, 1]); assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(13.37)));} return f'), this)(), [l33t, l33t, l33t, l33t]); var i32view = new Int32Array(heap);