memset_invariant.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. function* makeValueGen(a, b) {
  6. // return a for profiling
  7. yield a;
  8. // return b to bailout
  9. yield b;
  10. // return b again to compare with non jit function
  11. yield b;
  12. }
  13. function* makeStartGen(a, b) {
  14. yield 0; // for interpreter
  15. yield 32; // for jitted version
  16. yield 32; // for jitted version
  17. }
  18. function makeTest(name, config) {
  19. const f1 = `function ${name}(arr) {
  20. for(var i = -5; i < 15; ++i) {arr[i] = ${config.v1};}
  21. return arr;
  22. }`;
  23. const f2 = customName => `function ${customName}P(arr, v) {
  24. for(var i = 1; i < 8; ++i) {arr[i] = v;}
  25. return arr;
  26. }`;
  27. const f3 = `function ${name}V(arr) {
  28. const v = ${config.v1};
  29. for(var i = -2; i < 17; ++i) {arr[i] = v;}
  30. return arr;
  31. }`;
  32. const f4 = customName => `function ${customName}Z(arr, start) {
  33. const v = ${config.v1};
  34. for(var i = start; i < 5; ++i) {arr[i] = v;}
  35. return arr;
  36. }`;
  37. const extraTests = (config.wrongTypes || []).map((wrongType, i) => {
  38. const difValue = {f: f2(`${name}W${i}`), compare: f2(`${name}WC${i}`)};
  39. const genValue = makeValueGen(config.v1, wrongType);
  40. Reflect.defineProperty(difValue, "v", {
  41. get: () => genValue.next().value
  42. });
  43. return difValue;
  44. });
  45. const negativeLengthTest = {f: f4(name), compare: f4(`${name}C`), newForCompare: true};
  46. const genIndex = makeStartGen();
  47. Reflect.defineProperty(negativeLengthTest, "v", {
  48. get: () => genIndex.next().value
  49. });
  50. const tests = [
  51. {f: f1},
  52. {f: f2(name), v: config.v2 !== undefined ? config.v2 : config.v1},
  53. {f: f3},
  54. negativeLengthTest
  55. ].concat(extraTests);
  56. const convertTest = function(fnText) {
  57. var fn;
  58. eval(`fn = ${fnText}`);
  59. return fn;
  60. };
  61. for(const t of tests) {
  62. t.f = convertTest(t.f);
  63. t.compare = t.compare && convertTest(t.compare);
  64. }
  65. return tests;
  66. }
  67. const allTypes = [0, 1.5, undefined, null, 9223372036854775807, "string", {a: null, b: "b"}];
  68. const tests = [
  69. {name: "memsetUndefined", v1: undefined, wrongTypes: allTypes},
  70. {name: "memsetNull", v1: null, wrongTypes: allTypes},
  71. {name: "memsetFloat", v1: 3.14, v2: -87.684, wrongTypes: allTypes},
  72. {name: "memsetNumber", v1: 9223372036854775807, v2: -987654987654987, wrongTypes: allTypes},
  73. {name: "memsetBoolean", v1: true, v2: false, wrongTypes: allTypes},
  74. {name: "memsetString", v1: "\"thatString\"", v2: "`A template string`", wrongTypes: allTypes},
  75. {name: "memsetObject", v1: "{test: 1}", v2: [1, 2, 3], wrongTypes: allTypes},
  76. ];
  77. const types = "Int8Array Uint8Array Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array Array".split(" ");
  78. const global = this;
  79. let passed = true;
  80. for(const test of tests) {
  81. for(const t of types) {
  82. const fns = makeTest(`${test.name}${t}`, test);
  83. for(const detail of fns) {
  84. const fn = detail.f;
  85. let a1 = fn(new global[t](10), detail.v);
  86. const a2 = fn(new global[t](10), detail.v);
  87. if(detail.compare) {
  88. // the optimized version ran with a different value. Run again with a clean function to compare=
  89. a1 = detail.compare(detail.newForCompare ? new global[t](10) : a1, detail.v);
  90. }
  91. if(a1.length !== a2.length) {
  92. passed = false;
  93. print(`${fn.name} (${t}) didn't return arrays with same length`);
  94. continue;
  95. }
  96. for(let i = 0; i < a1.length; ++i) {
  97. if(a1[i] !== a2[i] && !(isNaN(a1[i]) && isNaN(a2[i]))) {
  98. passed = false;
  99. print(`${fn.name} (${t}): a1[${i}](${a1[i]}) != a2[${i}](${a2[i]})`);
  100. break;
  101. }
  102. }
  103. }
  104. }
  105. }
  106. function memsetSymbol() {const s = Symbol(); const arr = new Array(10); for(let i = 0; i < 10; ++i) {arr[i] = s;} return arr;}
  107. function memsetSymbolV(v) {const arr = new Array(10); for(let i = 0; i < 10; ++i) {arr[i] = v;} return arr;}
  108. function checkSymbols() {
  109. const s = Symbol();
  110. // Since symbol are unique, and we want to compare the result, we have to pass the same symbol everytime
  111. const a1 = memsetSymbolV(s);
  112. const a2 = memsetSymbolV(s);
  113. for(let i = 0; i < a1.length; ++i) {
  114. if(a1[i] !== a2[i]) {
  115. passed = false;
  116. // need explicit toString() for Symbol
  117. print(`memsetSymbolV: a1[${i}](${a1[i].toString()}) != a2[${i}](${a2 && a2[i].toString() || ""})`);
  118. break;
  119. }
  120. }
  121. memsetSymbol();
  122. const symbolArray = memsetSymbol();
  123. for(let i = 0; i < symbolArray.length; ++i) {
  124. if(typeof symbolArray[i] !== typeof s) {
  125. passed = false;
  126. print(`memsetSymbol: symbolArray[${i}] is not a Symbol`);
  127. break;
  128. }
  129. }
  130. }
  131. checkSymbols();
  132. print(passed ? "PASSED" : "FAILED");