1/*
2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef DFGNodeFlags_h
27#define DFGNodeFlags_h
28
29#if ENABLE(DFG_JIT)
30
31#include <wtf/PrintStream.h>
32#include <wtf/StdLibExtras.h>
33
34namespace JSC { namespace DFG {
35
36// Entries in the NodeType enum (below) are composed of an id, a result type (possibly none)
37// and some additional informative flags (must generate, is constant, etc).
38#define NodeResultMask                   0x0007
39#define NodeResultJS                     0x0001
40#define NodeResultNumber                 0x0002
41#define NodeResultDouble                 0x0003
42#define NodeResultInt32                  0x0004
43#define NodeResultInt52                  0x0005
44#define NodeResultBoolean                0x0006
45#define NodeResultStorage                0x0007
46
47#define NodeMustGenerate                 0x0008 // set on nodes that have side effects, and may not trivially be removed by DCE.
48#define NodeHasVarArgs                   0x0010
49#define NodeClobbersWorld                0x0020
50#define NodeMightClobber                 0x0040
51
52#define NodeBehaviorMask                 0x0780
53#define NodeMayOverflowInBaseline        0x0080
54#define NodeMayOverflowInDFG             0x0100
55#define NodeMayNegZeroInBaseline         0x0200
56#define NodeMayNegZeroInDFG              0x0400
57
58#define NodeBytecodeBackPropMask         0xf800
59#define NodeBytecodeUseBottom            0x0000
60#define NodeBytecodeUsesAsNumber         0x0800 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results.
61#define NodeBytecodeNeedsNegZero         0x1000 // The result of this computation may be used in a context that observes -0.
62#define NodeBytecodeUsesAsOther          0x2000 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined).
63#define NodeBytecodeUsesAsValue          (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther)
64#define NodeBytecodeUsesAsInt            0x4000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.
65#define NodeBytecodeUsesAsArrayIndex     0x8000 // The result of this computation is known to be used in a context that strongly prefers integer values, to the point that we should avoid using doubles if at all possible.
66
67#define NodeArithFlagsMask               (NodeBehaviorMask | NodeBytecodeBackPropMask)
68
69#define NodeDoesNotExit                 0x10000 // This flag is negated to make it natural for the default to be that a node does exit.
70
71#define NodeRelevantToOSR               0x20000
72
73#define NodeIsFlushed                   0x40000 // Used by Graph::computeIsFlushed(), will tell you which local nodes are backwards-reachable from a Flush.
74
75typedef uint32_t NodeFlags;
76
77static inline bool bytecodeUsesAsNumber(NodeFlags flags)
78{
79    return !!(flags & NodeBytecodeUsesAsNumber);
80}
81
82static inline bool bytecodeCanTruncateInteger(NodeFlags flags)
83{
84    return !bytecodeUsesAsNumber(flags);
85}
86
87static inline bool bytecodeCanIgnoreNegativeZero(NodeFlags flags)
88{
89    return !(flags & NodeBytecodeNeedsNegZero);
90}
91
92enum RareCaseProfilingSource {
93    BaselineRareCase, // Comes from slow case counting in the baseline JIT.
94    DFGRareCase, // Comes from OSR exit profiles.
95    AllRareCases
96};
97
98static inline bool nodeMayOverflow(NodeFlags flags, RareCaseProfilingSource source)
99{
100    NodeFlags mask;
101    switch (source) {
102    case BaselineRareCase:
103        mask = NodeMayOverflowInBaseline;
104        break;
105    case DFGRareCase:
106        mask = NodeMayOverflowInDFG;
107        break;
108    case AllRareCases:
109        mask = NodeMayOverflowInBaseline | NodeMayOverflowInDFG;
110        break;
111    }
112    return !!(flags & mask);
113}
114
115static inline bool nodeMayNegZero(NodeFlags flags, RareCaseProfilingSource source)
116{
117    NodeFlags mask;
118    switch (source) {
119    case BaselineRareCase:
120        mask = NodeMayNegZeroInBaseline;
121        break;
122    case DFGRareCase:
123        mask = NodeMayNegZeroInDFG;
124        break;
125    case AllRareCases:
126        mask = NodeMayNegZeroInBaseline | NodeMayNegZeroInDFG;
127        break;
128    }
129    return !!(flags & mask);
130}
131
132static inline bool nodeCanSpeculateInt32(NodeFlags flags, RareCaseProfilingSource source)
133{
134    if (nodeMayOverflow(flags, source))
135        return !bytecodeUsesAsNumber(flags);
136
137    if (nodeMayNegZero(flags, source))
138        return bytecodeCanIgnoreNegativeZero(flags);
139
140    return true;
141}
142
143static inline bool nodeCanSpeculateInt52(NodeFlags flags, RareCaseProfilingSource source)
144{
145    if (nodeMayNegZero(flags, source))
146        return bytecodeCanIgnoreNegativeZero(flags);
147
148    return true;
149}
150
151// FIXME: Get rid of this.
152// https://bugs.webkit.org/show_bug.cgi?id=131689
153static inline NodeFlags canonicalResultRepresentation(NodeFlags flags)
154{
155    switch (flags) {
156    case NodeResultDouble:
157    case NodeResultInt52:
158    case NodeResultStorage:
159        return flags;
160    default:
161        return NodeResultJS;
162    }
163}
164
165void dumpNodeFlags(PrintStream&, NodeFlags);
166MAKE_PRINT_ADAPTOR(NodeFlagsDump, NodeFlags, dumpNodeFlags);
167
168} } // namespace JSC::DFG
169
170#endif // ENABLE(DFG_JIT)
171
172#endif // DFGNodeFlags_h
173
174