зеркало из https://github.com/mozilla/gecko-dev.git
Bug 880204 - Asm.js: support constant global variables and make their loads hoistable. r=luke
This commit is contained in:
Родитель
5f525a4004
Коммит
848b25298d
|
@ -7,10 +7,10 @@ const ASM_TYPE_FAIL_STRING = "asm.js type error:";
|
|||
const ASM_DIRECTIVE_FAIL_STRING = "\"use asm\" is only meaningful in the Directive Prologue of a function body";
|
||||
|
||||
const USE_ASM = "'use asm';";
|
||||
const HEAP_IMPORTS = "var i8=new glob.Int8Array(b);var u8=new glob.Uint8Array(b);"+
|
||||
"var i16=new glob.Int16Array(b);var u16=new glob.Uint16Array(b);"+
|
||||
"var i32=new glob.Int32Array(b);var u32=new glob.Uint32Array(b);"+
|
||||
"var f32=new glob.Float32Array(b);var f64=new glob.Float64Array(b);";
|
||||
const HEAP_IMPORTS = "const i8=new glob.Int8Array(b);var u8=new glob.Uint8Array(b);"+
|
||||
"const i16=new glob.Int16Array(b);var u16=new glob.Uint16Array(b);"+
|
||||
"const i32=new glob.Int32Array(b);var u32=new glob.Uint32Array(b);"+
|
||||
"const f32=new glob.Float32Array(b);var f64=new glob.Float64Array(b);";
|
||||
const BUF_64KB = new ArrayBuffer(64 * 1024);
|
||||
|
||||
function asmCompile()
|
||||
|
|
|
@ -48,8 +48,11 @@ assertEq(f(), 2);
|
|||
assertEq(counter, 3);
|
||||
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add1=imp.add1; function g(i) { i=i|0; return add1(i|0)|0 } return g'), null, imp)(9), 10);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'const add1=imp.add1; function g(i) { i=i|0; return add1(i|0)|0 } return g'), null, imp)(9), 10);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add3=imp.add3; function g() { var i=1,j=3,k=9; return add3(i|0,j|0,k|0)|0 } return g'), null, imp)(), 13);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'const add3=imp.add3; function g() { var i=1,j=3,k=9; return add3(i|0,j|0,k|0)|0 } return g'), null, imp)(), 13);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add3=imp.add3; function g() { var i=1.4,j=2.3,k=32.1; return +add3(i,j,k) } return g'), null, imp)(), 1.4+2.3+32.1);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'const add3=imp.add3; function g() { var i=1.4,j=2.3,k=32.1; return +add3(i,j,k) } return g'), null, imp)(), 1.4+2.3+32.1);
|
||||
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var add3=imp.add3; function f(i,j,k) { i=i|0;j=+j;k=k|0; return add3(i|0,j,k|0)|0 } return f'), null, imp)(1, 2.5, 3), 6);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var addN=imp.addN; function f() { return +addN(1,2,3,4.1,5,6.1,7,8.1,9.1,10,11.1,12,13,14.1,15.1,16.1,17.1,18.1) } return f'), null, imp)(), 1+2+3+4.1+5+6.1+7+8.1+9.1+10+11.1+12+13+14.1+15.1+16.1+17.1+18.1);
|
||||
|
|
|
@ -27,18 +27,42 @@ assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) { i=i|0; return
|
|||
assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) { i=i|0; return tbl[i&1](3.0)|0 } var tbl=[f,f]; return g");
|
||||
assertAsmTypeFail(USE_ASM + "function f(d) {d=+d} function g(i) { i=i|0; return tbl[i&1](3)|0 } var tbl=[f,f]; return g");
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,f]; return g"))(0), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&1]()|0 } const tbl=[f,f]; return g"))(0), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,g]; return h"))(1), 13);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl[i&1]()|0 } const tbl=[f,g]; return h"))(1), 13);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&1]()|0 } var tbl1=[f,g]; var tbl2=[g,f]; return h"))(1), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&1]()|0 } const tbl1=[f,g]; const tbl2=[g,f]; return h"))(1), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&3]()|0 } var tbl1=[f,g]; var tbl2=[g,g,g,f]; return h"))(3), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl2[i&3]()|0 } const tbl1=[f,g]; const tbl2=[g,g,g,f]; return h"))(3), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl1[i&1]()|0 } var tbl1=[f,g]; var tbl2=[g,g,g,f]; return h"))(1), 13);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl1[i&1]()|0 } const tbl1=[f,g]; const tbl2=[g,g,g,f]; return h"))(1), 13);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var i=0,j=0; function f() {return i|0} function g() {return j|0} function h(x) { x=x|0; i=5;j=10; return tbl2[x&3]()|0 } var tbl1=[f,g]; var tbl2=[g,g,g,f]; return h"))(3), 5);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var i=0,j=0; function f() {return i|0} function g() {return j|0} function h(x) { x=x|0; i=5;j=10; return tbl2[x&3]()|0 } const tbl1=[f,g]; const tbl2=[g,g,g,f]; return h"))(3), 5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "var ffi=imp.ffi; function f() {return ffi()|0} function g() {return 13} function h(x) { x=x|0; return tbl2[x&3]()|0 } var tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 20);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "var ffi=imp.ffi; var i=0; function f() {return ((ffi()|0)+i)|0} function g() {return 13} function h(x) { x=x|0; i=2; return tbl2[x&3]()|0 } var tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 22);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "const ffi=imp.ffi; function f() {return ffi()|0} function g() {return 13} function h(x) { x=x|0; return tbl2[x&3]()|0 } const tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 20);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "var ffi=imp.ffi; var i=0; function f() {return ((ffi()|0)+i)|0} function g() {return 13} function h(x) { x=x|0; i=2; return tbl2[x&3]()|0 } var tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 22)
|
||||
;assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + "const ffi=imp.ffi; var i=0; function f() {return ((ffi()|0)+i)|0} function g() {return 13} function h(x) { x=x|0; i=2; return tbl2[x&3]()|0 } const tbl2=[g,g,g,f]; return h"), null, {ffi:function(){return 20}})(3), 22);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f(i) {i=i|0; return +((i+1)|0)} function g(d) { d=+d; return +(d+2.5) } function h(i,j) { i=i|0;j=j|0; return +tbl2[i&1](+tbl1[i&1](j)) } var tbl1=[f,f]; var tbl2=[g,g]; return h"))(0,10), 11+2.5);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f(i) {i=i|0; return +((i+1)|0)} function g(d) { d=+d; return +(d+2.5) } function h(i,j) { i=i|0;j=j|0; return +tbl2[i&1](+tbl1[i&1](j)) } const tbl1=[f,f]; const tbl2=[g,g]; return h"))(0,10), 11+2.5);
|
||||
|
||||
assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0]()|0 } var tbl=[f]; return g");
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() { return tbl[0&0]()|0 } var tbl=[f]; return g"))(), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() { return tbl[0&0]()|0 } const tbl=[f]; return g"))(), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f1() {return 42} function f2() {return 13} function g() { return tbl[1&1]()|0 } var tbl=[f1,f2]; return g"))(), 13);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f1() {return 42} function f2() {return 13} function g() { return tbl[1&1]()|0 } const tbl=[f1,f2]; return g"))(), 13);
|
||||
|
||||
// Test some literal constant paths.
|
||||
assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&4294967295]()|0 } var tbl=[f]; return g");
|
||||
assertAsmTypeFail(USE_ASM + "const i=4294967295; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g");
|
||||
assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&-1]()|0 } var tbl=[f]; return g");
|
||||
assertAsmTypeFail(USE_ASM + "const i=-1; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g");
|
||||
assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&0x80000000]()|0 } var tbl=[f]; return g");
|
||||
assertAsmTypeFail(USE_ASM + "const i=0x80000000; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g");
|
||||
assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&-2147483648]()|0 } var tbl=[f]; return g");
|
||||
assertAsmTypeFail(USE_ASM + "const i=-2147483648; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g");
|
||||
assertAsmTypeFail(USE_ASM + "const i=0; function f() {return 42} function g() { return tbl[0&i]()|0 } var tbl=[f]; return g");
|
||||
// Limited by the inability to test really large tables.
|
||||
assertAsmTypeFail(USE_ASM + "function f() {return 42} function g() { return tbl[0&0x7fffffff]()|0 } var tbl=[f]; return g");
|
||||
|
||||
var f = asmLink(asmCompile(USE_ASM + "function f1(d) {d=+d; return +(d/2.0)} function f2(d) {d=+d; return +(d+10.0)} function g(i,j) { i=i|0;j=+j; return +tbl[i&1](+tbl[(i+1)&1](j)) } var tbl=[f1,f2]; return g"));
|
||||
assertEq(f(0,10.2), (10.2+10)/2);
|
||||
|
|
|
@ -1,15 +1,29 @@
|
|||
load(libdir + "asm.js");
|
||||
|
||||
assertAsmTypeFail(USE_ASM + "var i; function f(){} return f");
|
||||
assertAsmTypeFail(USE_ASM + "const i; function f(){} return f");
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var i=0; function f(){} return f"))(), undefined);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "const i=0; function f(){} return f"))(), undefined);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var i=42; function f(){ return i|0 } return f"))(), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "const i=42; function f(){ return i|0 } return f"))(), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var i=4.2; function f(){ return +i } return f"))(), 4.2);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "const i=4.2; function f(){ return +i } return f"))(), 4.2);
|
||||
assertAsmTypeFail(USE_ASM + "var i=42; function f(){ return +(i+.1) } return f");
|
||||
assertAsmTypeFail(USE_ASM + "const i=42; function f(){ return +(i+.1) } return f");
|
||||
assertAsmTypeFail(USE_ASM + "var i=1.2; function f(){ return i|0 } return f");
|
||||
assertAsmTypeFail(USE_ASM + "const i=1.2; function f(){ return i|0 } return f");
|
||||
assertAsmTypeFail(USE_ASM + "var i=0; function f(e){ e=+e; i=e } return f");
|
||||
assertAsmTypeFail(USE_ASM + "const i=0; function f(e){ e=+e; i=e } return f");
|
||||
assertAsmTypeFail(USE_ASM + "var d=0.1; function f(i){ i=i|0; d=i } return f");
|
||||
assertAsmTypeFail(USE_ASM + "const d=0.1; function f(i){ i=i|0; d=i } return f");
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var i=13; function f(j) { j=j|0; i=j; return i|0 } return f"))(42), 42);
|
||||
assertAsmTypeFail(USE_ASM + "const i=13; function f(j) { j=j|0; i=j; return i|0 } return f");
|
||||
assertAsmTypeFail(USE_ASM + "const c=0,i=13; function f(j) { j=j|0; i=j; return i|0 } return f");
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var d=.1; function f(e) { e=+e; d=e; return +e } return f"))(42.1), 42.1);
|
||||
assertAsmTypeFail(USE_ASM + "const d=.1; function f(e) { e=+e; d=e; return +e } return f");
|
||||
assertAsmTypeFail(USE_ASM + "const c=0, d=.1; function f(e) { e=+e; d=e; return +e } return f");
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var i=13; function f(i, j) { i=i|0; j=j|0; i=j; return i|0 } return f"))(42,43), 43);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var i=13; function f(j) { j=j|0; var i=0; i=j; return i|0 } return f"))(42), 42);
|
||||
|
||||
var f = asmLink(asmCompile(USE_ASM + "var i=13; function f(j) { j=j|0; if ((j|0) != -1) { i=j } else { return i|0 } return 0 } return f"));
|
||||
assertEq(f(-1), 13);
|
||||
|
@ -17,19 +31,27 @@ assertEq(f(42), 0);
|
|||
assertEq(f(-1), 42);
|
||||
|
||||
assertAsmTypeFail('global', USE_ASM + "var i=global; function f() { return i|0 } return f");
|
||||
assertAsmTypeFail('global', USE_ASM + "const i=global; function f() { return i|0 } return f");
|
||||
assertAsmTypeFail('global', USE_ASM + "var i=global|0; function f() { return i|0 } return f");
|
||||
assertAsmTypeFail('global', USE_ASM + "const i=global|0; function f() { return i|0 } return f");
|
||||
assertAsmTypeFail('global', USE_ASM + "var j=0;var i=j.i|0; function f() { return i|0 } return f");
|
||||
assertAsmTypeFail('global', USE_ASM + "var i=global.i|0; function f() { return i|0 } return f");
|
||||
assertAsmTypeFail('global', USE_ASM + "const i=global.i|0; function f() { return i|0 } return f");
|
||||
assertAsmTypeFail('global', USE_ASM + "var i=global.i|0; function f() { return i|0 } return f");
|
||||
assertAsmTypeFail('global', USE_ASM + 'var i=global.Infinity; function f() { i = 0.0 } return f');
|
||||
assertAsmTypeFail('global', USE_ASM + 'const i=global.Infinity; function f() { i = 0.0 } return f');
|
||||
assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), undefined);
|
||||
assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), undefined);
|
||||
assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), null);
|
||||
assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), null);
|
||||
assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), 3);
|
||||
assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {});
|
||||
assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {Infinity:NaN});
|
||||
assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {Infinity:-Infinity});
|
||||
assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), {Infinity:Infinity})(), Infinity);
|
||||
assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), {Infinity:Infinity})(), Infinity);
|
||||
assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.Infinity; function f() { return +i } return f'), this)(), Infinity);
|
||||
assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.Infinity; function f() { return +i } return f'), this)(), Infinity);
|
||||
assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), undefined);
|
||||
assertAsmLinkAlwaysFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), null);
|
||||
assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), 3);
|
||||
|
@ -37,10 +59,14 @@ assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f()
|
|||
assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {Infinity:Infinity});
|
||||
assertAsmLinkFail(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {Infinity:-Infinity});
|
||||
assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), {NaN:NaN})(), NaN);
|
||||
assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.NaN; function f() { return +i } return f'), {NaN:NaN})(), NaN);
|
||||
assertEq(asmLink(asmCompile('global', USE_ASM + 'var i=global.NaN; function f() { return +i } return f'), this)(), NaN);
|
||||
assertEq(asmLink(asmCompile('global', USE_ASM + 'const i=global.NaN; function f() { return +i } return f'), this)(), NaN);
|
||||
|
||||
assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'var t = new glob.Int32Array(buf); function f() {} return f'), {get Int32Array(){return Int32Array}}, null, new ArrayBuffer(4096))
|
||||
assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'const t = new glob.Int32Array(buf); function f() {} return f'), {get Int32Array(){return Int32Array}}, null, new ArrayBuffer(4096))
|
||||
assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'var t = new glob.Int32Array(buf); function f() {} return f'), new Proxy({}, {get:function() {return Int32Array}}), null, new ArrayBuffer(4096))
|
||||
assertAsmLinkFail(asmCompile('glob','foreign','buf', USE_ASM + 'const t = new glob.Int32Array(buf); function f() {} return f'), new Proxy({}, {get:function() {return Int32Array}}), null, new ArrayBuffer(4096))
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), {get Math(){return Math}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), new Proxy({}, {get:function(){return Math}}));
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var t = glob.Math.sin; function f() {} return f'), {Math:{get sin(){return Math.sin}}});
|
||||
|
@ -61,9 +87,13 @@ assertAsmLinkAlwaysFail(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; fu
|
|||
assertAsmLinkAlwaysFail(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), this, null);
|
||||
assertAsmLinkFail(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f"), this, 42);
|
||||
assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f")(null, {i:42})), 42);
|
||||
assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=imp.i|0; function f() { return i|0 } return f")(null, {i:42})), 42);
|
||||
assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=imp.i|0; function f() { return i|0 } return f")(null, {i:1.4})), 1);
|
||||
assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=imp.i|0; function f() { return i|0 } return f")(null, {i:1.4})), 1);
|
||||
assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=+imp.i; function f() { return +i } return f")(null, {i:42})), 42);
|
||||
assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=+imp.i; function f() { return +i } return f")(null, {i:42})), 42);
|
||||
assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "var i=+imp.i; function f() { return +i } return f")(this, {i:1.4})), 1.4);
|
||||
assertEq(asmLink(asmCompile('global', 'imp', USE_ASM + "const i=+imp.i; function f() { return +i } return f")(this, {i:1.4})), 1.4);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var i=42; while (1) { break; } g = i; return g|0 } return f"))(), 42);
|
||||
|
||||
var f1 = asmCompile('global', 'foreign', 'heap', USE_ASM + 'var i32 = new global.Int32Array(heap); function g() { return i32[4]|0 } return g');
|
||||
|
|
|
@ -453,3 +453,81 @@ assertEq(new Int32Array(buf)[0], 1);
|
|||
|
||||
// Bug 882012
|
||||
assertEq(asmLink(asmCompile('stdlib', 'foreign', 'heap', USE_ASM + "var id=foreign.id;var doubles=new stdlib.Float64Array(heap);function g(){doubles[0]=+id(2.0);return +doubles[0];}return g"), this, {id: function(x){return x;}}, BUF_64KB)(), 2.0);
|
||||
|
||||
|
||||
// Some literal constant paths.
|
||||
|
||||
var buf = new ArrayBuffer(8192);
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[0>>4294967295]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[0>>-1]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[0>>0x80000000]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[0>>-2147483648]|0; } return f');
|
||||
|
||||
new Uint32Array(buf)[0] = 0xAA;
|
||||
new Uint32Array(buf)[0x5A>>2] = 0xA5;
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[(0x5A&4294967295)>>2]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=4294967295; function f() { return u32[(0x5A&i)>>2]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[(0x5A&-1)>>2]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-1; function f() { return u32[(0x5A&i)>>2]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[(0x5A&0x80000000)>>2]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=0x80000000; function f() { return u32[(0x5A&i)>>2]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[(0x5A&-2147483648)>>2]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-2147483648; function f() { return u32[(0x5A&i)>>2]|0; } return f'), this, null, buf)(),0xAA);
|
||||
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[(4294967295&0x5A)>>2]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=4294967295; function f() { return u32[(i&0x5A)>>2]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[(-1&0x5A)>>2]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-1; function f() { return u32[(i&0x5A)>>2]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[(0x80000000&0x5A)>>2]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=0x80000000; function f() { return u32[(i&0x5A)>>2]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[(-2147483648&0x5A)>>2]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-2147483648; function f() { return u32[(-2147483648&0x5A)>>2]|0; } return f'), this, null, buf)(),0xAA);
|
||||
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[4294967295>>2]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=4294967295; function f() { return u32[i>>2]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[-1>>2]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-1; function f() { return u32[i>>2]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[0x80000000>>2]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=0x80000000; function f() { return u32[i>>2]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[-2147483648>>2]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-2147483648; function f() { return u32[-2147483648>>2]|0; } return f'), this, null, buf)(),0);
|
||||
|
||||
var buf = new ArrayBuffer(8192);
|
||||
new Uint8Array(buf)[0] = 0xAA;
|
||||
new Uint8Array(buf)[0x5A] = 0xA5;
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x5A&4294967295]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=4294967295; function f() { return u8[0x5A&i]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x5A&-1]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-1; function f() { return u8[0x5A&i]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x5A&0x80000000]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=0x80000000; function f() { return u8[0x5A&i]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x5A&-2147483648]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-2147483648; function f() { return u8[0x5A&i]|0; } return f'), this, null, buf)(),0xAA);
|
||||
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[4294967295&0x5A]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=4294967295; function f() { return u8[i&0x5A]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[-1&0x5A]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-1; function f() { return u8[i&0x5A]|0; } return f'), this, null, buf)(),0xA5);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x80000000&0x5A]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=0x80000000; function f() { return u8[i&0x5A]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[-2147483648&0x5A]|0; } return f'), this, null, buf)(),0xAA);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-2147483648; function f() { return u8[i&0x5A]|0; } return f'), this, null, buf)(),0xAA);
|
||||
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[4294967295]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=4294967295; function f() { return u8[i]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[-1]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-1; function f() { return u8[i]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x80000000]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=0x80000000; function f() { return u8[i]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[-2147483648]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-2147483648; function f() { return u8[i]|0; } return f');
|
||||
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[4294967295>>0]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=4294967295; function f() { return u8[i>>0]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[-1>>0]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-1; function f() { return u8[i>>0]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[0x80000000>>0]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=0x80000000; function f() { return u8[i>>0]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u8[-2147483648>>0]|0; } return f'), this, null, buf)(),0);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'const i=-2147483648; function f() { return u8[i>>0]|0; } return f'), this, null, buf)(),0);
|
||||
|
||||
|
|
|
@ -41,6 +41,10 @@ assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { i=i|0; return (i+-2147483
|
|||
assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { i=i|0; return (i+4294967295)|0 } return f'))(0), 4294967295|0);
|
||||
|
||||
assertAsmTypeFail(USE_ASM + 'var i=-2147483649; function f() { return i|0 } return f');
|
||||
assertAsmTypeFail(USE_ASM + 'const i=-2147483649; function f() { return i|0 } return f');
|
||||
assertAsmTypeFail(USE_ASM + 'var i=4294967296; function f() { return i|0 } return f');
|
||||
assertAsmTypeFail(USE_ASM + 'const i=4294967296; function f() { return i|0 } return f');
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'var i=-2147483648; function f() { return i|0 } return f'))(), -2147483648);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'const i=-2147483648; function f() { return i|0 } return f'))(), -2147483648);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'var i=4294967295; function f() { return i|0 } return f'))(), 4294967295|0);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'const i=4294967295; function f() { return i|0 } return f'))(), 4294967295|0);
|
||||
|
|
|
@ -9,6 +9,7 @@ function testUnary(f, g) {
|
|||
assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:Math.sqrt}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:null}});
|
||||
testUnary(asmLink(asmCompile('glob', USE_ASM + 'var sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:Math.sin}}), Math.sin);
|
||||
testUnary(asmLink(asmCompile('glob', USE_ASM + 'const sq=glob.Math.sin; function f(d) { d=+d; return +sq(d) } return f'), {Math:{sin:Math.sin}}), Math.sin);
|
||||
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var co=glob.Math.cos; function f(d) { d=+d; return +co(d) } return f'), {Math:{cos:Math.sqrt}});
|
||||
assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var co=glob.Math.cos; function f(d) { d=+d; return +co(d) } return f'), {Math:{cos:null}});
|
||||
|
|
|
@ -146,7 +146,7 @@ CallArgList(ParseNode *pn)
|
|||
static inline ParseNode *
|
||||
VarListHead(ParseNode *pn)
|
||||
{
|
||||
JS_ASSERT(pn->isKind(PNK_VAR));
|
||||
JS_ASSERT(pn->isKind(PNK_VAR) || pn->isKind(PNK_CONST));
|
||||
return ListHead(pn);
|
||||
}
|
||||
|
||||
|
@ -370,9 +370,10 @@ PeekToken(AsmJSParser &parser)
|
|||
}
|
||||
|
||||
static bool
|
||||
ParseVarStatement(AsmJSParser &parser, ParseNode **var)
|
||||
ParseVarOrConstStatement(AsmJSParser &parser, ParseNode **var)
|
||||
{
|
||||
if (PeekToken(parser) != TOK_VAR) {
|
||||
TokenKind tk = PeekToken(parser);
|
||||
if (tk != TOK_VAR && tk != TOK_CONST) {
|
||||
*var = NULL;
|
||||
return true;
|
||||
}
|
||||
|
@ -381,7 +382,7 @@ ParseVarStatement(AsmJSParser &parser, ParseNode **var)
|
|||
if (!*var)
|
||||
return false;
|
||||
|
||||
JS_ASSERT((*var)->isKind(PNK_VAR));
|
||||
JS_ASSERT((*var)->isKind(PNK_VAR) || (*var)->isKind(PNK_CONST));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -823,7 +824,7 @@ ExtractNumericLiteral(ParseNode *pn)
|
|||
}
|
||||
|
||||
static inline bool
|
||||
IsLiteralUint32(ParseNode *pn, uint32_t *u32)
|
||||
IsLiteralInt(ParseNode *pn, uint32_t *u32)
|
||||
{
|
||||
if (!IsNumericLiteral(pn))
|
||||
return false;
|
||||
|
@ -832,9 +833,9 @@ IsLiteralUint32(ParseNode *pn, uint32_t *u32)
|
|||
switch (literal.which()) {
|
||||
case NumLit::Fixnum:
|
||||
case NumLit::BigUnsigned:
|
||||
case NumLit::NegativeInt:
|
||||
*u32 = uint32_t(literal.toInt32());
|
||||
return true;
|
||||
case NumLit::NegativeInt:
|
||||
case NumLit::Double:
|
||||
case NumLit::OutOfRangeInt:
|
||||
return false;
|
||||
|
@ -1019,6 +1020,9 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||
struct {
|
||||
uint32_t index_;
|
||||
VarType::Which type_;
|
||||
bool isConst_;
|
||||
bool isLitConst_;
|
||||
Value litConstValue_;
|
||||
} var;
|
||||
uint32_t funcIndex_;
|
||||
uint32_t funcPtrTableIndex_;
|
||||
|
@ -1045,6 +1049,19 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||
JS_ASSERT(which_ == Variable);
|
||||
return u.var.index_;
|
||||
}
|
||||
bool varIsConstant() const {
|
||||
JS_ASSERT(which_ == Variable);
|
||||
return u.var.isConst_;
|
||||
}
|
||||
bool varIsLitConstant() const {
|
||||
JS_ASSERT(which_ == Variable);
|
||||
return u.var.isLitConst_;
|
||||
}
|
||||
const Value &litConstValue() const {
|
||||
JS_ASSERT(which_ == Variable);
|
||||
JS_ASSERT(u.var.isLitConst_);
|
||||
return u.var.litConstValue_;
|
||||
}
|
||||
uint32_t funcIndex() const {
|
||||
JS_ASSERT(which_ == Function);
|
||||
return u.funcIndex_;
|
||||
|
@ -1361,7 +1378,8 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||
void initImportArgumentName(PropertyName *n) { module_->initImportArgumentName(n); }
|
||||
void initBufferArgumentName(PropertyName *n) { module_->initBufferArgumentName(n); }
|
||||
|
||||
bool addGlobalVarInitConstant(PropertyName *varName, VarType type, const Value &v) {
|
||||
bool addGlobalVarInitConstant(PropertyName *varName, VarType type, const Value &v,
|
||||
bool isConst) {
|
||||
uint32_t index;
|
||||
if (!module_->addGlobalVarInitConstant(v, &index))
|
||||
return false;
|
||||
|
@ -1370,9 +1388,14 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||
return false;
|
||||
global->u.var.index_ = index;
|
||||
global->u.var.type_ = type.which();
|
||||
global->u.var.isConst_ = isConst;
|
||||
global->u.var.isLitConst_ = isConst;
|
||||
if (isConst)
|
||||
global->u.var.litConstValue_ = v;
|
||||
return globals_.putNew(varName, global);
|
||||
}
|
||||
bool addGlobalVarImport(PropertyName *varName, PropertyName *fieldName, AsmJSCoercion coercion) {
|
||||
bool addGlobalVarImport(PropertyName *varName, PropertyName *fieldName, AsmJSCoercion coercion,
|
||||
bool isConst) {
|
||||
uint32_t index;
|
||||
if (!module_->addGlobalVarImport(fieldName, coercion, &index))
|
||||
return false;
|
||||
|
@ -1381,6 +1404,8 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||
return false;
|
||||
global->u.var.index_ = index;
|
||||
global->u.var.type_ = VarType(coercion).which();
|
||||
global->u.var.isConst_ = isConst;
|
||||
global->u.var.isLitConst_ = false;
|
||||
return globals_.putNew(varName, global);
|
||||
}
|
||||
bool addFunction(PropertyName *name, MoveRef<Signature> sig, Func **func) {
|
||||
|
@ -1990,9 +2015,16 @@ class FunctionCompiler
|
|||
{
|
||||
if (!curBlock_)
|
||||
return NULL;
|
||||
if (global.varIsLitConstant()) {
|
||||
JS_ASSERT(global.litConstValue().isNumber());
|
||||
MConstant *constant = MConstant::New(global.litConstValue());
|
||||
curBlock_->add(constant);
|
||||
return constant;
|
||||
}
|
||||
MIRType type = global.varType().toMIRType();
|
||||
unsigned globalDataOffset = module().globalVarIndexToGlobalDataOffset(global.varIndex());
|
||||
MAsmJSLoadGlobalVar *load = MAsmJSLoadGlobalVar::New(type, globalDataOffset);
|
||||
MAsmJSLoadGlobalVar *load = MAsmJSLoadGlobalVar::New(type, globalDataOffset,
|
||||
global.varIsConstant());
|
||||
curBlock_->add(load);
|
||||
return load;
|
||||
}
|
||||
|
@ -2692,7 +2724,8 @@ CheckPrecedingStatements(ModuleCompiler &m, ParseNode *stmtList)
|
|||
}
|
||||
|
||||
static bool
|
||||
CheckGlobalVariableInitConstant(ModuleCompiler &m, PropertyName *varName, ParseNode *initNode)
|
||||
CheckGlobalVariableInitConstant(ModuleCompiler &m, PropertyName *varName, ParseNode *initNode,
|
||||
bool isConst)
|
||||
{
|
||||
NumLit literal = ExtractNumericLiteral(initNode);
|
||||
VarType type;
|
||||
|
@ -2708,7 +2741,7 @@ CheckGlobalVariableInitConstant(ModuleCompiler &m, PropertyName *varName, ParseN
|
|||
case NumLit::OutOfRangeInt:
|
||||
return m.fail(initNode, "global initializer is out of representable integer range");
|
||||
}
|
||||
return m.addGlobalVarInitConstant(varName, type, literal.value());
|
||||
return m.addGlobalVarInitConstant(varName, type, literal.value(), isConst);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -2744,7 +2777,8 @@ CheckTypeAnnotation(ModuleCompiler &m, ParseNode *coercionNode, AsmJSCoercion *c
|
|||
}
|
||||
|
||||
static bool
|
||||
CheckGlobalVariableInitImport(ModuleCompiler &m, PropertyName *varName, ParseNode *initNode)
|
||||
CheckGlobalVariableInitImport(ModuleCompiler &m, PropertyName *varName, ParseNode *initNode,
|
||||
bool isConst)
|
||||
{
|
||||
AsmJSCoercion coercion;
|
||||
ParseNode *coercedExpr;
|
||||
|
@ -2763,7 +2797,7 @@ CheckGlobalVariableInitImport(ModuleCompiler &m, PropertyName *varName, ParseNod
|
|||
if (!IsUseOfName(base, importName))
|
||||
return m.failName(coercedExpr, "base of import expression must be '%s'", importName);
|
||||
|
||||
return m.addGlobalVarImport(varName, field, coercion);
|
||||
return m.addGlobalVarImport(varName, field, coercion, isConst);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -2850,7 +2884,7 @@ CheckGlobalDotImport(ModuleCompiler &m, PropertyName *varName, ParseNode *initNo
|
|||
}
|
||||
|
||||
static bool
|
||||
CheckModuleGlobal(ModuleCompiler &m, ParseNode *var)
|
||||
CheckModuleGlobal(ModuleCompiler &m, ParseNode *var, bool isConst)
|
||||
{
|
||||
if (!IsDefinition(var))
|
||||
return m.fail(var, "import variable names must be unique");
|
||||
|
@ -2863,10 +2897,10 @@ CheckModuleGlobal(ModuleCompiler &m, ParseNode *var)
|
|||
return m.fail(var, "module import needs initializer");
|
||||
|
||||
if (IsNumericLiteral(initNode))
|
||||
return CheckGlobalVariableInitConstant(m, var->name(), initNode);
|
||||
return CheckGlobalVariableInitConstant(m, var->name(), initNode, isConst);
|
||||
|
||||
if (initNode->isKind(PNK_BITOR) || initNode->isKind(PNK_POS))
|
||||
return CheckGlobalVariableInitImport(m, var->name(), initNode);
|
||||
return CheckGlobalVariableInitImport(m, var->name(), initNode, isConst);
|
||||
|
||||
if (initNode->isKind(PNK_NEW))
|
||||
return CheckNewArrayView(m, var->name(), initNode);
|
||||
|
@ -2882,12 +2916,12 @@ CheckModuleGlobals(ModuleCompiler &m)
|
|||
{
|
||||
while (true) {
|
||||
ParseNode *varStmt;
|
||||
if (!ParseVarStatement(m.parser(), &varStmt))
|
||||
if (!ParseVarOrConstStatement(m.parser(), &varStmt))
|
||||
return false;
|
||||
if (!varStmt)
|
||||
break;
|
||||
for (ParseNode *var = VarListHead(varStmt); var; var = NextNode(var)) {
|
||||
if (!CheckModuleGlobal(m, var))
|
||||
if (!CheckModuleGlobal(m, var, varStmt->isKind(PNK_CONST)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3106,6 +3140,30 @@ CheckVarRef(FunctionCompiler &f, ParseNode *varRef, MDefinition **def, Type *typ
|
|||
return f.failName(varRef, "'%s' not found in local or asm.js module scope", name);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsLiteralOrConstInt(FunctionCompiler &f, ParseNode *pn, uint32_t *u32)
|
||||
{
|
||||
if (IsLiteralInt(pn, u32))
|
||||
return true;
|
||||
|
||||
if (pn->getKind() != PNK_NAME)
|
||||
return false;
|
||||
|
||||
PropertyName *name = pn->name();
|
||||
const ModuleCompiler::Global *global = f.lookupGlobal(name);
|
||||
if (!global || global->which() != ModuleCompiler::Global::Variable ||
|
||||
!global->varIsLitConstant()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Value &v = global->litConstValue();
|
||||
if (!v.isInt32())
|
||||
return false;
|
||||
|
||||
*u32 = (uint32_t) v.toInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
FoldMaskedArrayIndex(FunctionCompiler &f, ParseNode **indexExpr, int32_t *mask,
|
||||
NeedsBoundsCheck *needsBoundsCheck)
|
||||
|
@ -3114,7 +3172,7 @@ FoldMaskedArrayIndex(FunctionCompiler &f, ParseNode **indexExpr, int32_t *mask,
|
|||
ParseNode *maskNode = BinaryRight(*indexExpr);
|
||||
|
||||
uint32_t mask2;
|
||||
if (IsLiteralUint32(maskNode, &mask2)) {
|
||||
if (IsLiteralOrConstInt(f, maskNode, &mask2)) {
|
||||
// Flag the access to skip the bounds check if the mask ensures that an 'out of
|
||||
// bounds' access can not occur based on the current heap length constraint.
|
||||
if (mask2 == 0 ||
|
||||
|
@ -3147,7 +3205,7 @@ CheckArrayAccess(FunctionCompiler &f, ParseNode *elem, ArrayBufferView::ViewType
|
|||
*viewType = global->viewType();
|
||||
|
||||
uint32_t pointer;
|
||||
if (IsLiteralUint32(indexExpr, &pointer)) {
|
||||
if (IsLiteralOrConstInt(f, indexExpr, &pointer)) {
|
||||
if (pointer > (uint32_t(INT32_MAX) >> TypedArrayShift(*viewType)))
|
||||
return f.fail(indexExpr, "constant index out of range");
|
||||
pointer <<= TypedArrayShift(*viewType);
|
||||
|
@ -3171,7 +3229,7 @@ CheckArrayAccess(FunctionCompiler &f, ParseNode *elem, ArrayBufferView::ViewType
|
|||
ParseNode *pointerNode = BinaryLeft(indexExpr);
|
||||
|
||||
uint32_t shift;
|
||||
if (!IsLiteralUint32(shiftNode, &shift))
|
||||
if (!IsLiteralInt(shiftNode, &shift))
|
||||
return f.failf(shiftNode, "shift amount must be constant");
|
||||
|
||||
unsigned requiredShift = TypedArrayShift(*viewType);
|
||||
|
@ -3184,7 +3242,7 @@ CheckArrayAccess(FunctionCompiler &f, ParseNode *elem, ArrayBufferView::ViewType
|
|||
// Fold a 'literal constant right shifted' now, and skip the bounds check if
|
||||
// currently possible. This handles the optimization of many of these uses without
|
||||
// the need for range analysis, and saves the generation of a MBitAnd op.
|
||||
if (IsLiteralUint32(pointerNode, &pointer) && pointer <= uint32_t(INT32_MAX)) {
|
||||
if (IsLiteralOrConstInt(f, pointerNode, &pointer) && pointer <= uint32_t(INT32_MAX)) {
|
||||
// Cases: b[c>>n], and b[(c&m)>>n]
|
||||
pointer &= mask;
|
||||
if (pointer < f.m().minHeapLength())
|
||||
|
@ -3297,6 +3355,8 @@ CheckAssignName(FunctionCompiler &f, ParseNode *lhs, ParseNode *rhs, MDefinition
|
|||
} else if (const ModuleCompiler::Global *global = f.lookupGlobal(name)) {
|
||||
if (global->which() != ModuleCompiler::Global::Variable)
|
||||
return f.failName(lhs, "'%s' is not a mutable variable", name);
|
||||
if (global->varIsConstant())
|
||||
return f.failName(lhs, "'%s' is a constant variable and not mutable", name);
|
||||
if (!(rhsType <= global->varType())) {
|
||||
return f.failf(lhs, "%s is not a subtype of %s",
|
||||
rhsType.toChars(), global->varType().toType().toChars());
|
||||
|
@ -3560,7 +3620,7 @@ CheckFuncPtrCall(FunctionCompiler &f, ParseNode *callNode, RetType retType, MDef
|
|||
ParseNode *maskNode = BinaryRight(indexExpr);
|
||||
|
||||
uint32_t mask;
|
||||
if (!IsLiteralUint32(maskNode, &mask) || mask == UINT32_MAX || !IsPowerOfTwo(mask + 1))
|
||||
if (!IsLiteralInt(maskNode, &mask) || mask == UINT32_MAX || !IsPowerOfTwo(mask + 1))
|
||||
return f.fail(maskNode, "function-pointer table index mask value must be a power of two");
|
||||
|
||||
MDefinition *indexDef;
|
||||
|
@ -5187,7 +5247,7 @@ CheckFuncPtrTables(ModuleCompiler &m)
|
|||
{
|
||||
while (true) {
|
||||
ParseNode *varStmt;
|
||||
if (!ParseVarStatement(m.parser(), &varStmt))
|
||||
if (!ParseVarOrConstStatement(m.parser(), &varStmt))
|
||||
return false;
|
||||
if (!varStmt)
|
||||
break;
|
||||
|
|
|
@ -8434,23 +8434,33 @@ class MAsmJSStoreHeap : public MBinaryInstruction, public MAsmJSHeapAccess
|
|||
|
||||
class MAsmJSLoadGlobalVar : public MNullaryInstruction
|
||||
{
|
||||
MAsmJSLoadGlobalVar(MIRType type, unsigned globalDataOffset)
|
||||
: globalDataOffset_(globalDataOffset)
|
||||
MAsmJSLoadGlobalVar(MIRType type, unsigned globalDataOffset, bool isConstant)
|
||||
: globalDataOffset_(globalDataOffset), isConstant_(isConstant)
|
||||
{
|
||||
JS_ASSERT(type == MIRType_Int32 || type == MIRType_Double);
|
||||
setResultType(type);
|
||||
if (isConstant)
|
||||
setMovable();
|
||||
}
|
||||
|
||||
unsigned globalDataOffset_;
|
||||
bool isConstant_;
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(AsmJSLoadGlobalVar);
|
||||
|
||||
static MAsmJSLoadGlobalVar *New(MIRType type, unsigned globalDataOffset) {
|
||||
return new MAsmJSLoadGlobalVar(type, globalDataOffset);
|
||||
static MAsmJSLoadGlobalVar *New(MIRType type, unsigned globalDataOffset, bool isConstant) {
|
||||
return new MAsmJSLoadGlobalVar(type, globalDataOffset, isConstant);
|
||||
}
|
||||
|
||||
unsigned globalDataOffset() const { return globalDataOffset_; }
|
||||
|
||||
AliasSet getAliasSet() const {
|
||||
if (isConstant_)
|
||||
return AliasSet::None();
|
||||
else
|
||||
return AliasSet::Store(AliasSet::Any);
|
||||
}
|
||||
};
|
||||
|
||||
class MAsmJSStoreGlobalVar : public MUnaryInstruction
|
||||
|
|
Загрузка…
Ссылка в новой задаче