gecko-dev/ef/Compiler/CodeGenerator/CGScheduler.cpp

227 строки
5.5 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):
*/
#include "Fundamentals.h"
#include "CGScheduler.h"
#include "ControlGraph.h"
#include "InstructionEmitter.h"
#include "GraphUtils.h"
inline static bool
isPredecessor(ControlNode& pred, ControlNode& node)
{
ControlEdge* limit = pred.getSuccessorsEnd();
for (ControlEdge* ptr = pred.getSuccessorsBegin(); ptr < limit; ptr++)
if (&ptr->getTarget() == &node)
return true;
return false;
}
ControlNode** ControlGraphScheduler::
scheduleNodes()
{
ControlNode** orderedNodes = orderNodes();
addAbsoluteBranches(orderedNodes);
return orderedNodes;
}
// addAbsoluteBranches
// Given an ordering of ControlNodes in the graph add necessary
// implicit branches demanded by the ordering (ie to satisfy the ControlEdges)
void ControlGraphScheduler::
addAbsoluteBranches(ControlNode** orderedNodes)
{
Uint32 nNodes = cg.nNodes;
// for each ControlNode in orderedNodes, determine for each sequential pairing
// if a falls through to b then don't add an absolute branch from a->b, otherwise
// if the edge a->b does not exist, then add an absolute branch to where a should
// connect.
for (Uint32 n = 0; n < nNodes; n++)
{
ControlNode* thisNode = orderedNodes[n];
ControlNode* nextNode = (n < (nNodes - 1)) ? orderedNodes[n+1] : (ControlNode *) 0;
ControlEdge* branchEdge;
switch(thisNode->getControlKind())
{
case ckIf:
case ckBlock:
case ckExc:
case ckAExc:
case ckCatch:
case ckBegin:
branchEdge = &thisNode->nthSuccessor(0);
break;
// these three ControlNodes never have any implicit branches
case ckSwitch:
case ckReturn:
case ckEnd:
case ckThrow:
branchEdge = NULL;
break;
default:
assert(false);
}
if (branchEdge != NULL && nextNode != NULL && &branchEdge->getTarget() != nextNode)
emitter.pushAbsoluteBranch(branchEdge->getSource(), branchEdge->getTarget());
}
}
ControlNode** ControlGraphScheduler::
orderNodes()
{
Uint32 nNodes = cg.nNodes - 1;
Uint32 myGeneration = ControlNode::getNextGeneration();
ControlNode** nodes = new ControlNode*[nNodes];
ControlNode** n_ptr = nodes;
SearchStackEntry<ControlEdge> *ceStack = new SearchStackEntry<ControlEdge>[nNodes];
SearchStackEntry<ControlEdge> *ceSp = ceStack;
ControlEdge beginEdge;
beginEdge.setTarget(cg.getBeginNode());
cg.getEndNode().generation = myGeneration;
ControlEdge* n = &beginEdge;
ControlEdge* l = &beginEdge + 1;
while(true)
{
if (n == l)
{
if (ceSp == ceStack)
break;
--ceSp;
n = ceSp->next;
l = ceSp->limit;
}
else
{
ControlNode& node = n++->getTarget();
if (node.generation != myGeneration)
{
node.generation = myGeneration;
node.schedulePos = Uint32(n_ptr - nodes);
*n_ptr++ = &node;
ceSp->next = n;
ceSp->limit = l;
ceSp++;
n = node.getSuccessorsBegin();
l = node.getSuccessorsEnd();
}
}
}
#ifndef WIN32 // ***** Visual C++ has a bug in the code for delete[].
delete ceStack;
#endif
Uint32* cnStack = new Uint32[nNodes];
Uint32* cnSp = cnStack;
ControlNode** orderedNodes = new(cg.pool) ControlNode*[nNodes + 1];
n_ptr = orderedNodes;
Uint32 next;
#if DEBUG
fill_n(orderedNodes, nNodes, (ControlNode *) 0);
#endif
myGeneration = ControlNode::getNextGeneration();
orderedNodes[nNodes] = &cg.getEndNode();
orderedNodes[nNodes]->generation = myGeneration;
*n_ptr++ = nodes[0];
*cnSp++ = 0;
next = 1;
while (true)
{
if (next == 0)
{
if (cnSp == cnStack)
break;
next = *--cnSp;
}
else
{
ControlNode& node = *nodes[next];
if (node.generation == myGeneration)
{
next = 0;
}
else
{
// if (node.hasControlKind(ckIf))
const DoublyLinkedList<ControlEdge>& edges = node.getPredecessors();
if (!edges.done(edges.advance(edges.begin()))) // more than one predecessor
{
for (DoublyLinkedList<ControlEdge>::iterator i = edges.begin(); !edges.done(i); i = edges.advance(i))
{
ControlNode& source = edges.get(i).getSource();
if ((source.dfsNum > node.dfsNum) && (source.generation != myGeneration))
{
*cnSp++ = next;
next = source.schedulePos;
while (isPredecessor(*nodes[next - 1], *nodes[next]) &&
(nodes[next - 1]->generation != myGeneration) && (next != node.schedulePos))
next--;
break;
}
}
if (next == node.schedulePos)
{
node.generation = myGeneration;
*n_ptr++ = &node;
if (++next >= nNodes)
next = 0;
}
}
else
{
node.generation = myGeneration;
*n_ptr++ = &node;
if (++next >= nNodes)
next = 0;
}
}
}
}
//delete cnStack;
//delete [] nodes;
#if DEBUG
for (Uint32 i = 0; i < nNodes + 1; i++)
assert(orderedNodes[i]);
#endif
return orderedNodes;
}