+2016-09-15 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r205931.
+ https://bugs.webkit.org/show_bug.cgi?id=162021
+
+ Tests for this change fail on 32-bit JSC bots (Requested by
+ ryanhaddad on #webkit).
+
+ Reverted changeset:
+
+ "[JSC] Make the rounding-related nodes support any type"
+ https://bugs.webkit.org/show_bug.cgi?id=161895
+ http://trac.webkit.org/changeset/205931
+
2016-09-15 Joseph Pecoraro <pecoraro@apple.com>
test262: Should be a SyntaxError for duplicate parameter names in function with default parameters
+++ /dev/null
-"use strict";
-
-let validInputTestCases = [
- // input as string, expected result as string.
- ["undefined", "NaN"],
- ["null", "0"],
- ["0", "0"],
- ["-0.", "-0"],
- ["0.5", "1"],
- ["-0.5", "-0"],
- ["4", "4"],
- ["42.1", "43"],
- ["42.5", "43"],
- ["42.9", "43"],
- ["-42.1", "-42"],
- ["-42.5", "-42"],
- ["-42.9", "-42"],
- ["Math.PI", "4"],
- ["Infinity", "Infinity"],
- ["-Infinity", "-Infinity"],
- ["NaN", "NaN"],
- ["\"WebKit\"", "NaN"],
- ["\"4\"", "4"],
- ["\"42.5\"", "43"],
- ["{ valueOf: () => { return 4; } }", "4"],
- ["{ valueOf: () => { return 0; } }", "0"],
- ["{ valueOf: () => { return -0; } }", "-0"],
- ["{ valueOf: () => { return 0.5; } }", "1"],
- ["{ valueOf: () => { return -0.5; } }", "-0"],
- ["{ valueOf: () => { return Number.MIN_SAFE_INTEGER; } }", "-9007199254740991"],
- ["{ valueOf: () => { return Number.MAX_SAFE_INTEGER; } }", "9007199254740991"],
- ["{ valueOf: () => { return 0x80000000|0; } }", "-2147483648"],
- ["{ valueOf: () => { return 0x7fffffff|0; } }", "2147483647"],
- ["{ valueOf: () => { return (0x80000000|0) - 0.5; } }", "-2147483648"],
- ["{ valueOf: () => { return (0x7fffffff|0) + 0.5; } }", "2147483648"],
-];
-
-let validInputTypedTestCases = validInputTestCases.map((element) => { return [eval("(" + element[0] + ")"), eval(element[1])] });
-
-function isIdentical(result, expected)
-{
- if (expected === expected) {
- if (result !== expected)
- return false;
- if (!expected && (1 / expected) !== (1 / result))
- return false;
-
- return true;
- }
- return result !== result;
-}
-
-
-// Test Math.ceil() without arguments.
-function opaqueCeilNoArgument() {
- return Math.ceil();
-}
-noInline(opaqueCeilNoArgument);
-noOSRExitFuzzing(opaqueCeilNoArgument);
-
-function testNoArgument() {
- for (let i = 0; i < 1e4; ++i) {
- let output = opaqueCeilNoArgument();
- if (!isIdentical(output, NaN)) {
- throw "Failed opaqueCeilNoArgument";
- }
- }
- if (numberOfDFGCompiles(opaqueCeilNoArgument) > 1)
- throw "The call without arguments should never exit.";
-}
-testNoArgument();
-
-
-// Test Math.ceil() with a very polymorphic input. All test cases are seen at each iteration.
-function opaqueAllTypesCeil(argument) {
- return Math.ceil(argument);
-}
-noInline(opaqueAllTypesCeil);
-noOSRExitFuzzing(opaqueAllTypesCeil);
-
-function testAllTypesCall() {
- for (let i = 0; i < 1e3; ++i) {
- for (let testCaseInput of validInputTypedTestCases) {
- let output = opaqueAllTypesCeil(testCaseInput[0]);
- if (!isIdentical(output, testCaseInput[1]))
- throw "Failed testAllTypesCall for input " + testCaseInput[0] + " expected " + testCaseInput[1] + " got " + output;
- }
- }
- if (numberOfDFGCompiles(opaqueAllTypesCeil) > 3)
- throw "We should have detected ceil() was polymorphic and generated a generic version.";
-}
-testAllTypesCall();
-
-
-// Polymorphic input but negative zero is not observable.
-function opaqueAllTypesCeilWithoutNegativeZero(argument) {
- return Math.ceil(argument) + 0;
-}
-noInline(opaqueAllTypesCeilWithoutNegativeZero);
-noOSRExitFuzzing(opaqueAllTypesCeilWithoutNegativeZero);
-
-function testAllTypesWithoutNegativeZeroCall() {
- for (let i = 0; i < 1e3; ++i) {
- for (let testCaseInput of validInputTypedTestCases) {
- let output = opaqueAllTypesCeilWithoutNegativeZero(testCaseInput[0]);
- if (!isIdentical(output, testCaseInput[1] + 0))
- throw "Failed testAllTypesWithoutNegativeZeroCall for input " + testCaseInput[0] + " expected " + testCaseInput[1] + " got " + output;
- }
- }
- if (numberOfDFGCompiles(opaqueAllTypesCeil) > 3)
- throw "We should have detected ceil() was polymorphic and generated a generic version.";
-}
-testAllTypesWithoutNegativeZeroCall();
-
-
-// Test Math.ceil() on a completely typed input. Every call see only one type.
-function testSingleTypeCall() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueCeil(argument) {
- return Math.ceil(argument);
- }
- noInline(opaqueCeil);
- noOSRExitFuzzing(opaqueCeil);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueCeil(${testCaseInput[0]}), ${testCaseInput[1]})) {
- throw "Failed testSingleTypeCall()";
- }
- }
- if (numberOfDFGCompiles(opaqueCeil) > 1)
- throw "We should have compiled a single ceil for the expected type.";
- `);
- }
-}
-testSingleTypeCall();
-
-
-// Test Math.ceil() on a completely typed input, but without negative zero.
-function testSingleTypeWithoutNegativeZeroCall() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueCeil(argument) {
- return Math.ceil(argument) + 0;
- }
- noInline(opaqueCeil);
- noOSRExitFuzzing(opaqueCeil);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueCeil(${testCaseInput[0]}), ${testCaseInput[1]} + 0)) {
- throw "Failed testSingleTypeWithoutNegativeZeroCall()";
- }
- }
- if (numberOfDFGCompiles(opaqueCeil) > 1)
- throw "We should have compiled a single ceil for the expected type.";
- `);
- }
-}
-testSingleTypeWithoutNegativeZeroCall();
-
-
-// Test Math.ceil() on constants
-function testConstant() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueCeilOnConstant() {
- return Math.ceil(${testCaseInput[0]});
- }
- noInline(opaqueCeilOnConstant);
- noOSRExitFuzzing(opaqueCeilOnConstant);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueCeilOnConstant(), ${testCaseInput[1]})) {
- throw "Failed testConstant()";
- }
- }
- if (numberOfDFGCompiles(opaqueCeilOnConstant) > 1)
- throw "We should have compiled a single ceil for the expected type.";
- `);
- }
-}
-testConstant();
-
-
-// Verify we call valueOf() exactly once per call.
-function opaqueCeilForSideEffects(argument) {
- return Math.ceil(argument);
-}
-noInline(opaqueCeilForSideEffects);
-noOSRExitFuzzing(opaqueCeilForSideEffects);
-
-function testSideEffect() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- let ceil16 = Math.ceil(16);
- for (let i = 0; i < 1e4; ++i) {
- if (opaqueCeilForSideEffects(testObject) !== ceil16)
- throw "Incorrect result in testSideEffect()";
- }
- if (testObject.counter !== 1e4)
- throw "Failed testSideEffect()";
- if (numberOfDFGCompiles(opaqueCeilForSideEffects) > 1)
- throw "opaqueCeilForSideEffects() is predictable, it should only be compiled once.";
-}
-testSideEffect();
-
-
-// Verify ceil() is not subject to CSE if the argument has side effects.
-function opaqueCeilForCSE(argument) {
- return Math.ceil(argument) + Math.ceil(argument) + Math.ceil(argument);
-}
-noInline(opaqueCeilForCSE);
-noOSRExitFuzzing(opaqueCeilForCSE);
-
-function testCSE() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- let ceil16 = Math.ceil(16);
- let threeCeil16 = ceil16 + ceil16 + ceil16;
- for (let i = 0; i < 1e4; ++i) {
- if (opaqueCeilForCSE(testObject) !== threeCeil16)
- throw "Incorrect result in testCSE()";
- }
- if (testObject.counter !== 3e4)
- throw "Failed testCSE()";
- if (numberOfDFGCompiles(opaqueCeilForCSE) > 1)
- throw "opaqueCeilForCSE() is predictable, it should only be compiled once.";
-}
-testCSE();
-
-
-// Verify ceil() is not subject to DCE if the argument has side effects.
-function opaqueCeilForDCE(argument) {
- Math.ceil(argument);
-}
-noInline(opaqueCeilForDCE);
-noOSRExitFuzzing(opaqueCeilForDCE);
-
-function testDCE() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- for (let i = 0; i < 1e4; ++i) {
- opaqueCeilForDCE(testObject);
- }
- if (testObject.counter !== 1e4)
- throw "Failed testDCE()";
- if (numberOfDFGCompiles(opaqueCeilForDCE) > 1)
- throw "opaqueCeilForDCE() is predictable, it should only be compiled once.";
-}
-testDCE();
-
-
-// Test exceptions in the argument.
-function testException() {
- let counter = 0;
- function opaqueCeilWithException(argument) {
- let result = Math.ceil(argument);
- ++counter;
- return result;
- }
- noInline(opaqueCeilWithException);
-
- let testObject = { valueOf: () => { return 64; } };
- let ceil64 = Math.ceil(64);
-
- // Warm up without exception.
- for (let i = 0; i < 1e3; ++i) {
- if (opaqueCeilWithException(testObject) !== ceil64)
- throw "Incorrect result in opaqueCeilWithException()";
- }
-
- let testThrowObject = { valueOf: () => { throw testObject; return 64; } };
-
- for (let i = 0; i < 1e2; ++i) {
- try {
- if (opaqueCeilWithException(testThrowObject) !== 8)
- throw "This code should not be reached!!";
- } catch (e) {
- if (e !== testObject) {
- throw "Wrong object thrown from opaqueCeilWithException."
- }
- }
- }
-
- if (counter !== 1e3) {
- throw "Invalid count in testException()";
- }
-}
-testException();
+++ /dev/null
-"use strict";
-
-let validInputTestCases = [
- // input as string, expected result as string.
- ["undefined", "NaN"],
- ["null", "0"],
- ["0", "0"],
- ["-0.", "-0"],
- ["0.5", "0"],
- ["-0.5", "-1"],
- ["4", "4"],
- ["42.1", "42"],
- ["42.5", "42"],
- ["42.9", "42"],
- ["-42.1", "-43"],
- ["-42.5", "-43"],
- ["-42.9", "-43"],
- ["Math.PI", "3"],
- ["Infinity", "Infinity"],
- ["-Infinity", "-Infinity"],
- ["NaN", "NaN"],
- ["\"WebKit\"", "NaN"],
- ["\"4\"", "4"],
- ["\"42.5\"", "42"],
- ["{ valueOf: () => { return 4; } }", "4"],
- ["{ valueOf: () => { return 0; } }", "0"],
- ["{ valueOf: () => { return -0; } }", "-0"],
- ["{ valueOf: () => { return 0.5; } }", "0"],
- ["{ valueOf: () => { return -0.5; } }", "-1"],
- ["{ valueOf: () => { return Number.MIN_SAFE_INTEGER; } }", "-9007199254740991"],
- ["{ valueOf: () => { return Number.MAX_SAFE_INTEGER; } }", "9007199254740991"],
- ["{ valueOf: () => { return 0x80000000|0; } }", "-2147483648"],
- ["{ valueOf: () => { return 0x7fffffff|0; } }", "2147483647"],
- ["{ valueOf: () => { return (0x80000000|0) - 0.5; } }", "-2147483649"],
- ["{ valueOf: () => { return (0x7fffffff|0) + 0.5; } }", "2147483647"],
-];
-
-let validInputTypedTestCases = validInputTestCases.map((element) => { return [eval("(" + element[0] + ")"), eval(element[1])] });
-
-function isIdentical(result, expected)
-{
- if (expected === expected) {
- if (result !== expected)
- return false;
- if (!expected && (1 / expected) !== (1 / result))
- return false;
-
- return true;
- }
- return result !== result;
-}
-
-
-// Test Math.floor() without arguments.
-function opaqueFloorNoArgument() {
- return Math.floor();
-}
-noInline(opaqueFloorNoArgument);
-noOSRExitFuzzing(opaqueFloorNoArgument);
-
-function testNoArgument() {
- for (let i = 0; i < 1e4; ++i) {
- let output = opaqueFloorNoArgument();
- if (!isIdentical(output, NaN)) {
- throw "Failed opaqueFloorNoArgument";
- }
- }
- if (numberOfDFGCompiles(opaqueFloorNoArgument) > 1)
- throw "The call without arguments should never exit.";
-}
-testNoArgument();
-
-
-// Test Math.floor() with a very polymorphic input. All test cases are seen at each iteration.
-function opaqueAllTypesFloor(argument) {
- return Math.floor(argument);
-}
-noInline(opaqueAllTypesFloor);
-noOSRExitFuzzing(opaqueAllTypesFloor);
-
-function testAllTypesCall() {
- for (let i = 0; i < 1e3; ++i) {
- for (let testCaseInput of validInputTypedTestCases) {
- let output = opaqueAllTypesFloor(testCaseInput[0]);
- if (!isIdentical(output, testCaseInput[1]))
- throw "Failed testAllTypesCall for input " + testCaseInput[0] + " expected " + testCaseInput[1] + " got " + output;
- }
- }
- if (numberOfDFGCompiles(opaqueAllTypesFloor) > 3)
- throw "We should have detected floor() was polymorphic and generated a generic version.";
-}
-testAllTypesCall();
-
-
-// Polymorphic input but negative zero is not observable.
-function opaqueAllTypesFloorWithoutNegativeZero(argument) {
- return Math.floor(argument) + 0;
-}
-noInline(opaqueAllTypesFloorWithoutNegativeZero);
-noOSRExitFuzzing(opaqueAllTypesFloorWithoutNegativeZero);
-
-function testAllTypesWithoutNegativeZeroCall() {
- for (let i = 0; i < 1e3; ++i) {
- for (let testCaseInput of validInputTypedTestCases) {
- let output = opaqueAllTypesFloorWithoutNegativeZero(testCaseInput[0]);
- if (!isIdentical(output, testCaseInput[1] + 0))
- throw "Failed testAllTypesWithoutNegativeZeroCall for input " + testCaseInput[0] + " expected " + testCaseInput[1] + " got " + output;
- }
- }
- if (numberOfDFGCompiles(opaqueAllTypesFloor) > 3)
- throw "We should have detected floor() was polymorphic and generated a generic version.";
-}
-testAllTypesWithoutNegativeZeroCall();
-
-
-// Test Math.floor() on a completely typed input. Every call see only one type.
-function testSingleTypeCall() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueFloor(argument) {
- return Math.floor(argument);
- }
- noInline(opaqueFloor);
- noOSRExitFuzzing(opaqueFloor);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueFloor(${testCaseInput[0]}), ${testCaseInput[1]})) {
- throw "Failed testSingleTypeCall()";
- }
- }
- if (numberOfDFGCompiles(opaqueFloor) > 1)
- throw "We should have compiled a single floor for the expected type.";
- `);
- }
-}
-testSingleTypeCall();
-
-
-// Test Math.floor() on a completely typed input, but without negative zero.
-function testSingleTypeWithoutNegativeZeroCall() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueFloor(argument) {
- return Math.floor(argument) + 0;
- }
- noInline(opaqueFloor);
- noOSRExitFuzzing(opaqueFloor);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueFloor(${testCaseInput[0]}), ${testCaseInput[1]} + 0)) {
- throw "Failed testSingleTypeWithoutNegativeZeroCall()";
- }
- }
- if (numberOfDFGCompiles(opaqueFloor) > 1)
- throw "We should have compiled a single floor for the expected type.";
- `);
- }
-}
-testSingleTypeWithoutNegativeZeroCall();
-
-
-// Test Math.floor() on constants
-function testConstant() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueFloorOnConstant() {
- return Math.floor(${testCaseInput[0]});
- }
- noInline(opaqueFloorOnConstant);
- noOSRExitFuzzing(opaqueFloorOnConstant);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueFloorOnConstant(), ${testCaseInput[1]})) {
- throw "Failed testConstant()";
- }
- }
- if (numberOfDFGCompiles(opaqueFloorOnConstant) > 1)
- throw "We should have compiled a single floor for the expected type.";
- `);
- }
-}
-testConstant();
-
-
-// Verify we call valueOf() exactly once per call.
-function opaqueFloorForSideEffects(argument) {
- return Math.floor(argument);
-}
-noInline(opaqueFloorForSideEffects);
-noOSRExitFuzzing(opaqueFloorForSideEffects);
-
-function testSideEffect() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- let floor16 = Math.floor(16);
- for (let i = 0; i < 1e4; ++i) {
- if (opaqueFloorForSideEffects(testObject) !== floor16)
- throw "Incorrect result in testSideEffect()";
- }
- if (testObject.counter !== 1e4)
- throw "Failed testSideEffect()";
- if (numberOfDFGCompiles(opaqueFloorForSideEffects) > 1)
- throw "opaqueFloorForSideEffects() is predictable, it should only be compiled once.";
-}
-testSideEffect();
-
-
-// Verify floor() is not subject to CSE if the argument has side effects.
-function opaqueFloorForCSE(argument) {
- return Math.floor(argument) + Math.floor(argument) + Math.floor(argument);
-}
-noInline(opaqueFloorForCSE);
-noOSRExitFuzzing(opaqueFloorForCSE);
-
-function testCSE() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- let floor16 = Math.floor(16);
- let threeFloor16 = floor16 + floor16 + floor16;
- for (let i = 0; i < 1e4; ++i) {
- if (opaqueFloorForCSE(testObject) !== threeFloor16)
- throw "Incorrect result in testCSE()";
- }
- if (testObject.counter !== 3e4)
- throw "Failed testCSE()";
- if (numberOfDFGCompiles(opaqueFloorForCSE) > 1)
- throw "opaqueFloorForCSE() is predictable, it should only be compiled once.";
-}
-testCSE();
-
-
-// Verify floor() is not subject to DCE if the argument has side effects.
-function opaqueFloorForDCE(argument) {
- Math.floor(argument);
-}
-noInline(opaqueFloorForDCE);
-noOSRExitFuzzing(opaqueFloorForDCE);
-
-function testDCE() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- for (let i = 0; i < 1e4; ++i) {
- opaqueFloorForDCE(testObject);
- }
- if (testObject.counter !== 1e4)
- throw "Failed testDCE()";
- if (numberOfDFGCompiles(opaqueFloorForDCE) > 1)
- throw "opaqueFloorForDCE() is predictable, it should only be compiled once.";
-}
-testDCE();
-
-
-// Test exceptions in the argument.
-function testException() {
- let counter = 0;
- function opaqueFloorWithException(argument) {
- let result = Math.floor(argument);
- ++counter;
- return result;
- }
- noInline(opaqueFloorWithException);
-
- let testObject = { valueOf: () => { return 64; } };
- let floor64 = Math.floor(64);
-
- // Warm up without exception.
- for (let i = 0; i < 1e3; ++i) {
- if (opaqueFloorWithException(testObject) !== floor64)
- throw "Incorrect result in opaqueFloorWithException()";
- }
-
- let testThrowObject = { valueOf: () => { throw testObject; return 64; } };
-
- for (let i = 0; i < 1e2; ++i) {
- try {
- if (opaqueFloorWithException(testThrowObject) !== 8)
- throw "This code should not be reached!!";
- } catch (e) {
- if (e !== testObject) {
- throw "Wrong object thrown from opaqueFloorWithException."
- }
- }
- }
-
- if (counter !== 1e3) {
- throw "Invalid count in testException()";
- }
-}
-testException();
+++ /dev/null
-"use strict";
-
-let validInputTestCases = [
- // input as string, expected result as string.
- ["undefined", "NaN"],
- ["null", "0"],
- ["0", "0"],
- ["-0.", "-0"],
- ["0.5", "1"],
- ["-0.5", "-0"],
- ["4", "4"],
- ["42.1", "42"],
- ["42.5", "43"],
- ["42.9", "43"],
- ["-42.1", "-42"],
- ["-42.5", "-42"],
- ["-42.9", "-43"],
- ["Math.PI", "3"],
- ["Infinity", "Infinity"],
- ["-Infinity", "-Infinity"],
- ["NaN", "NaN"],
- ["\"WebKit\"", "NaN"],
- ["\"4\"", "4"],
- ["\"42.5\"", "43"],
- ["{ valueOf: () => { return 4; } }", "4"],
- ["{ valueOf: () => { return 0; } }", "0"],
- ["{ valueOf: () => { return -0; } }", "-0"],
- ["{ valueOf: () => { return 0.5; } }", "1"],
- ["{ valueOf: () => { return -0.5; } }", "-0"],
- ["{ valueOf: () => { return Number.MIN_SAFE_INTEGER; } }", "-9007199254740991"],
- ["{ valueOf: () => { return Number.MAX_SAFE_INTEGER; } }", "9007199254740991"],
- ["{ valueOf: () => { return 0x80000000|0; } }", "-2147483648"],
- ["{ valueOf: () => { return 0x7fffffff|0; } }", "2147483647"],
- ["{ valueOf: () => { return (0x80000000|0) - 0.5; } }", "-2147483648"],
- ["{ valueOf: () => { return (0x7fffffff|0) + 0.5; } }", "2147483648"],
-];
-
-let validInputTypedTestCases = validInputTestCases.map((element) => { return [eval("(" + element[0] + ")"), eval(element[1])] });
-
-function isIdentical(result, expected)
-{
- if (expected === expected) {
- if (result !== expected)
- return false;
- if (!expected && (1 / expected) !== (1 / result))
- return false;
-
- return true;
- }
- return result !== result;
-}
-
-
-// Test Math.round() without arguments.
-function opaqueRoundNoArgument() {
- return Math.round();
-}
-noInline(opaqueRoundNoArgument);
-noOSRExitFuzzing(opaqueRoundNoArgument);
-
-function testNoArgument() {
- for (let i = 0; i < 1e4; ++i) {
- let output = opaqueRoundNoArgument();
- if (!isIdentical(output, NaN)) {
- throw "Failed opaqueRoundNoArgument";
- }
- }
- if (numberOfDFGCompiles(opaqueRoundNoArgument) > 1)
- throw "The call without arguments should never exit.";
-}
-testNoArgument();
-
-
-// Test Math.round() with a very polymorphic input. All test cases are seen at each iteration.
-function opaqueAllTypesRound(argument) {
- return Math.round(argument);
-}
-noInline(opaqueAllTypesRound);
-noOSRExitFuzzing(opaqueAllTypesRound);
-
-function testAllTypesCall() {
- for (let i = 0; i < 1e3; ++i) {
- for (let testCaseInput of validInputTypedTestCases) {
- let output = opaqueAllTypesRound(testCaseInput[0]);
- if (!isIdentical(output, testCaseInput[1]))
- throw "Failed testAllTypesCall for input " + testCaseInput[0] + " expected " + testCaseInput[1] + " got " + output;
- }
- }
- if (numberOfDFGCompiles(opaqueAllTypesRound) > 3)
- throw "We should have detected round() was polymorphic and generated a generic version.";
-}
-testAllTypesCall();
-
-
-// Polymorphic input but negative zero is not observable.
-function opaqueAllTypesRoundWithoutNegativeZero(argument) {
- return Math.round(argument) + 0;
-}
-noInline(opaqueAllTypesRoundWithoutNegativeZero);
-noOSRExitFuzzing(opaqueAllTypesRoundWithoutNegativeZero);
-
-function testAllTypesWithoutNegativeZeroCall() {
- for (let i = 0; i < 1e3; ++i) {
- for (let testCaseInput of validInputTypedTestCases) {
- let output = opaqueAllTypesRoundWithoutNegativeZero(testCaseInput[0]);
- if (!isIdentical(output, testCaseInput[1] + 0))
- throw "Failed testAllTypesWithoutNegativeZeroCall for input " + testCaseInput[0] + " expected " + testCaseInput[1] + " got " + output;
- }
- }
- if (numberOfDFGCompiles(opaqueAllTypesRound) > 3)
- throw "We should have detected round() was polymorphic and generated a generic version.";
-}
-testAllTypesWithoutNegativeZeroCall();
-
-
-// Test Math.round() on a completely typed input. Every call see only one type.
-function testSingleTypeCall() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueRound(argument) {
- return Math.round(argument);
- }
- noInline(opaqueRound);
- noOSRExitFuzzing(opaqueRound);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueRound(${testCaseInput[0]}), ${testCaseInput[1]})) {
- throw "Failed testSingleTypeCall()";
- }
- }
- if (numberOfDFGCompiles(opaqueRound) > 1)
- throw "We should have compiled a single round for the expected type.";
- `);
- }
-}
-testSingleTypeCall();
-
-
-// Test Math.round() on a completely typed input, but without negative zero.
-function testSingleTypeWithoutNegativeZeroCall() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueRound(argument) {
- return Math.round(argument) + 0;
- }
- noInline(opaqueRound);
- noOSRExitFuzzing(opaqueRound);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueRound(${testCaseInput[0]}), ${testCaseInput[1]} + 0)) {
- throw "Failed testSingleTypeWithoutNegativeZeroCall()";
- }
- }
- if (numberOfDFGCompiles(opaqueRound) > 1)
- throw "We should have compiled a single round for the expected type.";
- `);
- }
-}
-testSingleTypeWithoutNegativeZeroCall();
-
-
-// Test Math.round() on constants
-function testConstant() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueRoundOnConstant() {
- return Math.round(${testCaseInput[0]});
- }
- noInline(opaqueRoundOnConstant);
- noOSRExitFuzzing(opaqueRoundOnConstant);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueRoundOnConstant(), ${testCaseInput[1]})) {
- throw "Failed testConstant()";
- }
- }
- if (numberOfDFGCompiles(opaqueRoundOnConstant) > 1)
- throw "We should have compiled a single round for the expected type.";
- `);
- }
-}
-testConstant();
-
-
-// Verify we call valueOf() exactly once per call.
-function opaqueRoundForSideEffects(argument) {
- return Math.round(argument);
-}
-noInline(opaqueRoundForSideEffects);
-noOSRExitFuzzing(opaqueRoundForSideEffects);
-
-function testSideEffect() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- let round16 = Math.round(16);
- for (let i = 0; i < 1e4; ++i) {
- if (opaqueRoundForSideEffects(testObject) !== round16)
- throw "Incorrect result in testSideEffect()";
- }
- if (testObject.counter !== 1e4)
- throw "Failed testSideEffect()";
- if (numberOfDFGCompiles(opaqueRoundForSideEffects) > 1)
- throw "opaqueRoundForSideEffects() is predictable, it should only be compiled once.";
-}
-testSideEffect();
-
-
-// Verify round() is not subject to CSE if the argument has side effects.
-function opaqueRoundForCSE(argument) {
- return Math.round(argument) + Math.round(argument) + Math.round(argument);
-}
-noInline(opaqueRoundForCSE);
-noOSRExitFuzzing(opaqueRoundForCSE);
-
-function testCSE() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- let round16 = Math.round(16);
- let threeRound16 = round16 + round16 + round16;
- for (let i = 0; i < 1e4; ++i) {
- if (opaqueRoundForCSE(testObject) !== threeRound16)
- throw "Incorrect result in testCSE()";
- }
- if (testObject.counter !== 3e4)
- throw "Failed testCSE()";
- if (numberOfDFGCompiles(opaqueRoundForCSE) > 1)
- throw "opaqueRoundForCSE() is predictable, it should only be compiled once.";
-}
-testCSE();
-
-
-// Verify round() is not subject to DCE if the argument has side effects.
-function opaqueRoundForDCE(argument) {
- Math.round(argument);
-}
-noInline(opaqueRoundForDCE);
-noOSRExitFuzzing(opaqueRoundForDCE);
-
-function testDCE() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- for (let i = 0; i < 1e4; ++i) {
- opaqueRoundForDCE(testObject);
- }
- if (testObject.counter !== 1e4)
- throw "Failed testDCE()";
- if (numberOfDFGCompiles(opaqueRoundForDCE) > 1)
- throw "opaqueRoundForDCE() is predictable, it should only be compiled once.";
-}
-testDCE();
-
-
-// Test exceptions in the argument.
-function testException() {
- let counter = 0;
- function opaqueRoundWithException(argument) {
- let result = Math.round(argument);
- ++counter;
- return result;
- }
- noInline(opaqueRoundWithException);
-
- let testObject = { valueOf: () => { return 64; } };
- let round64 = Math.round(64);
-
- // Warm up without exception.
- for (let i = 0; i < 1e3; ++i) {
- if (opaqueRoundWithException(testObject) !== round64)
- throw "Incorrect result in opaqueRoundWithException()";
- }
-
- let testThrowObject = { valueOf: () => { throw testObject; return 64; } };
-
- for (let i = 0; i < 1e2; ++i) {
- try {
- if (opaqueRoundWithException(testThrowObject) !== 8)
- throw "This code should not be reached!!";
- } catch (e) {
- if (e !== testObject) {
- throw "Wrong object thrown from opaqueRoundWithException."
- }
- }
- }
-
- if (counter !== 1e3) {
- throw "Invalid count in testException()";
- }
-}
-testException();
+++ /dev/null
-"use strict";
-
-let validInputTestCases = [
- // input as string, expected result as string.
- ["undefined", "NaN"],
- ["null", "0"],
- ["0", "0"],
- ["-0.", "-0"],
- ["0.5", "0"],
- ["-0.5", "-0"],
- ["4", "4"],
- ["42.1", "42"],
- ["42.5", "42"],
- ["42.9", "42"],
- ["-42.1", "-42"],
- ["-42.5", "-42"],
- ["-42.9", "-42"],
- ["Math.PI", "3"],
- ["Infinity", "Infinity"],
- ["-Infinity", "-Infinity"],
- ["NaN", "NaN"],
- ["\"WebKit\"", "NaN"],
- ["\"4\"", "4"],
- ["\"42.5\"", "42"],
- ["{ valueOf: () => { return 4; } }", "4"],
- ["{ valueOf: () => { return 0; } }", "0"],
- ["{ valueOf: () => { return -0; } }", "-0"],
- ["{ valueOf: () => { return 0.5; } }", "0"],
- ["{ valueOf: () => { return -0.5; } }", "-0"],
- ["{ valueOf: () => { return Number.MIN_SAFE_INTEGER; } }", "-9007199254740991"],
- ["{ valueOf: () => { return Number.MAX_SAFE_INTEGER; } }", "9007199254740991"],
- ["{ valueOf: () => { return 0x80000000|0; } }", "-2147483648"],
- ["{ valueOf: () => { return 0x7fffffff|0; } }", "2147483647"],
- ["{ valueOf: () => { return (0x80000000|0) - 0.5; } }", "-2147483648"],
- ["{ valueOf: () => { return (0x7fffffff|0) + 0.5; } }", "2147483647"],
-];
-
-let validInputTypedTestCases = validInputTestCases.map((element) => { return [eval("(" + element[0] + ")"), eval(element[1])] });
-
-function isIdentical(result, expected)
-{
- if (expected === expected) {
- if (result !== expected)
- return false;
- if (!expected && (1 / expected) !== (1 / result))
- return false;
-
- return true;
- }
- return result !== result;
-}
-
-
-// Test Math.trunc() without arguments.
-function opaqueTruncNoArgument() {
- return Math.trunc();
-}
-noInline(opaqueTruncNoArgument);
-noOSRExitFuzzing(opaqueTruncNoArgument);
-
-function testNoArgument() {
- for (let i = 0; i < 1e4; ++i) {
- let output = opaqueTruncNoArgument();
- if (!isIdentical(output, NaN)) {
- throw "Failed opaqueTruncNoArgument";
- }
- }
- if (numberOfDFGCompiles(opaqueTruncNoArgument) > 1)
- throw "The call without arguments should never exit.";
-}
-testNoArgument();
-
-
-// Test Math.trunc() with a very polymorphic input. All test cases are seen at each iteration.
-function opaqueAllTypesTrunc(argument) {
- return Math.trunc(argument);
-}
-noInline(opaqueAllTypesTrunc);
-noOSRExitFuzzing(opaqueAllTypesTrunc);
-
-function testAllTypesCall() {
- for (let i = 0; i < 1e3; ++i) {
- for (let testCaseInput of validInputTypedTestCases) {
- let output = opaqueAllTypesTrunc(testCaseInput[0]);
- if (!isIdentical(output, testCaseInput[1]))
- throw "Failed testAllTypesCall for input " + testCaseInput[0] + " expected " + testCaseInput[1] + " got " + output;
- }
- }
- if (numberOfDFGCompiles(opaqueAllTypesTrunc) > 3)
- throw "We should have detected trunc() was polymorphic and generated a generic version.";
-}
-testAllTypesCall();
-
-
-// Polymorphic input but negative zero is not observable.
-function opaqueAllTypesTruncWithoutNegativeZero(argument) {
- return Math.trunc(argument) + 0;
-}
-noInline(opaqueAllTypesTruncWithoutNegativeZero);
-noOSRExitFuzzing(opaqueAllTypesTruncWithoutNegativeZero);
-
-function testAllTypesWithoutNegativeZeroCall() {
- for (let i = 0; i < 1e3; ++i) {
- for (let testCaseInput of validInputTypedTestCases) {
- let output = opaqueAllTypesTruncWithoutNegativeZero(testCaseInput[0]);
- if (!isIdentical(output, testCaseInput[1] + 0))
- throw "Failed testAllTypesWithoutNegativeZeroCall for input " + testCaseInput[0] + " expected " + testCaseInput[1] + " got " + output;
- }
- }
- if (numberOfDFGCompiles(opaqueAllTypesTrunc) > 3)
- throw "We should have detected trunc() was polymorphic and generated a generic version.";
-}
-testAllTypesWithoutNegativeZeroCall();
-
-
-// Test Math.trunc() on a completely typed input. Every call see only one type.
-function testSingleTypeCall() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueTrunc(argument) {
- return Math.trunc(argument);
- }
- noInline(opaqueTrunc);
- noOSRExitFuzzing(opaqueTrunc);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueTrunc(${testCaseInput[0]}), ${testCaseInput[1]})) {
- throw "Failed testSingleTypeCall()";
- }
- }
- if (numberOfDFGCompiles(opaqueTrunc) > 1)
- throw "We should have compiled a single trunc for the expected type.";
- `);
- }
-}
-testSingleTypeCall();
-
-
-// Test Math.trunc() on a completely typed input, but without negative zero.
-function testSingleTypeWithoutNegativeZeroCall() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueTrunc(argument) {
- return Math.trunc(argument) - 0;
- }
- noInline(opaqueTrunc);
- noOSRExitFuzzing(opaqueTrunc);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueTrunc(${testCaseInput[0]}), ${testCaseInput[1]} - 0)) {
- throw "Failed testSingleTypeWithoutNegativeZeroCall()";
- }
- }
- if (numberOfDFGCompiles(opaqueTrunc) > 1)
- throw "We should have compiled a single trunc for the expected type.";
- `);
- }
-}
-testSingleTypeWithoutNegativeZeroCall();
-
-
-// Test Math.trunc() on constants
-function testConstant() {
- for (let testCaseInput of validInputTestCases) {
- eval(`
- function opaqueTruncOnConstant() {
- return Math.trunc(${testCaseInput[0]});
- }
- noInline(opaqueTruncOnConstant);
- noOSRExitFuzzing(opaqueTruncOnConstant);
-
- for (let i = 0; i < 1e4; ++i) {
- if (!isIdentical(opaqueTruncOnConstant(), ${testCaseInput[1]})) {
- throw "Failed testConstant()";
- }
- }
- if (numberOfDFGCompiles(opaqueTruncOnConstant) > 1)
- throw "We should have compiled a single trunc for the expected type.";
- `);
- }
-}
-testConstant();
-
-
-// Verify we call valueOf() exactly once per call.
-function opaqueTruncForSideEffects(argument) {
- return Math.trunc(argument);
-}
-noInline(opaqueTruncForSideEffects);
-noOSRExitFuzzing(opaqueTruncForSideEffects);
-
-function testSideEffect() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- let trunc16 = Math.trunc(16);
- for (let i = 0; i < 1e4; ++i) {
- if (opaqueTruncForSideEffects(testObject) !== trunc16)
- throw "Incorrect result in testSideEffect()";
- }
- if (testObject.counter !== 1e4)
- throw "Failed testSideEffect()";
- if (numberOfDFGCompiles(opaqueTruncForSideEffects) > 1)
- throw "opaqueTruncForSideEffects() is predictable, it should only be compiled once.";
-}
-testSideEffect();
-
-
-// Verify trunc() is not subject to CSE if the argument has side effects.
-function opaqueTruncForCSE(argument) {
- return Math.trunc(argument) + Math.trunc(argument) + Math.trunc(argument);
-}
-noInline(opaqueTruncForCSE);
-noOSRExitFuzzing(opaqueTruncForCSE);
-
-function testCSE() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- let trunc16 = Math.trunc(16);
- let threeTrunc16 = trunc16 + trunc16 + trunc16;
- for (let i = 0; i < 1e4; ++i) {
- if (opaqueTruncForCSE(testObject) !== threeTrunc16)
- throw "Incorrect result in testCSE()";
- }
- if (testObject.counter !== 3e4)
- throw "Failed testCSE()";
- if (numberOfDFGCompiles(opaqueTruncForCSE) > 1)
- throw "opaqueTruncForCSE() is predictable, it should only be compiled once.";
-}
-testCSE();
-
-
-// Verify trunc() is not subject to DCE if the argument has side effects.
-function opaqueTruncForDCE(argument) {
- Math.trunc(argument);
-}
-noInline(opaqueTruncForDCE);
-noOSRExitFuzzing(opaqueTruncForDCE);
-
-function testDCE() {
- let testObject = {
- counter: 0,
- valueOf: function() { ++this.counter; return 16; }
- };
- for (let i = 0; i < 1e4; ++i) {
- opaqueTruncForDCE(testObject);
- }
- if (testObject.counter !== 1e4)
- throw "Failed testDCE()";
- if (numberOfDFGCompiles(opaqueTruncForDCE) > 1)
- throw "opaqueTruncForDCE() is predictable, it should only be compiled once.";
-}
-testDCE();
-
-
-// Test exceptions in the argument.
-function testException() {
- let counter = 0;
- function opaqueTruncWithException(argument) {
- let result = Math.trunc(argument);
- ++counter;
- return result;
- }
- noInline(opaqueTruncWithException);
-
- let testObject = { valueOf: () => { return 64; } };
- let trunc64 = Math.trunc(64);
-
- // Warm up without exception.
- for (let i = 0; i < 1e3; ++i) {
- if (opaqueTruncWithException(testObject) !== trunc64)
- throw "Incorrect result in opaqueTruncWithException()";
- }
-
- let testThrowObject = { valueOf: () => { throw testObject; return 64; } };
-
- for (let i = 0; i < 1e2; ++i) {
- try {
- if (opaqueTruncWithException(testThrowObject) !== 8)
- throw "This code should not be reached!!";
- } catch (e) {
- if (e !== testObject) {
- throw "Wrong object thrown from opaqueTruncWithException."
- }
- }
- }
-
- if (counter !== 1e3) {
- throw "Invalid count in testException()";
- }
-}
-testException();
+2016-09-15 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r205931.
+ https://bugs.webkit.org/show_bug.cgi?id=162021
+
+ Tests for this change fail on 32-bit JSC bots (Requested by
+ ryanhaddad on #webkit).
+
+ Reverted changeset:
+
+ "[JSC] Make the rounding-related nodes support any type"
+ https://bugs.webkit.org/show_bug.cgi?id=161895
+ http://trac.webkit.org/changeset/205931
+
2016-09-15 Joseph Pecoraro <pecoraro@apple.com>
test262: Should be a SyntaxError for duplicate parameter names in function with default parameters
case ArithCeil:
case ArithTrunc: {
JSValue operand = forNode(node->child1()).value();
- if (Optional<double> number = operand.toNumberFromPrimitive()) {
+ if (operand && operand.isNumber()) {
double roundedValue = 0;
if (node->op() == ArithRound)
- roundedValue = jsRound(*number);
+ roundedValue = jsRound(operand.asNumber());
else if (node->op() == ArithFloor)
- roundedValue = floor(*number);
+ roundedValue = floor(operand.asNumber());
else if (node->op() == ArithCeil)
- roundedValue = ceil(*number);
+ roundedValue = ceil(operand.asNumber());
else {
ASSERT(node->op() == ArithTrunc);
- roundedValue = trunc(*number);
+ roundedValue = trunc(operand.asNumber());
}
- if (node->child1().useKind() == UntypedUse) {
- setConstant(node, jsNumber(roundedValue));
- break;
- }
if (producesInteger(node->arithRoundingMode())) {
int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
if (roundedValueAsInt32 == roundedValue) {
break;
}
}
- if (node->child1().useKind() == DoubleRepUse) {
- if (producesInteger(node->arithRoundingMode()))
- forNode(node).setType(SpecInt32Only);
- else if (node->child1().useKind() == DoubleRepUse)
- forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
- } else {
- DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse);
- forNode(node).setType(SpecFullNumber);
- }
+ if (producesInteger(node->arithRoundingMode()))
+ forNode(node).setType(SpecInt32Only);
+ else
+ forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
break;
}
set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
return true;
}
- insertChecks();
- Node* operand = get(virtualRegisterForArgument(1, registerOffset));
- NodeType op;
- if (intrinsic == RoundIntrinsic)
- op = ArithRound;
- else if (intrinsic == FloorIntrinsic)
- op = ArithFloor;
- else if (intrinsic == CeilIntrinsic)
- op = ArithCeil;
- else {
- ASSERT(intrinsic == TruncIntrinsic);
- op = ArithTrunc;
+ if (argumentCountIncludingThis == 2) {
+ insertChecks();
+ Node* operand = get(virtualRegisterForArgument(1, registerOffset));
+ NodeType op;
+ if (intrinsic == RoundIntrinsic)
+ op = ArithRound;
+ else if (intrinsic == FloorIntrinsic)
+ op = ArithFloor;
+ else if (intrinsic == CeilIntrinsic)
+ op = ArithCeil;
+ else {
+ ASSERT(intrinsic == TruncIntrinsic);
+ op = ArithTrunc;
+ }
+ Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand);
+ set(VirtualRegister(resultOperand), roundNode);
+ return true;
}
- Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand);
- set(VirtualRegister(resultOperand), roundNode);
- return true;
+ return false;
}
case IMulIntrinsic: {
if (argumentCountIncludingThis != 3)
case ArithFloor:
case ArithCeil:
case ArithTrunc:
- if (node->child1().useKind() == DoubleRepUse)
- def(PureValue(node, static_cast<uintptr_t>(node->arithRoundingMode())));
- else {
- read(World);
- write(Heap);
- }
+ def(PureValue(node, static_cast<uintptr_t>(node->arithRoundingMode())));
return;
case CheckCell:
case ArithFloor:
case ArithCeil:
case ArithTrunc: {
- if (node->child1()->shouldSpeculateInt32OrBoolean() && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
+ if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
fixIntOrBooleanEdge(node->child1());
insertCheck<Int32Use>(m_indexInBlock, node->child1().node());
node->convertToIdentity();
break;
}
- if (node->child1()->shouldSpeculateNotCell()) {
- fixDoubleOrBooleanEdge(node->child1());
+ fixDoubleOrBooleanEdge(node->child1());
- if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
- node->setResult(NodeResultInt32);
- if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
- node->setArithRoundingMode(Arith::RoundingMode::Int32);
- else
- node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck);
- } else {
- node->setResult(NodeResultDouble);
- node->setArithRoundingMode(Arith::RoundingMode::Double);
- }
- node->clearFlags(NodeMustGenerate);
- } else
- fixEdge<UntypedUse>(node->child1());
+ if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
+ node->setResult(NodeResultInt32);
+ if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
+ node->setArithRoundingMode(Arith::RoundingMode::Int32);
+ else
+ node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck);
+ } else {
+ node->setResult(NodeResultDouble);
+ node->setArithRoundingMode(Arith::RoundingMode::Double);
+ }
break;
}
macro(ArithFRound, NodeResultDouble | NodeMustGenerate) \
macro(ArithPow, NodeResultDouble) \
macro(ArithRandom, NodeResultDouble | NodeMustGenerate) \
- macro(ArithRound, NodeResultNumber | NodeMustGenerate) \
- macro(ArithFloor, NodeResultNumber | NodeMustGenerate) \
- macro(ArithCeil, NodeResultNumber | NodeMustGenerate) \
- macro(ArithTrunc, NodeResultNumber | NodeMustGenerate) \
+ macro(ArithRound, NodeResultNumber) \
+ macro(ArithFloor, NodeResultNumber) \
+ macro(ArithCeil, NodeResultNumber) \
+ macro(ArithTrunc, NodeResultNumber) \
macro(ArithSqrt, NodeResultDouble | NodeMustGenerate) \
macro(ArithSin, NodeResultDouble | NodeMustGenerate) \
macro(ArithCos, NodeResultDouble | NodeMustGenerate) \
return tan(a);
}
-EncodedJSValue JIT_OPERATION operationArithRound(ExecState* exec, EncodedJSValue encodedArgument)
-{
- VM* vm = &exec->vm();
- NativeCallFrameTracer tracer(vm, exec);
- auto scope = DECLARE_THROW_SCOPE(*vm);
-
- JSValue argument = JSValue::decode(encodedArgument);
- double valueOfArgument = argument.toNumber(exec);
- if (UNLIKELY(scope.exception()))
- return JSValue::encode(JSValue());
- return JSValue::encode(jsNumber(jsRound(valueOfArgument)));
-}
-
-EncodedJSValue JIT_OPERATION operationArithFloor(ExecState* exec, EncodedJSValue encodedArgument)
-{
- VM* vm = &exec->vm();
- NativeCallFrameTracer tracer(vm, exec);
- auto scope = DECLARE_THROW_SCOPE(*vm);
-
- JSValue argument = JSValue::decode(encodedArgument);
- double valueOfArgument = argument.toNumber(exec);
- if (UNLIKELY(scope.exception()))
- return JSValue::encode(JSValue());
- return JSValue::encode(jsNumber(floor(valueOfArgument)));
-}
-
-EncodedJSValue JIT_OPERATION operationArithCeil(ExecState* exec, EncodedJSValue encodedArgument)
-{
- VM* vm = &exec->vm();
- NativeCallFrameTracer tracer(vm, exec);
- auto scope = DECLARE_THROW_SCOPE(*vm);
-
- JSValue argument = JSValue::decode(encodedArgument);
- double valueOfArgument = argument.toNumber(exec);
- if (UNLIKELY(scope.exception()))
- return JSValue::encode(JSValue());
- return JSValue::encode(jsNumber(ceil(valueOfArgument)));
-}
-
-EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState* exec, EncodedJSValue encodedArgument)
-{
- VM* vm = &exec->vm();
- NativeCallFrameTracer tracer(vm, exec);
- auto scope = DECLARE_THROW_SCOPE(*vm);
-
- JSValue argument = JSValue::decode(encodedArgument);
- double truncatedValueOfArgument = argument.toIntegerPreserveNaN(exec);
- if (UNLIKELY(scope.exception()))
- return JSValue::encode(JSValue());
- return JSValue::encode(jsNumber(truncatedValueOfArgument));
-}
-
static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
{
VM& vm = exec->vm();
/*
- * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
double JIT_OPERATION operationArithLog(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
double JIT_OPERATION operationArithSin(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
double JIT_OPERATION operationArithSqrt(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationArithRound(ExecState*, EncodedJSValue) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationArithFloor(ExecState*, EncodedJSValue) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationArithCeil(ExecState*, EncodedJSValue) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState*, EncodedJSValue) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationGetByValArrayInt(ExecState*, JSArray*, int32_t) WTF_INTERNAL;
break;
}
+ case ArithRound:
+ case ArithFloor:
+ case ArithCeil:
+ case ArithTrunc: {
+ if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, m_pass))
+ changed |= setPrediction(SpecInt32Only);
+ else
+ changed |= setPrediction(SpecBytecodeDouble);
+ break;
+ }
+
case ArithAbs: {
SpeculatedType childPrediction = node->child1()->prediction();
if (isInt32OrBooleanSpeculation(childPrediction)
break;
}
- case ArithRound:
- case ArithFloor:
- case ArithCeil:
- case ArithTrunc: {
- if (isInt32OrBooleanSpeculation(m_currentNode->getHeapPrediction())
- && m_graph.roundShouldSpeculateInt32(m_currentNode, m_pass))
- setPrediction(SpecInt32Only);
- else
- setPrediction(SpecBytecodeDouble);
- break;
- }
-
case ArithRandom: {
setPrediction(SpecDoubleReal);
break;
case ArithMul:
case ArithDiv:
case ArithMod:
+ case ArithRound:
+ case ArithFloor:
+ case ArithCeil:
+ case ArithTrunc:
case ArithAbs:
case GetByVal:
case ToThis:
void SpeculativeJIT::compileArithRounding(Node* node)
{
- if (node->child1().useKind() == DoubleRepUse) {
- SpeculateDoubleOperand value(this, node->child1());
- FPRReg valueFPR = value.fpr();
+ ASSERT(node->child1().useKind() == DoubleRepUse);
- auto setResult = [&] (FPRReg resultFPR) {
- if (producesInteger(node->arithRoundingMode())) {
- GPRTemporary roundedResultAsInt32(this);
- FPRTemporary scratch(this);
- FPRReg scratchFPR = scratch.fpr();
- GPRReg resultGPR = roundedResultAsInt32.gpr();
- JITCompiler::JumpList failureCases;
- m_jit.branchConvertDoubleToInt32(resultFPR, resultGPR, failureCases, scratchFPR, shouldCheckNegativeZero(node->arithRoundingMode()));
- speculationCheck(Overflow, JSValueRegs(), node, failureCases);
+ SpeculateDoubleOperand value(this, node->child1());
+ FPRReg valueFPR = value.fpr();
- int32Result(resultGPR, node);
- } else
- doubleResult(resultFPR, node);
- };
-
- if (m_jit.supportsFloatingPointRounding()) {
- switch (node->op()) {
- case ArithRound: {
- FPRTemporary result(this);
- FPRReg resultFPR = result.fpr();
- if (producesInteger(node->arithRoundingMode()) && !shouldCheckNegativeZero(node->arithRoundingMode())) {
- static const double halfConstant = 0.5;
- m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), resultFPR);
- m_jit.addDouble(valueFPR, resultFPR);
- m_jit.floorDouble(resultFPR, resultFPR);
- } else {
- m_jit.ceilDouble(valueFPR, resultFPR);
- FPRTemporary realPart(this);
- FPRReg realPartFPR = realPart.fpr();
- m_jit.subDouble(resultFPR, valueFPR, realPartFPR);
-
- FPRTemporary scratch(this);
- FPRReg scratchFPR = scratch.fpr();
- static const double halfConstant = 0.5;
- m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), scratchFPR);
-
- JITCompiler::Jump shouldUseCeiled = m_jit.branchDouble(JITCompiler::DoubleLessThanOrEqual, realPartFPR, scratchFPR);
- static const double oneConstant = -1.0;
- m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&oneConstant), scratchFPR);
- m_jit.addDouble(scratchFPR, resultFPR);
- shouldUseCeiled.link(&m_jit);
- }
- setResult(resultFPR);
- return;
- }
+ auto setResult = [&] (FPRReg resultFPR) {
+ if (producesInteger(node->arithRoundingMode())) {
+ GPRTemporary roundedResultAsInt32(this);
+ FPRTemporary scratch(this);
+ FPRReg scratchFPR = scratch.fpr();
+ GPRReg resultGPR = roundedResultAsInt32.gpr();
+ JITCompiler::JumpList failureCases;
+ m_jit.branchConvertDoubleToInt32(resultFPR, resultGPR, failureCases, scratchFPR, shouldCheckNegativeZero(node->arithRoundingMode()));
+ speculationCheck(Overflow, JSValueRegs(), node, failureCases);
- case ArithFloor: {
- FPRTemporary rounded(this);
- FPRReg resultFPR = rounded.fpr();
- m_jit.floorDouble(valueFPR, resultFPR);
- setResult(resultFPR);
- return;
- }
+ int32Result(resultGPR, node);
+ } else
+ doubleResult(resultFPR, node);
+ };
- case ArithCeil: {
- FPRTemporary rounded(this);
- FPRReg resultFPR = rounded.fpr();
+ if (m_jit.supportsFloatingPointRounding()) {
+ switch (node->op()) {
+ case ArithRound: {
+ FPRTemporary result(this);
+ FPRReg resultFPR = result.fpr();
+ if (producesInteger(node->arithRoundingMode()) && !shouldCheckNegativeZero(node->arithRoundingMode())) {
+ static const double halfConstant = 0.5;
+ m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), resultFPR);
+ m_jit.addDouble(valueFPR, resultFPR);
+ m_jit.floorDouble(resultFPR, resultFPR);
+ } else {
m_jit.ceilDouble(valueFPR, resultFPR);
- setResult(resultFPR);
- return;
- }
+ FPRTemporary realPart(this);
+ FPRReg realPartFPR = realPart.fpr();
+ m_jit.subDouble(resultFPR, valueFPR, realPartFPR);
- case ArithTrunc: {
- FPRTemporary rounded(this);
- FPRReg resultFPR = rounded.fpr();
- m_jit.roundTowardZeroDouble(valueFPR, resultFPR);
- setResult(resultFPR);
- return;
+ FPRTemporary scratch(this);
+ FPRReg scratchFPR = scratch.fpr();
+ static const double halfConstant = 0.5;
+ m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), scratchFPR);
+
+ JITCompiler::Jump shouldUseCeiled = m_jit.branchDouble(JITCompiler::DoubleLessThanOrEqual, realPartFPR, scratchFPR);
+ static const double oneConstant = -1.0;
+ m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&oneConstant), scratchFPR);
+ m_jit.addDouble(scratchFPR, resultFPR);
+ shouldUseCeiled.link(&m_jit);
}
+ setResult(resultFPR);
+ return;
+ }
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
- } else {
- flushRegisters();
- FPRResult roundedResultAsDouble(this);
- FPRReg resultFPR = roundedResultAsDouble.fpr();
- if (node->op() == ArithRound)
- callOperation(jsRound, resultFPR, valueFPR);
- else if (node->op() == ArithFloor)
- callOperation(floor, resultFPR, valueFPR);
- else if (node->op() == ArithCeil)
- callOperation(ceil, resultFPR, valueFPR);
- else {
- ASSERT(node->op() == ArithTrunc);
- callOperation(trunc, resultFPR, valueFPR);
- }
+ case ArithFloor: {
+ FPRTemporary rounded(this);
+ FPRReg resultFPR = rounded.fpr();
+ m_jit.floorDouble(valueFPR, resultFPR);
setResult(resultFPR);
+ return;
}
- return;
- }
- DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse);
+ case ArithCeil: {
+ FPRTemporary rounded(this);
+ FPRReg resultFPR = rounded.fpr();
+ m_jit.ceilDouble(valueFPR, resultFPR);
+ setResult(resultFPR);
+ return;
+ }
- JSValueOperand argument(this, node->child1());
- JSValueRegs argumentRegs = argument.jsValueRegs();
-#if USE(JSVALUE64)
- GPRTemporary result(this);
- JSValueRegs resultRegs = JSValueRegs(result.gpr());
-#else
- GPRTemporary resultTag(this);
- GPRTemporary resultPayload(this);
- JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
-#endif
- flushRegisters();
- J_JITOperation_EJ operation = nullptr;
- if (node->op() == ArithRound)
- operation = operationArithRound;
- else if (node->op() == ArithFloor)
- operation = operationArithFloor;
- else if (node->op() == ArithCeil)
- operation = operationArithCeil;
- else {
- ASSERT(node->op() == ArithTrunc);
- operation = operationArithTrunc;
+ case ArithTrunc: {
+ FPRTemporary rounded(this);
+ FPRReg resultFPR = rounded.fpr();
+ m_jit.roundTowardZeroDouble(valueFPR, resultFPR);
+ setResult(resultFPR);
+ return;
+ }
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+ } else {
+ flushRegisters();
+ FPRResult roundedResultAsDouble(this);
+ FPRReg resultFPR = roundedResultAsDouble.fpr();
+ if (node->op() == ArithRound)
+ callOperation(jsRound, resultFPR, valueFPR);
+ else if (node->op() == ArithFloor)
+ callOperation(floor, resultFPR, valueFPR);
+ else if (node->op() == ArithCeil)
+ callOperation(ceil, resultFPR, valueFPR);
+ else {
+ ASSERT(node->op() == ArithTrunc);
+ callOperation(trunc, resultFPR, valueFPR);
+ }
+ m_jit.exceptionCheck();
+ setResult(resultFPR);
}
- callOperation(operation, resultRegs, argumentRegs);
- m_jit.exceptionCheck();
- jsValueResult(resultRegs, node);
}
void SpeculativeJIT::compileArithSin(Node* node)
void compileArithRound()
{
- if (m_node->child1().useKind() == DoubleRepUse) {
- LValue result = nullptr;
- if (producesInteger(m_node->arithRoundingMode()) && !shouldCheckNegativeZero(m_node->arithRoundingMode())) {
- LValue value = lowDouble(m_node->child1());
- result = m_out.doubleFloor(m_out.doubleAdd(value, m_out.constDouble(0.5)));
- } else {
- LBasicBlock realPartIsMoreThanHalf = m_out.newBlock();
- LBasicBlock continuation = m_out.newBlock();
+ LValue result = nullptr;
- LValue value = lowDouble(m_node->child1());
- LValue integerValue = m_out.doubleCeil(value);
- ValueFromBlock integerValueResult = m_out.anchor(integerValue);
+ if (producesInteger(m_node->arithRoundingMode()) && !shouldCheckNegativeZero(m_node->arithRoundingMode())) {
+ LValue value = lowDouble(m_node->child1());
+ result = m_out.doubleFloor(m_out.doubleAdd(value, m_out.constDouble(0.5)));
+ } else {
+ LBasicBlock realPartIsMoreThanHalf = m_out.newBlock();
+ LBasicBlock continuation = m_out.newBlock();
- LValue realPart = m_out.doubleSub(integerValue, value);
+ LValue value = lowDouble(m_node->child1());
+ LValue integerValue = m_out.doubleCeil(value);
+ ValueFromBlock integerValueResult = m_out.anchor(integerValue);
- m_out.branch(m_out.doubleGreaterThanOrUnordered(realPart, m_out.constDouble(0.5)), unsure(realPartIsMoreThanHalf), unsure(continuation));
+ LValue realPart = m_out.doubleSub(integerValue, value);
- LBasicBlock lastNext = m_out.appendTo(realPartIsMoreThanHalf, continuation);
- LValue integerValueRoundedDown = m_out.doubleSub(integerValue, m_out.constDouble(1));
- ValueFromBlock integerValueRoundedDownResult = m_out.anchor(integerValueRoundedDown);
- m_out.jump(continuation);
- m_out.appendTo(continuation, lastNext);
+ m_out.branch(m_out.doubleGreaterThanOrUnordered(realPart, m_out.constDouble(0.5)), unsure(realPartIsMoreThanHalf), unsure(continuation));
- result = m_out.phi(Double, integerValueResult, integerValueRoundedDownResult);
- }
+ LBasicBlock lastNext = m_out.appendTo(realPartIsMoreThanHalf, continuation);
+ LValue integerValueRoundedDown = m_out.doubleSub(integerValue, m_out.constDouble(1));
+ ValueFromBlock integerValueRoundedDownResult = m_out.anchor(integerValueRoundedDown);
+ m_out.jump(continuation);
+ m_out.appendTo(continuation, lastNext);
- if (producesInteger(m_node->arithRoundingMode())) {
- LValue integerValue = convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode()));
- setInt32(integerValue);
- } else
- setDouble(result);
- return;
+ result = m_out.phi(Double, integerValueResult, integerValueRoundedDownResult);
}
- DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
- LValue argument = lowJSValue(m_node->child1());
- setJSValue(vmCall(Int64, m_out.operation(operationArithRound), m_callFrame, argument));
+ if (producesInteger(m_node->arithRoundingMode())) {
+ LValue integerValue = convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode()));
+ setInt32(integerValue);
+ } else
+ setDouble(result);
}
void compileArithFloor()
{
- if (m_node->child1().useKind() == DoubleRepUse) {
- LValue value = lowDouble(m_node->child1());
- LValue integerValue = m_out.doubleFloor(value);
- if (producesInteger(m_node->arithRoundingMode()))
- setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode())));
- else
- setDouble(integerValue);
- return;
- }
- DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
- LValue argument = lowJSValue(m_node->child1());
- setJSValue(vmCall(Int64, m_out.operation(operationArithFloor), m_callFrame, argument));
+ LValue value = lowDouble(m_node->child1());
+ LValue integerValue = m_out.doubleFloor(value);
+ if (producesInteger(m_node->arithRoundingMode()))
+ setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode())));
+ else
+ setDouble(integerValue);
}
void compileArithCeil()
{
- if (m_node->child1().useKind() == DoubleRepUse) {
- LValue value = lowDouble(m_node->child1());
- LValue integerValue = m_out.doubleCeil(value);
- if (producesInteger(m_node->arithRoundingMode()))
- setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode())));
- else
- setDouble(integerValue);
- return;
- }
- DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
- LValue argument = lowJSValue(m_node->child1());
- setJSValue(vmCall(Int64, m_out.operation(operationArithCeil), m_callFrame, argument));
+ LValue value = lowDouble(m_node->child1());
+ LValue integerValue = m_out.doubleCeil(value);
+ if (producesInteger(m_node->arithRoundingMode()))
+ setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode())));
+ else
+ setDouble(integerValue);
}
void compileArithTrunc()
{
- if (m_node->child1().useKind() == DoubleRepUse) {
- LValue value = lowDouble(m_node->child1());
- LValue result = m_out.doubleTrunc(value);
- if (producesInteger(m_node->arithRoundingMode()))
- setInt32(convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode())));
- else
- setDouble(result);
- return;
- }
- DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
- LValue argument = lowJSValue(m_node->child1());
- setJSValue(vmCall(Int64, m_out.operation(operationArithTrunc), m_callFrame, argument));
+ LValue value = lowDouble(m_node->child1());
+ LValue result = m_out.doubleTrunc(value);
+ if (producesInteger(m_node->arithRoundingMode()))
+ setInt32(convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode())));
+ else
+ setDouble(result);
}
void compileArithSqrt()