params.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. function* paramTypes() {
  6. while (true) {
  7. yield "i32";
  8. yield "f32";
  9. yield "f64";
  10. }
  11. }
  12. function* callArguments() {
  13. while (true) {
  14. yield {value: -12345, i32: "-12345", f32: `fr(${Math.fround(-12345)})`, f64: "-12345.0"};
  15. yield {value: Math.PI, i32: `${Math.PI|0}`, f32: `fr(${Math.fround(Math.PI)})`, f64: `+${Math.PI}`};
  16. }
  17. }
  18. function wrapType(type, name) {
  19. switch (type) {
  20. case "i32": return `${name}|0`;
  21. case "f32": return `fr(${name})`;
  22. case "f64": return `+${name}`;
  23. default: throw new Error("Invalid Type");
  24. }
  25. }
  26. let done = false;
  27. const tested = {};
  28. function test(n) {
  29. if (n in tested) {
  30. return tested[n];
  31. }
  32. print(`Test(${n})`);
  33. const typeGen = paramTypes();
  34. const argGen = callArguments();
  35. const params = [], callArgs = [], verify = [];
  36. for (let i = 0; i < n; ++i) {
  37. const type = typeGen.next().value;
  38. const paramName = `a${i|0}`;
  39. const arg = argGen.next().value;
  40. params.push({type, name: paramName});
  41. callArgs.push(arg.value);
  42. verify.push(`if (${wrapType(type, paramName)} != ${arg[type]}) return 1;`);
  43. }
  44. const paramList = params.map(p => p.name).join(",");
  45. const paramsTypes = params.map(({type, name}) => `${name} = ${wrapType(type, name)}`).join("; ");
  46. const txt = `
  47. return function AsmModule(stdlib) {
  48. "use asm";
  49. var fr = stdlib.Math.fround;
  50. function verify(${paramList}) {
  51. ${paramsTypes};
  52. ${verify.join("\n")}
  53. return 0;
  54. }
  55. function foo(${paramList}) {
  56. ${paramsTypes}
  57. return verify(${paramList})|0;
  58. }
  59. return foo;
  60. }`;
  61. //print(txt);
  62. try {
  63. var AsmModule = (new Function(txt))();
  64. var foo = AsmModule({Math});
  65. if (foo(...callArgs) !== 1) {
  66. print(`FAILED. Failed to validate with ${n} arguments`);
  67. }
  68. tested[n] = true;
  69. return true;
  70. } catch (e) {
  71. }
  72. tested[n] = false;
  73. }
  74. const [forceTest] = WScript.Arguments;
  75. if (forceTest !== undefined) {
  76. const res = test(forceTest);
  77. print(res ? "Module is valid" : "Module is invalid");
  78. done = true;
  79. }
  80. if (done === false) {
  81. let nParams = 8201;
  82. let inc = 100;
  83. let direction = true;
  84. while (inc !== 0) {
  85. if (test(nParams)) {
  86. if (direction) {
  87. nParams += inc;
  88. } else {
  89. direction = true;
  90. inc >>= 1;
  91. nParams += inc;
  92. }
  93. } else {
  94. if (!direction) {
  95. nParams -= inc;
  96. } else {
  97. direction = false;
  98. inc >>= 1;
  99. nParams -= inc;
  100. }
  101. }
  102. if (nParams > 100000 || nParams < 0) {
  103. print(`FAILED. Params reached ${nParams} long. Expected an error by now`);
  104. break;
  105. }
  106. }
  107. print(`Support at most ${nParams} params`);
  108. }