| //------------------------------------------------------------------------------------------------------- |
| // Copyright (C) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. |
| //------------------------------------------------------------------------------------------------------- |
| |
| // Notes on running this script: |
| // - rldirs.xml is set up in the following way so that this script is called 2 times: |
| // - First, it's called for interpreted variant. |
| // - Then, when it's called for dynapogo variant, jshost is called with: -args dynapogo. |
| // - This script is not called for the default variant. |
| // - Idea: |
| // - Collect dynamic profile cache when called for interpreted variant. |
| // - Use dynamic profile cache when called with -args dynapogo. |
| // - Some tests cause bailout by passing different parameter to test function |
| // as when dynamic profile cache was created. |
| // - How to manually run/repro: |
| // - jshost -nonative -dynamicprofilecache:inlineBuiltIns.dpl inlineBuiltIns.js |
| // - jshost -forcenative -dynamicprofileinput:inlineBuiltIns.dpl inlineBuiltIns.js -args dynapogo |
| // - also trying using -testtrace:bailout to make sure you get the bailouts. |
| // TODO: change passing -args native to jshost and instead |
| // add support to WScript to expose getFlagByString() for Js::ConfigFlagsTable flags and check for -native. |
| |
| if (typeof (WScript) != "undefined") { |
| WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js", "self"); |
| } |
| |
| var Runtime = { |
| // returns true when this jshost is called with arguments: -args native |
| get isDynapogo() { |
| return WScript.Arguments.length > 0 && WScript.Arguments[0] == "dynapogo"; |
| } |
| }; |
| |
| var tests = { |
| test01: { |
| name: "Bailout on function = null", |
| body: function () { |
| function TestSin(x) { |
| var r1 = Math.sin(x); |
| return r1; |
| }; |
| if (Runtime.isDynapogo) { |
| var sinOrig = Math.sin; // back up Math.sin |
| assert.throws(function() { |
| Math.sin = null; |
| var r = TestSin({}); |
| assert.isTrue(isNaN(r)); |
| }, TypeError); |
| Math.sin = sinOrig; // restore Math.sin |
| } |
| else TestSin(); |
| } |
| }, |
| |
| test02: { |
| name: "Bailout on function = object, not a function", |
| body: function () { |
| function TestSin(x) { |
| var r1 = Math.sin(x); |
| return r1; |
| }; |
| if (Runtime.isDynapogo) { |
| var sinOrig = Math.sin; // back up Math.sin |
| assert.throws(function() { |
| Math.sin = {}; |
| var r = TestSin({}); |
| assert.isTrue(isNaN(r)); |
| }, TypeError); |
| Math.sin = sinOrig; // restore Math.sin |
| } |
| else TestSin(); |
| } |
| }, |
| |
| test03: { |
| name: "Bailout on function = wrong function", |
| body: function () { |
| function TestSin(x) { |
| var r1 = Math.sin(x); |
| return r1; |
| }; |
| var sinOrig = Math.sin; // back up Math.sin |
| Math.sin = Math.cos; |
| var r = TestSin({}); |
| assert.isTrue(isNaN(r)); |
| Math.sin = sinOrig; // restore Math.sin |
| } |
| }, |
| |
| test04: { |
| name: "Bailout on argument = string", |
| body: function () { |
| function TestSin(x) { |
| var r1 = Math.sin(x); |
| return r1; |
| }; |
| var r = TestSin("string"); |
| assert.isTrue(isNaN(r)); |
| } |
| }, |
| |
| test05: { |
| name: "Bailout on argument = object", |
| body: function () { |
| function TestSin(x) { |
| var r1 = Math.sin(x); |
| return r1; |
| }; |
| var r = TestSin({}); |
| assert.isTrue(isNaN(r)); |
| } |
| }, |
| |
| test06: { |
| name: "Bailout on 2nd argument = string", |
| body: function () { |
| function TestPow(x, y) { |
| var r1 = Math.pow(x, y); |
| return r1; |
| }; |
| var r = TestPow(2, "string"); |
| assert.isTrue(isNaN(r)); |
| } |
| }, |
| |
| test07: { |
| name: "Float/int type specialized argOuts which we restore at bailout", |
| body: function () { |
| // As long as there is no assert/crash, we are fine. |
| (function() { |
| var i = -8.1E+18; |
| var r = Math.pow(1, Math.exp(Math.atan2(1, ((~i) - 737882964)))); |
| })(); |
| |
| (function() { |
| var e = 1; |
| return Math.pow(e >> 1, 3.2) |
| })(); |
| |
| (function() { |
| var e = 1; |
| Math.atan2(1, Math.pow((e >>= 1), Math.tan((-1031883772 * Math.abs(-951135089))))); |
| })(); |
| |
| (function() { |
| var ary = new Array(); |
| ary[0] = 0; |
| Math.pow(1808815940.1, -ary[0]); |
| })(); |
| |
| (function() { |
| return Math.pow(Math.sin(1), Math.pow(1, 1)); |
| })(); |
| |
| (function() { |
| var o = { x: 0 }; |
| var func0 = function() |
| { |
| Math.pow(1.1, o.x * -1); |
| } |
| Math.atan2(func0(), 1); |
| })(); |
| } |
| }, |
| |
| test08: { |
| name: "Bailout on argument after function copy-prop into InlineBuiltInStart", |
| body: function () { |
| for(var i in [0, 1]) |
| assert.isTrue(isNaN(Math.pow(Math.pow(/x/, 0.1), 0.1))); |
| } |
| }, |
| |
| test09: { |
| name: "Bailout (pre-op) on 2nd arg which is updated in the place of the call - make sure 1st arg is not updated", |
| body: function() { |
| var accumulator = ""; |
| var vOf = function vOf() { accumulator += "x"; return 3; } |
| function testFunc() { |
| var i = 1; |
| do { |
| // We need to make sure that we pass original value of i (== 1) as 1st arg. |
| var x = Math.pow(i, Runtime.isDynapogo ? i = { valueOf: vOf } : 1); |
| } while (vOf == undefined); |
| } |
| testFunc(); |
| if (Runtime.isDynapogo) { |
| assert.areEqual("x", accumulator, "valueOf was called wrong number of times"); |
| } |
| } |
| }, |
| }; // tests. |
| |
| testRunner.runTests(tests); |