+ unsigned numChildren(Node* node)
+ {
+ if (node->flags() & NodeHasVarArgs)
+ return varArgNumChildren(node);
+ return AdjacencyList::Size;
+ }
+
+ Edge& varArgChild(Node* node, unsigned index)
+ {
+ ASSERT(node->flags() & NodeHasVarArgs);
+ return m_varArgChildren[node->firstChild() + index];
+ }
+
+ Edge& child(Node* node, unsigned index)
+ {
+ if (node->flags() & NodeHasVarArgs)
+ return varArgChild(node, index);
+ return node->children.child(index);
+ }
+
+ void voteNode(Node* node, unsigned ballot, float weight = 1)
+ {
+ switch (node->op()) {
+ case ValueToInt32:
+ case UInt32ToNumber:
+ node = node->child1().node();
+ break;
+ default:
+ break;
+ }
+
+ if (node->op() == GetLocal)
+ node->variableAccessData()->vote(ballot, weight);
+ }
+
+ void voteNode(Edge edge, unsigned ballot, float weight = 1)
+ {
+ voteNode(edge.node(), ballot, weight);
+ }
+
+ void voteChildren(Node* node, unsigned ballot, float weight = 1)
+ {
+ if (node->flags() & NodeHasVarArgs) {
+ for (unsigned childIdx = node->firstChild();
+ childIdx < node->firstChild() + node->numChildren();
+ childIdx++) {
+ if (!!m_varArgChildren[childIdx])
+ voteNode(m_varArgChildren[childIdx], ballot, weight);
+ }
+ return;
+ }
+
+ if (!node->child1())
+ return;
+ voteNode(node->child1(), ballot, weight);
+ if (!node->child2())
+ return;
+ voteNode(node->child2(), ballot, weight);
+ if (!node->child3())
+ return;
+ voteNode(node->child3(), ballot, weight);
+ }
+
+ template<typename T> // T = Node* or Edge
+ void substitute(BasicBlock& block, unsigned startIndexInBlock, T oldThing, T newThing)
+ {
+ for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
+ Node* node = block[indexInBlock];
+ if (node->flags() & NodeHasVarArgs) {
+ for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); ++childIdx) {
+ if (!!m_varArgChildren[childIdx])
+ compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing);
+ }
+ continue;
+ }
+ if (!node->child1())
+ continue;
+ compareAndSwap(node->children.child1(), oldThing, newThing);
+ if (!node->child2())
+ continue;
+ compareAndSwap(node->children.child2(), oldThing, newThing);
+ if (!node->child3())
+ continue;
+ compareAndSwap(node->children.child3(), oldThing, newThing);
+ }
+ }
+
+ // Use this if you introduce a new GetLocal and you know that you introduced it *before*
+ // any GetLocals in the basic block.
+ // FIXME: it may be appropriate, in the future, to generalize this to handle GetLocals
+ // introduced anywhere in the basic block.
+ void substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal);
+
+ void invalidateCFG();
+
+ void clearFlagsOnAllNodes(NodeFlags);
+
+ void clearReplacements();
+ void initializeNodeOwners();
+
+ void getBlocksInDepthFirstOrder(Vector<BasicBlock*>& result);
+
+ Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
+
+ DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
+ DesiredWatchpoints& watchpoints() { return m_plan.watchpoints; }
+ DesiredStructureChains& chains() { return m_plan.chains; }
+
+ FullBytecodeLiveness& livenessFor(CodeBlock*);
+ FullBytecodeLiveness& livenessFor(InlineCallFrame*);
+ bool isLiveInBytecode(VirtualRegister, CodeOrigin);
+
+ unsigned frameRegisterCount();
+ unsigned stackPointerOffset();
+ unsigned requiredRegisterCountForExit();
+ unsigned requiredRegisterCountForExecutionAndExit();
+
+ JSActivation* tryGetActivation(Node*);
+ WriteBarrierBase<Unknown>* tryGetRegisters(Node*);
+
+ JSArrayBufferView* tryGetFoldableView(Node*);
+ JSArrayBufferView* tryGetFoldableView(Node*, ArrayMode);
+ JSArrayBufferView* tryGetFoldableViewForChild1(Node*);
+
+ virtual void visitChildren(SlotVisitor&) override;
+
+ VM& m_vm;
+ Plan& m_plan;