]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGNode.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGNode.h
CommitLineData
14957cd0 1/*
ed1e77d3 2 * Copyright (C) 2011-2015 Apple Inc. All rights reserved.
14957cd0
A
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 DFGNode_h
27#define DFGNode_h
28
14957cd0
A
29#if ENABLE(DFG_JIT)
30
ed1e77d3 31#include "BasicBlockLocation.h"
6fe7ccc8 32#include "CodeBlock.h"
93a37866 33#include "DFGAbstractValue.h"
6fe7ccc8 34#include "DFGAdjacencyList.h"
81345200 35#include "DFGArithMode.h"
93a37866 36#include "DFGArrayMode.h"
6fe7ccc8 37#include "DFGCommon.h"
ed1e77d3 38#include "DFGEpoch.h"
81345200 39#include "DFGLazyJSValue.h"
6fe7ccc8 40#include "DFGNodeFlags.h"
81345200 41#include "DFGNodeOrigin.h"
6fe7ccc8 42#include "DFGNodeType.h"
ed1e77d3
A
43#include "DFGObjectMaterializationData.h"
44#include "DFGTransition.h"
81345200 45#include "DFGUseKind.h"
6fe7ccc8 46#include "DFGVariableAccessData.h"
81345200 47#include "GetByIdVariant.h"
93a37866 48#include "JSCJSValue.h"
6fe7ccc8 49#include "Operands.h"
81345200 50#include "PutByIdVariant.h"
93a37866
A
51#include "SpeculatedType.h"
52#include "StructureSet.h"
ed1e77d3 53#include "TypeLocation.h"
6fe7ccc8 54#include "ValueProfile.h"
81345200 55#include <wtf/ListDump.h>
14957cd0
A
56
57namespace JSC { namespace DFG {
58
81345200 59class Graph;
ed1e77d3 60class PromotedLocationDescriptor;
81345200
A
61struct BasicBlock;
62
ed1e77d3
A
63struct StorageAccessData {
64 PropertyOffset offset;
65 unsigned identifierNumber;
66};
67
81345200
A
68struct MultiGetByOffsetData {
69 unsigned identifierNumber;
70 Vector<GetByIdVariant, 2> variants;
71};
72
73struct MultiPutByOffsetData {
74 unsigned identifierNumber;
75 Vector<PutByIdVariant, 2> variants;
76
77 bool writesStructures() const;
78 bool reallocatesStorage() const;
79};
80
93a37866
A
81struct NewArrayBufferData {
82 unsigned startConstant;
83 unsigned numConstants;
84 IndexingType indexingType;
85};
86
81345200
A
87struct BranchTarget {
88 BranchTarget()
89 : block(0)
90 , count(PNaN)
91 {
92 }
93
94 explicit BranchTarget(BasicBlock* block)
95 : block(block)
96 , count(PNaN)
97 {
98 }
99
100 void setBytecodeIndex(unsigned bytecodeIndex)
101 {
102 block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(bytecodeIndex));
103 }
104 unsigned bytecodeIndex() const { return bitwise_cast<uintptr_t>(block); }
105
106 void dump(PrintStream&) const;
107
108 BasicBlock* block;
109 float count;
110};
111
112struct BranchData {
113 static BranchData withBytecodeIndices(
114 unsigned takenBytecodeIndex, unsigned notTakenBytecodeIndex)
115 {
116 BranchData result;
117 result.taken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(takenBytecodeIndex));
118 result.notTaken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(notTakenBytecodeIndex));
119 return result;
120 }
121
122 unsigned takenBytecodeIndex() const { return taken.bytecodeIndex(); }
123 unsigned notTakenBytecodeIndex() const { return notTaken.bytecodeIndex(); }
124
125 BasicBlock*& forCondition(bool condition)
126 {
127 if (condition)
128 return taken.block;
129 return notTaken.block;
130 }
131
132 BranchTarget taken;
133 BranchTarget notTaken;
134};
135
136// The SwitchData and associated data structures duplicate the information in
137// JumpTable. The DFG may ultimately end up using the JumpTable, though it may
138// instead decide to do something different - this is entirely up to the DFG.
139// These data structures give the DFG a higher-level semantic description of
140// what is going on, which will allow it to make the right decision.
141//
142// Note that there will never be multiple SwitchCases in SwitchData::cases that
143// have the same SwitchCase::value, since the bytecode's JumpTables never have
144// duplicates - since the JumpTable maps a value to a target. It's a
145// one-to-many mapping. So we may have duplicate targets, but never duplicate
146// values.
147struct SwitchCase {
148 SwitchCase()
149 {
150 }
151
152 SwitchCase(LazyJSValue value, BasicBlock* target)
153 : value(value)
154 , target(target)
155 {
156 }
157
158 static SwitchCase withBytecodeIndex(LazyJSValue value, unsigned bytecodeIndex)
159 {
160 SwitchCase result;
161 result.value = value;
162 result.target.setBytecodeIndex(bytecodeIndex);
163 return result;
164 }
165
166 LazyJSValue value;
167 BranchTarget target;
168};
169
81345200
A
170struct SwitchData {
171 // Initializes most fields to obviously invalid values. Anyone
172 // constructing this should make sure to initialize everything they
173 // care about manually.
174 SwitchData()
175 : kind(static_cast<SwitchKind>(-1))
176 , switchTableIndex(UINT_MAX)
177 , didUseJumpTable(false)
178 {
179 }
180
181 Vector<SwitchCase> cases;
182 BranchTarget fallThrough;
183 SwitchKind kind;
184 unsigned switchTableIndex;
185 bool didUseJumpTable;
186};
187
ed1e77d3
A
188struct CallVarargsData {
189 int firstVarArgOffset;
190};
191
192struct LoadVarargsData {
193 VirtualRegister start; // Local for the first element. This is the first actual argument, not this.
194 VirtualRegister count; // Local for the count.
195 VirtualRegister machineStart;
196 VirtualRegister machineCount;
197 unsigned offset; // Which array element to start with. Usually this is 0.
198 unsigned mandatoryMinimum; // The number of elements on the stack that must be initialized; if the array is too short then the missing elements must get undefined. Does not include "this".
199 unsigned limit; // Maximum number of elements to load. Includes "this".
200};
201
202struct StackAccessData {
203 StackAccessData()
204 : format(DeadFlush)
205 {
206 }
207
208 StackAccessData(VirtualRegister local, FlushFormat format)
209 : local(local)
210 , format(format)
211 {
212 }
213
214 VirtualRegister local;
215 VirtualRegister machineLocal;
216 FlushFormat format;
217
218 FlushedAt flushedAt() { return FlushedAt(format, machineLocal); }
219};
220
14957cd0
A
221// This type used in passing an immediate argument to Node constructor;
222// distinguishes an immediate value (typically an index into a CodeBlock data structure -
93a37866 223// a constant index, argument, or identifier) from a Node*.
14957cd0 224struct OpInfo {
ed1e77d3 225 OpInfo() : m_value(0) { }
6fe7ccc8
A
226 explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { }
227 explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { }
228#if OS(DARWIN) || USE(JSVALUE64)
229 explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { }
230#endif
231 explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { }
232 uintptr_t m_value;
14957cd0
A
233};
234
235// === Node ===
236//
237// Node represents a single operation in the data flow graph.
238struct Node {
6fe7ccc8 239 enum VarArgTag { VarArg };
93a37866
A
240
241 Node() { }
242
81345200
A
243 Node(NodeType op, NodeOrigin nodeOrigin, const AdjacencyList& children)
244 : origin(nodeOrigin)
93a37866 245 , children(children)
81345200 246 , m_virtualRegister(VirtualRegister())
93a37866
A
247 , m_refCount(1)
248 , m_prediction(SpecNone)
ed1e77d3 249 , owner(nullptr)
93a37866 250 {
ed1e77d3 251 m_misc.replacement = nullptr;
93a37866
A
252 setOpAndDefaultFlags(op);
253 }
254
14957cd0 255 // Construct a node with up to 3 children, no immediate value.
81345200
A
256 Node(NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
257 : origin(nodeOrigin)
6fe7ccc8 258 , children(AdjacencyList::Fixed, child1, child2, child3)
81345200 259 , m_virtualRegister(VirtualRegister())
93a37866
A
260 , m_refCount(1)
261 , m_prediction(SpecNone)
81345200
A
262 , m_opInfo(0)
263 , m_opInfo2(0)
ed1e77d3 264 , owner(nullptr)
14957cd0 265 {
ed1e77d3 266 m_misc.replacement = nullptr;
6fe7ccc8
A
267 setOpAndDefaultFlags(op);
268 ASSERT(!(m_flags & NodeHasVarArgs));
14957cd0
A
269 }
270
81345200
A
271 // Construct a node with up to 3 children, no immediate value.
272 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
273 : origin(nodeOrigin)
274 , children(AdjacencyList::Fixed, child1, child2, child3)
275 , m_virtualRegister(VirtualRegister())
276 , m_refCount(1)
277 , m_prediction(SpecNone)
278 , m_opInfo(0)
279 , m_opInfo2(0)
ed1e77d3 280 , owner(nullptr)
81345200 281 {
ed1e77d3 282 m_misc.replacement = nullptr;
81345200
A
283 setOpAndDefaultFlags(op);
284 setResult(result);
285 ASSERT(!(m_flags & NodeHasVarArgs));
286 }
287
14957cd0 288 // Construct a node with up to 3 children and an immediate value.
81345200
A
289 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
290 : origin(nodeOrigin)
6fe7ccc8 291 , children(AdjacencyList::Fixed, child1, child2, child3)
81345200 292 , m_virtualRegister(VirtualRegister())
93a37866 293 , m_refCount(1)
81345200 294 , m_prediction(SpecNone)
14957cd0 295 , m_opInfo(imm.m_value)
81345200 296 , m_opInfo2(0)
ed1e77d3 297 , owner(nullptr)
81345200 298 {
ed1e77d3 299 m_misc.replacement = nullptr;
81345200
A
300 setOpAndDefaultFlags(op);
301 ASSERT(!(m_flags & NodeHasVarArgs));
302 }
303
304 // Construct a node with up to 3 children and an immediate value.
305 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
306 : origin(nodeOrigin)
307 , children(AdjacencyList::Fixed, child1, child2, child3)
308 , m_virtualRegister(VirtualRegister())
309 , m_refCount(1)
93a37866 310 , m_prediction(SpecNone)
81345200
A
311 , m_opInfo(imm.m_value)
312 , m_opInfo2(0)
ed1e77d3 313 , owner(nullptr)
14957cd0 314 {
ed1e77d3 315 m_misc.replacement = nullptr;
6fe7ccc8 316 setOpAndDefaultFlags(op);
81345200 317 setResult(result);
6fe7ccc8 318 ASSERT(!(m_flags & NodeHasVarArgs));
14957cd0
A
319 }
320
321 // Construct a node with up to 3 children and two immediate values.
81345200
A
322 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
323 : origin(nodeOrigin)
6fe7ccc8 324 , children(AdjacencyList::Fixed, child1, child2, child3)
81345200 325 , m_virtualRegister(VirtualRegister())
93a37866 326 , m_refCount(1)
93a37866 327 , m_prediction(SpecNone)
81345200
A
328 , m_opInfo(imm1.m_value)
329 , m_opInfo2(imm2.m_value)
ed1e77d3 330 , owner(nullptr)
6fe7ccc8 331 {
ed1e77d3 332 m_misc.replacement = nullptr;
6fe7ccc8
A
333 setOpAndDefaultFlags(op);
334 ASSERT(!(m_flags & NodeHasVarArgs));
335 }
336
337 // Construct a node with a variable number of children and two immediate values.
81345200
A
338 Node(VarArgTag, NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
339 : origin(nodeOrigin)
6fe7ccc8 340 , children(AdjacencyList::Variable, firstChild, numChildren)
81345200 341 , m_virtualRegister(VirtualRegister())
93a37866 342 , m_refCount(1)
93a37866 343 , m_prediction(SpecNone)
81345200
A
344 , m_opInfo(imm1.m_value)
345 , m_opInfo2(imm2.m_value)
ed1e77d3 346 , owner(nullptr)
6fe7ccc8 347 {
ed1e77d3 348 m_misc.replacement = nullptr;
6fe7ccc8
A
349 setOpAndDefaultFlags(op);
350 ASSERT(m_flags & NodeHasVarArgs);
351 }
352
353 NodeType op() const { return static_cast<NodeType>(m_op); }
354 NodeFlags flags() const { return m_flags; }
355
93a37866
A
356 // This is not a fast method.
357 unsigned index() const;
358
6fe7ccc8
A
359 void setOp(NodeType op)
360 {
361 m_op = op;
362 }
363
364 void setFlags(NodeFlags flags)
365 {
366 m_flags = flags;
367 }
368
369 bool mergeFlags(NodeFlags flags)
370 {
371 NodeFlags newFlags = m_flags | flags;
372 if (newFlags == m_flags)
373 return false;
374 m_flags = newFlags;
375 return true;
376 }
377
378 bool filterFlags(NodeFlags flags)
379 {
380 NodeFlags newFlags = m_flags & flags;
381 if (newFlags == m_flags)
382 return false;
383 m_flags = newFlags;
384 return true;
385 }
386
387 bool clearFlags(NodeFlags flags)
388 {
389 return filterFlags(~flags);
390 }
391
81345200 392 void setResult(NodeFlags result)
14957cd0 393 {
81345200
A
394 ASSERT(!(result & ~NodeResultMask));
395 clearFlags(NodeResultMask);
396 mergeFlags(result);
14957cd0 397 }
81345200
A
398
399 NodeFlags result() const
93a37866 400 {
81345200 401 return flags() & NodeResultMask;
93a37866 402 }
81345200
A
403
404 void setOpAndDefaultFlags(NodeType op)
93a37866
A
405 {
406 m_op = op;
81345200 407 m_flags = defaultFlags(op);
93a37866
A
408 }
409
ed1e77d3
A
410 void remove();
411
412 void convertToCheckStructure(StructureSet* set)
93a37866 413 {
ed1e77d3
A
414 setOpAndDefaultFlags(CheckStructure);
415 m_opInfo = bitwise_cast<uintptr_t>(set);
93a37866
A
416 }
417
ed1e77d3 418 void convertToCheckStructureImmediate(Node* structure)
93a37866 419 {
ed1e77d3
A
420 ASSERT(op() == CheckStructure);
421 m_op = CheckStructureImmediate;
422 children.setChild1(Edge(structure, CellUse));
423 }
424
425 void replaceWith(Node* other)
426 {
427 remove();
428 setReplacement(other);
93a37866
A
429 }
430
81345200 431 void convertToIdentity();
ed1e77d3 432 void convertToIdentityOn(Node*);
93a37866 433
14957cd0
A
434 bool mustGenerate()
435 {
6fe7ccc8 436 return m_flags & NodeMustGenerate;
14957cd0 437 }
93a37866 438
14957cd0
A
439 bool isConstant()
440 {
81345200
A
441 switch (op()) {
442 case JSConstant:
443 case DoubleConstant:
444 case Int52Constant:
445 return true;
446 default:
447 return false;
448 }
6fe7ccc8
A
449 }
450
6fe7ccc8
A
451 bool hasConstant()
452 {
93a37866
A
453 switch (op()) {
454 case JSConstant:
81345200
A
455 case DoubleConstant:
456 case Int52Constant:
93a37866 457 return true;
ed1e77d3
A
458
459 case PhantomDirectArguments:
460 case PhantomClonedArguments:
461 // These pretend to be the empty value constant for the benefit of the DFG backend, which
462 // otherwise wouldn't take kindly to a node that doesn't compute a value.
463 return true;
464
93a37866
A
465 default:
466 return false;
467 }
14957cd0
A
468 }
469
ed1e77d3 470 FrozenValue* constant()
14957cd0 471 {
ed1e77d3
A
472 ASSERT(hasConstant());
473
474 if (op() == PhantomDirectArguments || op() == PhantomClonedArguments) {
475 // These pretend to be the empty value constant for the benefit of the DFG backend, which
476 // otherwise wouldn't take kindly to a node that doesn't compute a value.
477 return FrozenValue::emptySingleton();
478 }
479
480 return bitwise_cast<FrozenValue*>(m_opInfo);
14957cd0 481 }
6fe7ccc8 482
ed1e77d3
A
483 // Don't call this directly - use Graph::convertToConstant() instead!
484 void convertToConstant(FrozenValue* value)
93a37866 485 {
81345200
A
486 if (hasDoubleResult())
487 m_op = DoubleConstant;
488 else if (hasInt52Result())
489 m_op = Int52Constant;
490 else
491 m_op = JSConstant;
ed1e77d3
A
492 m_flags &= ~NodeMustGenerate;
493 m_opInfo = bitwise_cast<uintptr_t>(value);
93a37866
A
494 children.reset();
495 }
496
81345200
A
497 void convertToConstantStoragePointer(void* pointer)
498 {
499 ASSERT(op() == GetIndexedPropertyStorage);
500 m_op = ConstantStoragePointer;
501 m_opInfo = bitwise_cast<uintptr_t>(pointer);
ed1e77d3 502 children.reset();
81345200
A
503 }
504
93a37866
A
505 void convertToGetLocalUnlinked(VirtualRegister local)
506 {
507 m_op = GetLocalUnlinked;
ed1e77d3 508 m_flags &= ~NodeMustGenerate;
81345200
A
509 m_opInfo = local.offset();
510 m_opInfo2 = VirtualRegister().offset();
93a37866
A
511 children.reset();
512 }
513
ed1e77d3 514 void convertToPutStack(StackAccessData* data)
93a37866 515 {
ed1e77d3
A
516 m_op = PutStack;
517 m_flags |= NodeMustGenerate;
518 m_opInfo = bitwise_cast<uintptr_t>(data);
519 m_opInfo2 = 0;
93a37866
A
520 }
521
ed1e77d3 522 void convertToGetStack(StackAccessData* data)
93a37866 523 {
ed1e77d3
A
524 m_op = GetStack;
525 m_flags &= ~NodeMustGenerate;
526 m_opInfo = bitwise_cast<uintptr_t>(data);
527 m_opInfo2 = 0;
528 children.reset();
93a37866
A
529 }
530
ed1e77d3 531 void convertToGetByOffset(StorageAccessData& data, Edge storage)
93a37866 532 {
81345200 533 ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
ed1e77d3 534 m_opInfo = bitwise_cast<uintptr_t>(&data);
81345200
A
535 children.setChild2(children.child1());
536 children.child2().setUseKind(KnownCellUse);
93a37866
A
537 children.setChild1(storage);
538 m_op = GetByOffset;
ed1e77d3 539 m_flags &= ~NodeMustGenerate;
93a37866
A
540 }
541
ed1e77d3 542 void convertToMultiGetByOffset(MultiGetByOffsetData* data)
93a37866 543 {
ed1e77d3
A
544 ASSERT(m_op == GetById || m_op == GetByIdFlush);
545 m_opInfo = bitwise_cast<intptr_t>(data);
546 child1().setUseKind(CellUse);
547 m_op = MultiGetByOffset;
548 ASSERT(m_flags & NodeMustGenerate);
549 }
550
551 void convertToPutByOffset(StorageAccessData& data, Edge storage)
552 {
553 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op == MultiPutByOffset);
554 m_opInfo = bitwise_cast<uintptr_t>(&data);
93a37866
A
555 children.setChild3(children.child2());
556 children.setChild2(children.child1());
557 children.setChild1(storage);
558 m_op = PutByOffset;
93a37866
A
559 }
560
ed1e77d3
A
561 void convertToMultiPutByOffset(MultiPutByOffsetData* data)
562 {
563 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
564 m_opInfo = bitwise_cast<intptr_t>(data);
565 m_op = MultiPutByOffset;
566 }
567
568 void convertToPutHint(const PromotedLocationDescriptor&, Node* base, Node* value);
569
570 void convertToPutByOffsetHint();
571 void convertToPutStructureHint(Node* structure);
572 void convertToPutClosureVarHint();
573
574 void convertToPhantomNewObject()
575 {
576 ASSERT(m_op == NewObject || m_op == MaterializeNewObject);
577 m_op = PhantomNewObject;
578 m_flags &= ~NodeHasVarArgs;
579 m_flags |= NodeMustGenerate;
580 m_opInfo = 0;
581 m_opInfo2 = 0;
582 children = AdjacencyList();
583 }
584
585 void convertToPhantomNewFunction()
586 {
587 ASSERT(m_op == NewFunction);
588 m_op = PhantomNewFunction;
589 m_flags |= NodeMustGenerate;
590 m_opInfo = 0;
591 m_opInfo2 = 0;
592 children = AdjacencyList();
593 }
594
595 void convertToPhantomCreateActivation()
596 {
597 ASSERT(m_op == CreateActivation || m_op == MaterializeCreateActivation);
598 m_op = PhantomCreateActivation;
599 m_flags &= ~NodeHasVarArgs;
600 m_flags |= NodeMustGenerate;
601 m_opInfo = 0;
602 m_opInfo2 = 0;
603 children = AdjacencyList();
604 }
605
606 void convertPhantomToPhantomLocal()
93a37866
A
607 {
608 ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
609 m_op = PhantomLocal;
610 m_opInfo = child1()->m_opInfo; // Copy the variableAccessData.
611 children.setChild1(Edge());
612 }
613
ed1e77d3
A
614 void convertFlushToPhantomLocal()
615 {
616 ASSERT(m_op == Flush);
617 m_op = PhantomLocal;
618 children = AdjacencyList();
619 }
620
93a37866
A
621 void convertToGetLocal(VariableAccessData* variable, Node* phi)
622 {
623 ASSERT(m_op == GetLocalUnlinked);
624 m_op = GetLocal;
625 m_opInfo = bitwise_cast<uintptr_t>(variable);
81345200 626 m_opInfo2 = 0;
93a37866
A
627 children.setChild1(Edge(phi));
628 }
629
630 void convertToToString()
631 {
632 ASSERT(m_op == ToPrimitive);
633 m_op = ToString;
634 }
ed1e77d3
A
635
636 void convertToArithSqrt()
6fe7ccc8 637 {
ed1e77d3
A
638 ASSERT(m_op == ArithPow);
639 child2() = Edge();
640 m_op = ArithSqrt;
6fe7ccc8
A
641 }
642
ed1e77d3 643 JSValue asJSValue()
6fe7ccc8 644 {
ed1e77d3 645 return constant()->value();
6fe7ccc8 646 }
ed1e77d3
A
647
648 bool isInt32Constant()
6fe7ccc8 649 {
ed1e77d3 650 return isConstant() && constant()->value().isInt32();
6fe7ccc8 651 }
ed1e77d3
A
652
653 int32_t asInt32()
6fe7ccc8 654 {
ed1e77d3 655 return asJSValue().asInt32();
6fe7ccc8 656 }
ed1e77d3
A
657
658 uint32_t asUInt32()
6fe7ccc8 659 {
ed1e77d3 660 return asInt32();
6fe7ccc8 661 }
ed1e77d3
A
662
663 bool isDoubleConstant()
81345200 664 {
ed1e77d3
A
665 return isConstant() && constant()->value().isDouble();
666 }
667
668 bool isNumberConstant()
669 {
670 return isConstant() && constant()->value().isNumber();
81345200
A
671 }
672
ed1e77d3 673 double asNumber()
6fe7ccc8 674 {
ed1e77d3
A
675 return asJSValue().asNumber();
676 }
677
678 bool isMachineIntConstant()
679 {
680 return isConstant() && constant()->value().isMachineInt();
681 }
682
683 int64_t asMachineInt()
684 {
685 return asJSValue().asMachineInt();
686 }
687
688 bool isBooleanConstant()
689 {
690 return isConstant() && constant()->value().isBoolean();
691 }
692
693 bool asBoolean()
694 {
695 return constant()->value().asBoolean();
696 }
697
698 bool isCellConstant()
699 {
700 return isConstant() && constant()->value() && constant()->value().isCell();
701 }
702
703 JSCell* asCell()
704 {
705 return constant()->value().asCell();
706 }
707
708 template<typename T>
709 T dynamicCastConstant()
710 {
711 if (!isCellConstant())
712 return nullptr;
713 return jsDynamicCast<T>(asCell());
6fe7ccc8
A
714 }
715
ed1e77d3
A
716 template<typename T>
717 T castConstant()
718 {
719 T result = dynamicCastConstant<T>();
720 RELEASE_ASSERT(result);
721 return result;
722 }
723
93a37866
A
724 bool containsMovHint()
725 {
726 switch (op()) {
93a37866 727 case MovHint:
93a37866
A
728 case ZombieHint:
729 return true;
730 default:
731 return false;
732 }
733 }
734
81345200
A
735 bool hasVariableAccessData(Graph&);
736 bool hasLocal(Graph& graph)
737 {
738 return hasVariableAccessData(graph);
739 }
740
741 // This is useful for debugging code, where a node that should have a variable
742 // access data doesn't have one because it hasn't been initialized yet.
743 VariableAccessData* tryGetVariableAccessData()
744 {
745 VariableAccessData* result = reinterpret_cast<VariableAccessData*>(m_opInfo);
746 if (!result)
747 return 0;
748 return result->find();
749 }
750
751 VariableAccessData* variableAccessData()
752 {
753 return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
754 }
755
756 VirtualRegister local()
757 {
758 return variableAccessData()->local();
759 }
760
761 VirtualRegister machineLocal()
762 {
763 return variableAccessData()->machineLocal();
764 }
765
766 bool hasUnlinkedLocal()
6fe7ccc8
A
767 {
768 switch (op()) {
81345200
A
769 case GetLocalUnlinked:
770 case ExtractOSREntryLocal:
93a37866 771 case MovHint:
93a37866 772 case ZombieHint:
ed1e77d3 773 case KillStack:
6fe7ccc8
A
774 return true;
775 default:
776 return false;
777 }
778 }
779
81345200 780 VirtualRegister unlinkedLocal()
14957cd0 781 {
81345200
A
782 ASSERT(hasUnlinkedLocal());
783 return static_cast<VirtualRegister>(m_opInfo);
14957cd0 784 }
6fe7ccc8 785
81345200 786 bool hasUnlinkedMachineLocal()
6fe7ccc8 787 {
81345200 788 return op() == GetLocalUnlinked;
6fe7ccc8
A
789 }
790
81345200 791 void setUnlinkedMachineLocal(VirtualRegister reg)
14957cd0 792 {
81345200
A
793 ASSERT(hasUnlinkedMachineLocal());
794 m_opInfo2 = reg.offset();
14957cd0 795 }
6fe7ccc8 796
81345200 797 VirtualRegister unlinkedMachineLocal()
93a37866 798 {
81345200
A
799 ASSERT(hasUnlinkedMachineLocal());
800 return VirtualRegister(m_opInfo2);
93a37866
A
801 }
802
ed1e77d3
A
803 bool hasStackAccessData()
804 {
805 switch (op()) {
806 case PutStack:
807 case GetStack:
808 return true;
809 default:
810 return false;
811 }
812 }
813
814 StackAccessData* stackAccessData()
815 {
816 ASSERT(hasStackAccessData());
817 return bitwise_cast<StackAccessData*>(m_opInfo);
818 }
819
81345200
A
820 bool hasPhi()
821 {
822 return op() == Upsilon;
823 }
824
825 Node* phi()
826 {
827 ASSERT(hasPhi());
828 return bitwise_cast<Node*>(m_opInfo);
829 }
830
831 bool isStoreBarrier()
832 {
ed1e77d3 833 return op() == StoreBarrier;
81345200
A
834 }
835
14957cd0
A
836 bool hasIdentifier()
837 {
6fe7ccc8
A
838 switch (op()) {
839 case GetById:
840 case GetByIdFlush:
841 case PutById:
81345200 842 case PutByIdFlush:
6fe7ccc8 843 case PutByIdDirect:
6fe7ccc8
A
844 return true;
845 default:
846 return false;
847 }
14957cd0
A
848 }
849
850 unsigned identifierNumber()
851 {
852 ASSERT(hasIdentifier());
853 return m_opInfo;
854 }
6fe7ccc8 855
ed1e77d3 856 bool hasPromotedLocationDescriptor()
6fe7ccc8 857 {
ed1e77d3 858 return op() == PutHint;
6fe7ccc8
A
859 }
860
ed1e77d3
A
861 PromotedLocationDescriptor promotedLocationDescriptor();
862
6fe7ccc8
A
863 // This corrects the arithmetic node flags, so that irrelevant bits are
864 // ignored. In particular, anything other than ArithMul does not need
865 // to know if it can speculate on negative zero.
866 NodeFlags arithNodeFlags()
867 {
93a37866 868 NodeFlags result = m_flags & NodeArithFlagsMask;
ed1e77d3 869 if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == ArithRound || op() == DoubleAsInt32)
6fe7ccc8 870 return result;
81345200 871 return result & ~NodeBytecodeNeedsNegZero;
6fe7ccc8
A
872 }
873
874 bool hasConstantBuffer()
875 {
876 return op() == NewArrayBuffer;
877 }
878
93a37866 879 NewArrayBufferData* newArrayBufferData()
6fe7ccc8
A
880 {
881 ASSERT(hasConstantBuffer());
93a37866
A
882 return reinterpret_cast<NewArrayBufferData*>(m_opInfo);
883 }
884
885 unsigned startConstant()
886 {
887 return newArrayBufferData()->startConstant;
6fe7ccc8
A
888 }
889
890 unsigned numConstants()
891 {
93a37866
A
892 return newArrayBufferData()->numConstants;
893 }
894
895 bool hasIndexingType()
896 {
897 switch (op()) {
898 case NewArray:
899 case NewArrayWithSize:
900 case NewArrayBuffer:
901 return true;
902 default:
903 return false;
904 }
905 }
906
907 IndexingType indexingType()
908 {
909 ASSERT(hasIndexingType());
910 if (op() == NewArrayBuffer)
911 return newArrayBufferData()->indexingType;
912 return m_opInfo;
913 }
914
81345200
A
915 bool hasTypedArrayType()
916 {
917 switch (op()) {
918 case NewTypedArray:
919 return true;
920 default:
921 return false;
922 }
923 }
924
925 TypedArrayType typedArrayType()
926 {
927 ASSERT(hasTypedArrayType());
928 TypedArrayType result = static_cast<TypedArrayType>(m_opInfo);
929 ASSERT(isTypedView(result));
930 return result;
931 }
932
93a37866
A
933 bool hasInlineCapacity()
934 {
935 return op() == CreateThis;
936 }
937
938 unsigned inlineCapacity()
939 {
940 ASSERT(hasInlineCapacity());
941 return m_opInfo;
942 }
943
944 void setIndexingType(IndexingType indexingType)
945 {
946 ASSERT(hasIndexingType());
947 m_opInfo = indexingType;
6fe7ccc8
A
948 }
949
950 bool hasRegexpIndex()
951 {
952 return op() == NewRegexp;
953 }
954
955 unsigned regexpIndex()
956 {
957 ASSERT(hasRegexpIndex());
958 return m_opInfo;
959 }
960
ed1e77d3 961 bool hasScopeOffset()
14957cd0 962 {
81345200 963 return op() == GetClosureVar || op() == PutClosureVar;
14957cd0
A
964 }
965
ed1e77d3 966 ScopeOffset scopeOffset()
14957cd0 967 {
ed1e77d3
A
968 ASSERT(hasScopeOffset());
969 return ScopeOffset(m_opInfo);
970 }
971
972 bool hasDirectArgumentsOffset()
973 {
974 return op() == GetFromArguments || op() == PutToArguments;
975 }
976
977 DirectArgumentsOffset capturedArgumentsOffset()
978 {
979 ASSERT(hasDirectArgumentsOffset());
980 return DirectArgumentsOffset(m_opInfo);
14957cd0 981 }
93a37866 982
93a37866
A
983 bool hasRegisterPointer()
984 {
81345200 985 return op() == GetGlobalVar || op() == PutGlobalVar;
93a37866
A
986 }
987
ed1e77d3 988 WriteBarrier<Unknown>* variablePointer()
93a37866
A
989 {
990 return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo);
6fe7ccc8 991 }
81345200 992
ed1e77d3
A
993 bool hasCallVarargsData()
994 {
995 switch (op()) {
996 case CallVarargs:
997 case CallForwardVarargs:
998 case ConstructVarargs:
999 case ConstructForwardVarargs:
1000 return true;
1001 default:
1002 return false;
1003 }
1004 }
1005
1006 CallVarargsData* callVarargsData()
1007 {
1008 ASSERT(hasCallVarargsData());
1009 return bitwise_cast<CallVarargsData*>(m_opInfo);
1010 }
1011
1012 bool hasLoadVarargsData()
1013 {
1014 return op() == LoadVarargs || op() == ForwardVarargs;
1015 }
1016
1017 LoadVarargsData* loadVarargsData()
1018 {
1019 ASSERT(hasLoadVarargsData());
1020 return bitwise_cast<LoadVarargsData*>(m_opInfo);
1021 }
1022
14957cd0
A
1023 bool hasResult()
1024 {
81345200 1025 return !!result();
14957cd0
A
1026 }
1027
1028 bool hasInt32Result()
1029 {
81345200
A
1030 return result() == NodeResultInt32;
1031 }
1032
1033 bool hasInt52Result()
1034 {
1035 return result() == NodeResultInt52;
14957cd0 1036 }
6fe7ccc8
A
1037
1038 bool hasNumberResult()
14957cd0 1039 {
81345200
A
1040 return result() == NodeResultNumber;
1041 }
1042
1043 bool hasDoubleResult()
1044 {
1045 return result() == NodeResultDouble;
14957cd0 1046 }
6fe7ccc8 1047
14957cd0
A
1048 bool hasJSResult()
1049 {
81345200 1050 return result() == NodeResultJS;
14957cd0 1051 }
6fe7ccc8
A
1052
1053 bool hasBooleanResult()
14957cd0 1054 {
81345200 1055 return result() == NodeResultBoolean;
14957cd0
A
1056 }
1057
93a37866
A
1058 bool hasStorageResult()
1059 {
81345200
A
1060 return result() == NodeResultStorage;
1061 }
1062
1063 UseKind defaultUseKind()
1064 {
1065 return useKindForResult(result());
1066 }
1067
1068 Edge defaultEdge()
1069 {
1070 return Edge(this, defaultUseKind());
93a37866
A
1071 }
1072
6fe7ccc8 1073 bool isJump()
14957cd0 1074 {
6fe7ccc8 1075 return op() == Jump;
14957cd0
A
1076 }
1077
6fe7ccc8 1078 bool isBranch()
14957cd0 1079 {
6fe7ccc8 1080 return op() == Branch;
14957cd0 1081 }
81345200
A
1082
1083 bool isSwitch()
1084 {
1085 return op() == Switch;
1086 }
14957cd0 1087
6fe7ccc8 1088 bool isTerminal()
14957cd0 1089 {
6fe7ccc8
A
1090 switch (op()) {
1091 case Jump:
1092 case Branch:
81345200 1093 case Switch:
6fe7ccc8 1094 case Return:
12899fa2 1095 case Unreachable:
6fe7ccc8
A
1096 return true;
1097 default:
1098 return false;
1099 }
14957cd0
A
1100 }
1101
81345200 1102 unsigned targetBytecodeOffsetDuringParsing()
14957cd0 1103 {
81345200 1104 ASSERT(isJump());
6fe7ccc8 1105 return m_opInfo;
14957cd0
A
1106 }
1107
81345200 1108 BasicBlock*& targetBlock()
14957cd0 1109 {
81345200
A
1110 ASSERT(isJump());
1111 return *bitwise_cast<BasicBlock**>(&m_opInfo);
14957cd0 1112 }
6fe7ccc8 1113
81345200 1114 BranchData* branchData()
14957cd0 1115 {
6fe7ccc8 1116 ASSERT(isBranch());
81345200 1117 return bitwise_cast<BranchData*>(m_opInfo);
14957cd0 1118 }
6fe7ccc8 1119
81345200 1120 SwitchData* switchData()
14957cd0 1121 {
81345200
A
1122 ASSERT(isSwitch());
1123 return bitwise_cast<SwitchData*>(m_opInfo);
6fe7ccc8
A
1124 }
1125
93a37866
A
1126 unsigned numSuccessors()
1127 {
1128 switch (op()) {
1129 case Jump:
1130 return 1;
1131 case Branch:
1132 return 2;
81345200
A
1133 case Switch:
1134 return switchData()->cases.size() + 1;
93a37866
A
1135 default:
1136 return 0;
1137 }
1138 }
1139
81345200 1140 BasicBlock*& successor(unsigned index)
93a37866 1141 {
81345200
A
1142 if (isSwitch()) {
1143 if (index < switchData()->cases.size())
1144 return switchData()->cases[index].target.block;
1145 RELEASE_ASSERT(index == switchData()->cases.size());
1146 return switchData()->fallThrough.block;
1147 }
93a37866
A
1148 switch (index) {
1149 case 0:
81345200
A
1150 if (isJump())
1151 return targetBlock();
1152 return branchData()->taken.block;
93a37866 1153 case 1:
81345200 1154 return branchData()->notTaken.block;
93a37866
A
1155 default:
1156 RELEASE_ASSERT_NOT_REACHED();
81345200 1157 return targetBlock();
93a37866
A
1158 }
1159 }
1160
ed1e77d3
A
1161 class SuccessorsIterable {
1162 public:
1163 SuccessorsIterable()
1164 : m_terminal(nullptr)
1165 {
1166 }
1167
1168 SuccessorsIterable(Node* terminal)
1169 : m_terminal(terminal)
1170 {
1171 }
1172
1173 class iterator {
1174 public:
1175 iterator()
1176 : m_terminal(nullptr)
1177 , m_index(UINT_MAX)
1178 {
1179 }
1180
1181 iterator(Node* terminal, unsigned index)
1182 : m_terminal(terminal)
1183 , m_index(index)
1184 {
1185 }
1186
1187 BasicBlock* operator*()
1188 {
1189 return m_terminal->successor(m_index);
1190 }
1191
1192 iterator& operator++()
1193 {
1194 m_index++;
1195 return *this;
1196 }
1197
1198 bool operator==(const iterator& other) const
1199 {
1200 return m_index == other.m_index;
1201 }
1202
1203 bool operator!=(const iterator& other) const
1204 {
1205 return !(*this == other);
1206 }
1207 private:
1208 Node* m_terminal;
1209 unsigned m_index;
1210 };
1211
1212 iterator begin()
1213 {
1214 return iterator(m_terminal, 0);
1215 }
1216
1217 iterator end()
1218 {
1219 return iterator(m_terminal, m_terminal->numSuccessors());
1220 }
1221
1222 private:
1223 Node* m_terminal;
1224 };
1225
1226 SuccessorsIterable successors()
1227 {
1228 return SuccessorsIterable(this);
1229 }
1230
81345200 1231 BasicBlock*& successorForCondition(bool condition)
93a37866 1232 {
81345200 1233 return branchData()->forCondition(condition);
93a37866
A
1234 }
1235
6fe7ccc8
A
1236 bool hasHeapPrediction()
1237 {
1238 switch (op()) {
ed1e77d3
A
1239 case ArithRound:
1240 case GetDirectPname:
6fe7ccc8
A
1241 case GetById:
1242 case GetByIdFlush:
1243 case GetByVal:
1244 case Call:
1245 case Construct:
ed1e77d3
A
1246 case CallVarargs:
1247 case ConstructVarargs:
1248 case CallForwardVarargs:
1249 case NativeCall:
1250 case NativeConstruct:
6fe7ccc8 1251 case GetByOffset:
81345200
A
1252 case MultiGetByOffset:
1253 case GetClosureVar:
ed1e77d3 1254 case GetFromArguments:
6fe7ccc8
A
1255 case ArrayPop:
1256 case ArrayPush:
1257 case RegExpExec:
1258 case RegExpTest:
1259 case GetGlobalVar:
1260 return true;
1261 default:
1262 return false;
1263 }
1264 }
1265
93a37866 1266 SpeculatedType getHeapPrediction()
6fe7ccc8
A
1267 {
1268 ASSERT(hasHeapPrediction());
93a37866 1269 return static_cast<SpeculatedType>(m_opInfo2);
6fe7ccc8 1270 }
ed1e77d3 1271
81345200
A
1272 void setHeapPrediction(SpeculatedType prediction)
1273 {
1274 ASSERT(hasHeapPrediction());
1275 m_opInfo2 = prediction;
1276 }
1277
ed1e77d3 1278 bool hasCellOperand()
6fe7ccc8 1279 {
93a37866 1280 switch (op()) {
ed1e77d3
A
1281 case CheckCell:
1282 case NativeConstruct:
1283 case NativeCall:
1284 case NewFunction:
1285 case CreateActivation:
1286 case MaterializeCreateActivation:
93a37866
A
1287 return true;
1288 default:
1289 return false;
1290 }
14957cd0
A
1291 }
1292
ed1e77d3 1293 FrozenValue* cellOperand()
93a37866 1294 {
ed1e77d3
A
1295 ASSERT(hasCellOperand());
1296 switch (op()) {
1297 case MaterializeCreateActivation:
1298 return reinterpret_cast<FrozenValue*>(m_opInfo2);
1299 default:
1300 return reinterpret_cast<FrozenValue*>(m_opInfo);
1301 }
1302 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8 1303 }
81345200 1304
ed1e77d3
A
1305 template<typename T>
1306 T castOperand()
81345200 1307 {
ed1e77d3 1308 return cellOperand()->cast<T>();
81345200
A
1309 }
1310
ed1e77d3 1311 void setCellOperand(FrozenValue* value)
81345200 1312 {
ed1e77d3
A
1313 ASSERT(hasCellOperand());
1314 m_opInfo = bitwise_cast<uintptr_t>(value);
81345200
A
1315 }
1316
ed1e77d3 1317 bool hasWatchpointSet()
81345200 1318 {
ed1e77d3 1319 return op() == NotifyWrite;
81345200
A
1320 }
1321
ed1e77d3 1322 WatchpointSet* watchpointSet()
81345200 1323 {
ed1e77d3
A
1324 ASSERT(hasWatchpointSet());
1325 return reinterpret_cast<WatchpointSet*>(m_opInfo);
81345200
A
1326 }
1327
1328 bool hasStoragePointer()
1329 {
1330 return op() == ConstantStoragePointer;
1331 }
1332
1333 void* storagePointer()
1334 {
ed1e77d3 1335 ASSERT(hasStoragePointer());
81345200
A
1336 return reinterpret_cast<void*>(m_opInfo);
1337 }
6fe7ccc8 1338
ed1e77d3 1339 bool hasTransition()
6fe7ccc8 1340 {
93a37866
A
1341 switch (op()) {
1342 case PutStructure:
93a37866
A
1343 case AllocatePropertyStorage:
1344 case ReallocatePropertyStorage:
1345 return true;
1346 default:
1347 return false;
1348 }
6fe7ccc8
A
1349 }
1350
ed1e77d3 1351 Transition* transition()
6fe7ccc8 1352 {
ed1e77d3
A
1353 ASSERT(hasTransition());
1354 return reinterpret_cast<Transition*>(m_opInfo);
6fe7ccc8
A
1355 }
1356
1357 bool hasStructureSet()
1358 {
93a37866
A
1359 switch (op()) {
1360 case CheckStructure:
ed1e77d3 1361 case CheckStructureImmediate:
93a37866
A
1362 return true;
1363 default:
1364 return false;
1365 }
6fe7ccc8
A
1366 }
1367
1368 StructureSet& structureSet()
1369 {
1370 ASSERT(hasStructureSet());
1371 return *reinterpret_cast<StructureSet*>(m_opInfo);
1372 }
1373
93a37866
A
1374 bool hasStructure()
1375 {
1376 switch (op()) {
93a37866
A
1377 case ArrayifyToStructure:
1378 case NewObject:
1379 case NewStringObject:
1380 return true;
1381 default:
1382 return false;
1383 }
1384 }
1385
1386 Structure* structure()
1387 {
1388 ASSERT(hasStructure());
1389 return reinterpret_cast<Structure*>(m_opInfo);
1390 }
1391
6fe7ccc8
A
1392 bool hasStorageAccessData()
1393 {
ed1e77d3
A
1394 switch (op()) {
1395 case GetByOffset:
1396 case PutByOffset:
1397 case GetGetterSetterByOffset:
1398 return true;
1399 default:
1400 return false;
1401 }
6fe7ccc8
A
1402 }
1403
ed1e77d3 1404 StorageAccessData& storageAccessData()
6fe7ccc8
A
1405 {
1406 ASSERT(hasStorageAccessData());
ed1e77d3 1407 return *bitwise_cast<StorageAccessData*>(m_opInfo);
6fe7ccc8
A
1408 }
1409
81345200
A
1410 bool hasMultiGetByOffsetData()
1411 {
1412 return op() == MultiGetByOffset;
1413 }
1414
1415 MultiGetByOffsetData& multiGetByOffsetData()
1416 {
ed1e77d3 1417 ASSERT(hasMultiGetByOffsetData());
81345200
A
1418 return *reinterpret_cast<MultiGetByOffsetData*>(m_opInfo);
1419 }
1420
1421 bool hasMultiPutByOffsetData()
1422 {
1423 return op() == MultiPutByOffset;
1424 }
1425
1426 MultiPutByOffsetData& multiPutByOffsetData()
1427 {
ed1e77d3 1428 ASSERT(hasMultiPutByOffsetData());
81345200
A
1429 return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1430 }
1431
ed1e77d3 1432 bool hasObjectMaterializationData()
6fe7ccc8 1433 {
ed1e77d3
A
1434 switch (op()) {
1435 case MaterializeNewObject:
1436 case MaterializeCreateActivation:
1437 return true;
1438
1439 default:
1440 return false;
1441 }
6fe7ccc8
A
1442 }
1443
ed1e77d3 1444 ObjectMaterializationData& objectMaterializationData()
6fe7ccc8 1445 {
ed1e77d3
A
1446 ASSERT(hasObjectMaterializationData());
1447 return *reinterpret_cast<ObjectMaterializationData*>(m_opInfo);
6fe7ccc8 1448 }
ed1e77d3
A
1449
1450 bool isObjectAllocation()
6fe7ccc8 1451 {
ed1e77d3
A
1452 switch (op()) {
1453 case NewObject:
1454 case MaterializeNewObject:
1455 return true;
1456 default:
1457 return false;
1458 }
6fe7ccc8
A
1459 }
1460
ed1e77d3 1461 bool isPhantomObjectAllocation()
6fe7ccc8 1462 {
ed1e77d3
A
1463 switch (op()) {
1464 case PhantomNewObject:
1465 return true;
1466 default:
1467 return false;
1468 }
6fe7ccc8
A
1469 }
1470
ed1e77d3 1471 bool isActivationAllocation()
81345200 1472 {
ed1e77d3
A
1473 switch (op()) {
1474 case CreateActivation:
1475 case MaterializeCreateActivation:
1476 return true;
1477 default:
1478 return false;
1479 }
81345200 1480 }
ed1e77d3
A
1481
1482 bool isPhantomActivationAllocation()
1483 {
1484 switch (op()) {
1485 case PhantomCreateActivation:
1486 return true;
1487 default:
1488 return false;
1489 }
1490 }
1491
1492 bool isFunctionAllocation()
1493 {
1494 switch (op()) {
1495 case NewFunction:
1496 return true;
1497 default:
1498 return false;
1499 }
1500 }
1501
1502 bool isPhantomFunctionAllocation()
81345200 1503 {
ed1e77d3
A
1504 switch (op()) {
1505 case PhantomNewFunction:
1506 return true;
1507 default:
1508 return false;
1509 }
1510 }
1511
1512 bool isPhantomAllocation()
1513 {
1514 switch (op()) {
1515 case PhantomNewObject:
1516 case PhantomDirectArguments:
1517 case PhantomClonedArguments:
1518 case PhantomNewFunction:
1519 case PhantomCreateActivation:
1520 return true;
1521 default:
1522 return false;
1523 }
81345200
A
1524 }
1525
93a37866
A
1526 bool hasArrayMode()
1527 {
1528 switch (op()) {
1529 case GetIndexedPropertyStorage:
1530 case GetArrayLength:
81345200 1531 case PutByValDirect:
93a37866
A
1532 case PutByVal:
1533 case PutByValAlias:
1534 case GetByVal:
1535 case StringCharAt:
1536 case StringCharCodeAt:
1537 case CheckArray:
1538 case Arrayify:
1539 case ArrayifyToStructure:
1540 case ArrayPush:
1541 case ArrayPop:
ed1e77d3 1542 case HasIndexedProperty:
93a37866
A
1543 return true;
1544 default:
1545 return false;
1546 }
1547 }
1548
1549 ArrayMode arrayMode()
1550 {
1551 ASSERT(hasArrayMode());
1552 if (op() == ArrayifyToStructure)
1553 return ArrayMode::fromWord(m_opInfo2);
1554 return ArrayMode::fromWord(m_opInfo);
1555 }
1556
1557 bool setArrayMode(ArrayMode arrayMode)
1558 {
1559 ASSERT(hasArrayMode());
1560 if (this->arrayMode() == arrayMode)
1561 return false;
1562 m_opInfo = arrayMode.asWord();
1563 return true;
1564 }
1565
81345200
A
1566 bool hasArithMode()
1567 {
1568 switch (op()) {
1569 case ArithAdd:
1570 case ArithSub:
1571 case ArithNegate:
1572 case ArithMul:
1573 case ArithDiv:
1574 case ArithMod:
1575 case UInt32ToNumber:
1576 case DoubleAsInt32:
1577 return true;
1578 default:
1579 return false;
1580 }
1581 }
1582
1583 Arith::Mode arithMode()
1584 {
1585 ASSERT(hasArithMode());
1586 return static_cast<Arith::Mode>(m_opInfo);
1587 }
1588
1589 void setArithMode(Arith::Mode mode)
1590 {
1591 m_opInfo = mode;
1592 }
ed1e77d3
A
1593
1594 bool hasArithRoundingMode()
1595 {
1596 return op() == ArithRound;
1597 }
1598
1599 Arith::RoundingMode arithRoundingMode()
1600 {
1601 ASSERT(hasArithRoundingMode());
1602 return static_cast<Arith::RoundingMode>(m_opInfo);
1603 }
1604
1605 void setArithRoundingMode(Arith::RoundingMode mode)
1606 {
1607 ASSERT(hasArithRoundingMode());
1608 m_opInfo = static_cast<uintptr_t>(mode);
1609 }
81345200 1610
6fe7ccc8
A
1611 bool hasVirtualRegister()
1612 {
81345200 1613 return m_virtualRegister.isValid();
6fe7ccc8
A
1614 }
1615
14957cd0
A
1616 VirtualRegister virtualRegister()
1617 {
1618 ASSERT(hasResult());
81345200 1619 ASSERT(m_virtualRegister.isValid());
14957cd0
A
1620 return m_virtualRegister;
1621 }
93a37866 1622
14957cd0
A
1623 void setVirtualRegister(VirtualRegister virtualRegister)
1624 {
1625 ASSERT(hasResult());
81345200 1626 ASSERT(!m_virtualRegister.isValid());
14957cd0
A
1627 m_virtualRegister = virtualRegister;
1628 }
93a37866 1629
93a37866
A
1630 bool hasExecutionCounter()
1631 {
1632 return op() == CountExecution;
1633 }
1634
1635 Profiler::ExecutionCounter* executionCounter()
1636 {
1637 return bitwise_cast<Profiler::ExecutionCounter*>(m_opInfo);
1638 }
14957cd0
A
1639
1640 bool shouldGenerate()
1641 {
6fe7ccc8 1642 return m_refCount;
14957cd0 1643 }
93a37866 1644
81345200
A
1645 bool isSemanticallySkippable()
1646 {
1647 return op() == CountExecution;
1648 }
14957cd0
A
1649
1650 unsigned refCount()
1651 {
1652 return m_refCount;
1653 }
1654
93a37866 1655 unsigned postfixRef()
14957cd0 1656 {
93a37866 1657 return m_refCount++;
14957cd0
A
1658 }
1659
1660 unsigned adjustedRefCount()
1661 {
1662 return mustGenerate() ? m_refCount - 1 : m_refCount;
1663 }
6fe7ccc8
A
1664
1665 void setRefCount(unsigned refCount)
1666 {
1667 m_refCount = refCount;
1668 }
1669
93a37866 1670 Edge& child1()
6fe7ccc8
A
1671 {
1672 ASSERT(!(m_flags & NodeHasVarArgs));
1673 return children.child1();
1674 }
1675
1676 // This is useful if you want to do a fast check on the first child
1677 // before also doing a check on the opcode. Use this with care and
1678 // avoid it if possible.
1679 Edge child1Unchecked()
1680 {
1681 return children.child1Unchecked();
1682 }
1683
93a37866 1684 Edge& child2()
6fe7ccc8
A
1685 {
1686 ASSERT(!(m_flags & NodeHasVarArgs));
1687 return children.child2();
1688 }
1689
93a37866 1690 Edge& child3()
6fe7ccc8
A
1691 {
1692 ASSERT(!(m_flags & NodeHasVarArgs));
1693 return children.child3();
1694 }
1695
1696 unsigned firstChild()
1697 {
1698 ASSERT(m_flags & NodeHasVarArgs);
1699 return children.firstChild();
1700 }
1701
1702 unsigned numChildren()
1703 {
1704 ASSERT(m_flags & NodeHasVarArgs);
1705 return children.numChildren();
1706 }
1707
93a37866
A
1708 UseKind binaryUseKind()
1709 {
1710 ASSERT(child1().useKind() == child2().useKind());
1711 return child1().useKind();
1712 }
1713
81345200
A
1714 bool isBinaryUseKind(UseKind left, UseKind right)
1715 {
1716 return child1().useKind() == left && child2().useKind() == right;
1717 }
1718
93a37866
A
1719 bool isBinaryUseKind(UseKind useKind)
1720 {
81345200
A
1721 return isBinaryUseKind(useKind, useKind);
1722 }
1723
1724 Edge childFor(UseKind useKind)
1725 {
1726 if (child1().useKind() == useKind)
1727 return child1();
1728 if (child2().useKind() == useKind)
1729 return child2();
1730 if (child3().useKind() == useKind)
1731 return child3();
1732 return Edge();
93a37866
A
1733 }
1734
1735 SpeculatedType prediction()
6fe7ccc8
A
1736 {
1737 return m_prediction;
1738 }
1739
93a37866 1740 bool predict(SpeculatedType prediction)
6fe7ccc8 1741 {
93a37866 1742 return mergeSpeculation(m_prediction, prediction);
6fe7ccc8
A
1743 }
1744
81345200 1745 bool shouldSpeculateInt32()
6fe7ccc8 1746 {
93a37866
A
1747 return isInt32Speculation(prediction());
1748 }
1749
81345200
A
1750 bool sawBooleans()
1751 {
1752 return !!(prediction() & SpecBoolean);
1753 }
1754
1755 bool shouldSpeculateInt32OrBoolean()
1756 {
1757 return isInt32OrBooleanSpeculation(prediction());
1758 }
1759
1760 bool shouldSpeculateInt32ForArithmetic()
93a37866
A
1761 {
1762 return isInt32SpeculationForArithmetic(prediction());
1763 }
1764
81345200
A
1765 bool shouldSpeculateInt32OrBooleanForArithmetic()
1766 {
1767 return isInt32OrBooleanSpeculationForArithmetic(prediction());
1768 }
1769
1770 bool shouldSpeculateInt32OrBooleanExpectingDefined()
1771 {
1772 return isInt32OrBooleanSpeculationExpectingDefined(prediction());
1773 }
1774
1775 bool shouldSpeculateMachineInt()
93a37866 1776 {
81345200 1777 return isMachineIntSpeculation(prediction());
6fe7ccc8
A
1778 }
1779
1780 bool shouldSpeculateDouble()
1781 {
93a37866
A
1782 return isDoubleSpeculation(prediction());
1783 }
1784
ed1e77d3
A
1785 bool shouldSpeculateDoubleReal()
1786 {
1787 return isDoubleRealSpeculation(prediction());
1788 }
1789
81345200 1790 bool shouldSpeculateNumber()
93a37866 1791 {
81345200 1792 return isFullNumberSpeculation(prediction());
6fe7ccc8
A
1793 }
1794
81345200 1795 bool shouldSpeculateNumberOrBoolean()
6fe7ccc8 1796 {
81345200 1797 return isFullNumberOrBooleanSpeculation(prediction());
93a37866
A
1798 }
1799
81345200 1800 bool shouldSpeculateNumberOrBooleanExpectingDefined()
93a37866 1801 {
81345200 1802 return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
6fe7ccc8
A
1803 }
1804
1805 bool shouldSpeculateBoolean()
1806 {
93a37866
A
1807 return isBooleanSpeculation(prediction());
1808 }
81345200
A
1809
1810 bool shouldSpeculateOther()
1811 {
1812 return isOtherSpeculation(prediction());
1813 }
1814
1815 bool shouldSpeculateMisc()
1816 {
1817 return isMiscSpeculation(prediction());
1818 }
93a37866 1819
81345200
A
1820 bool shouldSpeculateStringIdent()
1821 {
1822 return isStringIdentSpeculation(prediction());
1823 }
1824
1825 bool shouldSpeculateNotStringVar()
1826 {
1827 return isNotStringVarSpeculation(prediction());
1828 }
1829
93a37866
A
1830 bool shouldSpeculateString()
1831 {
1832 return isStringSpeculation(prediction());
1833 }
1834
1835 bool shouldSpeculateStringObject()
1836 {
1837 return isStringObjectSpeculation(prediction());
1838 }
1839
1840 bool shouldSpeculateStringOrStringObject()
1841 {
1842 return isStringOrStringObjectSpeculation(prediction());
6fe7ccc8
A
1843 }
1844
1845 bool shouldSpeculateFinalObject()
1846 {
93a37866 1847 return isFinalObjectSpeculation(prediction());
6fe7ccc8
A
1848 }
1849
1850 bool shouldSpeculateFinalObjectOrOther()
1851 {
93a37866 1852 return isFinalObjectOrOtherSpeculation(prediction());
6fe7ccc8
A
1853 }
1854
1855 bool shouldSpeculateArray()
1856 {
93a37866
A
1857 return isArraySpeculation(prediction());
1858 }
1859
ed1e77d3
A
1860 bool shouldSpeculateDirectArguments()
1861 {
1862 return isDirectArgumentsSpeculation(prediction());
1863 }
1864
1865 bool shouldSpeculateScopedArguments()
93a37866 1866 {
ed1e77d3 1867 return isScopedArgumentsSpeculation(prediction());
6fe7ccc8
A
1868 }
1869
1870 bool shouldSpeculateInt8Array()
1871 {
93a37866 1872 return isInt8ArraySpeculation(prediction());
6fe7ccc8
A
1873 }
1874
1875 bool shouldSpeculateInt16Array()
1876 {
93a37866 1877 return isInt16ArraySpeculation(prediction());
6fe7ccc8
A
1878 }
1879
1880 bool shouldSpeculateInt32Array()
1881 {
93a37866 1882 return isInt32ArraySpeculation(prediction());
6fe7ccc8
A
1883 }
1884
1885 bool shouldSpeculateUint8Array()
1886 {
93a37866 1887 return isUint8ArraySpeculation(prediction());
6fe7ccc8
A
1888 }
1889
1890 bool shouldSpeculateUint8ClampedArray()
1891 {
93a37866 1892 return isUint8ClampedArraySpeculation(prediction());
6fe7ccc8
A
1893 }
1894
1895 bool shouldSpeculateUint16Array()
1896 {
93a37866 1897 return isUint16ArraySpeculation(prediction());
6fe7ccc8
A
1898 }
1899
1900 bool shouldSpeculateUint32Array()
1901 {
93a37866 1902 return isUint32ArraySpeculation(prediction());
6fe7ccc8
A
1903 }
1904
1905 bool shouldSpeculateFloat32Array()
1906 {
93a37866 1907 return isFloat32ArraySpeculation(prediction());
6fe7ccc8
A
1908 }
1909
1910 bool shouldSpeculateFloat64Array()
1911 {
93a37866 1912 return isFloat64ArraySpeculation(prediction());
6fe7ccc8
A
1913 }
1914
1915 bool shouldSpeculateArrayOrOther()
1916 {
93a37866 1917 return isArrayOrOtherSpeculation(prediction());
6fe7ccc8
A
1918 }
1919
1920 bool shouldSpeculateObject()
1921 {
93a37866 1922 return isObjectSpeculation(prediction());
6fe7ccc8
A
1923 }
1924
93a37866
A
1925 bool shouldSpeculateObjectOrOther()
1926 {
1927 return isObjectOrOtherSpeculation(prediction());
1928 }
1929
6fe7ccc8
A
1930 bool shouldSpeculateCell()
1931 {
93a37866
A
1932 return isCellSpeculation(prediction());
1933 }
1934
ed1e77d3
A
1935 bool shouldSpeculateNotCell()
1936 {
1937 return isNotCellSpeculation(prediction());
1938 }
1939
93a37866
A
1940 static bool shouldSpeculateBoolean(Node* op1, Node* op2)
1941 {
1942 return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean();
1943 }
1944
81345200 1945 static bool shouldSpeculateInt32(Node* op1, Node* op2)
93a37866 1946 {
81345200 1947 return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32();
93a37866
A
1948 }
1949
81345200 1950 static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2)
93a37866 1951 {
81345200
A
1952 return op1->shouldSpeculateInt32OrBoolean()
1953 && op2->shouldSpeculateInt32OrBoolean();
93a37866
A
1954 }
1955
81345200 1956 static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2)
93a37866 1957 {
81345200
A
1958 return op1->shouldSpeculateInt32OrBooleanForArithmetic()
1959 && op2->shouldSpeculateInt32OrBooleanForArithmetic();
6fe7ccc8
A
1960 }
1961
81345200 1962 static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2)
6fe7ccc8 1963 {
81345200
A
1964 return op1->shouldSpeculateInt32OrBooleanExpectingDefined()
1965 && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
1966 }
1967
1968 static bool shouldSpeculateMachineInt(Node* op1, Node* op2)
1969 {
1970 return op1->shouldSpeculateMachineInt() && op2->shouldSpeculateMachineInt();
6fe7ccc8
A
1971 }
1972
93a37866 1973 static bool shouldSpeculateNumber(Node* op1, Node* op2)
6fe7ccc8 1974 {
93a37866 1975 return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
6fe7ccc8
A
1976 }
1977
81345200
A
1978 static bool shouldSpeculateNumberOrBoolean(Node* op1, Node* op2)
1979 {
1980 return op1->shouldSpeculateNumberOrBoolean()
1981 && op2->shouldSpeculateNumberOrBoolean();
1982 }
1983
1984 static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node* op1, Node* op2)
6fe7ccc8 1985 {
81345200
A
1986 return op1->shouldSpeculateNumberOrBooleanExpectingDefined()
1987 && op2->shouldSpeculateNumberOrBooleanExpectingDefined();
93a37866
A
1988 }
1989
1990 static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
1991 {
1992 return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
6fe7ccc8 1993 }
14957cd0 1994
93a37866 1995 static bool shouldSpeculateArray(Node* op1, Node* op2)
6fe7ccc8 1996 {
93a37866 1997 return op1->shouldSpeculateArray() && op2->shouldSpeculateArray();
6fe7ccc8
A
1998 }
1999
81345200
A
2000 bool canSpeculateInt32(RareCaseProfilingSource source)
2001 {
2002 return nodeCanSpeculateInt32(arithNodeFlags(), source);
2003 }
2004
2005 bool canSpeculateInt52(RareCaseProfilingSource source)
2006 {
2007 return nodeCanSpeculateInt52(arithNodeFlags(), source);
2008 }
2009
2010 RareCaseProfilingSource sourceFor(PredictionPass pass)
2011 {
2012 if (pass == PrimaryPass || child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
2013 return DFGRareCase;
2014 return AllRareCases;
2015 }
2016
2017 bool canSpeculateInt32(PredictionPass pass)
6fe7ccc8 2018 {
81345200
A
2019 return canSpeculateInt32(sourceFor(pass));
2020 }
2021
2022 bool canSpeculateInt52(PredictionPass pass)
2023 {
2024 return canSpeculateInt52(sourceFor(pass));
6fe7ccc8 2025 }
ed1e77d3
A
2026
2027 bool hasTypeLocation()
2028 {
2029 return op() == ProfileType;
2030 }
2031
2032 TypeLocation* typeLocation()
2033 {
2034 ASSERT(hasTypeLocation());
2035 return reinterpret_cast<TypeLocation*>(m_opInfo);
2036 }
2037
2038 bool hasBasicBlockLocation()
2039 {
2040 return op() == ProfileControlFlow;
2041 }
2042
2043 BasicBlockLocation* basicBlockLocation()
2044 {
2045 ASSERT(hasBasicBlockLocation());
2046 return reinterpret_cast<BasicBlockLocation*>(m_opInfo);
2047 }
2048
2049 Node* replacement() const
2050 {
2051 return m_misc.replacement;
2052 }
2053
2054 void setReplacement(Node* replacement)
2055 {
2056 m_misc.replacement = replacement;
2057 }
2058
2059 Epoch epoch() const
2060 {
2061 return Epoch::fromUnsigned(m_misc.epoch);
2062 }
2063
2064 void setEpoch(Epoch epoch)
2065 {
2066 m_misc.epoch = epoch.toUnsigned();
2067 }
6fe7ccc8 2068
93a37866 2069 void dumpChildren(PrintStream& out)
6fe7ccc8
A
2070 {
2071 if (!child1())
2072 return;
93a37866 2073 out.printf("@%u", child1()->index());
6fe7ccc8
A
2074 if (!child2())
2075 return;
93a37866 2076 out.printf(", @%u", child2()->index());
6fe7ccc8
A
2077 if (!child3())
2078 return;
93a37866 2079 out.printf(", @%u", child3()->index());
6fe7ccc8
A
2080 }
2081
93a37866 2082 // NB. This class must have a trivial destructor.
81345200
A
2083
2084 NodeOrigin origin;
2085
6fe7ccc8
A
2086 // References to up to 3 children, or links to a variable length set of children.
2087 AdjacencyList children;
14957cd0
A
2088
2089private:
93a37866
A
2090 unsigned m_op : 10; // real type is NodeType
2091 unsigned m_flags : 22;
14957cd0
A
2092 // The virtual register number (spill location) associated with this .
2093 VirtualRegister m_virtualRegister;
2094 // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
2095 unsigned m_refCount;
81345200
A
2096 // The prediction ascribed to this node after propagation.
2097 SpeculatedType m_prediction;
6fe7ccc8
A
2098 // Immediate values, accesses type-checked via accessors above. The first one is
2099 // big enough to store a pointer.
2100 uintptr_t m_opInfo;
81345200 2101 uintptr_t m_opInfo2;
93a37866
A
2102
2103public:
2104 // Fields used by various analyses.
2105 AbstractValue value;
81345200
A
2106
2107 // Miscellaneous data that is usually meaningless, but can hold some analysis results
ed1e77d3 2108 // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner
81345200
A
2109 // will tell you which basic block a node belongs to. You cannot rely on this persisting
2110 // across transformations unless you do the maintenance work yourself. Other phases use
ed1e77d3
A
2111 // Node::replacement, but they do so manually: first you do Graph::clearReplacements()
2112 // and then you set, and use, replacement's yourself. Same thing for epoch.
81345200
A
2113 //
2114 // Bottom line: don't use these fields unless you initialize them yourself, or by
2115 // calling some appropriate methods that initialize them the way you want. Otherwise,
2116 // these fields are meaningless.
ed1e77d3 2117private:
81345200
A
2118 union {
2119 Node* replacement;
ed1e77d3
A
2120 unsigned epoch;
2121 } m_misc;
2122public:
2123 BasicBlock* owner;
14957cd0
A
2124};
2125
81345200
A
2126inline bool nodeComparator(Node* a, Node* b)
2127{
2128 return a->index() < b->index();
2129}
2130
2131template<typename T>
2132CString nodeListDump(const T& nodeList)
2133{
2134 return sortedListDump(nodeList, nodeComparator);
2135}
2136
2137template<typename T>
2138CString nodeMapDump(const T& nodeMap, DumpContext* context = 0)
2139{
2140 Vector<typename T::KeyType> keys;
2141 for (
2142 typename T::const_iterator iter = nodeMap.begin();
2143 iter != nodeMap.end(); ++iter)
2144 keys.append(iter->key);
2145 std::sort(keys.begin(), keys.end(), nodeComparator);
2146 StringPrintStream out;
2147 CommaPrinter comma;
2148 for(unsigned i = 0; i < keys.size(); ++i)
2149 out.print(comma, keys[i], "=>", inContext(nodeMap.get(keys[i]), context));
2150 return out.toCString();
2151}
2152
14957cd0
A
2153} } // namespace JSC::DFG
2154
93a37866
A
2155namespace WTF {
2156
81345200 2157void printInternal(PrintStream&, JSC::DFG::SwitchKind);
93a37866
A
2158void printInternal(PrintStream&, JSC::DFG::Node*);
2159
81345200
A
2160inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; }
2161
93a37866
A
2162} // namespace WTF
2163
81345200
A
2164using WTF::inContext;
2165
14957cd0
A
2166#endif
2167#endif