mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
Bug 864600 - OdinMonkey: change asm.js validation to require explicit coercion of all call expressions (r=sstangl)
--HG-- extra : rebase_source : f1235b48a1cfd96d52e96a9727d6d0b7852281b6
This commit is contained in:
parent
1a13eccebb
commit
c5cdc01cec
@ -590,7 +590,7 @@ class Use
|
||||
JS_ASSERT(which_ == AddOrSub);
|
||||
return *pcount_;
|
||||
}
|
||||
Type toFFIReturnType() const {
|
||||
Type toReturnType() const {
|
||||
switch (which_) {
|
||||
case NoCoercion: return Type::Void;
|
||||
case ToInt32: return Type::Intish;
|
||||
@ -614,6 +614,27 @@ class Use
|
||||
bool operator!=(Use rhs) const { return which_ != rhs.which_; }
|
||||
};
|
||||
|
||||
// Implements <: (subtype) operator when the type of the rhs is
|
||||
// 'rhs.toReturnType'.
|
||||
static inline bool
|
||||
operator<=(RetType lhs, Use rhs)
|
||||
{
|
||||
switch (rhs.which()) {
|
||||
case Use::NoCoercion:
|
||||
case Use::AddOrSub:
|
||||
JS_ASSERT(rhs.toReturnType() == Type::Void);
|
||||
return true;
|
||||
case Use::ToInt32:
|
||||
JS_ASSERT(rhs.toReturnType() == Type::Intish);
|
||||
return lhs == RetType::Signed;
|
||||
case Use::ToNumber:
|
||||
JS_ASSERT(rhs.toReturnType() == Type::Doublish);
|
||||
return lhs == RetType::Double;
|
||||
}
|
||||
JS_NOT_REACHED("Unexpected use kind");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// Numeric literal utilities
|
||||
|
||||
@ -3246,7 +3267,7 @@ CheckCallArgs(FunctionCompiler &f, ParseNode *callNode, Use use, FunctionCompile
|
||||
|
||||
static bool
|
||||
CheckInternalCall(FunctionCompiler &f, ParseNode *callNode, const ModuleCompiler::Func &callee,
|
||||
MDefinition **def, Type *type)
|
||||
Use use, MDefinition **def, Type *type)
|
||||
{
|
||||
FunctionCompiler::Args args(f);
|
||||
|
||||
@ -3264,7 +3285,27 @@ CheckInternalCall(FunctionCompiler &f, ParseNode *callNode, const ModuleCompiler
|
||||
if (!f.internalCall(callee, args, def))
|
||||
return false;
|
||||
|
||||
*type = callee.returnType().toType();
|
||||
// Note: the eventual goal for this code is to perform single-pass type
|
||||
// checking. A single pass means that we may not have seen the callee's definition
|
||||
// when we encounter a callsite. To address this, asm.js requires call
|
||||
// sites to coerce return values before use (unused values require no such
|
||||
// coercion). More specifically, the spec widens the return type of a
|
||||
// function from int to intish and double to doublish (similar to how
|
||||
// asm.js requires coercions on loads). A single-pass implementation of
|
||||
// this typing rule can achieve the same effect by:
|
||||
// - optimistically giving a call expression use.toReturnType (thus, one
|
||||
// of 'void', 'intish', 'doublish').
|
||||
// - later checking that use.toReturnType was conservative, i.e., that the
|
||||
// declared return type was a subtype of use.toReturnType.
|
||||
// For now, we check both conditions here. With a single-pass type checking
|
||||
// algorithm, we'd accumulate all the uses for a given callee name
|
||||
// (detecting inconsistencies between uses) and check this meet-over-uses
|
||||
// against the declared return type when the definition was encountered.
|
||||
|
||||
if (!(callee.returnType() <= use))
|
||||
return f.fail("return type of callee not compatible with use", callNode);
|
||||
|
||||
*type = use.toReturnType();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3344,7 +3385,7 @@ CheckFFICall(FunctionCompiler &f, ParseNode *callNode, unsigned ffiIndex, Use us
|
||||
if (!f.ffiCall(exitIndex, args, use.toMIRType(), def))
|
||||
return false;
|
||||
|
||||
*type = use.toFFIReturnType();
|
||||
*type = use.toReturnType();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3418,7 +3459,7 @@ CheckCall(FunctionCompiler &f, ParseNode *call, Use use, MDefinition **def, Type
|
||||
if (const ModuleCompiler::Global *global = f.lookupGlobal(callee->name())) {
|
||||
switch (global->which()) {
|
||||
case ModuleCompiler::Global::Function:
|
||||
return CheckInternalCall(f, call, f.m().function(global->funcIndex()), def, type);
|
||||
return CheckInternalCall(f, call, f.m().function(global->funcIndex()), use, def, type);
|
||||
case ModuleCompiler::Global::FFI:
|
||||
return CheckFFICall(f, call, global->ffiIndex(), use, def, type);
|
||||
case ModuleCompiler::Global::MathBuiltin:
|
||||
|
@ -11,11 +11,11 @@ assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { var i=0.1; i=f(
|
||||
assertAsmTypeFail(USE_ASM+"function f(){return 0.1} function g() { var i=0; i=f() } return g");
|
||||
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f() {return 42} function g() { return f()|0 } return g"))(), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=i|0; return (i+2)|0 } function h(i) { i=i|0; return (g(i)+8)|0 } return h"))(50), 60);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=i|0; return (i+2)|0 } function h(i) { i=i|0; return (g(i)+i)|0 } return h"))(50), 102);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=+i; return +(i+.1) } function h(i) { i=+i; return +(g(i)+.2) } return h"))(20), 20+.1+.2);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function g(i,j) { i=i|0;j=j|0; return (i-j)|0 } function h(j,i) { j=j|0;i=i|0; return (g(i,j)+8)|0 } return h"))(10,20), 18);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function g(i,j) { i=i|0;j=+j; return +(+~~i+j) } function h(i,j) { i=i|0;j=+j; return +(g(i,j)+8.6) } return h"))(10, 1.5), 10+1.5+8.6);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=i|0; return (i+2)|0 } function h(i) { i=i|0; return ((g(i)|0)+8)|0 } return h"))(50), 60);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=i|0; return (i+2)|0 } function h(i) { i=i|0; return ((g(i)|0)+i)|0 } return h"))(50), 102);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function g(i) { i=+i; return +(i+.1) } function h(i) { i=+i; return +(+g(i)+.2) } return h"))(20), 20+.1+.2);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function g(i,j) { i=i|0;j=j|0; return (i-j)|0 } function h(j,i) { j=j|0;i=i|0; return ((g(i,j)|0)+8)|0 } return h"))(10,20), 18);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function g(i,j) { i=i|0;j=+j; return +(+~~i+j) } function h(i,j) { i=i|0;j=+j; return +(+g(i,j)+8.6) } return h"))(10, 1.5), 10+1.5+8.6);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0; return (n-o)|0 } return f"))(1,2,3,4,5,6,100), -94);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } return f"))(1,2,3,4,5,6,100,20), 80);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (((o+p)|0) + ((o+p)|0))|0 } return f"))(1,2,3,4,5,6,30,20), 100);
|
||||
@ -24,16 +24,16 @@ assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p,q,r) { i=+i;j=+j
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0; return (n-o)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,i,j)|0 } return g"))(20,5), 15);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,i,j)|0 } return g"))(20,5), 15);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,i,j) } return g"))(.5, .1), .5-.1);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; var k=0; k=(i+j)|0; return (f(0,0,0,0,0,0,i,j)+k)|0 } return g"))(20,10), 40);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; var k=0.1; k=i+j; return +(f(0.0,0.0,0.0,0.0,0.0,0.0,i,j)+k) } return g"))(.5, .1), (.5+.1)+(.5-.1));
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; var k=0; k=(i+j)|0; return ((f(0,0,0,0,0,0,i,j)|0)+k)|0 } return g"))(20,10), 40);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; var k=0.1; k=i+j; return +(+f(0.0,0.0,0.0,0.0,0.0,0.0,i,j)+k) } return g"))(.5, .1), (.5+.1)+(.5-.1));
|
||||
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p,q) { i=i|0;j=j|0;k=k|0;l=l|0;m=+m;n=n|0;o=o|0;p=+p;q=q|0; return +((m-p) + +~~q) } function g(i,j,k) { i=+i;j=+j;k=k|0; return +f(0,0,0,0,j,0,0,i,k) } return g"))(.5, 20.1, 4), (20.1-.5)+4);
|
||||
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,f(0,0,0,0,0,0,i,j),j)|0 } return g"))(20,5), 10);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,f(0,0,0,0,0,0,i,j),f(0,0,0,0,0,0,j,i))|0 } return g"))(20,5), 30);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,f(0.0,0.0,0.0,0.0,0.0,0.0,i,j),j) } return g"))(10.3, .2), 10.3-.2-.2);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,f(0.0,0.0,0.0,0.0,0.0,0.0,i,j),f(0.0,0.0,0.0,0.0,0.0,0.0,j,i)) } return g"))(10.3, .2), (10.3-.2)-(.2-10.3));
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p,q) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0;q=q|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,i,f(0,0,0,0,0,0,i,j,0),0)|0 } return g"))(20,5), 5);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,f(0,0,0,0,0,0,i,j)|0,j)|0 } return g"))(20,5), 10);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,f(0,0,0,0,0,0,i,j)|0,f(0,0,0,0,0,0,j,i)|0)|0 } return g"))(20,5), 30);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,+f(0.0,0.0,0.0,0.0,0.0,0.0,i,j),j) } return g"))(10.3, .2), 10.3-.2-.2);
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p) { i=+i;j=+j;k=+k;l=+l;m=+m;n=+n;o=+o;p=+p; return +(o-p) } function g(i,j) { i=+i;j=+j; return +f(0.0,0.0,0.0,0.0,0.0,0.0,+f(0.0,0.0,0.0,0.0,0.0,0.0,i,j),+f(0.0,0.0,0.0,0.0,0.0,0.0,j,i)) } return g"))(10.3, .2), (10.3-.2)-(.2-10.3));
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i,j,k,l,m,n,o,p,q) { i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;o=o|0;p=p|0;q=q|0; return (o-p)|0 } function g(i,j) { i=i|0;j=j|0; return f(0,0,0,0,0,0,i,f(0,0,0,0,0,0,i,j,0)|0,0)|0 } return g"))(20,5), 5);
|
||||
|
||||
assertEq(asmLink(asmCompile(USE_ASM+"function f(i) {i=i|0; return i|0} function g() { return 42; return f(13)|0 } return g"))(), 42);
|
||||
|
||||
@ -42,8 +42,13 @@ assertEq(asmLink(asmCompile(USE_ASM+"function e() { return 42 } function f(i) {
|
||||
var rec = asmLink(asmCompile(USE_ASM+"function rec() { rec() } return rec"));
|
||||
assertThrowsInstanceOf(rec, InternalError);
|
||||
|
||||
var rec = asmLink(asmCompile(USE_ASM+"function rec(i) { i=i|0; if (!i) return 0; return (rec((i-1)|0)+1)|0 } return rec"));
|
||||
var rec = asmLink(asmCompile(USE_ASM+"function rec(i) { i=i|0; if (!i) return 0; return ((rec((i-1)|0)|0)+1)|0 } return rec"));
|
||||
assertEq(rec(100), 100);
|
||||
assertEq(rec(1000), 1000);
|
||||
assertThrowsInstanceOf(function() rec(100000000000), InternalError);
|
||||
assertEq(rec(2000), 2000);
|
||||
|
||||
assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { var i=0; i=f() } return g");
|
||||
assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { var i=0.0; i=f() } return g");
|
||||
assertAsmTypeFail(USE_ASM+"function f(){return 0} function g() { return (f()+1)|0 } return g");
|
||||
assertAsmTypeFail(USE_ASM+"function f(){return 0.0} function g() { return +(f()+1.0) } return g");
|
||||
|
@ -273,7 +273,7 @@ assertEq(asmLink(asmCompile(USE_ASM + "function f() { return (4 | (!2))|0 } retu
|
||||
|
||||
// get that order-of-operations right!
|
||||
var buf = new ArrayBuffer(4096);
|
||||
asmLink(asmCompile('glob','imp','buf', USE_ASM + "var i32=new glob.Int32Array(buf); var x=0; function a() { return x|0 } function b() { x=42; return 0 } function f() { i32[(b() & 0x3) >> 2] = a() } return f"), this, null, buf)();
|
||||
asmLink(asmCompile('glob','imp','buf', USE_ASM + "var i32=new glob.Int32Array(buf); var x=0; function a() { return x|0 } function b() { x=42; return 0 } function f() { i32[(b() & 0x3) >> 2] = a()|0 } return f"), this, null, buf)();
|
||||
assertEq(new Int32Array(buf)[0], 42);
|
||||
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() { var a=0,i=0; for (; ~~i!=4; i=(i+1)|0) { a = (a*5)|0; if (+(a>>>0) != 0.0) return 1; } return 0; } return f"))(), 0)
|
||||
|
@ -5,7 +5,7 @@ function ffi(a,b,c,d) {
|
||||
return a+b+c+d;
|
||||
}
|
||||
|
||||
var f = asmLink(asmCompile('global','imp', USE_ASM + 'var ffi=imp.ffi; function g() { return 1 } function f() { var i=0; i=g(); return ((ffi(4,5,6,7)|0)+i)|0 } return f'), null, {ffi:ffi});
|
||||
var f = asmLink(asmCompile('global','imp', USE_ASM + 'var ffi=imp.ffi; function g() { return 1 } function f() { var i=0; i=g()|0; return ((ffi(4,5,6,7)|0)+i)|0 } return f'), null, {ffi:ffi});
|
||||
assertEq(f(1), 23);
|
||||
|
||||
var counter = 0;
|
||||
|
@ -11,10 +11,10 @@ assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=1.0e2; e=d; r
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-1.0e2; e=d; return +e } return f'))(0.1), 0.1);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=1.0e0; e=d; return +e } return f'))(0.1), 0.1);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f(d) { d=+d; var e=-1.0e0; e=d; return +e } return f'))(0.1), 0.1);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return 0.0 } function g() { var d=0.1; d=f(); return +d } return g'))(), 0);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return -0.0 } function g() { var d=0.1; d=f(); return +d } return g'))(), -0);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return 10.0 } function g() { var d=0.1; d=f(); return +d } return g'))(), 10);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return -10.0 } function g() { var d=0.1; d=f(); return +d } return g'))(), -10.0);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return 0.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), 0);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return -0.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), -0);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return 10.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), 10);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f() { return -10.0 } function g() { var d=0.1; d=+f(); return +d } return g'))(), -10.0);
|
||||
|
||||
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=1e10; j=i; return j|0 } return f");
|
||||
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; var j=1e100; j=i; return j|0 } return f");
|
||||
|
Loading…
Reference in New Issue
Block a user