LossyLosslessInt32.js 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. // Lossless conversion to int32 for compensation, needs to bail out even with aggressive int spec disabled. Incr_A is not
  6. // type-specialized on loop second pass, because 'a' is live on the back-edge and becomes a NumberValue on merge, in turn
  7. // because '++a' may overflow a 32-bit integer during the loop. The lossless conversion to int32 therefore must include bailout,
  8. // to account for the overflow. Ideally, we should not do the conversion to int32 on the back-edge, and instead make the var sym
  9. // live in the landing pad (or loop header if it's only live inside the loop).
  10. function test0(n) {
  11. var k = 0x3fffffff;
  12. k <<= 1;
  13. if(n === 1)
  14. --k;
  15. var a = k;
  16. while(n-- !== 0)
  17. ++a;
  18. return a;
  19. }
  20. WScript.Echo("test0: " + test0(2));
  21. // Array element type specialization bug (uses lossy int32 index)
  22. function test1() {
  23. var a = [1];
  24. a.foo = 2;
  25. function test1a(i) {
  26. var j = i & 1;
  27. return a[i] + a[j];
  28. }
  29. return test1a("foo");
  30. }
  31. WScript.Echo("test1: " + test1());
  32. // Loop prepass, upon type specialization, should keep the destination value consistent with that sym's liveness. In this case,
  33. // 'i' is not int-specialized in the loop prepass when aggressive int type specialization is disabled, so 'i' should be given
  34. // a number or unknown value.
  35. function test2() {
  36. var i = 0;
  37. do {
  38. ++i;
  39. } while(i < 1);
  40. return i;
  41. }
  42. WScript.Echo("test2: " + test2());
  43. // - Lossy conversion of 'a' to int32 due to 'a | 0' should include a bailout on implicit calls since it may have a side effect
  44. // - The FromVar with bailout should not be dead-store-removed due to the possibility of side effects
  45. // - When lossy int type specialization is disabled, the resulting value of '~a' should still be an int range value so that the
  46. // '+' can still be int-specialized
  47. // - Errors during ToPrimitive are handled appropriately by throwing after bailing out
  48. function test3a(a) {
  49. a | 0;
  50. return ~a + 1;
  51. }
  52. WScript.Echo("test3a: " + test3a(-2));
  53. function test3b(a) {
  54. a | 0;
  55. return ~a + 1;
  56. }
  57. WScript.Echo(
  58. "test3b: " +
  59. test3b(
  60. {
  61. valueOf:
  62. function () {
  63. WScript.Echo("test3b: valueOf");
  64. return -2;
  65. }
  66. }));
  67. function test3c(a) {
  68. a | 0;
  69. return a | 0;
  70. }
  71. WScript.Echo("test3c: " + safeCall(test3c, { valueOf: null, toString: null }));
  72. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  73. function safeCall(f) {
  74. var args = [];
  75. for(var a = 1; a < arguments.length; ++a)
  76. args.push(arguments[a]);
  77. try {
  78. return f.apply(this, args);
  79. } catch(ex) {
  80. return ex.name;
  81. }
  82. }