Harden JSC a bit with RELEASE_ASSERT
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGValueSource.h
1 /*
2  * Copyright (C) 2011 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 DFGValueSource_h
27 #define DFGValueSource_h
28
29 #include <wtf/Platform.h>
30
31 #if ENABLE(DFG_JIT)
32
33 #include "DFGCommon.h"
34 #include "DataFormat.h"
35 #include "SpeculatedType.h"
36 #include "ValueRecovery.h"
37
38 namespace JSC { namespace DFG {
39
40 enum ValueSourceKind {
41     SourceNotSet,
42     ValueInJSStack,
43     Int32InJSStack,
44     CellInJSStack,
45     BooleanInJSStack,
46     DoubleInJSStack,
47     ArgumentsSource,
48     SourceIsDead,
49     HaveNode
50 };
51
52 static inline ValueSourceKind dataFormatToValueSourceKind(DataFormat dataFormat)
53 {
54     switch (dataFormat) {
55     case DataFormatInteger:
56         return Int32InJSStack;
57     case DataFormatDouble:
58         return DoubleInJSStack;
59     case DataFormatBoolean:
60         return BooleanInJSStack;
61     case DataFormatCell:
62         return CellInJSStack;
63     case DataFormatDead:
64         return SourceIsDead;
65     case DataFormatArguments:
66         return ArgumentsSource;
67     default:
68         RELEASE_ASSERT(dataFormat & DataFormatJS);
69         return ValueInJSStack;
70     }
71 }
72
73 static inline DataFormat valueSourceKindToDataFormat(ValueSourceKind kind)
74 {
75     switch (kind) {
76     case ValueInJSStack:
77         return DataFormatJS;
78     case Int32InJSStack:
79         return DataFormatInteger;
80     case CellInJSStack:
81         return DataFormatCell;
82     case BooleanInJSStack:
83         return DataFormatBoolean;
84     case DoubleInJSStack:
85         return DataFormatDouble;
86     case ArgumentsSource:
87         return DataFormatArguments;
88     case SourceIsDead:
89         return DataFormatDead;
90     default:
91         return DataFormatNone;
92     }
93 }
94
95 static inline bool isInJSStack(ValueSourceKind kind)
96 {
97     DataFormat format = valueSourceKindToDataFormat(kind);
98     return format != DataFormatNone && format < DataFormatOSRMarker;
99 }
100
101 // Can this value be recovered without having to look at register allocation state or
102 // DFG node liveness?
103 static inline bool isTriviallyRecoverable(ValueSourceKind kind)
104 {
105     return valueSourceKindToDataFormat(kind) != DataFormatNone;
106 }
107
108 class ValueSource {
109 public:
110     ValueSource()
111         : m_nodeIndex(nodeIndexFromKind(SourceNotSet))
112     {
113     }
114     
115     explicit ValueSource(ValueSourceKind valueSourceKind)
116         : m_nodeIndex(nodeIndexFromKind(valueSourceKind))
117     {
118         ASSERT(kind() != SourceNotSet);
119         ASSERT(kind() != HaveNode);
120     }
121     
122     explicit ValueSource(NodeIndex nodeIndex)
123         : m_nodeIndex(nodeIndex)
124     {
125         RELEASE_ASSERT(nodeIndex != NoNode);
126         ASSERT(kind() == HaveNode);
127     }
128     
129     static ValueSource forSpeculation(SpeculatedType prediction)
130     {
131         if (isInt32Speculation(prediction))
132             return ValueSource(Int32InJSStack);
133         if (isArraySpeculation(prediction) || isCellSpeculation(prediction))
134             return ValueSource(CellInJSStack);
135         if (isBooleanSpeculation(prediction))
136             return ValueSource(BooleanInJSStack);
137         return ValueSource(ValueInJSStack);
138     }
139     
140     static ValueSource forDataFormat(DataFormat dataFormat)
141     {
142         return ValueSource(dataFormatToValueSourceKind(dataFormat));
143     }
144     
145     bool isSet() const
146     {
147         return kindFromNodeIndex(m_nodeIndex) != SourceNotSet;
148     }
149     
150     ValueSourceKind kind() const
151     {
152         return kindFromNodeIndex(m_nodeIndex);
153     }
154     
155     bool isInJSStack() const { return JSC::DFG::isInJSStack(kind()); }
156     bool isTriviallyRecoverable() const { return JSC::DFG::isTriviallyRecoverable(kind()); }
157     
158     DataFormat dataFormat() const
159     {
160         return valueSourceKindToDataFormat(kind());
161     }
162     
163     ValueRecovery valueRecovery() const
164     {
165         ASSERT(isTriviallyRecoverable());
166         switch (kind()) {
167         case ValueInJSStack:
168             return ValueRecovery::alreadyInJSStack();
169             
170         case Int32InJSStack:
171             return ValueRecovery::alreadyInJSStackAsUnboxedInt32();
172             
173         case CellInJSStack:
174             return ValueRecovery::alreadyInJSStackAsUnboxedCell();
175             
176         case BooleanInJSStack:
177             return ValueRecovery::alreadyInJSStackAsUnboxedBoolean();
178             
179         case DoubleInJSStack:
180             return ValueRecovery::alreadyInJSStackAsUnboxedDouble();
181             
182         case SourceIsDead:
183             return ValueRecovery::constant(jsUndefined());
184             
185         case ArgumentsSource:
186             return ValueRecovery::argumentsThatWereNotCreated();
187             
188         default:
189             RELEASE_ASSERT_NOT_REACHED();
190             return ValueRecovery();
191         }
192     }
193     
194     NodeIndex nodeIndex() const
195     {
196         ASSERT(kind() == HaveNode);
197         return m_nodeIndex;
198     }
199     
200     void dump(FILE* out) const;
201     
202 private:
203     static NodeIndex nodeIndexFromKind(ValueSourceKind kind)
204     {
205         ASSERT(kind >= SourceNotSet && kind < HaveNode);
206         return NoNode - kind;
207     }
208     
209     static ValueSourceKind kindFromNodeIndex(NodeIndex nodeIndex)
210     {
211         unsigned kind = static_cast<unsigned>(NoNode - nodeIndex);
212         if (kind >= static_cast<unsigned>(HaveNode))
213             return HaveNode;
214         return static_cast<ValueSourceKind>(kind);
215     }
216     
217     NodeIndex m_nodeIndex;
218 };
219
220 } } // namespace JSC::DFG
221
222 #endif // ENABLE(DFG_JIT)
223
224 #endif // DFGValueSource_h
225