gecko-dev/ef/Compiler/PrimitiveGraph/ControlGraph.h
1999-11-02 06:38:29 +00:00

146 lines
4.8 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef CONTROLGRAPH_H
#define CONTROLGRAPH_H
#include "ControlNodes.h"
#include "LogModule.h"
struct MethodDescriptor;
class ControlGraph
{
public:
Pool &pool; // Memory pool from which this graph is allocated
DoublyLinkedList<ControlNode> controlNodes; // List of control nodes in this graph
Uint32 nMonitorSlots; // Number of slots needed for MEnter/MExit primitives in this graph
private:
ControlNode beginNode; // The Begin node
ControlNode endNode; // The End node
ControlNode *returnNode; // The graph's Return node or nil if none
ControlNode *recycleBuffer; // A free ControlNode ready for reuse or nil if none
public:
ControlNode** dfsList; // List of control nodes in depth first search order.
Uint32 nNodes;
bool hasBackEdges;
ControlNode** lndList; // List of control nodes in loop nesting depth order.
ControlGraph(Pool &pool, uint nArguments, const ValueKind *argumentKinds, bool hasSelfArgument, Uint32 nMonitorSlots);
private:
ControlGraph(const ControlGraph &); // Copying forbidden
void operator=(const ControlGraph &); // Copying forbidden
public:
ControlNode &newControlNode();
void recycle(ControlNode &cn);
ControlNode &getBeginNode() {return beginNode;}
ControlNode &getEndNode() {return endNode;}
ControlNode *getReturnNode() const {return returnNode;}
void setReturnNode(ControlNode &cr) {assert(!returnNode && cr.hasControlKind(ckReturn)); returnNode = &cr;}
Uint32 assignProducerNumbers(Uint32 base);
bool dfsListIsValid() const {return dfsList != 0;}
void dfsSearch();
bool lndListIsValid() const {return lndList != 0;}
void lndSearch();
#ifdef DEBUG_LOG
void print(LogModuleObject &f);
#endif
#ifdef DEBUG
void validate(); // verifies that this control graph is 'correct'
#endif
};
// ----------------------------------------------------------------------------
// Control flow builders and utilities
DataNode &makeVariable(const VariableOrConstant &input, ControlNode &cn, Uint32 bci);
const VariableOrConstant &followVariableBack(const VariableOrConstant &input, ControlNode &cn, ControlEdge &e);
ControlNode &joinControlFlows(uint nPredecessors, ControlNode *const*predecessors, ControlGraph &cg);
void joinDataFlows(uint nPredecessors, ControlNode &cn, const VariableOrConstant *inputs, VariableOrConstant &output);
void addDataFlow(ControlNode &cn, DataConsumer &consumer, const VariableOrConstant &newSource);
void changeDataFlow(ControlNode &cn, ControlEdge &e, DataConsumer &consumer, const VariableOrConstant &newSource);
ControlNode &obtainSuccessorSite(ControlNode &cn, Uint32 successorNumber = 0);
ControlNode &insertControlNodeAfter(ControlNode &cn, ControlNode *&successor, DoublyLinkedList<ControlEdge>::iterator &where,
Uint32 successorNumber = 0);
ControlNode &insertControlNodeBefore(ControlNode &cn);
ControlNode *insertControlNodeBefore(ControlNode &cn, Function1<bool, ControlEdge &> &f);
// --- INLINES ----------------------------------------------------------------
//
// Initialize a ControlNode.
// Don't call this directly; call ControlGraph::newControlNode instead.
//
inline ControlNode::ControlNode(ControlGraph &cg):
noRecycle(false),
controlGraph(cg),
generation(0),
liveAtBegin(cg.pool),
liveAtEnd(cg.pool),
workingNode(false)
{
#if defined(DEBUG) || defined(DEBUG_LOG)
controlKind = ckNone;
#endif
#ifdef DEBUG
successorsBegin = 0;
successorsEnd = 0;
phisDisengaged = 0;
#endif
}
//
// Return the pool for allocating primitives in this control node.
//
inline Pool &ControlNode::getPrimitivePool() const
{
return controlGraph.pool;
}
//
// Recycle the ControlNode so that it can be reused by newControlNode.
// The given ControlNode must satisfy the empty() method; have no predecessors,
// instructions, extra, or generation; and belong to this ControlGraph.
//
inline void ControlGraph::recycle(ControlNode &cn)
{
assert(&cn.controlGraph == this);
cn.remove();
cn.recycle();
recycleBuffer = &cn;
}
#endif