diff options
Diffstat (limited to 'meta/recipes-sato/webkit/webkitgtk/CVE-2022-32923.patch')
-rw-r--r-- | meta/recipes-sato/webkit/webkitgtk/CVE-2022-32923.patch | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/meta/recipes-sato/webkit/webkitgtk/CVE-2022-32923.patch b/meta/recipes-sato/webkit/webkitgtk/CVE-2022-32923.patch new file mode 100644 index 0000000000..60342a14f8 --- /dev/null +++ b/meta/recipes-sato/webkit/webkitgtk/CVE-2022-32923.patch | |||
@@ -0,0 +1,435 @@ | |||
1 | CVE: CVE-2022-32923 | ||
2 | Upstream-Status: Backport [https://github.com/WebKit/WebKit/commit/ef76e31] | ||
3 | |||
4 | [1]: https://support.apple.com/en-us/HT213495 | ||
5 | [2]: https://bugs.webkit.org/show_bug.cgi?id=242964 | ||
6 | |||
7 | Signed-off-by: Kai Kang <kai.kang@windriver.com> | ||
8 | |||
9 | From ef76e31a2a066c3d65a9c94a9e2cd88133260c1f Mon Sep 17 00:00:00 2001 | ||
10 | From: Yusuke Suzuki <ysuzuki@apple.com> | ||
11 | Date: Wed, 20 Jul 2022 19:30:48 -0700 | ||
12 | Subject: [PATCH] [JSC] BakcwardPropagationPhase should carry NaN / Infinity | ||
13 | handling https://bugs.webkit.org/show_bug.cgi?id=242964 rdar://96791603 | ||
14 | |||
15 | Reviewed by Mark Lam. | ||
16 | |||
17 | For correctness, we should carry NaN / Infinity handling to make it more clear in the code generation site. | ||
18 | |||
19 | * Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp: | ||
20 | (JSC::DFG::BackwardsPropagationPhase::propagate): | ||
21 | * Source/JavaScriptCore/dfg/DFGFixupPhase.cpp: | ||
22 | (JSC::DFG::FixupPhase::fixupArithDivInt32): | ||
23 | (JSC::DFG::FixupPhase::fixupArithDiv): | ||
24 | * Source/JavaScriptCore/dfg/DFGGraph.h: | ||
25 | * Source/JavaScriptCore/dfg/DFGNode.h: | ||
26 | * Source/JavaScriptCore/dfg/DFGNodeFlags.cpp: | ||
27 | (JSC::DFG::dumpNodeFlags): | ||
28 | * Source/JavaScriptCore/dfg/DFGNodeFlags.h: | ||
29 | (JSC::DFG::bytecodeCanIgnoreNaNAndInfinity): | ||
30 | (JSC::DFG::nodeCanSpeculateInt32ForDiv): | ||
31 | * Source/JavaScriptCore/dfg/DFGNodeType.h: | ||
32 | |||
33 | Canonical link: https://commits.webkit.org/252675@main | ||
34 | --- | ||
35 | .../dfg/DFGBackwardsPropagationPhase.cpp | 51 +++++++++++-------- | ||
36 | Source/JavaScriptCore/dfg/DFGFixupPhase.cpp | 6 ++- | ||
37 | Source/JavaScriptCore/dfg/DFGGraph.h | 11 ++++ | ||
38 | Source/JavaScriptCore/dfg/DFGNode.h | 12 +++-- | ||
39 | Source/JavaScriptCore/dfg/DFGNodeFlags.cpp | 10 ++-- | ||
40 | Source/JavaScriptCore/dfg/DFGNodeFlags.h | 37 +++++++++++--- | ||
41 | Source/JavaScriptCore/dfg/DFGNodeType.h | 3 +- | ||
42 | 7 files changed, 91 insertions(+), 39 deletions(-) | ||
43 | |||
44 | diff --git a/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp | ||
45 | index 306ea5d6b974..83a08aff7c20 100644 | ||
46 | --- a/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp | ||
47 | +++ b/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp | ||
48 | @@ -272,7 +272,7 @@ private: | ||
49 | case ValueBitNot: | ||
50 | case ArithBitNot: { | ||
51 | flags |= NodeBytecodeUsesAsInt; | ||
52 | - flags &= ~(NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther); | ||
53 | + flags &= ~(NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeNeedsNaNOrInfinity | NodeBytecodeUsesAsOther); | ||
54 | flags &= ~NodeBytecodeUsesAsArrayIndex; | ||
55 | node->child1()->mergeFlags(flags); | ||
56 | break; | ||
57 | @@ -291,7 +291,7 @@ private: | ||
58 | case BitURShift: | ||
59 | case ArithIMul: { | ||
60 | flags |= NodeBytecodeUsesAsInt; | ||
61 | - flags &= ~(NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther); | ||
62 | + flags &= ~(NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeNeedsNaNOrInfinity | NodeBytecodeUsesAsOther); | ||
63 | flags &= ~NodeBytecodeUsesAsArrayIndex; | ||
64 | node->child1()->mergeFlags(flags); | ||
65 | node->child2()->mergeFlags(flags); | ||
66 | @@ -308,9 +308,9 @@ private: | ||
67 | |||
68 | case StringSlice: { | ||
69 | node->child1()->mergeFlags(NodeBytecodeUsesAsValue); | ||
70 | - node->child2()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); | ||
71 | + node->child2()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex | NodeBytecodeNeedsNaNOrInfinity); | ||
72 | if (node->child3()) | ||
73 | - node->child3()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); | ||
74 | + node->child3()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex | NodeBytecodeNeedsNaNOrInfinity); | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | @@ -320,11 +320,11 @@ private: | ||
79 | if (node->numChildren() == 2) | ||
80 | m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsValue); | ||
81 | else if (node->numChildren() == 3) { | ||
82 | - m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); | ||
83 | + m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex | NodeBytecodeNeedsNaNOrInfinity); | ||
84 | m_graph.varArgChild(node, 2)->mergeFlags(NodeBytecodeUsesAsValue); | ||
85 | } else if (node->numChildren() == 4) { | ||
86 | - m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); | ||
87 | - m_graph.varArgChild(node, 2)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); | ||
88 | + m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex | NodeBytecodeNeedsNaNOrInfinity); | ||
89 | + m_graph.varArgChild(node, 2)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex | NodeBytecodeNeedsNaNOrInfinity); | ||
90 | m_graph.varArgChild(node, 3)->mergeFlags(NodeBytecodeUsesAsValue); | ||
91 | } | ||
92 | break; | ||
93 | @@ -345,6 +345,7 @@ private: | ||
94 | flags |= NodeBytecodeUsesAsNumber; | ||
95 | if (!m_allowNestedOverflowingAdditions) | ||
96 | flags |= NodeBytecodeUsesAsNumber; | ||
97 | + flags |= NodeBytecodeNeedsNaNOrInfinity; | ||
98 | |||
99 | node->child1()->mergeFlags(flags); | ||
100 | node->child2()->mergeFlags(flags); | ||
101 | @@ -359,6 +360,7 @@ private: | ||
102 | flags |= NodeBytecodeUsesAsNumber; | ||
103 | if (!m_allowNestedOverflowingAdditions) | ||
104 | flags |= NodeBytecodeUsesAsNumber; | ||
105 | + flags |= NodeBytecodeNeedsNaNOrInfinity; | ||
106 | |||
107 | node->child1()->mergeFlags(flags); | ||
108 | node->child2()->mergeFlags(flags); | ||
109 | @@ -366,7 +368,7 @@ private: | ||
110 | } | ||
111 | |||
112 | case ArithClz32: { | ||
113 | - flags &= ~(NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther | ~NodeBytecodeUsesAsArrayIndex); | ||
114 | + flags &= ~(NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeNeedsNaNOrInfinity | NodeBytecodeUsesAsOther | ~NodeBytecodeUsesAsArrayIndex); | ||
115 | flags |= NodeBytecodeUsesAsInt; | ||
116 | node->child1()->mergeFlags(flags); | ||
117 | break; | ||
118 | @@ -380,6 +382,7 @@ private: | ||
119 | flags |= NodeBytecodeUsesAsNumber; | ||
120 | if (!m_allowNestedOverflowingAdditions) | ||
121 | flags |= NodeBytecodeUsesAsNumber; | ||
122 | + flags |= NodeBytecodeNeedsNaNOrInfinity; | ||
123 | |||
124 | node->child1()->mergeFlags(flags); | ||
125 | node->child2()->mergeFlags(flags); | ||
126 | @@ -387,6 +390,7 @@ private: | ||
127 | } | ||
128 | |||
129 | case ArithNegate: { | ||
130 | + // negation does not care about NaN, Infinity, -Infinity are converted into 0 if the result is evaluated under the integer context. | ||
131 | flags &= ~NodeBytecodeUsesAsOther; | ||
132 | |||
133 | node->child1()->mergeFlags(flags); | ||
134 | @@ -401,6 +405,7 @@ private: | ||
135 | flags |= NodeBytecodeUsesAsNumber; | ||
136 | if (!m_allowNestedOverflowingAdditions) | ||
137 | flags |= NodeBytecodeUsesAsNumber; | ||
138 | + flags |= NodeBytecodeNeedsNaNOrInfinity; | ||
139 | |||
140 | node->child1()->mergeFlags(flags); | ||
141 | break; | ||
142 | @@ -421,7 +426,7 @@ private: | ||
143 | |||
144 | node->mergeFlags(flags); | ||
145 | |||
146 | - flags |= NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero; | ||
147 | + flags |= NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeNeedsNaNOrInfinity; | ||
148 | flags &= ~NodeBytecodeUsesAsOther; | ||
149 | |||
150 | node->child1()->mergeFlags(flags); | ||
151 | @@ -431,7 +436,13 @@ private: | ||
152 | |||
153 | case ValueDiv: | ||
154 | case ArithDiv: { | ||
155 | - flags |= NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero; | ||
156 | + // ArithDiv / ValueDiv need to have NodeBytecodeUsesAsNumber even if it is used in the context of integer. | ||
157 | + // For example, | ||
158 | + // ((@x / @y) + @z) | 0 | ||
159 | + // In this context, (@x / @y) can have integer context at first, but the result can be different if div | ||
160 | + // generates NaN. Div and Mod are operations that can produce NaN / Infinity though only taking binary Int32 operands. | ||
161 | + // Thus, we always need to check for overflow since it can affect downstream calculations. | ||
162 | + flags |= NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeNeedsNaNOrInfinity; | ||
163 | flags &= ~NodeBytecodeUsesAsOther; | ||
164 | |||
165 | node->child1()->mergeFlags(flags); | ||
166 | @@ -441,7 +452,7 @@ private: | ||
167 | |||
168 | case ValueMod: | ||
169 | case ArithMod: { | ||
170 | - flags |= NodeBytecodeUsesAsNumber; | ||
171 | + flags |= NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeNeedsNaNOrInfinity; | ||
172 | flags &= ~NodeBytecodeUsesAsOther; | ||
173 | |||
174 | node->child1()->mergeFlags(flags); | ||
175 | @@ -452,7 +463,7 @@ private: | ||
176 | case EnumeratorGetByVal: | ||
177 | case GetByVal: { | ||
178 | m_graph.varArgChild(node, 0)->mergeFlags(NodeBytecodeUsesAsValue); | ||
179 | - m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); | ||
180 | + m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeNeedsNaNOrInfinity | NodeBytecodeUsesAsArrayIndex); | ||
181 | break; | ||
182 | } | ||
183 | |||
184 | @@ -461,13 +472,13 @@ private: | ||
185 | // Negative zero is not observable. NaN versus undefined are only observable | ||
186 | // in that you would get a different exception message. So, like, whatever: we | ||
187 | // claim here that NaN v. undefined is observable. | ||
188 | - node->child1()->mergeFlags(NodeBytecodeUsesAsInt | NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsArrayIndex); | ||
189 | + node->child1()->mergeFlags(NodeBytecodeUsesAsInt | NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeNeedsNaNOrInfinity | NodeBytecodeUsesAsArrayIndex); | ||
190 | break; | ||
191 | } | ||
192 | |||
193 | case ToString: | ||
194 | case CallStringConstructor: { | ||
195 | - node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther); | ||
196 | + node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeNeedsNaNOrInfinity); | ||
197 | break; | ||
198 | } | ||
199 | |||
200 | @@ -487,15 +498,15 @@ private: | ||
201 | case CompareBelowEq: | ||
202 | case CompareEq: | ||
203 | case CompareStrictEq: { | ||
204 | - node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther); | ||
205 | - node->child2()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther); | ||
206 | + node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeNeedsNaNOrInfinity); | ||
207 | + node->child2()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeNeedsNaNOrInfinity); | ||
208 | break; | ||
209 | } | ||
210 | |||
211 | case PutByValDirect: | ||
212 | case PutByVal: { | ||
213 | m_graph.varArgChild(node, 0)->mergeFlags(NodeBytecodeUsesAsValue); | ||
214 | - m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); | ||
215 | + m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex | NodeBytecodeNeedsNaNOrInfinity); | ||
216 | m_graph.varArgChild(node, 2)->mergeFlags(NodeBytecodeUsesAsValue); | ||
217 | break; | ||
218 | } | ||
219 | @@ -508,20 +519,20 @@ private: | ||
220 | // then -0 and 0 are treated the same. We don't need NodeBytecodeUsesAsOther | ||
221 | // because if all of the cases are integers then NaN and undefined are | ||
222 | // treated the same (i.e. they will take default). | ||
223 | - node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsInt); | ||
224 | + node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsInt | NodeBytecodeNeedsNaNOrInfinity); | ||
225 | break; | ||
226 | case SwitchChar: { | ||
227 | // We don't need NodeBytecodeNeedsNegZero because if the cases are all strings | ||
228 | // then -0 and 0 are treated the same. We don't need NodeBytecodeUsesAsOther | ||
229 | // because if all of the cases are single-character strings then NaN | ||
230 | // and undefined are treated the same (i.e. they will take default). | ||
231 | - node->child1()->mergeFlags(NodeBytecodeUsesAsNumber); | ||
232 | + node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNaNOrInfinity); | ||
233 | break; | ||
234 | } | ||
235 | case SwitchString: | ||
236 | // We don't need NodeBytecodeNeedsNegZero because if the cases are all strings | ||
237 | // then -0 and 0 are treated the same. | ||
238 | - node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther); | ||
239 | + node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeNeedsNaNOrInfinity); | ||
240 | break; | ||
241 | case SwitchCell: | ||
242 | // There is currently no point to being clever here since this is used for switching | ||
243 | diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp | ||
244 | index e8bee58ada15..b679539de2e6 100644 | ||
245 | --- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp | ||
246 | +++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp | ||
247 | @@ -81,7 +81,9 @@ private: | ||
248 | if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) { | ||
249 | fixIntOrBooleanEdge(leftChild); | ||
250 | fixIntOrBooleanEdge(rightChild); | ||
251 | - if (bytecodeCanTruncateInteger(node->arithNodeFlags())) | ||
252 | + // We need to be careful about skipping overflow check because div / mod can generate non integer values | ||
253 | + // from (Int32, Int32) inputs. For now, we always check non-zero divisor. | ||
254 | + if (bytecodeCanTruncateInteger(node->arithNodeFlags()) && bytecodeCanIgnoreNaNAndInfinity(node->arithNodeFlags()) && bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) | ||
255 | node->setArithMode(Arith::Unchecked); | ||
256 | else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) | ||
257 | node->setArithMode(Arith::CheckOverflow); | ||
258 | @@ -122,7 +124,7 @@ private: | ||
259 | |||
260 | void fixupArithDiv(Node* node, Edge& leftChild, Edge& rightChild) | ||
261 | { | ||
262 | - if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) { | ||
263 | + if (m_graph.divShouldSpeculateInt32(node, FixupPass)) { | ||
264 | fixupArithDivInt32(node, leftChild, rightChild); | ||
265 | return; | ||
266 | } | ||
267 | diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h | ||
268 | index ca566d3a484e..284c87672849 100644 | ||
269 | --- a/Source/JavaScriptCore/dfg/DFGGraph.h | ||
270 | +++ b/Source/JavaScriptCore/dfg/DFGGraph.h | ||
271 | @@ -373,6 +373,17 @@ public: | ||
272 | |||
273 | return shouldSpeculateInt52ForAdd(left) && shouldSpeculateInt52ForAdd(right); | ||
274 | } | ||
275 | + | ||
276 | + bool divShouldSpeculateInt32(Node* node, PredictionPass pass) | ||
277 | + { | ||
278 | + // Even if inputs are Int32, div can generate NaN or Infinity. | ||
279 | + // Thus, Overflow in div can be caused by these non integer values as well as actual Int32 overflow. | ||
280 | + Node* left = node->child1().node(); | ||
281 | + Node* right = node->child2().node(); | ||
282 | + | ||
283 | + return Node::shouldSpeculateInt32OrBooleanForArithmetic(left, right) | ||
284 | + && nodeCanSpeculateInt32ForDiv(node->arithNodeFlags(), node->sourceFor(pass)); | ||
285 | + } | ||
286 | |||
287 | bool binaryArithShouldSpeculateInt32(Node* node, PredictionPass pass) | ||
288 | { | ||
289 | diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h | ||
290 | index f9ff50658e93..04509a3846ca 100644 | ||
291 | --- a/Source/JavaScriptCore/dfg/DFGNode.h | ||
292 | +++ b/Source/JavaScriptCore/dfg/DFGNode.h | ||
293 | @@ -3308,21 +3308,25 @@ public: | ||
294 | out.printf(", @%u", child3()->index()); | ||
295 | } | ||
296 | |||
297 | - NodeOrigin origin; | ||
298 | + NO_UNIQUE_ADDRESS NodeOrigin origin; | ||
299 | |||
300 | +private: | ||
301 | + NO_UNIQUE_ADDRESS NodeType m_op; | ||
302 | + | ||
303 | + NO_UNIQUE_ADDRESS unsigned m_index { std::numeric_limits<unsigned>::max() }; | ||
304 | + | ||
305 | +public: | ||
306 | // References to up to 3 children, or links to a variable length set of children. | ||
307 | AdjacencyList children; | ||
308 | |||
309 | private: | ||
310 | friend class B3::SparseCollection<Node>; | ||
311 | |||
312 | - unsigned m_index { std::numeric_limits<unsigned>::max() }; | ||
313 | - unsigned m_op : 10; // real type is NodeType | ||
314 | - unsigned m_flags : 21; | ||
315 | // The virtual register number (spill location) associated with this . | ||
316 | VirtualRegister m_virtualRegister; | ||
317 | // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects). | ||
318 | unsigned m_refCount; | ||
319 | + NodeFlags m_flags; | ||
320 | // The prediction ascribed to this node after propagation. | ||
321 | SpeculatedType m_prediction { SpecNone }; | ||
322 | // Immediate values, accesses type-checked via accessors above. | ||
323 | diff --git a/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp b/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp | ||
324 | index 88242947f6ef..0c53cd976c5c 100644 | ||
325 | --- a/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp | ||
326 | +++ b/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp | ||
327 | @@ -74,12 +74,14 @@ void dumpNodeFlags(PrintStream& actualOut, NodeFlags flags) | ||
328 | out.print(comma, "VarArgs"); | ||
329 | |||
330 | if (flags & NodeResultMask) { | ||
331 | - if (!(flags & NodeBytecodeUsesAsNumber) && !(flags & NodeBytecodeNeedsNegZero)) | ||
332 | + if (!(flags & NodeBytecodeUsesAsNumber)) | ||
333 | out.print(comma, "PureInt"); | ||
334 | - else if (!(flags & NodeBytecodeUsesAsNumber)) | ||
335 | - out.print(comma, "PureInt(w/ neg zero)"); | ||
336 | - else if (!(flags & NodeBytecodeNeedsNegZero)) | ||
337 | + else | ||
338 | out.print(comma, "PureNum"); | ||
339 | + if (flags & NodeBytecodeNeedsNegZero) | ||
340 | + out.print(comma, "NeedsNegZero"); | ||
341 | + if (flags & NodeBytecodeNeedsNaNOrInfinity) | ||
342 | + out.print(comma, "NeedsNaNOrInfinity"); | ||
343 | if (flags & NodeBytecodeUsesAsOther) | ||
344 | out.print(comma, "UseAsOther"); | ||
345 | } | ||
346 | diff --git a/Source/JavaScriptCore/dfg/DFGNodeFlags.h b/Source/JavaScriptCore/dfg/DFGNodeFlags.h | ||
347 | index 2ebe3544f601..aa60db7e6ba0 100644 | ||
348 | --- a/Source/JavaScriptCore/dfg/DFGNodeFlags.h | ||
349 | +++ b/Source/JavaScriptCore/dfg/DFGNodeFlags.h | ||
350 | @@ -61,18 +61,19 @@ namespace JSC { namespace DFG { | ||
351 | #define NodeBytecodeUseBottom 0x00000 | ||
352 | #define NodeBytecodeUsesAsNumber 0x04000 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results. | ||
353 | #define NodeBytecodeNeedsNegZero 0x08000 // The result of this computation may be used in a context that observes -0. | ||
354 | -#define NodeBytecodeUsesAsOther 0x10000 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined). | ||
355 | -#define NodeBytecodeUsesAsInt 0x20000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values. | ||
356 | -#define NodeBytecodeUsesAsArrayIndex 0x40000 // 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. | ||
357 | -#define NodeBytecodeUsesAsValue (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther) | ||
358 | -#define NodeBytecodeBackPropMask (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex) | ||
359 | +#define NodeBytecodeNeedsNaNOrInfinity 0x10000 // The result of this computation may be used in a context that observes NaN or Infinity. | ||
360 | +#define NodeBytecodeUsesAsOther 0x20000 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined). | ||
361 | +#define NodeBytecodeUsesAsInt 0x40000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values. | ||
362 | +#define NodeBytecodeUsesAsArrayIndex 0x80000 // 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. | ||
363 | +#define NodeBytecodeUsesAsValue (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeNeedsNaNOrInfinity | NodeBytecodeUsesAsOther) | ||
364 | +#define NodeBytecodeBackPropMask (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeNeedsNaNOrInfinity | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex) | ||
365 | |||
366 | #define NodeArithFlagsMask (NodeBehaviorMask | NodeBytecodeBackPropMask) | ||
367 | |||
368 | -#define NodeIsFlushed 0x80000 // Computed by CPSRethreadingPhase, will tell you which local nodes are backwards-reachable from a Flush. | ||
369 | +#define NodeIsFlushed 0x100000 // Computed by CPSRethreadingPhase, will tell you which local nodes are backwards-reachable from a Flush. | ||
370 | |||
371 | -#define NodeMiscFlag1 0x100000 | ||
372 | -#define NodeMiscFlag2 0x200000 | ||
373 | +#define NodeMiscFlag1 0x200000 | ||
374 | +#define NodeMiscFlag2 0x400000 | ||
375 | |||
376 | typedef uint32_t NodeFlags; | ||
377 | |||
378 | @@ -91,6 +92,11 @@ static inline bool bytecodeCanIgnoreNegativeZero(NodeFlags flags) | ||
379 | return !(flags & NodeBytecodeNeedsNegZero); | ||
380 | } | ||
381 | |||
382 | +static inline bool bytecodeCanIgnoreNaNAndInfinity(NodeFlags flags) | ||
383 | +{ | ||
384 | + return !(flags & NodeBytecodeNeedsNaNOrInfinity); | ||
385 | +} | ||
386 | + | ||
387 | enum RareCaseProfilingSource { | ||
388 | BaselineRareCase, // Comes from slow case counting in the baseline JIT. | ||
389 | DFGRareCase, // Comes from OSR exit profiles. | ||
390 | @@ -147,6 +153,21 @@ static inline bool nodeCanSpeculateInt32(NodeFlags flags, RareCaseProfilingSourc | ||
391 | return true; | ||
392 | } | ||
393 | |||
394 | +static inline bool nodeCanSpeculateInt32ForDiv(NodeFlags flags, RareCaseProfilingSource source) | ||
395 | +{ | ||
396 | + if (nodeMayOverflowInt32(flags, source)) { | ||
397 | + if (bytecodeUsesAsNumber(flags)) | ||
398 | + return false; | ||
399 | + if (!bytecodeCanIgnoreNaNAndInfinity(flags)) | ||
400 | + return false; | ||
401 | + } | ||
402 | + | ||
403 | + if (nodeMayNegZero(flags, source)) | ||
404 | + return bytecodeCanIgnoreNegativeZero(flags); | ||
405 | + | ||
406 | + return true; | ||
407 | +} | ||
408 | + | ||
409 | static inline bool nodeCanSpeculateInt52(NodeFlags flags, RareCaseProfilingSource source) | ||
410 | { | ||
411 | if (nodeMayOverflowInt52(flags, source)) | ||
412 | diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h | ||
413 | index 8f885b570665..aad4d559ccf7 100644 | ||
414 | --- a/Source/JavaScriptCore/dfg/DFGNodeType.h | ||
415 | +++ b/Source/JavaScriptCore/dfg/DFGNodeType.h | ||
416 | @@ -567,7 +567,7 @@ namespace JSC { namespace DFG { | ||
417 | |||
418 | // This enum generates a monotonically increasing id for all Node types, | ||
419 | // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask). | ||
420 | -enum NodeType { | ||
421 | +enum NodeType : uint16_t { | ||
422 | #define DFG_OP_ENUM(opcode, flags) opcode, | ||
423 | FOR_EACH_DFG_OP(DFG_OP_ENUM) | ||
424 | #undef DFG_OP_ENUM | ||
425 | @@ -577,6 +577,7 @@ enum NodeType { | ||
426 | #define DFG_OP_COUNT(opcode, flags) + 1 | ||
427 | constexpr unsigned numberOfNodeTypes = FOR_EACH_DFG_OP(DFG_OP_COUNT); | ||
428 | #undef DFG_OP_COUNT | ||
429 | +static_assert(numberOfNodeTypes <= UINT16_MAX); | ||
430 | |||
431 | // Specifies the default flags for each node. | ||
432 | inline NodeFlags defaultFlags(NodeType op) | ||
433 | -- | ||
434 | 2.34.1 | ||
435 | |||