| /* |
| * Copyright (C) 2014 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #include "MathCommon.h" |
| |
| #if ENABLE(DFG_JIT) |
| |
| namespace JSC { |
| |
| class CallFrame; |
| class JSGlobalObject; |
| using EncodedJSValue = int64_t; |
| |
| namespace DFG { |
| |
| // Arith::Mode describes the mode of an arithmetic operation that speculates integer. |
| // Note that not all modes are valid for all operations. |
| namespace Arith { |
| enum Mode { |
| NotSet, // Arithmetic mode is either not relevant because we're using doubles anyway or we are at a phase in compilation where we don't know what we're doing, yet. Should never see this after FixupPhase except for nodes that take doubles as inputs already. |
| Unchecked, // Don't check anything and just do the direct hardware operation. |
| CheckOverflow, // Check for overflow but don't bother with negative zero. |
| CheckOverflowAndNegativeZero, // Check for both overflow and negative zero. |
| DoOverflow // Up-convert to the smallest type that soundly represents all possible results after input type speculation. |
| }; |
| |
| // Define the type of operation the rounding operation will perform. |
| enum class RoundingMode { |
| Int32, // The round operation produces a integer and -0 is considered as 0. |
| Int32WithNegativeZeroCheck, // The round operation produces a integer and checks for -0. |
| Double // The round operation produce a double. The result can be -0, NaN or (+/-)Infinity. |
| }; |
| |
| enum class UnaryType : uint32_t { |
| #define DFG_ARITH_UNARY_ENUM(capitalizedName, lowerName) capitalizedName, |
| FOR_EACH_ARITH_UNARY_OP(DFG_ARITH_UNARY_ENUM) |
| #undef DFG_ARITH_UNARY_ENUM |
| }; |
| |
| using UnaryFunction = double(JIT_OPERATION_ATTRIBUTES*)(double); |
| using UnaryOperation = double(JIT_OPERATION_ATTRIBUTES*)(JSGlobalObject*, EncodedJSValue); |
| |
| } // namespace Arith |
| |
| inline bool doesOverflow(Arith::Mode mode) |
| { |
| switch (mode) { |
| case Arith::NotSet: |
| ASSERT_NOT_REACHED(); |
| #if !ASSERT_ENABLED |
| FALLTHROUGH; |
| #endif |
| case Arith::Unchecked: |
| case Arith::CheckOverflow: |
| case Arith::CheckOverflowAndNegativeZero: |
| return false; |
| case Arith::DoOverflow: |
| return true; |
| } |
| ASSERT_NOT_REACHED(); |
| return true; |
| } |
| |
| // It's only valid to call this once you've determined that you don't need to *do* |
| // overflow. For most nodes, that's implicit. |
| inline bool shouldCheckOverflow(Arith::Mode mode) |
| { |
| switch (mode) { |
| case Arith::NotSet: |
| case Arith::DoOverflow: |
| ASSERT_NOT_REACHED(); |
| return true; |
| case Arith::Unchecked: |
| return false; |
| case Arith::CheckOverflow: |
| case Arith::CheckOverflowAndNegativeZero: |
| return true; |
| } |
| ASSERT_NOT_REACHED(); |
| return true; |
| } |
| |
| inline bool shouldCheckNegativeZero(Arith::Mode mode) |
| { |
| switch (mode) { |
| case Arith::NotSet: |
| case Arith::DoOverflow: |
| ASSERT_NOT_REACHED(); |
| return true; |
| case Arith::Unchecked: |
| case Arith::CheckOverflow: |
| return false; |
| case Arith::CheckOverflowAndNegativeZero: |
| return true; |
| } |
| ASSERT_NOT_REACHED(); |
| return true; |
| } |
| |
| inline bool subsumes(Arith::Mode earlier, Arith::Mode later) |
| { |
| switch (earlier) { |
| case Arith::CheckOverflow: |
| switch (later) { |
| case Arith::Unchecked: |
| case Arith::CheckOverflow: |
| return true; |
| default: |
| return false; |
| } |
| case Arith::CheckOverflowAndNegativeZero: |
| switch (later) { |
| case Arith::Unchecked: |
| case Arith::CheckOverflow: |
| case Arith::CheckOverflowAndNegativeZero: |
| return true; |
| default: |
| return false; |
| } |
| default: |
| return earlier == later; |
| } |
| } |
| |
| inline bool producesInteger(Arith::RoundingMode mode) |
| { |
| return mode == Arith::RoundingMode::Int32WithNegativeZeroCheck || mode == Arith::RoundingMode::Int32; |
| } |
| |
| inline bool shouldCheckNegativeZero(Arith::RoundingMode mode) |
| { |
| return mode == Arith::RoundingMode::Int32WithNegativeZeroCheck; |
| } |
| |
| Arith::UnaryFunction arithUnaryFunction(Arith::UnaryType); |
| Arith::UnaryOperation arithUnaryOperation(Arith::UnaryType); |
| |
| } } // namespace JSC::DFG |
| |
| namespace WTF { |
| |
| class PrintStream; |
| void printInternal(PrintStream&, JSC::DFG::Arith::Mode); |
| void printInternal(PrintStream&, JSC::DFG::Arith::RoundingMode); |
| void printInternal(PrintStream&, JSC::DFG::Arith::UnaryType); |
| |
| } // namespace WTF |
| |
| #endif // ENABLE(DFG_JIT) |