Compare commits

..

2 Commits

Author SHA1 Message Date
fur%netscape.com
1c43d4984f This is a copy of regalloc_code2_BRANCH from Netscape's private repository,
as it existed in January of 1998.


git-svn-id: svn://10.0.0.236/branches/regalloc_code2_BRANCH@22571 18797224-902f-48f8-a5cc-f745e15eee43
1999-03-02 16:12:08 +00:00
(no author)
cfe021ff88 This commit was manufactured by cvs2svn to create branch
'regalloc_code2_BRANCH'.

git-svn-id: svn://10.0.0.236/branches/regalloc_code2_BRANCH@22567 18797224-902f-48f8-a5cc-f745e15eee43
1999-03-02 15:57:58 +00:00
293 changed files with 5324 additions and 95236 deletions

View File

@@ -0,0 +1,134 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "BitSet.h"
// Return the next bit after index set to true or -1 if none.
//
Int32 BitSet::nextOne(Int32 pos) const
{
++pos;
if (pos < 0 || Uint32(pos) >= universeSize)
return -1;
Uint32 offset = getWordOffset(pos);
Uint8 index = getBitOffset(pos);
Word* ptr = &word[offset];
Word currentWord = *ptr++ >> index;
if (currentWord != Word(0)) {
while ((currentWord & Word(1)) == 0) {
++index;
currentWord >>= 1;
}
return (offset << nBitsInWordLog2) + index;
}
Word* limit = &word[getSizeInWords(universeSize)];
while (ptr < limit) {
++offset;
currentWord = *ptr++;
if (currentWord != Word(0)) {
index = 0;
while ((currentWord & Word(1)) == 0) {
++index;
currentWord >>= 1;
}
return (offset << nBitsInWordLog2) + index;
}
}
return -1;
}
// Return the next bit after index set to false or -1 if none.
//
Int32 BitSet::nextZero(Int32 pos) const
{
++pos;
if (pos < 0 || Uint32(pos) >= universeSize)
return -1;
Uint32 offset = getWordOffset(pos);
Uint8 index = getBitOffset(pos);
Word* ptr = &word[offset];
Word currentWord = *ptr++ >> index;
if (currentWord != Word(~0)) {
for (; index < nBitsInWord; ++index) {
if ((currentWord & Word(1)) == 0) {
Int32 ret = (offset << nBitsInWordLog2) + index;
return (Uint32(ret) < universeSize) ? ret : -1;
}
currentWord >>= 1;
}
}
Word* limit = &word[getSizeInWords(universeSize)];
while (ptr < limit) {
++offset;
currentWord = *ptr++;
if (currentWord != Word(~0)) {
for (index = 0; index < nBitsInWord; ++index) {
if ((currentWord & Word(1)) == 0) {
Int32 ret = (offset << nBitsInWordLog2) + index;
return (Uint32(ret) < universeSize) ? ret : -1;
}
currentWord >>= 1;
}
}
}
return -1;
}
#ifdef DEBUG_LOG
// Print the set.
//
void BitSet::printPretty(LogModuleObject log)
{
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("[ "));
for (Int32 i = firstOne(); i != -1; i = nextOne(i)) {
Int32 currentBit = i;
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", currentBit));
Int32 nextBit = nextOne(currentBit);
if (nextBit != currentBit + 1) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" "));
continue;
}
while ((nextBit != -1) && (nextBit == (currentBit + 1))) {
currentBit = nextBit;
nextBit = nextOne(nextBit);
}
if (currentBit > (i+1))
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("-%d ", currentBit));
else
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" %d ", currentBit));
i = currentBit;
}
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("]\n"));
}
#endif // DEBUG_LOG

View File

@@ -0,0 +1,195 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _BITSET_H_
#define _BITSET_H_
#include "Fundamentals.h"
#include "LogModule.h"
#include "Pool.h"
#include <string.h>
//------------------------------------------------------------------------------
// BitSet -
class BitSet
{
private:
#if (PR_BITS_PER_WORD == 64)
typedef Uint64 Word;
#elif (PR_BITS_PER_WORD == 32)
typedef Uint32 Word;
#endif
static const nBitsInWord = PR_BITS_PER_WORD;
static const nBytesInWord = PR_BYTES_PER_WORD;
static const nBitsInWordLog2 = PR_BITS_PER_WORD_LOG2;
static const nBytesInWordLog2 = PR_BYTES_PER_WORD_LOG2;
// Return the number of Word need to store the universe.
static Uint32 getSizeInWords(Uint32 sizeOfUniverse) {return (sizeOfUniverse + (nBitsInWord - 1)) >> nBitsInWordLog2;}
// Return the given element offset in its containing Word.
static Uint32 getBitOffset(Uint32 element) {return element & (nBitsInWord - 1);}
// Return the Word offset for the given element int the universe.
static Uint32 getWordOffset(Uint32 element) {return element >> nBitsInWordLog2;}
// Return the mask for the given bit index.
static Word getMask(Uint8 index) {return Word(1) << index;}
private:
Uint32 universeSize; // Size of the universe
Word* word; // universe memory.
private:
// No copy constructor.
BitSet(const BitSet&);
// Check if the given set's universe is of the same size than this universe.
void checkUniverseCompatibility(const BitSet& set) const {assert(set.universeSize == universeSize);}
// Check if pos is valid for this set's universe.
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
public:
// Create a bitset of universeSize bits.
BitSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {word = new(pool) Word[getSizeInWords(universeSize)]; clear();}
// Return the size of this bitset.
Uint32 getSize() const {return universeSize;}
// Clear the bitset.
void clear() {memset(word, 0x00, getSizeInWords(universeSize) << nBytesInWordLog2);}
// Clear the bit at index.
void clear(Uint32 index) {checkMember(index); word[getWordOffset(index)] &= ~getMask(index);}
// Set the bitset.
void set() {memset(word, 0xFF, getSizeInWords(universeSize) << nBytesInWordLog2);}
// Set the bit at index.
void set(Uint32 index) {checkMember(index); word[getWordOffset(index)] |= getMask(index);}
// Return true if the bit at index is set.
bool test(Uint32 index) const {checkMember(index); return (word[getWordOffset(index)] & getMask(index)) != 0;}
// Union with the given bitset.
inline void or(const BitSet& set);
// Intersection with the given bitset.
inline void and(const BitSet& set);
// Difference with the given bitset.
inline void difference(const BitSet& set);
// Copy set.
inline BitSet& operator = (const BitSet& set);
// Return true if the bitset are identical.
friend bool operator == (const BitSet& set1, const BitSet& set2);
// Return true if the bitset are different.
friend bool operator != (const BitSet& set1, const BitSet& set2);
// Logical operators.
BitSet& operator |= (const BitSet& set) {or(set); return *this;}
BitSet& operator &= (const BitSet& set) {and(set); return *this;}
BitSet& operator -= (const BitSet& set) {difference(set); return *this;}
// Return the first bit at set to true or -1 if none.
Int32 firstOne() const {return nextOne(-1);}
// Return the next bit after index set to true or -1 if none.
Int32 nextOne(Int32 pos) const;
// Return the first bit at set to false or -1 if none.
Int32 firstZero() const {return nextZero(-1);}
// Return the next bit after index set to false or -1 if none.
Int32 nextZero(Int32 pos) const;
// Iterator to conform with the set API.
typedef Int32 iterator;
// Return true if the walk is ordered.
static bool isOrdered() {return true;}
// Return the iterator for the first element of this set.
iterator begin() const {return firstOne();}
// Return the next iterator.
iterator advance(iterator pos) const {return nextOne(pos);}
// Return true if the iterator is at the end of the set.
bool done(iterator pos) const {return pos == -1;}
// Return the element corresponding to the given iterator.
Uint32 get(iterator pos) const {return pos;}
#ifdef DEBUG_LOG
// Print the set.
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
// Union with the given bitset.
//
inline void BitSet::or(const BitSet& set)
{
checkUniverseCompatibility(set);
Word* src = set.word;
Word* dst = word;
Word* limit = &src[getSizeInWords(universeSize)];
while (src < limit)
*dst++ |= *src++;
}
// Intersection with the given bitset.
//
inline void BitSet::and(const BitSet& set)
{
checkUniverseCompatibility(set);
Word* src = set.word;
Word* dst = word;
Word* limit = &src[getSizeInWords(universeSize)];
while (src < limit)
*dst++ &= *src++;
}
// Difference with the given bitset.
//
inline void BitSet::difference(const BitSet& set)
{
checkUniverseCompatibility(set);
Word* src = set.word;
Word* dst = word;
Word* limit = &src[getSizeInWords(universeSize)];
while (src < limit)
*dst++ &= ~*src++;
}
// Copy the given set into this set.
//
inline BitSet& BitSet::operator = (const BitSet& set)
{
checkUniverseCompatibility(set);
if (this != &set)
memcpy(word, set.word, getSizeInWords(universeSize) << nBytesInWordLog2);
return *this;
}
// Return true if the given set is identical to this set.
inline bool operator == (const BitSet& set1, const BitSet& set2)
{
set1.checkUniverseCompatibility(set2);
if (&set1 == &set2)
return true;
return memcmp(set1.word, set2.word, BitSet::getSizeInWords(set1.universeSize) << BitSet::nBytesInWordLog2) == 0;
}
inline bool operator != (const BitSet& set1, const BitSet& set2) {return !(set1 == set2);}
#endif // _BITSET_H

View File

@@ -0,0 +1,159 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _COALESCING_H_
#define _COALESCING_H_
#include "Fundamentals.h"
#include "Pool.h"
#include "RegisterPressure.h"
#include "InterferenceGraph.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "SparseSet.h"
#include "RegisterAllocator.h"
#include "RegisterAllocatorTools.h"
#if 1
// Performing an ultra conservative coalescing meens that when we look at
// candidates (source,destination) for coalescing we need to make sure
// that the combined interference of the source and destination register
// will not exceed the total number of register available for the register
// class.
#define ULTRA_CONSERVATIVE_COALESCING
#else
// If we are not doing an ultra conservative coalescing we have to make sure
// that the total number of neighbor whose degree is greater than the total
// number of register is not greater than the total number of register.
#undef ULTRA_CONSERVATIVE_COALESCING
#endif
template <class RegisterPressure>
struct Coalescing
{
static bool coalesce(RegisterAllocator& registerAllocator);
};
template <class RegisterPressure>
bool Coalescing<RegisterPressure>::coalesce(RegisterAllocator& registerAllocator)
{
Pool& pool = registerAllocator.pool;
// Initialize the lookup table
//
Uint32 rangeCount = registerAllocator.rangeCount;
RegisterName* newRange = new RegisterName[2 * rangeCount];
RegisterName* coalescedRange = &newRange[rangeCount];
RegisterName* name2range = registerAllocator.name2range;
init(coalescedRange, rangeCount);
SparseSet interferences(pool, rangeCount);
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
bool removedInstructions = false;
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.lndList;
Uint32 nNodes = controlGraph.nNodes;
// Walk the nodes in the loop nesting depth list.
for (Int32 n = nNodes - 1; n >= 0; n--) {
InstructionList& instructions = nodes[n]->getInstructions();
InstructionList::iterator it = instructions.begin();
while (!instructions.done(it)) {
Instruction& instruction = instructions.get(it);
it = instructions.advance(it);
if ((instruction.getFlags() & ifCopy) != 0) {
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
RegisterName source = findRoot(name2range[instruction.getInstructionUseBegin()[0].getRegisterName()], coalescedRange);
RegisterName destination = findRoot(name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()], coalescedRange);
if (source == destination) {
instruction.remove();
} else if (!iGraph.interfere(source, destination)) {
InterferenceVector* sourceVector = iGraph.getInterferenceVector(source);
InterferenceVector* destinationVector = iGraph.getInterferenceVector(destination);
#ifdef ULTRA_CONSERVATIVE_COALESCING
interferences.clear();
InterferenceVector* vector;
for (vector = sourceVector; vector != NULL; vector = vector->next) {
RegisterName* neighbors = vector->neighbors;
for (Uint32 i = 0; i < vector->count; i++)
interferences.set(findRoot(neighbors[i], coalescedRange));
}
for (vector = destinationVector; vector != NULL; vector = vector->next) {
RegisterName* neighbors = vector->neighbors;
for (Uint32 i = 0; i < vector->count; i++)
interferences.set(findRoot(neighbors[i], coalescedRange));
}
Uint32 count = interferences.getSize();
#else // ULTRA_CONSERVATIVE_COALESCING
trespass("not implemented");
Uint32 count = 0;
#endif // ULTRA_CONSERVATIVE_COALESCING
if (count < 6 /* FIX: should get the number from the class */) {
// Update the interferences vector.
if (sourceVector == NULL) {
iGraph.setInterferenceVector(source, destinationVector);
sourceVector = destinationVector;
} else if (destinationVector == NULL)
iGraph.setInterferenceVector(destination, sourceVector);
else {
InterferenceVector* last = NULL;
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next)
last = v;
assert(last);
last->next = destinationVector;
iGraph.setInterferenceVector(destination, sourceVector);
}
// Update the interference matrix.
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next) {
RegisterName* neighbors = v->neighbors;
for (Uint32 i = 0; i < v->count; i++) {
RegisterName neighbor = findRoot(neighbors[i], coalescedRange);
iGraph.setInterference(neighbor, source);
iGraph.setInterference(neighbor, destination);
}
}
instruction.remove();
coalescedRange[source] = destination;
removedInstructions = true;
}
}
}
}
}
registerAllocator.rangeCount = compress(registerAllocator.name2range, coalescedRange, registerAllocator.nameCount, rangeCount);
delete newRange;
return removedInstructions;
}
#endif // _COALESCING_H_

View File

@@ -0,0 +1,283 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef NEW_LAURENTM_CODE
#include "Coloring.h"
#include "VirtualRegister.h"
#include "FastBitSet.h"
#include "FastBitMatrix.h"
#include "CpuInfo.h"
bool Coloring::
assignRegisters(FastBitMatrix& interferenceMatrix)
{
PRUint32 *stackPtr = new(pool) PRUint32[vRegManager.count()];
return select(interferenceMatrix, stackPtr, simplify(interferenceMatrix, stackPtr));
}
PRInt32 Coloring::
getLowestSpillCostRegister(FastBitSet& bitset)
{
PRInt32 lowest = bitset.firstOne();
if (lowest != -1)
{
Flt32 cost = vRegManager.getVirtualRegister(lowest).spillInfo.spillCost;
for (PRInt32 r = bitset.nextOne(lowest); r != -1; r = bitset.nextOne(r))
{
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
if (!vReg.spillInfo.infiniteSpillCost && (vReg.spillInfo.spillCost < cost))
{
cost = vReg.spillInfo.spillCost;
lowest = r;
}
}
}
return lowest;
}
PRUint32* Coloring::
simplify(FastBitMatrix interferenceMatrix, PRUint32* stackPtr)
{
// first we construct the sets low and high. low contains all nodes of degree
// inferior to the number of register available on the processor. All the
// nodes with an high degree and a finite spill cost are placed in high.
// Nodes of high degree and infinite spill cost are not included in either sets.
PRUint32 nRegisters = vRegManager.count();
FastBitSet low(pool, nRegisters);
FastBitSet high(pool, nRegisters);
FastBitSet stack(pool, nRegisters);
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
{
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
if (vReg.getClass() == vrcStackSlot)
{
stack.set(i);
vReg.colorRegister(nRegisters);
}
else
{
if (vReg.colorInfo.interferenceDegree < NUMBER_OF_REGISTERS)
low.set(i);
else // if (!vReg.spillInfo.infiniteSpillCost)
high.set(i);
// Set coloring info.
vReg.spillInfo.willSpill = false;
switch(vReg.getClass())
{
case vrcInteger:
vReg.colorRegister(LAST_GREGISTER + 1);
break;
case vrcFloatingPoint:
case vrcFixedPoint:
vReg.colorRegister(LAST_FPREGISTER + 1);
break;
default:
PR_ASSERT(false); // Cannot happen.
}
}
}
// push the stack registers
PRInt32 j;
for (j = stack.firstOne(); j != -1; j = stack.nextOne(j))
*stackPtr++ = j;
// simplify
while (true)
{
PRInt32 r;
while ((r = getLowestSpillCostRegister(low)) != -1)
{
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
/* update low and high */
FastBitSet inter(interferenceMatrix.getRow(r), nRegisters);
for (j = inter.firstOne(); j != -1; j = inter.nextOne(j))
{
VirtualRegister& neighbor = vRegManager.getVirtualRegister(j);
// if the new interference degree of one of his neighbor becomes
// NUMBER_OF_REGISTERS - 1 then it is added to the set 'low'.
PRUint32 maxInterference = 0;
switch (neighbor.getClass())
{
case vrcInteger:
maxInterference = NUMBER_OF_GREGISTERS;
break;
case vrcFloatingPoint:
case vrcFixedPoint:
maxInterference = NUMBER_OF_FPREGISTERS;
break;
default:
PR_ASSERT(false);
}
if ((vRegManager.getVirtualRegister(j).colorInfo.interferenceDegree-- == maxInterference))
{
high.clear(j);
low.set(j);
}
vReg.colorInfo.interferenceDegree--;
interferenceMatrix.clear(r, j);
interferenceMatrix.clear(j, r);
}
low.clear(r);
// Push this register.
*stackPtr++ = r;
}
if ((r = getLowestSpillCostRegister(high)) != -1)
{
high.clear(r);
low.set(r);
}
else
break;
}
return stackPtr;
}
bool Coloring::
select(FastBitMatrix& interferenceMatrix, PRUint32* stackBase, PRUint32* stackPtr)
{
PRUint32 nRegisters = vRegManager.count();
FastBitSet usedRegisters(NUMBER_OF_REGISTERS + 1); // usedRegisters if used for both GR & FPR.
FastBitSet preColoredRegisters(NUMBER_OF_REGISTERS + 1);
FastBitSet usedStack(nRegisters + 1);
bool success = true;
Int32 lastUsedSSR = -1;
// select
while (stackPtr != stackBase)
{
// Pop one register.
PRUint32 r = *--stackPtr;
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
FastBitSet neighbors(interferenceMatrix.getRow(r), nRegisters);
if (vReg.getClass() == vrcStackSlot)
// Stack slots coloring.
{
usedStack.clear();
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
usedStack.set(vRegManager.getVirtualRegister(i).getColor());
Int32 color = usedStack.firstZero();
vReg.colorRegister(color);
if (color > lastUsedSSR)
lastUsedSSR = color;
}
else
// Integer & Floating point register coloring.
{
usedRegisters.clear();
preColoredRegisters.clear();
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
{
VirtualRegister& nvReg = vRegManager.getVirtualRegister(i);
usedRegisters.set(nvReg.getColor());
if (nvReg.isPreColored())
preColoredRegisters.set(nvReg.getPreColor());
}
if (vReg.hasSpecialInterference)
usedRegisters |= vReg.specialInterference;
PRInt8 c = -1;
PRInt8 maxColor = 0;
PRInt8 firstColor = 0;
switch (vReg.getClass())
{
case vrcInteger:
firstColor = FIRST_GREGISTER;
maxColor = LAST_GREGISTER;
break;
case vrcFloatingPoint:
case vrcFixedPoint:
firstColor = FIRST_FPREGISTER;
maxColor = LAST_FPREGISTER;
break;
default:
PR_ASSERT(false);
}
if (vReg.isPreColored())
{
c = vReg.getPreColor();
if (usedRegisters.test(c))
c = -1;
}
else
{
for (c = usedRegisters.nextZero(firstColor - 1); (c >= 0) && (c <= maxColor) && (preColoredRegisters.test(c));
c = usedRegisters.nextZero(c)) {}
}
if ((c >= 0) && (c <= maxColor))
{
vReg.colorRegister(c);
}
else
{
VirtualRegister& stackRegister = vRegManager.newVirtualRegister(vrcStackSlot);
vReg.equivalentRegister[vrcStackSlot] = &stackRegister;
vReg.spillInfo.willSpill = true;
success = false;
}
}
}
#ifdef DEBUG
if (success)
{
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
{
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
switch (vReg.getClass())
{
case vrcInteger:
if (vReg.getColor() > LAST_GREGISTER)
PR_ASSERT(false);
break;
case vrcFloatingPoint:
case vrcFixedPoint:
#if NUMBER_OF_FPREGISTERS != 0
if (vReg.getColor() > LAST_FPREGISTER)
PR_ASSERT(false);
#endif
break;
default:
break;
}
}
}
#endif
vRegManager.nUsedStackSlots = lastUsedSSR + 1;
return success;
}
#endif // NEW_LAURENTM_CODE

View File

@@ -0,0 +1,284 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "RegisterAllocator.h"
#include "VirtualRegister.h"
#include "InterferenceGraph.h"
#include "SparseSet.h"
#include "Spilling.h"
#include "Splits.h"
UT_EXTERN_LOG_MODULE(RegAlloc);
template <class RegisterPressure>
class Coloring
{
private:
static RegisterName* simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack);
static bool select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr);
public:
static bool color(RegisterAllocator& registerAllocator);
static void finalColoring(RegisterAllocator& registerAllocator);
};
template <class RegisterPressure>
void Coloring<RegisterPressure>::finalColoring(RegisterAllocator& registerAllocator)
{
RegisterName* color = registerAllocator.color;
RegisterName* name2range = registerAllocator.name2range;
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
usePtr->setRegisterName(color[name2range[usePtr->getRegisterName()]]);
#ifdef DEBUG
RegisterID rid = usePtr->getRegisterID();
setColoredRegister(rid);
usePtr->setRegisterID(rid);
#endif // DEBUG
}
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
definePtr->setRegisterName(color[name2range[definePtr->getRegisterName()]]);
#ifdef DEBUG
RegisterID rid = definePtr->getRegisterID();
setColoredRegister(rid);
definePtr->setRegisterID(rid);
#endif // DEBUG
}
}
}
}
template <class RegisterPressure>
bool Coloring<RegisterPressure>::select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr)
{
Uint32 rangeCount = registerAllocator.rangeCount;
RegisterName* color = new RegisterName[rangeCount];
registerAllocator.color = color;
for (Uint32 r = 1; r < rangeCount; r++)
color[r] = RegisterName(6); // FIX;
// Color the preColored registers.
//
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
RegisterName* name2range = registerAllocator.name2range;
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
if (machinePtr->id != invalidID) {
color[name2range[getName(machinePtr->id)]] = machinePtr->color;
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill preColor range %d as %d\n", name2range[getName(machinePtr->id)], machinePtr->color));
}
SpillCost* cost = registerAllocator.spillCost;
Pool& pool = registerAllocator.pool;
SparseSet& spill = *new(pool) SparseSet(pool, rangeCount);
registerAllocator.willSpill = &spill;
SparseSet neighborColors(pool, 6); // FIX
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
bool coloringFailed = false;
while (coloringStackPtr > coloringStack) {
RegisterName range = *--coloringStackPtr;
if (!cost[range].infinite && cost[range].cost < 0) {
coloringFailed = true;
spill.set(range);
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, will spill.\n", range));
} else {
neighborColors.clear();
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
for (Int32 i = vector->count - 1; i >= 0; --i) {
RegisterName neighborColor = color[vector->neighbors[i]];
if (neighborColor < 6) // FIX
neighborColors.set(neighborColor);
}
if (neighborColors.getSize() == 6) { // FIX
coloringFailed = true;
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, ", range));
if (!Splits<RegisterPressure>::findSplit(registerAllocator, color, range)) {
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will spill.\n"));
spill.set(range);
} else
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will split.\n"));
} else {
for (Uint32 i = 0; i < 6; i++) // FIX
if (!neighborColors.test(i)) {
fprintf(stdout, "\twill color %d as %d\n", range, i);
color[range] = RegisterName(i);
break;
}
}
}
}
#ifdef DEBUG_LOG
if (coloringFailed) {
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring failed:\n"));
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill spill: "));
spill.printPretty(UT_LOG_MODULE(RegAlloc));
} else {
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring succeeded:\n"));
for (Uint32 i = 1; i < rangeCount; i++)
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\trange %d colored as %d\n", i, color[i]));
}
#endif
return !coloringFailed;
}
template <class RegisterPressure>
RegisterName* Coloring<RegisterPressure>::simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack)
{
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
SpillCost* spillCost = registerAllocator.spillCost;
Uint32 rangeCount = registerAllocator.rangeCount;
Uint32* degree = new Uint32[rangeCount];
for (RegisterName i = RegisterName(1); i < rangeCount; i = RegisterName(i + 1)) {
InterferenceVector* vector = iGraph.getInterferenceVector(i);
degree[i] = (vector != NULL) ? vector->count : 0;
}
Pool& pool = registerAllocator.pool;
SparseSet low(pool, rangeCount);
SparseSet high(pool, rangeCount);
SparseSet highInfinite(pool, rangeCount);
SparseSet preColored(pool, rangeCount);
// Get the precolored registers.
//
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
RegisterName* name2range = registerAllocator.name2range;
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
if (machinePtr->id != invalidID)
preColored.set(name2range[getName(machinePtr->id)]);
// Insert the live ranges in the sets.
//
for (Uint32 range = 1; range < rangeCount; range++)
if (!preColored.test(range))
if (degree[range] < 6) // FIX
low.set(range);
else if (!spillCost[range].infinite)
high.set(range);
else
highInfinite.set(range);
#ifdef DEBUG_LOG
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring sets:\n\tlow = "));
low.printPretty(UT_LOG_MODULE(RegAlloc));
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thigh = "));
high.printPretty(UT_LOG_MODULE(RegAlloc));
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thighInfinite = "));
highInfinite.printPretty(UT_LOG_MODULE(RegAlloc));
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tpreColored = "));
preColored.printPretty(UT_LOG_MODULE(RegAlloc));
#endif // DEBUG_LOG
RegisterName* coloringStackPtr = coloringStack;
while (low.getSize() != 0 || high.getSize() != 0) {
while (low.getSize() != 0) {
RegisterName range = RegisterName(low.getOne());
low.clear(range);
*coloringStackPtr++ = range;
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
for (Int32 i = (vector->count - 1); i >= 0; --i) {
RegisterName neighbor = vector->neighbors[i];
degree[neighbor]--;
if (degree[neighbor] < 6) // FIX
if (high.test(neighbor)) {
high.clear(neighbor);
low.set(neighbor);
} else if (highInfinite.test(neighbor)) {
highInfinite.clear(neighbor);
low.set(neighbor);
}
}
}
if (high.getSize() != 0) {
RegisterName best = RegisterName(high.getOne());
double bestCost = spillCost[best].cost;
double bestDegree = degree[best];
// Choose the next best candidate.
//
for (SparseSet::iterator i = high.begin(); !high.done(i); i = high.advance(i)) {
RegisterName range = RegisterName(high.get(i));
double thisCost = spillCost[range].cost;
double thisDegree = degree[range];
if (thisCost * bestDegree < bestCost * thisDegree) {
best = range;
bestCost = thisCost;
bestDegree = thisDegree;
}
}
high.clear(best);
low.set(best);
}
}
assert(highInfinite.getSize() == 0);
delete degree;
#ifdef DEBUG_LOG
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring stack:\n\t"));
for (RegisterName* sp = coloringStack; sp < coloringStackPtr; ++sp)
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("%d ", *sp));
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\n"));
#endif // DEBUG_LOG
return coloringStackPtr;
}
template <class RegisterPressure>
bool Coloring<RegisterPressure>::color(RegisterAllocator& registerAllocator)
{
RegisterName* coloringStack = new RegisterName[registerAllocator.rangeCount];
return select(registerAllocator, coloringStack, simplify(registerAllocator, coloringStack));
}

View File

@@ -0,0 +1,212 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include <string.h>
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "DominatorGraph.h"
DominatorGraph::DominatorGraph(ControlGraph& controlGraph) : controlGraph(controlGraph)
{
Uint32 nNodes = controlGraph.nNodes;
GtoV = new Uint32[nNodes + 1];
VtoG = new Uint32[nNodes + 1];
Uint32 v = 1;
for (Uint32 n = 0; n < nNodes; n++) {
VtoG[v] = n;
GtoV[n] = v++;
}
// Initialize all the 1-based arrays.
//
parent = new Uint32[v];
semi = new Uint32[v];
vertex = new Uint32[v];
label = new Uint32[v];
size = new Uint32[v];
ancestor = new Uint32[v];
child = new Uint32[v];
dom = new Uint32[v];
bucket = new DGLinkedList*[v];
memset(semi, '\0', v * sizeof(Uint32));
memset(bucket, '\0', v * sizeof(DGLinkedList*));
vCount = v;
build();
delete parent;
delete semi;
delete vertex;
delete label;
delete size;
delete ancestor;
delete child;
delete dom;
delete bucket;
}
Uint32 DominatorGraph::DFS(Uint32 vx, Uint32 n)
{
semi[vx] = ++n;
vertex[n] = label[vx] = vx;
ancestor[vx] = child[vx] = 0;
size[vx] = 1;
ControlNode& node = *controlGraph.dfsList[VtoG[vx]];
ControlEdge* successorEnd = node.getSuccessorsEnd();
for (ControlEdge* successorPtr = node.getSuccessorsBegin(); successorPtr < successorEnd; successorPtr++) {
Uint32 w = GtoV[successorPtr->getTarget().dfsNum];
if (semi[w] == 0) {
parent[w] = vx;
n = DFS(w, n);
}
}
return n;
}
void DominatorGraph::LINK(Uint32 vx, Uint32 w)
{
Uint32 s = w;
while (semi[label[w]] < semi[label[child[s]]]) {
if (size[s] + size[child[child[s]]] >= (size[child[s]] << 1)) {
ancestor[child[s]] = s;
child[s] = child[child[s]];
} else {
size[child[s]] = size[s];
s = ancestor[s] = child[s];
}
}
label[s] = label[w];
size[vx] += size[w];
if(size[vx] < (size[w] << 1)) {
Uint32 t = s;
s = child[vx];
child[vx] = t;
}
while( s != 0 ) {
ancestor[s] = vx;
s = child[s];
}
}
void DominatorGraph::COMPRESS(Uint32 vx)
{
if(ancestor[ancestor[vx]] != 0) {
COMPRESS(ancestor[vx]);
if(semi[label[ancestor[vx]]] < semi[label[vx]])
label[vx] = label[ancestor[vx]];
ancestor[vx] = ancestor[ancestor[vx]];
}
}
Uint32 DominatorGraph::EVAL(Uint32 vx)
{
if(ancestor[vx] == 0)
return label[vx];
COMPRESS(vx);
return (semi[label[ancestor[vx]]] >= semi[label[vx]]) ? label[vx] : label[ancestor[vx]];
}
void DominatorGraph::build()
{
Uint32 n = DFS(GtoV[0], 0);
size[0] = label[0] = semi[0];
for (Uint32 i = n; i >= 2; i--) {
Uint32 w = vertex[i];
ControlNode& node = *controlGraph.dfsList[VtoG[w]];
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p)) {
Uint32 vx = GtoV[predecessors.get(p).getSource().dfsNum];
Uint32 u = EVAL(vx);
if(semi[u] < semi[w])
semi[w] = semi[u];
}
DGLinkedList* elem = new DGLinkedList();
elem->next = bucket[vertex[semi[w]]];
elem->index = w;
bucket[vertex[semi[w]]] = elem;
LINK(parent[w], w);
elem = bucket[parent[w]];
while(elem != NULL) {
Uint32 vx = elem->index;
Uint32 u = EVAL(vx);
dom[vx] = (semi[u] < semi[vx]) ? u : parent[w];
elem = elem->next;
}
}
memset(size, '\0', n * sizeof(Uint32));
Pool& pool = controlGraph.pool;
nodes = new(pool) DGNode[n];
for(Uint32 j = 2; j <= n; j++) {
Uint32 w = vertex[j];
Uint32 d = dom[w];
if(d != vertex[semi[w]]) {
d = dom[d];
dom[w] = d;
}
size[d]++;
}
dom[GtoV[0]] = 0;
for (Uint32 k = 1; k <= n; k++) {
DGNode& node = nodes[VtoG[k]];
Uint32 count = size[k];
node.successorsEnd = node.successorsBegin = (count) ? new(pool) Uint32[count] : (Uint32*) 0;
}
for (Uint32 l = 2; l <= n; l++)
*(nodes[VtoG[dom[l]]].successorsEnd)++ = VtoG[l];
}
#ifdef DEBUG_LOG
void DominatorGraph::printPretty(LogModuleObject log)
{
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Dominator Graph:\n"));
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 i = 0; i < nNodes; i++) {
DGNode& node = nodes[i];
if (node.successorsBegin != node.successorsEnd) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tN%d dominates ", i));
for (Uint32* successorsPtr = node.successorsBegin; successorsPtr < node.successorsEnd; successorsPtr++)
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d ", *successorsPtr));
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
}
}
#endif // DEBUG_LOG

View File

@@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _DOMINATOR_GRAPH_H_
#define _DOMINATOR_GRAPH_H_
#include "LogModule.h"
class ControlGraph;
struct DGNode
{
Uint32* successorsBegin;
Uint32* successorsEnd;
};
struct DGLinkedList
{
DGLinkedList* next;
Uint32 index;
};
class DominatorGraph
{
private:
ControlGraph& controlGraph;
Uint32 vCount;
Uint32* VtoG;
Uint32* GtoV;
Uint32* parent;
Uint32* semi;
Uint32* vertex;
Uint32* label;
Uint32* size;
Uint32* ancestor;
Uint32* child;
Uint32* dom;
DGLinkedList** bucket;
DGNode* nodes;
private:
void build();
Uint32 DFS(Uint32 vx, Uint32 n);
void LINK(Uint32 vx, Uint32 w);
void COMPRESS(Uint32 vx);
Uint32 EVAL(Uint32 vx);
public:
DominatorGraph(ControlGraph& controlGraph);
Uint32* getSuccessorsBegin(Uint32 n) const {return nodes[n].successorsBegin;}
Uint32* getSuccessorsEnd(Uint32 n) const {return nodes[n].successorsEnd;}
#ifdef DEBUG_LOG
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
#endif // _DOMINATOR_GRAPH_H_

View File

@@ -0,0 +1,20 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "HashSet.h"

View File

@@ -0,0 +1,97 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _HASH_SET_H_
#define _HASH_SET_H_
#include "Fundamentals.h"
#include "Pool.h"
#include <string.h>
struct HashSetElement
{
Uint32 index;
HashSetElement* next;
};
class HashSet
{
private:
static const hashSize = 64;
// Return the hash code for the given element index.
static Uint32 getHashCode(Uint32 index) {return index & (hashSize - 1);} // Could be better !
private:
Pool& allocationPool;
HashSetElement** bucket;
HashSetElement* free;
private:
// No copy constructor.
HashSet(const HashSet&);
// No copy operator.
void operator = (const HashSet&);
public:
// Create a new HashSet.
inline HashSet(Pool& pool, Uint32 universeSize);
// Clear the hashset.
void clear();
// Clear the element for the given index.
void clear(Uint32 index);
// Set the element for the given index.
void set(Uint32 index);
// Return true if the element at index is a member.
bool test(Uint32 index) const;
// Union with the given hashset.
inline void or(const HashSet& set);
// Intersection with the given hashset.
inline void and(const HashSet& set);
// Difference with the given hashset.
inline void difference(const HashSet& set);
// Logical operators.
HashSet& operator |= (const HashSet& set) {or(set); return *this;}
HashSet& operator &= (const HashSet& set) {and(set); return *this;}
HashSet& operator -= (const HashSet& set) {difference(set); return *this;}
// Iterator to conform with the set API.
typedef HashSetElement* iterator;
// Return the iterator for the first element of this set.
iterator begin() const;
// Return the next iterator.
iterator advance(iterator pos) const;
// Return true if the iterator is at the end of the set.
bool done(iterator pos) const {return pos == NULL;}
};
inline HashSet::HashSet(Pool& pool, Uint32 /*universeSize*/)
: allocationPool(pool), free(NULL)
{
bucket = new(pool) HashSetElement*[hashSize];
memset(bucket, '\0', sizeof(HashSetElement*));
}
#endif // _HASH_SET_H_

View File

@@ -0,0 +1,213 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _INDEXED_POOL_H_
#define _INDEXED_POOL_H_
#include "Fundamentals.h"
#include <string.h>
#include <stdlib.h>
//------------------------------------------------------------------------------
// IndexedPool<IndexedObjectSubclass> is an indexed pool of objects. The
// template parameter 'IndexedObjectSubclass' must be a subclass of the struct
// IndexedObject.
//
// When the indexed pool is ask to allocate and initialize a new object (using
// the operator new(anIndexedPool) it will zero the memory used to store the
// object and initialize the field 'index' of this object to its position in
// the pool.
//
// An object allocated by the indexed pool can be freed by calling the method
// IndexedPool::release(IndexedElement& objectIndex).
//
// example:
//
// IndexedPool<IndexedElement> elementPool;
//
// IndexedElement& element1 = *new(elementPool) IndexedElement();
// IndexedElement& element2 = *new(elementPool) IndexedElement();
//
// indexedPool.release(element1);
// IndexedElement& element3 = *new(elementPool) IndexedElement();
//
// At this point element1 is no longer a valid object, element2 is at
// index 2 and element3 is at index 1.
//
//------------------------------------------------------------------------------
// IndexedObject -
//
template<class Object>
struct IndexedObject
{
Uint32 index; // Index in the pool.
Object* next; // Used to link IndexedObject together.
Uint32 getIndex() {return index;}
};
//------------------------------------------------------------------------------
// IndexedPool<IndexedObject> -
//
template <class IndexedObject>
class IndexedPool
{
private:
static const blockSize = 4; // Size of one block.
Uint32 nBlocks; // Number of blocks in the pool.
IndexedObject** block; // Array of block pointers.
IndexedObject* freeObjects; // Chained list of free IndexedObjects.
Uint32 nextIndex; // Index of the next free object in the last block.
private:
void allocateAnotherBlock();
IndexedObject& newObject();
public:
IndexedPool() : nBlocks(0), block(NULL), freeObjects(NULL), nextIndex(1) {}
~IndexedPool();
IndexedObject& get(Uint32 index) const;
void release(IndexedObject& object);
void setSize(Uint32 size) {assert(size < nextIndex); nextIndex = size;}
// Return the universe size.
Uint32 getSize() {return nextIndex;}
friend void* operator new(size_t, IndexedPool<IndexedObject>& pool); // Needs to call newObject().
};
// Free all the memory allocated for this object.
//
template <class IndexedObject>
IndexedPool<IndexedObject>::~IndexedPool()
{
for (Uint32 n = 0; n < nBlocks; n++)
free(&((IndexedObject **) &block[n][n*blockSize])[-(n + 1)]);
}
// Release the given. This object will be iserted in the chained
// list of free IndexedObjects. To minimize the fragmentation the chained list
// is ordered by ascending indexes.
//
template <class IndexedObject>
void IndexedPool<IndexedObject>::release(IndexedObject& object)
{
Uint32 index = object.index;
IndexedObject* list = freeObjects;
assert(&object == &get(index)); // Make sure that object is owned by this pool.
if (list == NULL) { // The list is empty.
freeObjects = &object;
object.next = NULL;
} else { // The list contains at least 1 element.
if (index < list->index) { // insert as first element.
freeObjects = &object;
object.next = list;
} else { // Find this object's place.
while ((list->next) != NULL && (list->next->index < index))
list = list->next;
object.next = list->next;
list->next = &object;
}
}
#ifdef DEBUG
// Sanity check to be sure that the list is correctly ordered.
for (IndexedObject* obj = freeObjects; obj != NULL; obj = obj->next)
if (obj->next != NULL)
assert(obj->index < obj->next->index);
#endif
}
// Create a new block of IndexedObjects. We will allocate the memory to
// store IndexedPool::blockSize IndexedObject and the new Array of block
// pointers.
// The newly created IndexedObjects will not be initialized.
//
template <class IndexedObject>
void IndexedPool<IndexedObject>::allocateAnotherBlock()
{
void* memory = (void *) malloc((nBlocks + 1) * sizeof(Uint32) + blockSize * sizeof(IndexedObject));
memcpy(memory, block, nBlocks * sizeof(Uint32));
block = (IndexedObject **) memory;
IndexedObject* objects = (IndexedObject *) &block[nBlocks + 1];
block[nBlocks] = &objects[-(nBlocks * blockSize)];
nBlocks++;
}
// Return the IndexedObject at the position 'index' in the pool.
//
template <class IndexedObject>
IndexedObject& IndexedPool<IndexedObject>::get(Uint32 index) const
{
Uint32 blockIndex = index / blockSize;
assert(blockIndex < nBlocks);
return block[blockIndex][index];
}
// Return the reference of an unused object in the pool.
//
template <class IndexedObject>
IndexedObject& IndexedPool<IndexedObject>::newObject()
{
if (freeObjects != NULL) {
IndexedObject& newObject = *freeObjects;
freeObjects = newObject.next;
return newObject;
}
Uint32 nextIndex = this->nextIndex++;
Uint32 blockIndex = nextIndex / blockSize;
while (blockIndex >= nBlocks)
allocateAnotherBlock();
IndexedObject& newObject = block[blockIndex][nextIndex];
newObject.index = nextIndex;
return newObject;
}
// Return the address of the next unsused object in the given
// indexed pool. The field index of the newly allocated object
// will be initialized to the corresponding index of this object
// in the pool.
//
template <class IndexedObject>
void* operator new(size_t size, IndexedPool<IndexedObject>& pool)
{
assert(size == sizeof(IndexedObject));
return (void *) &pool.newObject();
}
#endif // _INDEXED_POOL_H_

View File

@@ -0,0 +1,258 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _INTERFERENCE_GRAPH_H_
#define _INTERFERENCE_GRAPH_H_
#include "Fundamentals.h"
#include "ControlGraph.h"
#include "Primitives.h"
#include "Instruction.h"
#include "VirtualRegister.h"
#include "RegisterPressure.h"
#include "SparseSet.h"
#include <string.h>
struct InterferenceVector
{
Uint32 count;
InterferenceVector* next;
RegisterName* neighbors;
InterferenceVector() : count(0), next(NULL) {}
};
class RegisterAllocator;
template <class RegisterPressure>
class InterferenceGraph
{
private:
RegisterAllocator& registerAllocator;
RegisterPressure::Set* interferences;
InterferenceVector** vector;
Uint32* offset;
Uint32 rangeCount;
private:
// No copy constructor.
InterferenceGraph(const InterferenceGraph&);
// No copy operator.
void operator = (const InterferenceGraph&);
// Check if reg is a member of the universe.
void checkMember(RegisterName name) {assert(name < rangeCount);}
// Return the edge index for the interference between name1 and name2.
Uint32 getEdgeIndex(RegisterName name1, RegisterName name2);
public:
InterferenceGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
// Calculate the interferences.
void build();
// Return true if reg1 and reg2 interfere.
bool interfere(RegisterName name1, RegisterName name2);
// Return the interference vector for the given register or NULL if there is none.
InterferenceVector* getInterferenceVector(RegisterName name) {return vector[name];}
// Set the interference between name1 and name2.
void setInterference(RegisterName name1, RegisterName name2);
// Set the interference vector for the given register.
void setInterferenceVector(RegisterName name, InterferenceVector* v) {vector[name] = v;}
#ifdef DEBUG_LOG
// Print the interferences.
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
template <class RegisterPressure>
void InterferenceGraph<RegisterPressure>::build()
{
Pool& pool = registerAllocator.pool;
Uint32 rangeCount = registerAllocator.rangeCount;
this->rangeCount = rangeCount;
// Initialize the structures.
//
offset = new(pool) Uint32[rangeCount + 1];
vector = new(pool) InterferenceVector*[rangeCount];
memset(vector, '\0', sizeof(InterferenceVector*) * rangeCount);
Uint32 o = 0;
offset[0] = 0;
for (Uint32 i = 1; i <= rangeCount; ++i) {
offset[i] = o;
o += i;
}
interferences = new(pool) RegisterPressure::Set(pool, (rangeCount * rangeCount) / 2);
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
RegisterName* name2range = registerAllocator.name2range;
LivenessInfo<RegisterPressure> liveness = Liveness<RegisterPressure>::analysis(controlGraph, rangeCount, name2range);
registerAllocator.liveness = liveness;
SparseSet currentLive(pool, rangeCount);
for (Uint32 n = 0; n < nNodes; n++) {
ControlNode& node = *nodes[n];
currentLive = liveness.liveOut[n];
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
InstructionDefine* definePtr;
// Handle the copy instruction to avoid unnecessary interference between the 2 registers.
if ((instruction.getFlags() & ifCopy) != 0) {
assert(useBegin != useEnd && useBegin[0].isRegister());
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
}
// Create the interferences.
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName define = name2range[definePtr->getRegisterName()];
for (SparseSet::iterator e = currentLive.begin(); !currentLive.done(e); e = currentLive.advance(e)) {
RegisterName live = RegisterName(currentLive.get(e));
if ((live != define) && !interfere(live, define) && registerAllocator.canInterfere(live, define)) {
if (vector[define] == NULL)
vector[define] = new(pool) InterferenceVector();
vector[define]->count++;
if (vector[live] == NULL)
vector[live] = new(pool) InterferenceVector();
vector[live]->count++;
setInterference(live, define);
}
}
}
// Now update the liveness.
//
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
currentLive.clear(name2range[definePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
currentLive.set(name2range[usePtr->getRegisterName()]);
}
}
// Allocate the memory to store the interferences.
//
for (Uint32 e = 0; e < rangeCount; e++)
if (vector[e] != NULL) {
InterferenceVector& v = *vector[e];
v.neighbors = new(pool) RegisterName[v.count];
v.count = 0;
}
// Initialize the edges.
//
if (RegisterPressure::Set::isOrdered()) {
RegisterName name1 = RegisterName(0);
for (RegisterPressure::Set::iterator i = interferences->begin(); !interferences->done(i); i = interferences->advance(i)) {
Uint32 interferenceIndex = interferences->get(i);
while(interferenceIndex >= offset[name1 + 1])
name1 = RegisterName(name1 + 1);
assert((interferenceIndex >= offset[name1]) && (interferenceIndex < offset[name1 + 1]));
RegisterName name2 = RegisterName(interferenceIndex - offset[name1]);
assert(interfere(name1, name2));
InterferenceVector& vector1 = *vector[name1];
vector1.neighbors[vector1.count++] = name2;
InterferenceVector& vector2 = *vector[name2];
vector2.neighbors[vector2.count++] = name1;
}
} else {
trespass("not Implemented"); // FIX: need one more pass to initialize the vectors.
}
}
template <class RegisterPressure>
Uint32 InterferenceGraph<RegisterPressure>::getEdgeIndex(RegisterName name1, RegisterName name2)
{
checkMember(name1); checkMember(name2);
assert(name1 != name2); // This is not possible.
return (name1 < name2) ? offset[name2] + name1 : offset[name1] + name2;
}
template <class RegisterPressure>
void InterferenceGraph<RegisterPressure>::setInterference(RegisterName name1, RegisterName name2)
{
interferences->set(getEdgeIndex(name1, name2));
}
template <class RegisterPressure>
bool InterferenceGraph<RegisterPressure>::interfere(RegisterName name1, RegisterName name2)
{
return interferences->test(getEdgeIndex(name1, name2));
}
#ifdef DEBUG_LOG
template <class RegisterPressure>
void InterferenceGraph<RegisterPressure>::printPretty(LogModuleObject log)
{
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Vectors:\n"));
for (Uint32 i = 1; i < rangeCount; i++) {
if (vector[i] != NULL) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tvr%d: (", i));
for (InterferenceVector* v = vector[i]; v != NULL; v = v->next)
for (Uint32 j = 0; j < v->count; j++) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", v->neighbors[j]));
if (v->next != NULL || j != (v->count - 1))
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (","));
}
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (")\n"));
}
}
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Matrix:\n"));
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && interfere(name1, name2)) ? '1' : '0'));
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
}
#endif // DEBUG_LOG
#endif // _INTERFERENCE_GRAPH_H_

View File

@@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _LIVE_RANGE_H_
#define _LIVE_RANGE_H_
#include "Fundamentals.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Primitives.h"
#include "Instruction.h"
#include "RegisterAllocator.h"
#include "RegisterAllocatorTools.h"
template <class RegisterPressure>
struct LiveRange
{
static void build(RegisterAllocator& registerAllocator);
};
template <class RegisterPressure>
void LiveRange<RegisterPressure>::build(RegisterAllocator& registerAllocator)
{
// Intialize the lookup table.
//
Uint32 nameCount = registerAllocator.nameCount;
RegisterName* nameTable = new(registerAllocator.pool) RegisterName[2*nameCount];
RegisterName* rangeName = &nameTable[nameCount];
init(rangeName, nameCount);
// Walk the graph.
//
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
SparseSet destination(registerAllocator.pool, nameCount);
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
destination.clear();
for (InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
Instruction& phiNode = phiNodes.get(i);
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
destination.set(findRoot(phiNode.getInstructionDefineBegin()[0].getRegisterName(), rangeName));
}
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& phiNode = phiNodes.get(p);
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
RegisterName destinationName = phiNode.getInstructionDefineBegin()[0].getRegisterName();
RegisterName destinationRoot = findRoot(destinationName, rangeName);
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
assert(usePtr->isRegister());
RegisterName sourceName = usePtr->getRegisterName();
RegisterName sourceRoot = findRoot(sourceName, rangeName);
if (sourceRoot != destinationRoot && !destination.test(sourceRoot))
rangeName[sourceRoot] = destinationRoot;
}
}
}
registerAllocator.rangeCount = compress(registerAllocator.name2range, rangeName, nameCount, nameCount);
}
#endif // _LIVE_RANGE_H_

View File

@@ -0,0 +1,163 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _LIVE_RANGE_GRAPH_
#define _LIVE_RANGE_GRAPH_
#include "Fundamentals.h"
#include "Pool.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "RegisterTypes.h"
class RegisterAllocator;
template <class RegisterPressure>
class LiveRangeGraph
{
private:
RegisterAllocator& registerAllocator;
RegisterPressure::Set* edges;
Uint32 rangeCount;
public:
//
//
LiveRangeGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
//
//
void build();
//
//
void addEdge(RegisterName name1, RegisterName name2);
//
//
bool haveEdge(RegisterName name1, RegisterName name2);
#ifdef DEBUG_LOG
//
//
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
template <class RegisterPressure>
void LiveRangeGraph<RegisterPressure>::build()
{
Pool& pool = registerAllocator.pool;
Uint32 rangeCount = registerAllocator.rangeCount;
this->rangeCount = rangeCount;
edges = new(pool) RegisterPressure::Set(pool, rangeCount * rangeCount);
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
RegisterName* name2range = registerAllocator.name2range;
LivenessInfo<RegisterPressure>& liveness = registerAllocator.liveness;
SparseSet currentLive(pool, rangeCount);
for (Uint32 n = 0; n < nNodes; n++) {
ControlNode& node = *nodes[n];
currentLive = liveness.liveOut[n];
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
InstructionDefine* definePtr;
if ((instruction.getFlags() & ifCopy) != 0) {
assert(useBegin != useEnd && useBegin[0].isRegister());
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName define = name2range[definePtr->getRegisterName()];
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
RegisterName live = RegisterName(currentLive.get(l));
if (define != live && registerAllocator.canInterfere(define, live))
addEdge(define, live);
}
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
currentLive.clear(name2range[definePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
currentLive.set(name2range[usePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName use = name2range[usePtr->getRegisterName()];
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
RegisterName live = RegisterName(currentLive.get(l));
if (use != live && registerAllocator.canInterfere(use, live))
addEdge(use, live);
}
}
}
}
}
template <class RegisterPressure>
void LiveRangeGraph<RegisterPressure>::addEdge(RegisterName name1, RegisterName name2)
{
assert(name1 != name2);
edges->set(name1 * rangeCount + name2);
}
template <class RegisterPressure>
bool LiveRangeGraph<RegisterPressure>::haveEdge(RegisterName name1, RegisterName name2)
{
assert(name1 != name2);
return edges->test(name1 * rangeCount + name2);
}
#ifdef DEBUG_LOG
template <class RegisterPressure>
void LiveRangeGraph<RegisterPressure>::printPretty(LogModuleObject log)
{
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Live ranges graph:\n"));
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && haveEdge(name1, name2)) ? '1' : '0'));
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
}
#endif // DEBUG_LOG
#endif // _LIVE_RANGE_GRAPH_

View File

@@ -0,0 +1,21 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "Liveness.h"

View File

@@ -0,0 +1,301 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _LIVENESS_H_
#define _LIVENESS_H_
#include "Fundamentals.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "RegisterTypes.h"
// ----------------------------------------------------------------------------
// LivenessInfo -
template <class RegisterPressure>
struct LivenessInfo
{
RegisterPressure::Set* liveIn;
RegisterPressure::Set* liveOut;
DEBUG_LOG_ONLY(Uint32 size);
#ifdef DEBUG_LOG
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
// ----------------------------------------------------------------------------
// Liveness
//
// The liveness is defined by the following data-flow equations:
//
// LiveIn(n) = LocalLive(n) U (LiveOut(n) - Killed(n)).
// LiveOut(n) = U LiveIn(s) (s a successor of n).
//
// where LocalLive(n) is the set of used registers in the block n, Killed(n)
// is the set of defined registers in the block n, LiveIn(n) is the set of
// live registers at the begining of the block n and LiveOut(n) is the set
// of live registers at the end of the block n.
//
//
// We will compute the liveness analysis in two stages:
//
// 1- Build LocalLive(n) (wich is an approximation of LiveIn(n)) and Killed(n)
// for each block n.
// 2- Perform a backward data-flow analysis to propagate the liveness information
// through the entire control-flow graph.
//
template <class RegisterPressure>
struct Liveness
{
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range);
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 nameCount);
};
template <class RegisterPressure>
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range)
{
Pool& pool = controlGraph.pool;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
// Allocate the temporary sets.
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
// Allocate the globals sets.
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
//
for (Uint32 n = 0; n < (nNodes - 1); n++) {
ControlNode& node = *nodes[n];
RegisterPressure::Set& currentLocalLive = liveIn[n];
RegisterPressure::Set& currentKilled = killed[n];
// Find the instructions contributions to the sets LocalLive and Killed.
//
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
Uint32 index = name2range[usePtr->getRegisterName()];
if (!currentKilled.test(index))
currentLocalLive.set(index);
}
// If a Virtualregister is 'defined' then we add it to the set Killed.
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
currentKilled.set(name2range[definePtr->getRegisterName()]);
}
}
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
// control-flow graph.
//
RegisterPressure::Set temp(pool, rangeCount);
bool changed;
do {
changed = false;
// For all nodes is this graph except the endNode.
for (Int32 n = (nNodes - 2); n >= 0; n--) {
ControlNode& node = *nodes[n];
RegisterPressure::Set& currentLiveIn = liveIn[n];
RegisterPressure::Set& currentLiveOut = liveOut[n];
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
// temp will be the new LiveOut(n).
Uint32 nSuccessors = node.nSuccessors();
if (nSuccessors != 0) {
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
for (Uint32 s = 1; s < nSuccessors; s++)
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
} else
temp.clear();
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
// new LiveIn(n).
if (currentLiveOut != temp) {
currentLiveOut = temp;
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
temp |= currentLiveIn;
if (currentLiveIn != temp) {
currentLiveIn = temp;
changed = true;
}
}
}
} while(changed);
LivenessInfo<RegisterPressure> liveness;
liveness.liveIn = liveIn;
liveness.liveOut = liveOut;
DEBUG_LOG_ONLY(liveness.size = nNodes);
return liveness;
}
template <class RegisterPressure>
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 nameCount)
{
Pool& pool = controlGraph.pool;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
// Allocate the temporary sets.
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
RegisterPressure::Set* usedByPhiNodes = NULL;
// Allocate the globals sets.
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
//
for (Uint32 n = 0; n < (nNodes - 1); n++) {
ControlNode& node = *nodes[n];
RegisterPressure::Set& currentLocalLive = liveIn[n];
RegisterPressure::Set& currentKilled = killed[n];
InstructionList& phiNodes = node.getPhiNodeInstructions();
if ((usedByPhiNodes == NULL) && !phiNodes.empty())
usedByPhiNodes = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& phiNode = phiNodes.get(p);
InstructionDefine& define = phiNode.getInstructionDefineBegin()[0];
currentKilled.set(define.getRegisterName());
typedef DoublyLinkedList<ControlEdge> ControlEdgeList;
const ControlEdgeList& predecessors = node.getPredecessors();
ControlEdgeList::iterator p = predecessors.begin();
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++, p = predecessors.advance(p))
if (usePtr->isRegister())
usedByPhiNodes[predecessors.get(p).getSource().dfsNum].set(usePtr->getRegisterName());
}
// Find the instructions contributions to the sets LocalLive and Killed.
//
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
Uint32 index = usePtr->getRegisterName();
if (!currentKilled.test(index))
currentLocalLive.set(index);
}
// If a Virtualregister is 'defined' then we add it to the set Killed.
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
currentKilled.set(definePtr->getRegisterName());
}
}
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
// control-flow graph.
//
RegisterPressure::Set temp(pool, nameCount);
bool changed;
do {
changed = false;
// For all nodes is this graph except the endNode.
for (Int32 n = (nNodes - 2); n >= 0; n--) {
ControlNode& node = *nodes[n];
RegisterPressure::Set& currentLiveIn = liveIn[n];
RegisterPressure::Set& currentLiveOut = liveOut[n];
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
// temp will be the new LiveOut(n).
Uint32 nSuccessors = node.nSuccessors();
if (nSuccessors != 0) {
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
for (Uint32 s = 1; s < nSuccessors; s++)
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
} else
temp.clear();
// Insert the phiNodes contribution.
if (usedByPhiNodes != NULL)
temp |= usedByPhiNodes[n];
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
// new LiveIn(n).
if (currentLiveOut != temp) {
currentLiveOut = temp;
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
temp |= currentLiveIn;
if (currentLiveIn != temp) {
currentLiveIn = temp;
changed = true;
}
}
}
} while(changed);
LivenessInfo<RegisterPressure> liveness;
liveness.liveIn = liveIn;
liveness.liveOut = liveOut;
DEBUG_LOG_ONLY(liveness.size = nNodes);
return liveness;
}
#ifdef DEBUG_LOG
template <class RegisterPressure>
void LivenessInfo<RegisterPressure>::printPretty(LogModuleObject log)
{
for (Uint32 n = 0; n < size; n++) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Node N%d:\n\tliveIn = ", n));
liveIn[n].printPretty(log);
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tliveOut = "));
liveOut[n].printPretty(log);
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
}
#endif // DEBUG_LOG
#endif // _LIVENESS_H_

View File

@@ -0,0 +1,40 @@
#! gmake
DEPTH = ../..
MODULE_NAME = RegisterAllocator
include $(DEPTH)/config/config.mk
INCLUDES += \
-I$(DEPTH)/Utilities/General \
-I$(DEPTH)/Utilities/zlib \
-I$(DEPTH)/Runtime/ClassReader \
-I$(DEPTH)/Runtime/NativeMethods \
-I$(DEPTH)/Runtime/System \
-I$(DEPTH)/Runtime/ClassInfo \
-I$(DEPTH)/Runtime/FileReader \
-I$(DEPTH)/Compiler/PrimitiveGraph \
-I$(DEPTH)/Compiler/FrontEnd \
-I$(DEPTH)/Compiler/Optimizer \
-I$(DEPTH)/Compiler/CodeGenerator \
-I$(DEPTH)/Compiler/CodeGenerator/md \
-I$(DEPTH)/Compiler/CodeGenerator/md/$(CPU_ARCH) \
-I$(DEPTH)/Compiler/RegisterAllocator \
-I$(DEPTH)/Driver/StandAloneJava \
-I$(DEPTH)/Debugger \
$(NULL)
CXXSRCS = \
RegisterAllocator.cpp \
RegisterAllocatorTools.cpp \
DominatorGraph.cpp \
VirtualRegister.cpp \
BitSet.cpp \
SparseSet.cpp \
$(NULL)
include $(DEPTH)/config/rules.mk
libs:: $(MODULE)

View File

@@ -0,0 +1,392 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _PHI_NODE_REMOVER_H_
#define _PHI_NODE_REMOVER_H_
#include "Fundamentals.h"
#include "Pool.h"
#include "ControlGraph.h"
#include "DominatorGraph.h"
#include "VirtualRegister.h"
#include "RegisterPressure.h"
#include "Liveness.h"
#include "Instruction.h"
#include "InstructionEmitter.h"
#include "SparseSet.h"
#include <string.h>
//------------------------------------------------------------------------------
// RegisterNameNode -
struct RegisterNameNode
{
RegisterNameNode* next;
RegisterName newName;
Uint32 nextPushed;
};
//------------------------------------------------------------------------------
// CopyData -
struct CopyData
{
RegisterName source;
RegisterClassKind classKind;
Uint32 useCount;
bool isLiveOut;
RegisterName sourceNameToUse;
RegisterName temporaryName;
RegisterNameNode* newName;
};
//------------------------------------------------------------------------------
// PhiNodeRemover<RegisterPressure> -
template <class RegisterPressure>
struct PhiNodeRemover
{
// Replace the phi nodes by copy instructions.
static void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
};
// Split some of the critical edges and return true if there are still some
// in the graph after that.
//
static bool splitCriticalEdges(ControlGraph& /*cg*/)
{
// FIX: not implemented.
return true;
}
inline void pushName(Pool& pool, RegisterNameNode** stack, SparseSet& pushed, Uint32* nodeListPointer, RegisterName oldName, RegisterName newName)
{
RegisterNameNode& newNode = *new(pool) RegisterNameNode();
if (pushed.test(oldName))
(*stack)->newName = newName;
else {
newNode.newName = newName;
newNode.nextPushed = *nodeListPointer;
*nodeListPointer = oldName;
newNode.next = *stack;
*stack = &newNode;
pushed.set(oldName);
}
}
template <class RegisterPressure>
void PhiNodeRemover<RegisterPressure>::replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
{
Pool& pool = controlGraph.pool;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
// Initialize the local variables.
//
// When we insert the copies we will also need to create new VirtualRegisters for
// the insertion of temporaries. The maximum number of temporary register will not
// exceed the number of phiNodes in the primitive graph.
Uint32 nameCount = vrManager.getSize();
Uint32 maxNameCount = nameCount;
for (Uint32 n = 0; n < nNodes; n++)
maxNameCount += nodes[n]->getPhiNodes().length();
// If the CFG contains some critical edges (backward edge which source has more than one
// outgoing edge and destination has more than one incomimg edge) then we need the liveness
// information to be able to insert temporary copies.
RegisterPressure::Set* liveOut = NULL;
if (splitCriticalEdges(controlGraph))
liveOut = Liveness<LowRegisterPressure>::analysis(controlGraph, nameCount).liveOut;
DominatorGraph dGraph(controlGraph);
SparseSet pushed(pool, maxNameCount);
SparseSet destinationList(pool, maxNameCount);
SparseSet workList(pool, maxNameCount);
CopyData* copyStats = new(pool) CopyData[maxNameCount];
memset(copyStats, '\0', maxNameCount*sizeof(CopyData));
struct NodeStack {
Uint32* next;
Uint32* limit;
Uint32 pushedList;
};
// Allocate the node stack and initialize the node stack pointer.
NodeStack* nodeStack = new(pool) NodeStack[nNodes + 1];
NodeStack* nodeStackPtr = nodeStack;
// We start by the begin node.
Uint32 startNode = 0;
Uint32* next = &startNode;
Uint32* limit = &startNode + 1;
while (true) {
if (next == limit) {
// If there are no more node in the sibling, we have to pop the current
// frame from the stack and update the copyStats of the pushed nodes.
//
if (nodeStackPtr == nodeStack)
// We are at the bottom of the stack and there are no more nodes
// to look at. We are done !
break;
--nodeStackPtr;
// We are done with all the children of this node in the dominator tree.
// We need to update the copy information of all the new names pushed
// during the walk over this node.
Uint32 pushedList = nodeStackPtr->pushedList;
while (pushedList != 0) {
Uint32 nextName = copyStats[pushedList].newName->nextPushed;
copyStats[pushedList].newName = copyStats[pushedList].newName->next;
pushedList = nextName;
}
// restore the previous frame.
next = nodeStackPtr->next;
limit = nodeStackPtr->limit;
} else {
Uint32 currentNode = *next++;
Uint32 pushedList = 0;
// Initialize the sets.
pushed.clear();
destinationList.clear();
// STEP1:
// Walk the instruction list and to replace all the instruction uses with their new name.
// If the instruction is a phi node and its defined register is alive at the end of this
// block then we push the defined register into the stack.
//
ControlNode& node = *nodes[currentNode];
RegisterPressure::Set* currentLiveOut = (liveOut != NULL) ? &liveOut[currentNode] : (RegisterPressure::Set*) 0;
InstructionList& phiNodes = node.getPhiNodeInstructions();
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& phiNode = phiNodes.get(p);
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
assert(usePtr->isRegister());
RegisterName name = usePtr->getRegisterName();
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
usePtr->setRegisterName(copyStats[name].newName->newName);
}
if (currentLiveOut != NULL) {
// This is a phi node and we have to push its defined name if it is live
// at the end of the node. We only need to do this if the CFG has critical edges.
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
RegisterName name = phiNode.getInstructionDefineBegin()[0].getRegisterName();
if (currentLiveOut->test(name))
pushName(pool, &(copyStats[name].newName), pushed, &pushedList, name, name);
}
}
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName name = usePtr->getRegisterName();
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
usePtr->setRegisterName(copyStats[name].newName->newName);
}
}
// STEP2:
// Look at this node's successors' phiNodes. We keep track of the number of time
// a VR will be used by another copy instruction and insert each definition into the
// destinationList. This is the only pass over this node's successors as we will
// get all the information we need in the CopyData structures.
//
ControlEdge* successorEdgeEnd = node.getSuccessorsEnd();
for (ControlEdge* successorEdgePtr = node.getSuccessorsBegin(); successorEdgePtr < successorEdgeEnd; successorEdgePtr++) {
Uint32 useIndex = successorEdgePtr->getIndex();
ControlNode& successor = successorEdgePtr->getTarget();
// Look at its phi nodes. The phi nodes are at the top of the instruction list. We exit
// as soon as we find an instruction which is not a phi node
InstructionList& phiNodes = successor.getPhiNodeInstructions();
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& phiNode = phiNodes.get(p);
assert((phiNode.getInstructionUseBegin() + useIndex) < phiNode.getInstructionUseEnd());
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd());
InstructionUse& source = phiNode.getInstructionUseBegin()[useIndex];
InstructionDefine& destination = phiNode.getInstructionDefineBegin()[0];
assert(source.isRegister() && destination.isRegister());
RegisterName sourceName = source.getRegisterName();
RegisterName destinationName = destination.getRegisterName();
// Get the correct name for the source.
if (copyStats[sourceName].newName != NULL)
sourceName = copyStats[sourceName].newName->newName;
// Update the CopyData structures.
if ((sourceName != rnInvalid) && (sourceName != destinationName)) {
copyStats[destinationName].source = sourceName;
copyStats[destinationName].classKind = destination.getRegisterClass();
copyStats[destinationName].isLiveOut = (currentLiveOut != NULL) ? currentLiveOut->test(destinationName) : false;
copyStats[destinationName].sourceNameToUse = destinationName;
copyStats[sourceName].sourceNameToUse = sourceName;
copyStats[sourceName].useCount++;
destinationList.set(destinationName);
}
}
}
// STEP3:
// Insert into the worklist only the destination registers that will be not used in
// another copy instruction in this block.
//
assert(workList.getSize() == 0);
for (SparseSet::iterator d = destinationList.begin(); !destinationList.done(d); d = destinationList.advance(d)) {
Uint32 dest = destinationList.get(d);
if (copyStats[dest].useCount == 0)
workList.set(dest);
}
// STEP4:
// Insert the copy instructions.
//
Uint32 destinationListSize = destinationList.getSize();
InstructionList::iterator endOfTheNode = instructions.end();
// Find the right place to insert the copy instructions.
if (destinationListSize != 0)
while (instructions.get(endOfTheNode).getFlags() & ifControl)
endOfTheNode = instructions.retreat(endOfTheNode);
while (destinationListSize != 0) {
while(workList.getSize()) {
RegisterName destinationName = RegisterName(workList.getOne());
RegisterName sourceName = copyStats[destinationName].source;
workList.clear(destinationName);
if (copyStats[destinationName].isLiveOut && !copyStats[destinationName].temporaryName) {
// Lost copy problem.
copyStats[destinationName].isLiveOut = false;
RegisterName sourceName = destinationName;
RegisterClassKind classKind = copyStats[sourceName].classKind;
RegisterName destinationName = getName(vrManager.newVirtualRegister(classKind));
assert(destinationName < maxNameCount);
copyStats[destinationName].classKind = classKind;
copyStats[sourceName].useCount = 0;
// We need to insert a copy to a temporary register to keep the
// source register valid at the end of the node defining it.
// This copy will be inserted right after the phi node defining it.
RegisterName from = copyStats[sourceName].sourceNameToUse;
Instruction* definingPhiNode = vrManager.getVirtualRegister(from).getDefiningInstruction();
assert(definingPhiNode && (definingPhiNode->getFlags() & ifPhiNode) != 0);
RegisterID fromID = buildRegisterID(from, classKind);
RegisterID toID = buildRegisterID(destinationName, classKind);
Instruction& copy = emitter.newCopy(*definingPhiNode->getPrimitive(), fromID, toID);
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
definingPhiNode->getPrimitive()->getContainer()->getInstructions().addFirst(copy);
copyStats[sourceName].temporaryName = destinationName;
copyStats[sourceName].sourceNameToUse = destinationName;
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
}
// Insert the copy instruction at the end of the current node.
RegisterName from = copyStats[sourceName].sourceNameToUse;
RegisterClassKind classKind = copyStats[destinationName].classKind;
RegisterID fromID = buildRegisterID(from, classKind);
RegisterID toID = buildRegisterID(destinationName, classKind);
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
instructions.insertAfter(copy, endOfTheNode);
endOfTheNode = instructions.advance(endOfTheNode);
copyStats[sourceName].useCount = 0;
if (destinationList.test(sourceName) && copyStats[sourceName].isLiveOut)
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
copyStats[sourceName].isLiveOut = false;
copyStats[sourceName].sourceNameToUse = destinationName;
if (destinationList.test(sourceName))
workList.set(sourceName);
destinationList.clear(destinationName);
}
destinationListSize = destinationList.getSize();
if (destinationListSize != 0) {
RegisterName sourceName = RegisterName(destinationList.getOne());
RegisterName destinationName;
if (!copyStats[sourceName].temporaryName) {
// Cycle problem.
RegisterClassKind classKind = copyStats[sourceName].classKind;
destinationName = getName(vrManager.newVirtualRegister(classKind));
assert(destinationName < maxNameCount);
copyStats[destinationName].classKind = classKind;
copyStats[sourceName].temporaryName = destinationName;
// Insert the copy instruction at the end of the current node.
RegisterName from = copyStats[sourceName].sourceNameToUse;
RegisterID fromID = buildRegisterID(from, classKind);
RegisterID toID = buildRegisterID(destinationName, classKind);
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
instructions.insertAfter(copy, endOfTheNode);
endOfTheNode = instructions.advance(endOfTheNode);
} else
destinationName = copyStats[sourceName].temporaryName;
copyStats[sourceName].useCount = 0;
copyStats[sourceName].isLiveOut = false;
copyStats[sourceName].sourceNameToUse = destinationName;
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
workList.set(sourceName);
}
}
nodeStackPtr->pushedList = pushedList;
nodeStackPtr->next = next;
nodeStackPtr->limit = limit;
++nodeStackPtr;
next = dGraph.getSuccessorsBegin(currentNode);
limit = dGraph.getSuccessorsEnd(currentNode);
}
}
}
#endif // _PHI_NODE_REMOVER_H_

View File

@@ -0,0 +1,155 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "LogModule.h"
#include "RegisterAllocator.h"
#include "RegisterPressure.h"
#include "RegisterAllocatorTools.h"
#include "PhiNodeRemover.h"
#include "LiveRange.h"
#include "Liveness.h"
#include "InterferenceGraph.h"
#include "LiveRangeGraph.h"
#include "Coalescing.h"
#include "Spilling.h"
#include "Coloring.h"
#include "Splits.h"
class Pool;
class ControlGraph;
class VirtualRegisterManager;
class InstructionEmitter;
UT_DEFINE_LOG_MODULE(RegAlloc);
void RegisterAllocator::allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
{
// Insert the phi node instructions. We want to do this to have a single defined register per instruction.
// If we keep the PhiNode (as a DataNode) and a PhiNode is of DoubleWordKind then we have to execute
// some special code for the high word annotation.
//
RegisterAllocatorTools::insertPhiNodeInstructions(controlGraph, emitter);
// Perform some tests on the instruction graph.
//
DEBUG_ONLY(RegisterAllocatorTools::testTheInstructionGraph(controlGraph, vrManager));
// Replace the phi node instructions by their equivalent copy instructions.
//
PhiNodeRemover<LowRegisterPressure>::replacePhiNodes(controlGraph, vrManager, emitter);
// Do the register allocation.
//
RegisterAllocator registerAllocator(pool, controlGraph, vrManager, emitter);
registerAllocator.doGraphColoring();
}
void RegisterAllocator::doGraphColoring()
{
// Initialize the liverange map.
//
initLiveRanges();
// Build the live ranges. We do this to compress the number of RegisterNames
// used in the insterference graph.
//
LiveRange<LowRegisterPressure>::build(*this);
// Remove unnecessary copies.
//
RegisterAllocatorTools::removeUnnecessaryCopies(*this);
for (Uint8 loop = 0; loop < 10; loop++) {
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********* RegisterAllocator loop %d *********\n", loop));
while(true) {
// Build the interference graph.
//
iGraph.build();
// Coalesce the copy instructions.
//
if (!Coalescing<LowRegisterPressure>::coalesce(*this))
break;
}
// Print the interference graph.
//
DEBUG_LOG_ONLY(iGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
// Calculate the spill costs.
//
Spilling<LowRegisterPressure>::calculateSpillCosts(*this);
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSpillCosts(*this));
// Calculate the split costs.
//
Splits<LowRegisterPressure>::calculateSplitCosts(*this);
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSplitCosts(*this));
// Build the live range graph.
//
lGraph.build();
DEBUG_LOG_ONLY(lGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
// Color the graph. If it succeeds then we're done with the
// register allocation.
//
if (Coloring<LowRegisterPressure>::color(*this)) {
// Write the final colors in the instruction graph.
//
Coloring<LowRegisterPressure>::finalColoring(*this);
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********** RegisterAllocator done **********\n"));
DEBUG_LOG_ONLY(RegisterAllocatorTools::printInstructions(*this));
return;
}
// We need to spill some registers.
//
Spilling<LowRegisterPressure>::insertSpillCode(*this);
// Insert the split instructions.
//
Splits<LowRegisterPressure>::insertSplitCode(*this);
// Update the live ranges.
//
// FIX
}
#ifdef DEBUG_LOG
RegisterAllocatorTools::updateInstructionGraph(*this);
RegisterAllocatorTools::printInstructions(*this);
#endif
fprintf(stderr, "!!! Coloring failed after 10 loops !!!\n");
abort();
}
void RegisterAllocator::initLiveRanges()
{
Uint32 count = this->nameCount;
RegisterName* name2range = new(pool) RegisterName[nameCount];
for (RegisterName r = RegisterName(1); r < count; r = RegisterName(r + 1))
name2range[r] = r;
this->name2range = name2range;
rangeCount = count;
}

View File

@@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _REGISTER_ALLOCATOR_H_
#define _REGISTER_ALLOCATOR_H_
class Pool;
class ControlGraph;
class InstructionEmitter;
struct SpillCost;
struct SplitCost;
#include "Liveness.h"
#include "VirtualRegister.h"
#include "RegisterPressure.h" // This should included by Backend.cpp
#include "InterferenceGraph.h"
#include "LiveRangeGraph.h"
//template <class RegisterPressure>
class RegisterAllocator
{
public:
Pool& pool; //
ControlGraph& controlGraph; //
VirtualRegisterManager& vrManager; //
InstructionEmitter& emitter; //
RegisterName* name2range; //
RegisterName* color; //
SpillCost* spillCost; //
SparseSet* willSpill; //
SplitCost* splitCost; //
NameLinkedList** splitAround; //
InterferenceGraph<LowRegisterPressure> iGraph; //
LiveRangeGraph<LowRegisterPressure> lGraph; //
LivenessInfo<LowRegisterPressure> liveness; //
Uint32 nameCount; //
Uint32 rangeCount; //
bool splitFound; //
private:
//
//
void doGraphColoring();
public:
//
//
inline RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
//
//
bool canInterfere(RegisterName /*name1*/, RegisterName /*name2*/) const {return true;}
//
//
void initLiveRanges();
//
//
static void allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
};
//
//
inline RegisterAllocator::RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
: pool(pool), controlGraph(controlGraph), vrManager(vrManager), emitter(emitter), iGraph(*this), lGraph(*this), nameCount(vrManager.getSize()) {}
#endif // _REGISTER_ALLOCATOR_H_

View File

@@ -0,0 +1,355 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "LogModule.h"
#include "RegisterAllocatorTools.h"
#include "Pool.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Primitives.h"
#include "InstructionEmitter.h"
#include "Instruction.h"
#include "RegisterAllocator.h"
#include "Spilling.h"
#include "Splits.h"
#include "BitSet.h"
UT_EXTERN_LOG_MODULE(RegAlloc);
#ifdef DEBUG
void RegisterAllocatorTools::testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
{
// Test the declared VirtualRegisters. The register allocator tries to condense the register universe.
// Any gap in the VirtualRegister names will be a loss of efficiency !!!!
Uint32 nameCount = vrManager.getSize();
BitSet registerSeen(controlGraph.pool, nameCount);
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
registerSeen.set(usePtr->getRegisterName());
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
registerSeen.set(definePtr->getRegisterName());
}
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& instruction = phiNodes.get(p);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
registerSeen.set(usePtr->getRegisterName());
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
registerSeen.set(definePtr->getRegisterName());
}
}
bool renameRegisters = false;
for (BitSet::iterator i = registerSeen.nextZero(0); !registerSeen.done(i); i = registerSeen.nextZero(i)) {
renameRegisters = true;
fprintf(stderr,
"WARNING: The VirtualRegister vr%d has been allocated during CodeGeneration but\n"
" is never used nor defined by any instruction in the instruction graph\n"
" PLEASE FIX \n",
i);
}
if (renameRegisters) {
Instruction** definingInstruction = new Instruction*[nameCount];
memset(definingInstruction, '\0', nameCount * sizeof(Instruction*));
RegisterName* newName = new RegisterName[nameCount];
memset(newName, '\0', nameCount * sizeof(RegisterName));
RegisterName nextName = RegisterName(1);
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName name = usePtr->getRegisterName();
if (newName[name] == rnInvalid) {
newName[name] = nextName;
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
nextName = RegisterName(nextName + 1);
}
usePtr->setRegisterName(newName[name]);
}
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName name = definePtr->getRegisterName();
if (newName[name] == rnInvalid) {
newName[name] = nextName;
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
nextName = RegisterName(nextName + 1);
}
definePtr->setRegisterName(newName[name]);
}
}
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& instruction = phiNodes.get(p);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName name = usePtr->getRegisterName();
if (newName[name] == rnInvalid) {
newName[name] = nextName;
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
nextName = RegisterName(nextName + 1);
}
usePtr->setRegisterName(newName[name]);
}
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName name = definePtr->getRegisterName();
if (newName[name] == rnInvalid) {
newName[name] = nextName;
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
nextName = RegisterName(nextName + 1);
}
definePtr->setRegisterName(newName[name]);
}
}
}
vrManager.setSize(nextName);
for (RegisterName r = RegisterName(1); r < nextName; r = RegisterName(r + 1))
vrManager.getVirtualRegister(r).definingInstruction = definingInstruction[r];
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("RegisterMap:\n"));
for (Uint32 i = 1; i < nameCount; i++)
if (newName[i] != 0)
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d becomes vr%d.\n", i, newName[i]));
else
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d is dead.\n", i));
delete newName;
delete definingInstruction;
}
}
#endif // DEBUG
void RegisterAllocatorTools::removeUnnecessaryCopies(RegisterAllocator& registerAllocator)
{
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
RegisterName* name2range = registerAllocator.name2range;
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i);) {
Instruction& instruction = instructions.get(i);
i = instructions.advance(i);
if (instruction.getFlags() & ifCopy) {
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
RegisterName source = name2range[instruction.getInstructionUseBegin()[0].getRegisterName()];
RegisterName destination = name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()];
if (source == destination)
instruction.remove();
}
}
}
}
void RegisterAllocatorTools::updateInstructionGraph(RegisterAllocator& registerAllocator)
{
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
RegisterName* name2range = registerAllocator.name2range;
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
}
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& instruction = phiNodes.get(p);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
}
}
}
void RegisterAllocatorTools::insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter)
{
Pool& pool = controlGraph.pool;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
ControlNode& node = *nodes[n];
DoublyLinkedList<PhiNode>& phiNodes = node.getPhiNodes();
if (!phiNodes.empty()) {
// Set the index of the incoming edges.
Uint32 index = 0;
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p))
predecessors.get(p).setIndex(index++);
// Insert the phi node instruction in the instruction list.
for (DoublyLinkedList<PhiNode>::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
PhiNode& phiNode = phiNodes.get(i);
ValueKind kind = phiNode.getKind();
if (!isStorableKind(kind))
continue;
RegisterClassKind classKind = rckGeneral; // FIX: get class kind from phi node kind.
Uint32 nInputs = phiNode.nInputs();
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drLow);
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drLow);
node.addPhiNodeInstruction(phiNodeInstruction);
if (isDoublewordKind(kind)) {
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drHigh);
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drHigh);
node.addPhiNodeInstruction(phiNodeInstruction);
}
}
}
}
}
#ifdef DEBUG_LOG
void RegisterAllocatorTools::printSpillCosts(RegisterAllocator& registerAllocator)
{
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
Uint32 rangeCount = registerAllocator.rangeCount;
SpillCost* cost = registerAllocator.spillCost;
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Spill costs:\n"));
for (Uint32 i = 1; i < rangeCount; i++) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : ", i));
if (cost[i].infinite)
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("infinite\n"));
else
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%f\n", cost[i].cost));
}
}
void RegisterAllocatorTools::printSplitCosts(RegisterAllocator& registerAllocator)
{
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
Uint32 rangeCount = registerAllocator.rangeCount;
SplitCost* cost = registerAllocator.splitCost;
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Split costs:\n"));
for (Uint32 i = 1; i < rangeCount; i++) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : loads = %f stores = %f\n", i, cost[i].loads, cost[i].stores));
}
}
void RegisterAllocatorTools::printInstructions(RegisterAllocator& registerAllocator)
{
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
ControlNode** nodes = registerAllocator.controlGraph.dfsList;
Uint32 nNodes = registerAllocator.controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d:\n", n));
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
InstructionList& instructions = nodes[n]->getInstructions();
if (!phiNodes.empty()) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" PhiNodes:\n", n));
for(InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
phiNodes.get(i).printPretty(log);
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
if (!instructions.empty())
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" Instructions:\n", n));
}
for(InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
instructions.get(i).printPretty(log);
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
}
}
#endif // DEBUG_LOG

View File

@@ -0,0 +1,117 @@
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
//
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
// NETSCAPE COMMUNICATIONS CORPORATION
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
// Reserved. Use of this Source Code is subject to the terms of the
// applicable license agreement from Netscape Communications Corporation.
// The copyright notice(s) in this Source Code does not indicate actual or
// intended publication of this Source Code.
//
// $Id: RegisterAllocatorTools.h,v 1.1.2.1 1999-03-02 16:12:05 fur%netscape.com Exp $
//
#ifndef _REGISTER_ALLOCATOR_TOOLS_H_
#define _REGISTER_ALLOCATOR_TOOLS_H_
#include "LogModule.h"
#include "RegisterTypes.h"
#include <string.h>
class RegisterAllocator;
class ControlGraph;
class InstructionEmitter;
class VirtualRegisterManager;
struct RegisterAllocatorTools
{
//
//
static void insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter);
//
//
static void updateInstructionGraph(RegisterAllocator& registerAllocator);
//
//
static void removeUnnecessaryCopies(RegisterAllocator& registerAllocator);
#ifdef DEBUG
//
//
static void testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
#endif // DEBUG
#ifdef DEBUG_LOG
//
//
static void printInstructions(RegisterAllocator& registerAllocator);
//
//
static void printSpillCosts(RegisterAllocator& registerAllocator);
//
//
static void printSplitCosts(RegisterAllocator& registerAllocator);
#endif // DEBUG_LOG
};
//
// FIX: this should go in a class (LookupTable ?)
//
inline RegisterName findRoot(RegisterName name, RegisterName* table)
{
RegisterName* stack = table;
RegisterName* stackPtr = stack;
RegisterName newName;
while((newName = table[name]) != name) {
*--stackPtr = name;
name = newName;
}
while (stackPtr != stack)
table[*stackPtr++] = name;
return name;
}
inline void init(RegisterName* table, Uint32 nameCount)
{
for (RegisterName r = RegisterName(0); r < nameCount; r = RegisterName(r + 1))
table[r] = r;
}
inline Uint32 compress(RegisterName* name2range, RegisterName* table, Uint32 nameCount, Uint32 tableSize)
{
RegisterName* liveRange = new RegisterName[tableSize];
memset(liveRange, '\0', tableSize * sizeof(RegisterName));
// Update the lookup table.
for (RegisterName r = RegisterName(1); r < tableSize; r = RegisterName(r + 1))
findRoot(r, table);
// Count the liveranges.
Uint32 liveRangeCount = 1;
for (RegisterName s = RegisterName(1); s < tableSize; s = RegisterName(s + 1))
if (table[s] == s)
liveRange[s] = RegisterName(liveRangeCount++);
for (RegisterName t = RegisterName(1); t < nameCount; t = RegisterName(t + 1))
name2range[t] = liveRange[table[name2range[t]]];
return liveRangeCount;
}
inline double doLog10(Uint32 power)
{
double log = 1.0;
while (power--)
log *= 10.0;
return log;
}
#endif // _REGISTER_ALLOCATOR_TOOLS_H_

View File

@@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _REGISTER_ASSIGNER_H_
#define _REGISTER_ASSIGNER_H_
#include "Fundamentals.h"
#include "VirtualRegister.h"
class FastBitMatrix;
class RegisterAssigner
{
protected:
VirtualRegisterManager& vRegManager;
public:
RegisterAssigner(VirtualRegisterManager& vrMan) : vRegManager(vrMan) {}
virtual bool assignRegisters(FastBitMatrix& interferenceMatrix) = 0;
};
#endif /* _REGISTER_ASSIGNER_H_ */

View File

@@ -0,0 +1,25 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _REGISTER_CLASS_H_
#define _REGISTER_CLASS_H_
#include "Fundamentals.h"
#include "RegisterTypes.h"
#endif // _REGISTER_CLASS_H_

View File

@@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _REGISTER_PRESSURE_H_
#define _REGISTER_PRESSURE_H_
#include "BitSet.h"
#include "HashSet.h"
struct LowRegisterPressure
{
typedef BitSet Set;
static const bool setIsOrdered = true;
};
struct HighRegisterPressure
{
typedef HashSet Set;
static const bool setIsOrdered = false;
};
#endif // _REGISTER_PRESSURE_H_

View File

@@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _REGISTER_TYPES_H_
#define _REGISTER_TYPES_H_
#include "Fundamentals.h"
//------------------------------------------------------------------------------
// RegisterName -
//
enum RegisterName {
rnInvalid = 0,
};
//------------------------------------------------------------------------------
// RegisterClassKind -
//
enum RegisterClassKind {
rckInvalid = 0,
rckGeneral,
rckStackSlot,
nRegisterClassKind
};
//------------------------------------------------------------------------------
// RegisterID -
//
enum RegisterID {
invalidID = 0
};
//------------------------------------------------------------------------------
// RegisterKind -
//
enum RegisterKind {
rkCallerSave = 0,
rkCalleeSave,
};
struct NameLinkedList {
RegisterName name;
NameLinkedList* next;
};
#ifdef DEBUG
const registerNameMask = 0x03ffffff;
const coloredRegisterMask = 0x04000000;
const machineRegisterMask = 0x08000000;
const registerClassMask = 0xf0000000;
const registerNameShift = 0;
const coloredRegisterShift = 26;
const machineRegisterShift = 27;
const registerClassShift = 28;
#else // DEBUG
const registerNameMask = 0x0fffffff;
const registerClassMask = 0xf0000000;
const registerNameShift = 0;
const registerClassShift = 28;
#endif // DEBUG
inline RegisterClassKind getClass(RegisterID registerID) {return RegisterClassKind((registerID & registerClassMask) >> registerClassShift);}
inline RegisterName getName(RegisterID registerID) {return RegisterName((registerID & registerNameMask) >> registerNameShift);}
inline void setClass(RegisterID& registerID, RegisterClassKind classKind) {registerID = RegisterID((registerID & ~registerClassMask) | ((classKind << registerClassShift) & registerClassMask));}
inline void setName(RegisterID& registerID, RegisterName name) {assert((name & ~registerNameMask) == 0); registerID = RegisterID((registerID & ~registerNameMask) | ((name << registerNameShift) & registerNameMask));}
inline RegisterID buildRegisterID(RegisterName name, RegisterClassKind classKind) {return RegisterID(((classKind << registerClassShift) & registerClassMask) | ((name << registerNameShift) & registerNameMask));}
#ifdef DEBUG
inline bool isMachineRegister(RegisterID rid) {return (rid & machineRegisterMask) != 0;}
inline void setMachineRegister(RegisterID& rid) {rid = RegisterID(rid | machineRegisterMask);}
inline bool isColoredRegister(RegisterID rid) {return (rid & coloredRegisterMask) != 0;}
inline void setColoredRegister(RegisterID& rid) {rid = RegisterID(rid | coloredRegisterMask);}
#endif // DEBUG
#endif // _REGISTER_TYPES_H_

View File

@@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "SSATools.h"
#include "ControlGraph.h"
#include "VirtualRegister.h"
#include "Liveness.h"
void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
{
if (!controlGraph.hasBackEdges)
return;
Liveness liveness(controlGraph.pool);
liveness.buildLivenessAnalysis(controlGraph, vrManager);
}

View File

@@ -0,0 +1,29 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _SSA_TOOLS_H_
#define _SSA_TOOLS_H_
#include "Fundamentals.h"
class ControlGraph;
class VirtualRegisterManager;
extern void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
#endif // _SSA_TOOLS_H_

View File

@@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "SparseSet.h"
#include "BitSet.h"
#include "Pool.h"
#ifdef DEBUG_LOG
// Print the set.
//
void SparseSet::printPretty(LogModuleObject log)
{
Pool pool;
BitSet set(pool, universeSize);
for (Uint32 i = 0; i < count; i++)
set.set(node[i].element);
set.printPretty(log);
}
#endif // DEBUG_LOG

View File

@@ -0,0 +1,168 @@
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
//
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
// NETSCAPE COMMUNICATIONS CORPORATION
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
// Reserved. Use of this Source Code is subject to the terms of the
// applicable license agreement from Netscape Communications Corporation.
// The copyright notice(s) in this Source Code does not indicate actual or
// intended publication of this Source Code.
//
// $Id: SparseSet.h,v 1.1.2.1 1999-03-02 16:12:07 fur%netscape.com Exp $
//
#ifndef _SPARSE_SET_H_
#define _SPARSE_SET_H_
#include "Fundamentals.h"
#include "Pool.h"
#include "LogModule.h"
#include "BitSet.h"
class SparseSet
{
private:
struct Node {
Uint32 element;
Uint32 stackIndex;
};
Node* node;
Uint32 count;
Uint32 universeSize;
private:
// No copy constructor.
SparseSet(const SparseSet&);
// Check if the given set's universe is of the same size than this universe.
void checkUniverseCompatibility(const SparseSet& set) const {assert(set.universeSize == universeSize);}
// Check if pos is valid for this set's universe.
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
public:
SparseSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {node = new(pool) Node[universeSize]; clear();}
// Clear the sparse set.
void clear() {count = 0;}
// Clear the element at index.
inline void clear(Uint32 index);
// Set the element at index.
inline void set(Uint32 index);
// Return true if the element at index is set.
inline bool test(Uint32 index) const;
// Union with the given sparse set.
inline void or(const SparseSet& set);
// Intersection with the given sparse set.
inline void and(const SparseSet& set);
// Difference with the given sparse set.
inline void difference(const SparseSet& set);
// Copy set.
inline SparseSet& operator = (const SparseSet& set);
inline SparseSet& operator = (const BitSet& set);
// Return true if the sparse sets are identical.
friend bool operator == (const SparseSet& set1, const SparseSet& set2);
// Return true if the sparse sets are different.
friend bool operator != (const SparseSet& set1, const SparseSet& set2);
// Logical operators.
SparseSet& operator |= (const SparseSet& set) {or(set); return *this;}
SparseSet& operator &= (const SparseSet& set) {and(set); return *this;}
SparseSet& operator -= (const SparseSet& set) {difference(set); return *this;}
// Iterator to conform with the set API.
typedef Int32 iterator;
// Return the iterator for the first element of this set.
iterator begin() const {return count - 1;}
// Return the next iterator.
iterator advance(iterator pos) const {return --pos;}
// Return true if the iterator is at the end of the set.
bool done(iterator pos) const {return pos < 0;}
// Return the element for the given iterator;
Uint32 get(iterator pos) const {return node[pos].element;}
// Return one element of this set.
Uint32 getOne() const {assert(count > 0); return node[0].element;}
// Return the size of this set.
Uint32 getSize() const {return count;}
#ifdef DEBUG_LOG
// Print the set.
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
inline void SparseSet::clear(Uint32 element)
{
checkMember(element);
Uint32 count = this->count;
Node* node = this->node;
Uint32 stackIndex = node[element].stackIndex;
if ((stackIndex < count) && (node[stackIndex].element == element)) {
Uint32 stackTop = node[count - 1].element;
node[stackIndex].element = stackTop;
node[stackTop].stackIndex = stackIndex;
this->count = count - 1;
}
}
inline void SparseSet::set(Uint32 element)
{
checkMember(element);
Uint32 count = this->count;
Node* node = this->node;
Uint32 stackIndex = node[element].stackIndex;
if ((stackIndex >= count) || (node[stackIndex].element != element)) {
node[count].element = element;
node[element].stackIndex = count;
this->count = count + 1;
}
}
inline bool SparseSet::test(Uint32 element) const
{
checkMember(element);
Node* node = this->node;
Uint32 stackIndex = node[element].stackIndex;
return ((stackIndex < count) && (node[stackIndex].element == element));
}
inline SparseSet& SparseSet::operator = (const SparseSet& set)
{
checkUniverseCompatibility(set);
Uint32 sourceCount = set.getSize();
Node* node = this->node;
memcpy(node, set.node, sourceCount * sizeof(Node));
for (Uint32 i = 0; i < sourceCount; i++) {
Uint32 element = node[i].element;
node[element].stackIndex = i;
}
count = sourceCount;
return *this;
}
inline SparseSet& SparseSet::operator = (const BitSet& set)
{
// FIX: there's room for optimization here.
assert(universeSize == set.getSize());
clear();
for (Int32 i = set.firstOne(); i != -1; i = set.nextOne(i))
this->set(i);
return *this;
}
#endif // _SPARSE_SET_H_

View File

@@ -0,0 +1,270 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef NEW_LAURENTM_CODE
#define INCLUDE_EMITTER
#include "CpuInfo.h"
#include "Fundamentals.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "InstructionEmitter.h"
#include "Spilling.h"
void Spilling::
insertSpillCode(ControlNode** dfsList, Uint32 nNodes)
{
PRUint32 nVirtualRegisters = vRegManager.count();
FastBitSet currentLive(vRegManager.pool, nVirtualRegisters);
FastBitSet usedInThisInstruction(vRegManager.pool, nVirtualRegisters);
RegisterFifo grNeedLoad(nVirtualRegisters);
RegisterFifo fpNeedLoad(nVirtualRegisters);
for (PRInt32 n = nNodes - 1; n >= 0; n--)
{
PR_ASSERT(grNeedLoad.empty() & fpNeedLoad.empty());
ControlNode& node = *dfsList[n];
currentLive = node.liveAtEnd;
PRUint32 nGeneralAlive = 0;
PRUint32 nFloatingPointAlive = 0;
// Get the number of registers alive at the end of this node.
for (PRInt32 j = currentLive.firstOne(); j != -1; j = currentLive.nextOne(j))
{
VirtualRegister& vReg = vRegManager.getVirtualRegister(j);
if (vReg.spillInfo.willSpill)
{
currentLive.clear(j);
}
else
{
switch (vReg.getClass())
{
case vrcInteger:
nGeneralAlive++;
break;
case vrcFloatingPoint:
case vrcFixedPoint:
nFloatingPointAlive++;
break;
default:
break;
}
}
}
// if(node.dfsNum == 8) printf("\n________Begin Node %d________\n", node.dfsNum);
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i))
{
Instruction& instruction = instructions.get(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defEnd = instruction.getInstructionDefineEnd();
InstructionDefine* defPtr;
// if(node.dfsNum == 8) { printf("\n");
// instruction.printPretty(stdout);
// printf("\n"); }
// Handle definitions
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
if (defPtr->isVirtualRegister())
{
VirtualRegister& vReg = defPtr->getVirtualRegister();
currentLive.clear(vReg.getRegisterIndex());
switch (vReg.getClass())
{
case vrcInteger:
nGeneralAlive--;
break;
case vrcFloatingPoint:
case vrcFixedPoint:
nFloatingPointAlive--;
break;
default:
break;
}
}
// Check for deaths
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isVirtualRegister())
{
VirtualRegister& vReg = usePtr->getVirtualRegister();
if (!currentLive.test(vReg.getRegisterIndex()))
// This is the last use of this register.
{
currentLive.set(vReg.getRegisterIndex());
switch (vReg.getClass())
{
case vrcInteger:
nGeneralAlive++;
while (/*(nGeneralAlive > NUMBER_OF_GREGISTERS) &&*/ !grNeedLoad.empty())
{
PRUint32 toLoad = grNeedLoad.get();
currentLive.clear(toLoad);
nGeneralAlive--;
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
nReg.releaseSelf();
}
break;
case vrcFloatingPoint:
case vrcFixedPoint:
nFloatingPointAlive++;
while (/*(nFloatingPointAlive > NUMBER_OF_FPREGISTERS) &&*/ !fpNeedLoad.empty())
{
PRUint32 toLoad = fpNeedLoad.get();
currentLive.clear(toLoad);
nFloatingPointAlive--;
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
nReg.releaseSelf();
}
break;
default:
break;
}
}
}
// Handle uses
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isVirtualRegister())
{
VirtualRegister& vReg = usePtr->getVirtualRegister();
PRUint32 registerIndex = vReg.getRegisterIndex();
if (vReg.spillInfo.willSpill) {
#if defined(GENERATE_FOR_X86)
if (!instruction.switchUseToSpill((usePtr - useBegin), *vReg.equivalentRegister[vrcStackSlot]))
#endif
{
switch (vReg.getClass())
{
case vrcInteger:
if (!grNeedLoad.test(registerIndex))
{
grNeedLoad.put(registerIndex);
VirtualRegister& alias = vRegManager.newVirtualRegister(vrcInteger);
if (vReg.isPreColored())
alias.preColorRegister(vReg.getPreColor());
/* if (vReg.hasSpecialInterference) {
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
alias.specialInterference = vReg.specialInterference;
alias.hasSpecialInterference = true;
} */
vReg.setAlias(alias);
vReg.retainSelf();
}
break;
case vrcFloatingPoint:
case vrcFixedPoint:
if (!fpNeedLoad.test(registerIndex))
{
fpNeedLoad.put(registerIndex);
VirtualRegister& alias = vRegManager.newVirtualRegister(vReg.getClass());
if (vReg.isPreColored())
alias.preColorRegister(vReg.getPreColor());
/*if (vReg.hasSpecialInterference) {
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
alias.specialInterference = vReg.specialInterference;
alias.hasSpecialInterference = true;
} */
vReg.setAlias(alias);
vReg.retainSelf();
}
break;
default:
break;
}
usePtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
usedInThisInstruction.set(registerIndex);
vReg.spillInfo.lastUsingInstruction = &instruction;
}
currentLive.clear(registerIndex);
} else { // will not spill
currentLive.set(registerIndex);
}
}
// Handle definitions
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
if (defPtr->isVirtualRegister())
{
VirtualRegister& vReg = defPtr->getVirtualRegister();
if (vReg.spillInfo.willSpill)
#if defined(GENERATE_FOR_X86)
if (!instruction.switchDefineToSpill((defPtr - defBegin), *vReg.equivalentRegister[vrcStackSlot]))
#endif
{
if (usedInThisInstruction.test(vReg.getRegisterIndex()))
// this virtualRegister was used in this instruction and is also defined. We need to move
// this virtual register to its alias first and then save it to memory.
{
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
vReg.getAlias(), *vReg.equivalentRegister[vrcStackSlot]);
defPtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
}
else
{
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
vReg, *vReg.equivalentRegister[vrcStackSlot]);
}
}
}
}
while (!grNeedLoad.empty())
{
PRUint32 nl = grNeedLoad.get();
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
nlReg.releaseSelf();
}
while (!fpNeedLoad.empty())
{
PRUint32 nl = fpNeedLoad.get();
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
nlReg.releaseSelf();
}
// if(node.dfsNum == 8) printf("\n________End Node %d________\n", node.dfsNum);
}
}
#endif

View File

@@ -0,0 +1,269 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _SPILLING_H_
#define _SPILLING_H_
#include "Fundamentals.h"
#include <string.h>
#include "RegisterAllocator.h"
#include "RegisterAllocatorTools.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "SparseSet.h"
template <class RegisterPressure>
class Spilling
{
private:
static void insertStoreAfter(Instruction& instruction, RegisterName name);
static void insertLoadBefore(Instruction& instruction, RegisterName name);
public:
static void calculateSpillCosts(RegisterAllocator& registerAllocator);
static void insertSpillCode(RegisterAllocator& registerAllocator);
};
struct SpillCost
{
double loads;
double stores;
double copies;
double cost;
bool infinite;
};
template <class RegisterPressure>
void Spilling<RegisterPressure>::insertSpillCode(RegisterAllocator& registerAllocator)
{
Uint32 rangeCount = registerAllocator.rangeCount;
RegisterName* name2range = registerAllocator.name2range;
Pool& pool = registerAllocator.pool;
SparseSet currentLive(pool, rangeCount);
SparseSet needLoad(pool, rangeCount);
SparseSet mustSpill(pool, rangeCount);
SparseSet& willSpill = *registerAllocator.willSpill;
ControlGraph& controlGraph = registerAllocator.controlGraph;
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
needLoad.clear();
currentLive = liveOut[n];
mustSpill = currentLive;
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i);) {
Instruction& instruction = instructions.get(i);
i = instructions.retreat(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
InstructionDefine* definePtr;
bool foundLiveDefine = false;
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
if (currentLive.test(name2range[definePtr->getRegisterName()])) {
foundLiveDefine = true;
break;
}
} else {
foundLiveDefine = true;
break;
}
if (defineBegin != defineEnd && !foundLiveDefine) {
fprintf(stderr, "!!! Removed instruction because it was only defining unused registers !!!\n");
instruction.remove();
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName range = name2range[definePtr->getRegisterName()];
#ifdef DEBUG
if (needLoad.test(range))
if (!mustSpill.test(range) && registerAllocator.spillCost[range].infinite && willSpill.test(range)) {
fprintf(stderr, "Tried to spill a register with infinite spill cost\n");
abort();
}
#endif // DEBUG
if (willSpill.test(range))
insertStoreAfter(instruction, range);
needLoad.clear(range);
}
if (instruction.getFlags() & ifCopy)
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName range = name2range[usePtr->getRegisterName()];
if (!currentLive.test(range))
for (SparseSet::iterator r = needLoad.begin(); !needLoad.done(r); r = needLoad.advance(r)) {
RegisterName load = RegisterName(needLoad.get(r));
if (willSpill.test(load))
insertLoadBefore(instruction, load);
mustSpill.set(load);
}
needLoad.clear();
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
currentLive.clear(name2range[definePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName range = name2range[usePtr->getRegisterName()];
currentLive.set(range);
needLoad.set(range);
}
}
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
RegisterName load = RegisterName(needLoad.get(l));
if (willSpill.test(load))
insertLoadBefore(instructions.first(), load);
}
}
}
template <class RegisterPressure>
void Spilling<RegisterPressure>::insertLoadBefore(Instruction& /*instruction*/, RegisterName name)
{
fprintf(stdout, "will insert load for range %d\n", name);
}
template <class RegisterPressure>
void Spilling<RegisterPressure>::insertStoreAfter(Instruction& /*instruction*/, RegisterName name)
{
fprintf(stdout, "will insert store for range %d\n", name);
}
template <class RegisterPressure>
void Spilling<RegisterPressure>::calculateSpillCosts(RegisterAllocator& registerAllocator)
{
Uint32 rangeCount = registerAllocator.rangeCount;
RegisterName* name2range = registerAllocator.name2range;
Pool& pool = registerAllocator.pool;
SparseSet live(pool, rangeCount);
SparseSet needLoad(pool, rangeCount);
SparseSet mustSpill(pool, rangeCount);
SparseSet alreadyStored(pool, rangeCount); // FIX: should get this from previous spilling.
SpillCost* cost = new SpillCost[rangeCount];
memset(cost, '\0', rangeCount * sizeof(SpillCost));
ControlGraph& controlGraph = registerAllocator.controlGraph;
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
ControlNode& node = *nodes[n];
double weight = doLog10(node.loopDepth);
needLoad.clear();
live = liveOut[n];
mustSpill = live;
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
InstructionDefine* definePtr;
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName range = name2range[definePtr->getRegisterName()];
if (needLoad.test(range))
if (!mustSpill.test(range))
cost[range].infinite = true;
if ((false /* !rematerializable(range) */ || !needLoad.test(range)) && !alreadyStored.test(range))
cost[range].stores += weight;
needLoad.clear(range);
}
if (instruction.getFlags() & ifCopy)
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
if (!live.test(name2range[usePtr->getRegisterName()])) {
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
Uint32 range = needLoad.get(l);
cost[range].loads += weight;
mustSpill.set(range);
}
needLoad.clear();
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
live.clear(name2range[definePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName range = name2range[usePtr->getRegisterName()];
live.set(range);
needLoad.set(range);
}
if (instruction.getFlags() & ifCopy) {
assert(useBegin != useEnd && useBegin[0].isRegister());
assert(defineBegin != defineEnd && defineBegin[0].isRegister());
RegisterName source = name2range[useBegin[0].getRegisterName()];
RegisterName destination = name2range[defineBegin[0].getRegisterName()];
cost[source].copies += weight;
cost[destination].copies += weight;
}
}
for (SparseSet::iterator s = needLoad.begin(); !needLoad.done(s); s = needLoad.advance(s))
cost[needLoad.get(s)].loads += weight;
}
for (Uint32 r = 0; r < rangeCount; r++) {
SpillCost& c = cost[r];
c.cost = 2 * (c.loads + c.stores) - c.copies;
}
registerAllocator.spillCost = cost;
}
#endif // _SPILLING_H_

View File

@@ -0,0 +1,239 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _SPLITS_H_
#define _SPLITS_H_
#include "Fundamentals.h"
#include <string.h>
#include "Pool.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "RegisterAllocator.h"
#include "RegisterAllocatorTools.h"
UT_EXTERN_LOG_MODULE(RegAlloc);
template <class RegisterPressure>
struct Splits
{
static void calculateSplitCosts(RegisterAllocator& registerAllocator);
static bool findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range);
static void insertSplitCode(RegisterAllocator& registerAllocator);
};
struct SplitCost
{
double loads;
double stores;
};
template <class RegisterPressure>
void Splits<RegisterPressure>::insertSplitCode(RegisterAllocator& /*registerAllocator*/)
{
// FIX
}
template <class RegisterPressure>
bool Splits<RegisterPressure>::findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range)
{
Pool& pool = registerAllocator.pool;
NameLinkedList** neighborsWithColor = new(pool) NameLinkedList*[6]; // FIX
memset(neighborsWithColor, '\0', 6 * sizeof(NameLinkedList*));
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
for (Int32 i = vector->count - 1; i >=0; --i) {
RegisterName neighbor = vector->neighbors[i];
RegisterName c = color[neighbor];
if (c < 6) { // FIX
NameLinkedList* node = new(pool) NameLinkedList();
node->name = neighbor;
node->next = neighborsWithColor[c];
neighborsWithColor[c] = node;
}
}
bool splitAroundName = true;
LiveRangeGraph<RegisterPressure>& lGraph = registerAllocator.lGraph;
RegisterName bestColor = RegisterName(6); // FIX
double bestCost = registerAllocator.spillCost[range].cost;
SplitCost* splitCost = registerAllocator.splitCost;
for (RegisterName i = RegisterName(0); i < 6; i = RegisterName(i + 1)) { // FIX
double splitAroundNameCost = 0.0;
bool canSplitAroundName = true;
SplitCost& sCost = splitCost[range];
double addedCost = 2.0 * (sCost.stores + sCost.loads);
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
RegisterName neighbor = node->name;
if (lGraph.haveEdge(neighbor, range)) {
canSplitAroundName = false;
break;
} else
splitAroundNameCost += addedCost;
}
if (canSplitAroundName && splitAroundNameCost < bestCost) {
bestCost = splitAroundNameCost;
bestColor = i;
splitAroundName = true;
}
double splitAroundColorCost = 0.0;
bool canSplitAroundColor = true;
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
RegisterName neighbor = node->name;
if (lGraph.haveEdge(range, neighbor)) {
canSplitAroundColor = false;
break;
} else {
SplitCost& sCost = splitCost[neighbor];
double addedCost = 2.0 * (sCost.stores + sCost.loads);
splitAroundColorCost += addedCost;
}
}
if (canSplitAroundColor && splitAroundColorCost < bestCost) {
bestCost = splitAroundColorCost;
bestColor = i;
splitAroundName = false;
}
}
if (bestColor < RegisterName(6)) {
color[range] = bestColor;
registerAllocator.splitFound = true;
NameLinkedList** splitAround = registerAllocator.splitAround;
if (splitAroundName)
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
NameLinkedList* newNode = new(pool) NameLinkedList();
newNode->name = node->name;
newNode->next = splitAround[range];
splitAround[range] = newNode;
}
else
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
NameLinkedList* newNode = new(pool) NameLinkedList();
RegisterName neighbor = node->name;
newNode->name = range;
newNode->next = splitAround[neighbor];
splitAround[neighbor] = newNode;
}
trespass("Found a split");
return true;
}
return false;
}
template <class RegisterPressure>
void Splits<RegisterPressure>::calculateSplitCosts(RegisterAllocator& registerAllocator)
{
Pool& pool = registerAllocator.pool;
Uint32 rangeCount = registerAllocator.rangeCount;
RegisterName* name2range = registerAllocator.name2range;
SplitCost* splitCost = new(pool) SplitCost[rangeCount];
memset(splitCost, '\0', rangeCount * sizeof(SplitCost));
SparseSet live(pool, rangeCount);
RegisterPressure::Set* liveIn = registerAllocator.liveness.liveIn;
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
ControlNode& node = *nodes[n];
double weight = doLog10(node.loopDepth);
live = liveOut[n];
ControlEdge* successorsEnd = node.getSuccessorsEnd();
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++) {
ControlNode& successor = successorsPtr->getTarget();
if (successor.getControlKind() != ckEnd) {
RegisterPressure::Set& successorLiveIn = liveIn[successor.dfsNum];
for (SparseSet::iterator i = live.begin(); !live.done(i); i = live.advance(i)) {
RegisterName name = RegisterName(live.get(i));
if (!successorLiveIn.test(name))
splitCost[name].loads += doLog10(successor.loopDepth);
}
}
}
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
InstructionDefine* definePtr;
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
splitCost[name2range[definePtr->getRegisterName()]].stores += weight;
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName range = name2range[usePtr->getRegisterName()];
if (!live.test(range)) {
if (&instruction != &instructions.last())
splitCost[range].loads += weight;
else {
ControlEdge* successorsEnd = node.getSuccessorsEnd();
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++)
splitCost[range].loads += doLog10(successorsPtr->getTarget().loopDepth);
}
}
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
live.clear(name2range[definePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
live.set(name2range[usePtr->getRegisterName()]);
}
}
NameLinkedList** splitAround = new(pool) NameLinkedList*[rangeCount];
memset(splitAround, '\0', rangeCount * sizeof(NameLinkedList*));
registerAllocator.splitAround = splitAround;
registerAllocator.splitCost = splitCost;
registerAllocator.splitFound = false;
}
#endif // _SPLITS_H_

View File

@@ -0,0 +1,186 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "HashTable.h"
#include "Timer.h"
#include "Pool.h"
static Pool pool; // Pool for the Timer class.
static HashTable<TimerEntry*> timerEntries(pool); // Timers hashtable.
const nTimersInABlock = 128; // Number of timers in a block.
static PRTime *timers = new(pool) PRTime[nTimersInABlock]; // A block of timers.
static Uint8 nextTimer = 0; // nextAvailableTimer.
//
// Calibrate the call to PR_Now().
//
static PRTime calibrate()
{
PRTime t = PR_Now();
PRTime& a = *new(pool) PRTime();
// Call 10 times the PR_Now() function.
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
t = (PR_Now() - t + 9) / 10;
return t;
}
static PRTime adjust = calibrate();
//
// Return the named timer..
//
TimerEntry& Timer::getTimerEntry(const char* name)
{
if (!timerEntries.exists(name)) {
TimerEntry* newEntry = new(pool) TimerEntry();
newEntry->accumulator = 0;
newEntry->running = false;
timerEntries.add(name, newEntry);
}
return *timerEntries[name];
}
//
// Return a reference to a new timer.
//
PRTime& Timer::getNewTimer()
{
if (nextTimer >= nTimersInABlock) {
timers = new(pool) PRTime[nTimersInABlock];
nextTimer = 0;
}
return timers[nextTimer++];
}
static Uint32 timersAreFrozen = 0;
//
// Start the named timer.
//
void Timer::start(const char* name)
{
if (timersAreFrozen)
return;
freezeTimers();
TimerEntry& timer = getTimerEntry(name);
PR_ASSERT(!timer.running);
timer.accumulator = 0;
timer.running = true;
timer.done = false;
unfreezeTimers();
}
//
// Stop the named timer.
//
void Timer::stop(const char* name)
{
if (timersAreFrozen)
return;
freezeTimers();
TimerEntry& timer = getTimerEntry(name);
PR_ASSERT(timer.running);
timer.running = false;
timer.done = true;
unfreezeTimers();
}
//
// Freeze all the running timers.
//
void Timer::freezeTimers()
{
PRTime when = PR_Now() - adjust;
if (timersAreFrozen == 0) {
Vector<TimerEntry*> entries = timerEntries;
Uint32 count = entries.size();
for (Uint32 i = 0; i < count; i++) {
TimerEntry& entry = *entries[i];
if (entry.running) {
entry.accumulator += (when - *entry.startTime);
}
}
}
timersAreFrozen++;
}
//
// Unfreeze all the running timers.
//
void Timer::unfreezeTimers()
{
PR_ASSERT(timersAreFrozen != 0);
timersAreFrozen--;
if (timersAreFrozen == 0) {
Vector<TimerEntry *> entries = timerEntries;
Uint32 count = entries.size();
PRTime& newStart = getNewTimer();
for (Uint32 i = 0; i < count; i++) {
TimerEntry& entry = *entries[i];
if (entry.running) {
entry.startTime = &newStart;
}
}
newStart = PR_Now();
}
}
//
// Print the named timer in the file f.
//
void Timer::print(FILE* f, const char *name)
{
if (timersAreFrozen)
return;
freezeTimers();
TimerEntry& timer = getTimerEntry(name);
PR_ASSERT(timer.done);
PRTime elapsed = timer.accumulator;
if (elapsed >> 32) {
fprintf(f, "[timer %s out of range]\n", name);
} else {
fprintf(f, "[%dus in %s]\n", Uint32(elapsed), name);
}
fflush(f);
unfreezeTimers();
}

View File

@@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _TIMER_H_
#define _TIMER_H_
#include "Fundamentals.h"
#include "HashTable.h"
#include "prtime.h"
//
// Naming convention:
// As the class Timer contains only static methods, the timer's name should start with the
// module name. Otherwise starting 2 timers with the same name will assert.
//
#ifndef NO_TIMER
struct TimerEntry
{
PRTime *startTime; // Current time when we start the timer.
PRTime accumulator; // Time spent in this timer.
bool running; // True if the timer is running.
bool done; // True if the timer was running and was stopped.
};
class Timer
{
private:
// Return the named timer.
static TimerEntry& getTimerEntry(const char* name);
// Return a reference to a new Timer.
static PRTime& getNewTimer();
public:
// Start the timer.
static void start(const char* name);
// Stop the timer.
static void stop(const char* name);
// Freeze all the running timers.
static void freezeTimers();
// Unfreeze all the running timers.
static void unfreezeTimers();
// Print the timer.
static void print(FILE* f, const char *name);
};
inline void startTimer(const char* name) {Timer::start(name);}
inline void stopTimer(const char* name) {Timer::stop(name); Timer::print(stdout, name);}
#define START_TIMER_SAFE Timer::freezeTimers();
#define END_TIMER_SAFE Timer::unfreezeTimers();
#define TIMER_SAFE(x) START_TIMER_SAFE x; END_TIMER_SAFE
#else /* NO_TIMER */
inline void startTimer(const char* /*name*/) {}
inline void stopTimer(const char* /*name*/) {}
#define START_TIMER_SAFE
#define END_TIMER_SAFE
#define TIMER_SAFE(x) x;
#endif /* NO_TIMER */
#endif /* _TIMER_H_ */

View File

@@ -0,0 +1,40 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "VirtualRegister.h"
#include "Instruction.h"
//------------------------------------------------------------------------------
// VirtualRegister -
#ifdef MANUAL_TEMPLATES
template class IndexedPool<VirtualRegister>;
#endif
// Set the defining instruction.
//
void VirtualRegister::setDefiningInstruction(Instruction& instruction)
{
if (definingInstruction != NULL) {
if ((instruction.getFlags() & ifCopy) && (definingInstruction->getFlags() & ifPhiNode))
return;
}
definingInstruction = &instruction;
}

View File

@@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _VIRTUAL_REGISTER_H_
#define _VIRTUAL_REGISTER_H_
#include "Fundamentals.h"
#include "IndexedPool.h"
#include <string.h>
#include "RegisterTypes.h"
#include "RegisterClass.h"
//------------------------------------------------------------------------------
// VirtualRegister - 24b
class Instruction;
class VirtualRegister : public IndexedObject<VirtualRegister>
{
public:
Instruction* definingInstruction; // Instruction defining this VR.
// Initialize a VR of the given classKind.
VirtualRegister(RegisterClassKind /*classKind*/) : definingInstruction(NULL) {}
// Return the defining instruction for this VR.
Instruction* getDefiningInstruction() const {return definingInstruction;}
// Set the defining instruction.
void setDefiningInstruction(Instruction& insn);
};
// Return true if the VirtualRegisters are equals. The only way 2 VRs can be equal is if
// they have the same index. If they have the same index then they are at the same
// address in the indexed pool.
//
inline bool operator == (const VirtualRegister& regA, const VirtualRegister& regB) {return &regA == &regB;}
//------------------------------------------------------------------------------
// VirtualRegisterManager -
struct PreColoredRegister
{
RegisterID id;
RegisterName color;
};
class VirtualRegisterManager
{
private:
IndexedPool<VirtualRegister> registerPool;
PreColoredRegister machineRegister[6];
public:
VirtualRegisterManager()
{
for (Uint32 i = 0; i < 6; i++)
machineRegister[i].id = invalidID;
}
// Return the VirtualRegister at the given index.
VirtualRegister& getVirtualRegister(RegisterName name) const {return registerPool.get(name);}
// Return a new VirtualRegister.
RegisterID newVirtualRegister(RegisterClassKind classKind)
{
VirtualRegister& vReg = *new(registerPool) VirtualRegister(classKind);
RegisterID rid;
setName(rid, RegisterName(vReg.getIndex()));
setClass(rid, classKind);
return rid;
}
RegisterID newMachineRegister(RegisterName name, RegisterClassKind classKind)
{
RegisterID rid = machineRegister[name].id;
if (rid == invalidID) {
rid = newVirtualRegister(classKind);
DEBUG_ONLY(setMachineRegister(rid));
machineRegister[name].id = rid;
machineRegister[name].color = name;
}
return rid;
}
PreColoredRegister* getMachineRegistersBegin() const {return (PreColoredRegister*) machineRegister;} // FIX
PreColoredRegister* getMachineRegistersEnd() const {return (PreColoredRegister*) &machineRegister[6];} // FIX
// Return the VirtualRegister universe size.
Uint32 getSize() {return registerPool.getSize();}
void setSize(Uint32 size) {registerPool.setSize(size);}
};
#endif // _VIRTUAL_REGISTER_H_

View File

@@ -1 +0,0 @@

View File

@@ -1,29 +0,0 @@
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 oqr
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the JavaScript 2 Prototype.
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.
Alternatively, the contents of this file may be used under the
terms of the GNU Public License (the "GPL"), in which case the
provisions of the GPL are applicable instead of those above.
If you wish to allow use of your version of this file only
under the terms of the GPL and not to allow others to use your
version of this file under the NPL, indicate your decision by
deleting the provisions above and replace them with the notice
and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this
file under either the NPL or the GPL.

View File

@@ -1,14 +0,0 @@
2001-01-30 <rginda@netscape.com>
* broke apart some classes contained parser.* and utilities.* into
seperate files.
parser.* begat lexer.*, token.*, reader.*
utilities.* begat mem.*, stlcfg.h, ds.h, strings.*, exception.*,
formatter.*, and algo.h
* parser reorg compile time data:
new layout: 0:48.01elapsed 86%CPU
old layout: 0:55.85elapsed 57%CPU
(old layout includes only hash numerics utilities parser world object
files)

View File

@@ -1 +0,0 @@

View File

@@ -1,2 +0,0 @@
SUBDIRS = src tests

View File

@@ -1 +0,0 @@

View File

@@ -1,98 +0,0 @@
parse functions
parseIdentifierQualifiers(ExprNode *e, bool &foundQualifiers,
parseParenthesesAndIdentifierQualifiers(const Token &tParen,
parseQualifiedIdentifier(const Token &t, bool preferRegExp)
parseArrayLiteral(const Token &initialToken)
parseObjectLiteral(const Token &initialToken)
parsePrimaryExpression()
parseMember(ExprNode *target, const Token &tOperator,
parseInvoke(ExprNode *target, uint32 pos,
parsePostfixExpression(bool newExpression)
parseUnaryExpression()
parseExpression(bool noIn, bool noAssignment, bool noComma)
parseParenthesizedExpression()
parseTypeExpression(bool noIn)
parseTypedIdentifier(ExprNode *&type)
parseTypeBinding(Token::Kind kind, bool noIn)
parseTypeListBinding(Token::Kind kind)
parseVariableBinding(bool noQualifiers, bool noIn)
parseFunctionName(FunctionName &fn)
parseFunctionSignature(FunctionDefinition &fd)
parseBlock(bool inSwitch, bool noCloseBrace)
parseBody(SemicolonState *semicolonState)
parseAttributeStatement(uint32 pos, IdentifierList *attributes,
parseAttributesAndStatement(const Token *t, AttributeStatement as,
parseAnnotatedBlock()
parseFor(uint32 pos, SemicolonState &semicolonState)
parseTry(uint32 pos)
parseStatement(bool /*topLevel*/, bool inSwitch,
parseStatementAndSemicolon(SemicolonState &semicolonState)
parseIdentifier()
parseLiteralField()
parseFieldName()
parseArgumentList(NodeQueue<ExprPairList> &args)
parseArgumentListPrime(NodeQueue<ExprPairList> &args)
parseNamedArgumentListPrime(NodeQueue<ExprPairList> &args)
parseAllParameters(FunctionDefinition &fd,
parseOptionalNamedRestParameters (FunctionDefinition &fd,
parseNamedRestParameters(FunctionDefinition &fd,
parseNamedParameters(FunctionDefinition &fd,
parseRestParameter()
parseParameter()
parseOptionalParameter()
parseOptionalParameterPrime(VariableBinding *first)
parseNamedParameter(NodeQueue<IdentifierList> &aliases)
parseResultSignature()
1/28/01
Files:
cpucfg.h
formatter.cpp formatter.h
"Formatter" class, iostream like wrapper around stdio.
gc_allocator.h, gc_container.h
boehm gc stuff.
hash.cpp hash.h
a hash
lexer.cpp lexer.h
main lexer.
mem.cpp mem.h
zone, arena, and pool classes for memory management.
nodefactory.h
parse node factory.
numerics.cpp numerics.h
numbers and stuff.
parser.cpp parser.h
main parser source.
tables in parser.h:
enum ExprNode::Kind; types of expressions
enum StmtNode::Kind; types of statements
reader.cpp reader.h
"Reader" class, feeds source to the parser/lexer.
stlcfg.h
stupid stl tricks
.
systemtypes.h
basic typedefs.
token.cpp token.h
token class.
utilities.cpp utilities.h
random things.
world.cpp world.h
the whole world.

View File

@@ -1,26 +0,0 @@
redo parseAllPArameters code
move js/js2 to js2/src
move js/semantics to js2/semantics
compile on mac and windows
parser:
1. Parser is out of date (by 10%?)
a. rework parser to reflect grammer productions.
b. functional attrs.
c. parser node struct changes.
2. Parser Restructuring (2 weeks.)
3. Common lisp generator running?
4. const-ness
a. compile time detection.
b. read before assign.
c. runtime assignment prevention.
d. class/ function/ const equivalence.
export, namespace, import, package ?

140
mozilla/js2/aclocal.m4 vendored
View File

@@ -1,140 +0,0 @@
dnl aclocal.m4 generated automatically by aclocal 1.4
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.
# serial 1
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN(AM_INIT_AUTOMAKE,
[AC_REQUIRE([AC_PROG_INSTALL])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_SUBST(VERSION)
dnl test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
#
# Check to make sure that the build environment is sane.
#
AC_DEFUN(AM_SANITY_CHECK,
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "[$]*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "[$]*" != "X $srcdir/configure conftestfile" \
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "[$]2" = conftestfile
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
rm -f conftest*
AC_MSG_RESULT(yes)])
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
AC_DEFUN(AM_MISSING_PROG,
[AC_MSG_CHECKING(for working $2)
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if ($2 --version) < /dev/null > /dev/null 2>&1; then
$1=$2
AC_MSG_RESULT(found)
else
$1="$3/missing $2"
AC_MSG_RESULT(missing)
fi
AC_SUBST($1)])
# Define a conditional.
AC_DEFUN(AM_CONDITIONAL,
[AC_SUBST($1_TRUE)
AC_SUBST($1_FALSE)
if $2; then
$1_TRUE=
$1_FALSE='#'
else
$1_TRUE='#'
$1_FALSE=
fi])
# Like AC_CONFIG_HEADER, but automatically create stamp file.
AC_DEFUN(AM_CONFIG_HEADER,
[AC_PREREQ([2.12])
AC_CONFIG_HEADER([$1])
dnl When config.status generates a header, we must update the stamp-h file.
dnl This file resides in the same directory as the config header
dnl that is generated. We must strip everything past the first ":",
dnl and everything past the last "/".
AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
<<am_indx=1
for am_file in <<$1>>; do
case " <<$>>CONFIG_HEADERS " in
*" <<$>>am_file "*<<)>>
echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
;;
esac
am_indx=`expr "<<$>>am_indx" + 1`
done<<>>dnl>>)
changequote([,]))])

View File

@@ -1,16 +0,0 @@
BOEHM_DIR = $(top_srcdir)/../gc/boehm/
LIBBOEHM = $(BOEHM_DIR)/gc.a
JS2_DIR = $(top_srcdir)/src/
LIBJS2 = $(JS2_DIR)/libjs2.a
WFLAGS = -Wmissing-prototypes -Wstrict-prototypes -Wunused \
-Wswitch
if DEBUG
CXXFLAGS = -DXP_UNIX -g -DDEBUG -DNEW_PARSER $(WFLAGS)
else
CXXFLAGS = -DXP_UNIX -O2 -DNEW_PARSER -Wuninitialized $(WFLAGS)
endif

View File

@@ -1,42 +0,0 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if using alloca.c. */
#undef C_ALLOCA
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
#undef CRAY_STACKSEG_END
/* Define if you have alloca, as a function or macro. */
#undef HAVE_ALLOCA
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#undef HAVE_ALLOCA_H
/* Define if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#undef STACK_DIRECTION
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if you have the getpagesize function. */
#undef HAVE_GETPAGESIZE
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Name of package */
#undef PACKAGE
/* Version number of package */
#undef VERSION

2407
mozilla/js2/configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,57 +0,0 @@
dnl Process this file with autoconf to produce a configure script.
PACKAGE=JavaScript2
VERSION=0.1
AC_INIT(src/parser.h)
AM_INIT_AUTOMAKE(JavaScript2, 0.1)
AC_ARG_ENABLE(debug,
[ --enable-debug Turn on debugging],
[case "${enableval}" in
yes) debug=true ;;
no) debug=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
esac],[debug=false])
AM_CONDITIONAL(DEBUG, test x$debug = xtrue)
AM_CONFIG_HEADER(config.h)
dnl Checks for programs.
AC_PROG_CXX
AC_PROG_AWK
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_RANLIB
dnl AM_PATH_GTK(1.2.0, ,
dnl AC_MSG_ERROR(Cannot find GTK: Is gtk-config in path?))
dnl Checks for libraries.
dnl Replace `main' with a function in -ldl:
dnl AC_CHECK_LIB(dl, main)
dnl Replace `main' with a function in -lgdk:
dnl AC_CHECK_LIB(gdk, main)
dnl Replace `main' with a function in -lglib:
dnl AC_CHECK_LIB(glib, main)
dnl Replace `main' with a function in -lgmodule:
dnl AC_CHECK_LIB(gmodule, main)
dnl Replace `main' with a function in -lgtk:
dnl AC_CHECK_LIB(gtk, main)
dnl Replace `main' with a function in -lm:
dnl AC_CHECK_LIB(m, main)
dnl Checks for header files.
AC_HEADER_STDC
dnl AC_CHECK_HEADERS(fcntl.h limits.h malloc.h strings.h unistd.h)
dnl Checks for typedefs, structures, and compiler characteristics.
dnl AC_C_CONST
dnl AC_C_INLINE
dnl AC_TYPE_SIZE_T
dnl Checks for library functions.
AC_FUNC_ALLOCA
AC_FUNC_MMAP
dnl AC_CHECK_FUNCS(getcwd getwd putenv strdup strerror tcgetattr)
AC_OUTPUT(./Makefile src/Makefile tests/Makefile tests/cpp/Makefile tests/js/Makefile)

View File

@@ -1,251 +0,0 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

View File

@@ -1,65 +0,0 @@
# Makefile for ESC in Java
# Targets:
# all -- to build all parts.
# input, lexer, parser, semantics, generator -- to build a specfic part.
# sanity -- to run the compiler against a simple script. If things are
# working the compiler will return the value: completion( 0, okay, null )
all: util input lexer parser semantics generator runtime main sanity
main:
javac -d Debug -classpath Debug ../../src/java/main/*.java
util:
javac -d Debug -classpath Debug ../../src/java/util/*.java
input:
javac -d Debug -classpath Debug ../../src/java/input/*.java
lexer:
javac -d Debug -classpath Debug ../../src/java/lexer/*.java
parser:
javac -d Debug -classpath Debug ../../src/java/parser/*.java
semantics:
javac -d Debug -classpath Debug ../../src/java/semantics/*.java ../../src/java/semantics/values/*.java ../../src/java/semantics/types/*.java
generator:
javac -d Debug -classpath Debug ../../src/java/generator/*.java
runtime:
javac -d Debug -classpath Debug ../../src/java/runtime/*.java
testcase:
javac -d Debug -classpath Debug Script1.java
java -classpath Debug Test1 Script1
sanity:
java -classpath Debug Main ../../test/sanity.js
test:
java -classpath Debug Main -d ../../test/ecma-e4/02.expressions/primary.1.js
java -classpath Debug Main -d ../../test/ecma-e4/02.expressions/prefixunary.1.js
java -classpath Debug Main -d ../../test/ecma-e4/02.expressions/postfixunary.1.js
java -classpath Debug Main -d ../../test/ecma-e4/02.expressions/binary.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/break.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/continue.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/do.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/for.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/forin.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/if.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/labeled.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/return.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/switch.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/throw.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/try.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/while.1.js
java -classpath Debug Main -d ../../test/ecma-e4/03.statements/with.1.js
java -classpath Debug Main -d ../../test/ecma-e4/04.definitions/definition.1.js
java -classpath Debug Main -d ../../test/ecma-e4/04.definitions/definition.2.js
test_functions:
java -classpath Debug Main -debug ../../test/ecma-e4/06.functions/function.1.js

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

View File

@@ -1,321 +0,0 @@
/*
* Defines token classes and their print names.
*
* This interface defines values for each token class that occurs in
* ECMAScript 4. All but numericliteral, stringliteral, regexpliteral, and
* identifier are singleton and therefore a fully described by their
* token class defined here. The other four however can have an infinite number
* of instances each with a unique identifier and associated instance
* data. We use positive identifiers to signify instances of these
* token classes so that the instance data can be stored in an array,
* or set of arrays with the token value specifying its index.
*/
/**
* The base Node class.
*/
#ifndef Tokens_h
#define Tokens_h
namespace esc {
namespace v1 {
class Tokens {
#if 0
public interface Tokens {
/**
* Token class values are negative, and token instances are positive so
* that their values can point to their instance data in an array.
*/
public static final int first_token = -1;
public static final int eos_token = first_token-0;
public static final int minus_token = first_token - 1;
public static final int minusminus_token = minus_token - 1;
public static final int not_token = minusminus_token - 1;
public static final int notequals_token = not_token - 1;
public static final int strictnotequals_token = notequals_token - 1;
public static final int pound_token = strictnotequals_token - 1;
public static final int modulus_token = pound_token - 1;
public static final int modulusassign_token = modulus_token - 1;
public static final int bitwiseand_token = modulusassign_token - 1;
public static final int logicaland_token = bitwiseand_token - 1;
public static final int logicalandassign_token = logicaland_token - 1;
public static final int bitwiseandassign_token = logicalandassign_token - 1;
public static final int leftparen_token = bitwiseandassign_token - 1;
public static final int rightparen_token = leftparen_token - 1;
public static final int mult_token = rightparen_token - 1;
public static final int multassign_token = mult_token - 1;
public static final int comma_token = multassign_token - 1;
public static final int dot_token = comma_token - 1;
public static final int doubledot_token = dot_token - 1;
public static final int tripledot_token = doubledot_token - 1;
public static final int div_token = tripledot_token - 1;
public static final int divassign_token = div_token - 1;
public static final int colon_token = divassign_token - 1;
public static final int doublecolon_token = colon_token - 1;
public static final int semicolon_token = doublecolon_token - 1;
public static final int questionmark_token = semicolon_token - 1;
public static final int ampersand_token = questionmark_token - 1;
public static final int leftbracket_token = ampersand_token - 1;
public static final int rightbracket_token = leftbracket_token - 1 ;
public static final int bitwisexor_token = rightbracket_token - 1;
public static final int logicalxor_token = bitwisexor_token - 1;
public static final int logicalxorassign_token = logicalxor_token - 1;
public static final int bitwisexorassign_token = logicalxorassign_token - 1;
public static final int leftbrace_token = bitwisexorassign_token - 1;
public static final int bitwiseor_token = leftbrace_token - 1;
public static final int logicalor_token = bitwiseor_token - 1;
public static final int logicalorassign_token = logicalor_token - 1;
public static final int bitwiseorassign_token = logicalorassign_token - 1;
public static final int rightbrace_token = bitwiseorassign_token - 1;
public static final int bitwisenot_token = rightbrace_token - 1;
public static final int plus_token = bitwisenot_token - 1;
public static final int plusplus_token = plus_token - 1;
public static final int plusassign_token = plusplus_token - 1;
public static final int lessthan_token = plusassign_token - 1;
public static final int leftshift_token = lessthan_token - 1;
public static final int leftshiftassign_token = leftshift_token - 1;
public static final int lessthanorequals_token = leftshiftassign_token - 1;
public static final int assign_token = lessthanorequals_token - 1;
public static final int minusassign_token = assign_token - 1;
public static final int equals_token = minusassign_token - 1;
public static final int strictequals_token = equals_token - 1;
public static final int greaterthan_token = strictequals_token - 1;
public static final int arrow_token = greaterthan_token - 1;
public static final int greaterthanorequals_token = arrow_token - 1;
public static final int rightshift_token = greaterthanorequals_token - 1;
public static final int rightshiftassign_token = rightshift_token - 1;
public static final int unsignedrightshift_token = rightshiftassign_token - 1;
public static final int unsignedrightshiftassign_token = unsignedrightshift_token - 1;
public static final int abstract_token = unsignedrightshiftassign_token - 1;
public static final int attribute_token = abstract_token - 1;
public static final int boolean_token = attribute_token - 1;
public static final int break_token = boolean_token - 1;
public static final int byte_token = break_token - 1;
public static final int case_token = byte_token - 1;
public static final int catch_token = case_token - 1;
public static final int char_token = catch_token - 1;
public static final int class_token = char_token - 1;
public static final int const_token = class_token - 1;
public static final int constructor_token = const_token - 1;
public static final int continue_token = constructor_token - 1;
public static final int debugger_token = continue_token - 1;
public static final int default_token = debugger_token - 1;
public static final int delete_token = default_token - 1;
public static final int do_token = delete_token - 1;
public static final int double_token = do_token - 1;
public static final int else_token = double_token - 1;
public static final int enum_token = else_token - 1;
public static final int eval_token = enum_token - 1;
public static final int export_token = eval_token - 1;
public static final int extends_token = export_token - 1;
public static final int false_token = extends_token - 1;
public static final int final_token = false_token - 1;
public static final int finally_token = final_token - 1;
public static final int float_token = finally_token - 1;
public static final int for_token = float_token - 1;
public static final int function_token = for_token - 1;
public static final int get_token = function_token - 1;
public static final int goto_token = get_token - 1;
public static final int if_token = goto_token - 1;
public static final int implements_token = if_token - 1;
public static final int import_token = implements_token - 1;
public static final int in_token = import_token - 1;
public static final int include_token = in_token - 1;
public static final int instanceof_token = include_token - 1;
public static final int int_token = instanceof_token - 1;
public static final int interface_token = int_token - 1;
public static final int long_token = interface_token - 1;
public static final int namespace_token = long_token - 1;
public static final int native_token = namespace_token - 1;
public static final int new_token = native_token - 1;
public static final int null_token = new_token - 1;
public static final int package_token = null_token - 1;
public static final int private_token = package_token - 1;
public static final int protected_token = private_token - 1;
public static final int public_token = protected_token - 1;
public static final int return_token = public_token - 1;
public static final int set_token = return_token - 1;
public static final int short_token = set_token - 1;
public static final int static_token = short_token - 1;
public static final int super_token = static_token - 1;
public static final int switch_token = super_token - 1;
public static final int synchronized_token = switch_token - 1;
public static final int this_token = synchronized_token - 1;
public static final int throw_token = this_token - 1;
public static final int throws_token = throw_token - 1;
public static final int transient_token = throws_token - 1;
public static final int true_token = transient_token - 1;
public static final int try_token = true_token - 1;
public static final int typeof_token = try_token - 1;
public static final int use_token = typeof_token - 1;
public static final int var_token = use_token - 1;
public static final int void_token = var_token - 1;
public static final int volatile_token = void_token - 1;
public static final int while_token = volatile_token - 1;
public static final int with_token = while_token - 1;
public static final int identifier_token = with_token - 1;
public static final int numberliteral_token = identifier_token - 1;
public static final int regexpliteral_token = numberliteral_token - 1;
public static final int stringliteral_token = regexpliteral_token - 1;
public static final int eol_token = stringliteral_token - 1;
public static final int empty_token = eol_token - 1;
public static final int error_token = empty_token - 1;
public static final int last_token = empty_token - 1;
public static final String[] tokenClassNames = {
"<unused index>",
"<eos>",
"minus_token",
"minusminus_token",
"not_token",
"notequals_token",
"strictnotequals_token",
"pound_token",
"modulus_token",
"modulusassign_token",
"bitwiseand_token",
"logicaland_token",
"logicalandassign_token",
"bitwiseandassign_token",
"leftparen_token",
"rightparen_token",
"mult_token",
"multassign_token",
"comma_token",
"dot_token",
"doubledot_token",
"tripledot_token",
"div_token",
"divassign_token",
"colon_token",
"doublecolon_token",
"semicolon_token",
"questionmark_token",
"ampersand_token",
"leftbracket_token",
"rightbracket_token",
"bitwisexor_token",
"logicalxor_token",
"logicalxorassign_token",
"bitwisexorassign_token",
"leftbrace_token",
"bitwiseor_token",
"logicalor_token",
"logicalorassign_token",
"bitwiseorassign_token",
"rightbrace_token",
"bitwisenot_token",
"plus_token",
"plusplus_token",
"plusassign_token",
"lessthan_token",
"leftshift_token",
"leftshiftassign_token",
"lessthanorequals_token",
"assign_token",
"minusassign_token",
"equals_token",
"strictequals_token",
"greaterthan_token",
"arrow_token",
"greaterthanorequals_token",
"rightshift_token",
"rightshiftassign_token",
"unsignedrightshift_token",
"unsignedrightshiftassign_token",
"abstract_token",
"attribute_token",
"boolean_token",
"break_token",
"byte_token",
"case_token",
"catch_token",
"char_token",
"class_token",
"const_token",
"constructor_token",
"continue_token",
"debugger_token",
"default_token",
"delete_token",
"do_token",
"double_token",
"else_token",
"enum_token",
"eval_token",
"export_token",
"extends_token",
"false_token",
"final_token",
"finally_token",
"float_token",
"for_token",
"function_token",
"get_token",
"goto_token",
"if_token",
"implements_token",
"import_token",
"in_token",
"include_token",
"instanceof_token",
"int_token",
"interface_token",
"long_token",
"namespace_token",
"native_token",
"new_token",
"null_token",
"package_token",
"private_token",
"protected_token",
"public_token",
"return_token",
"set_token",
"short_token",
"static_token",
"super_token",
"switch_token",
"synchronized_token",
"this_token",
"throw_token",
"throws_token",
"transient_token",
"true_token",
"try_token",
"typeof_token",
"use_token",
"var_token",
"void_token",
"volatile_token",
"while_token",
"with_token",
"identifier_token",
"numberliteral_token",
"regexpliteral_token",
"stringliteral_token",
"<eol>",
"<empty>",
"<error>"
};
#endif
};
}
}
#endif // Tokens_h
/*
* The end.
*/

View File

@@ -1,26 +0,0 @@
/*
* Activation interface. An activation provides slot storage.
*/
#ifndef Builder_h
#define Builder_h
namespace esc {
namespace v1 {
class ObjectValue;
class Builder {
public:
virtual void build(Context& cx, ObjectValue* ob) = 0;
};
}
}
#endif // Builder_h
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,62 +0,0 @@
/*
* Execution context.
*/
#ifndef Context_h
#define Context_h
#include <stack>
#include <vector>
namespace esc {
namespace v1 {
class Value;
class ObjectValue;
class Context {
ObjectValue* global;
std::stack<ObjectValue*> scopes;
public:
Context() {
}
void pushScope(ObjectValue* scope) {
if(scopes.empty()) {
global = scope;
}
scopes.push(scope);
}
void popScope() {
scopes.pop();
}
std::stack<ObjectValue*> getScopes() {
return scopes;
}
ObjectValue* scope() {
return scopes.top();
}
ObjectValue* globalScope() {
return global;
}
std::vector<Value*> used_namespaces;
};
}
}
#endif // Context_h
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,345 +0,0 @@
/**
* The base visitor object extended by semantic evaluators.
*
* This is a visitor that is used by the compiler for various forms for
* evaluation of a parse tree (e.g. a type evaluator might compute the
* static type of an expression.)
*/
#ifndef Evaluator_h
#define Evaluator_h
#include "Value.h"
#include "Context.h"
namespace esc {
namespace v1 {
struct Node;
struct IdentifierNode;
struct ThisExpressionNode;
struct SuperExpressionNode;
struct QualifiedIdentifierNode;
struct LiteralNullNode;
struct LiteralBooleanNode;
struct LiteralNumberNode;
struct LiteralStringNode;
struct LiteralUndefinedNode;
struct LiteralRegExpNode;
struct UnitExpressionNode;
struct FunctionExpressionNode;
struct ParenthesizedExpressionNode;
struct ParenthesizedListExpressionNode;
struct LiteralObjectNode;
struct LiteralFieldNode;
struct LiteralArrayNode;
struct PostfixExpressionNode;
struct NewExpressionNode;
struct IndexedMemberExpressionNode;
struct ClassofExpressionNode;
struct MemberExpressionNode;
struct CoersionExpressionNode;
struct CallExpressionNode;
struct GetExpressionNode;
struct SetExpressionNode;
struct UnaryExpressionNode;
struct BinaryExpressionNode;
struct ConditionalExpressionNode;
struct AssignmentExpressionNode;
struct ListNode;
struct StatementListNode;
struct EmptyStatementNode;
struct ExpressionStatementNode;
struct AnnotatedBlockNode;
struct LabeledStatementNode;
struct IfStatementNode;
struct SwitchStatementNode;
struct CaseLabelNode;
struct DoStatementNode;
struct WhileStatementNode;
struct ForInStatementNode;
struct ForStatementNode;
struct WithStatementNode;
struct ContinueStatementNode;
struct BreakStatementNode;
struct ReturnStatementNode;
struct ThrowStatementNode;
struct TryStatementNode;
struct CatchClauseNode;
struct FinallyClauseNode;
struct UseStatementNode;
struct IncludeStatementNode;
struct ImportDefinitionNode;
struct ImportBindingNode;
struct AnnotatedDefinitionNode;
struct AttributeListNode;
struct ExportDefinitionNode;
struct ExportBindingNode;
struct VariableDefinitionNode;
struct VariableBindingNode;
struct TypedVariableNode;
struct FunctionDefinitionNode;
struct FunctionDeclarationNode;
struct FunctionNameNode;
struct FunctionSignatureNode;
struct ParameterNode;
struct OptionalParameterNode;
struct RestParameterNode;
struct NamedParameterNode;
struct ClassDefinitionNode;
struct ClassDeclarationNode;
struct InheritanceNode;
struct NamespaceDefinitionNode;
struct PackageDefinitionNode;
struct LanguageDeclarationNode;
struct ProgramNode;
class Evaluator {
public:
// Base node
virtual Value* evaluate( Context& cx, Node* node ) {
throw;
}
// Expression evaluators
virtual Value* evaluate( Context& cx, IdentifierNode* node ) {
throw;
}
// Expression evaluators
virtual Value* evaluate( Context& cx, ThisExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, QualifiedIdentifierNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, LiteralBooleanNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, LiteralNumberNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, LiteralStringNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, LiteralUndefinedNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, LiteralRegExpNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, UnitExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, FunctionExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ParenthesizedExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ParenthesizedListExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, LiteralObjectNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, LiteralFieldNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, LiteralArrayNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, PostfixExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, NewExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, IndexedMemberExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ClassofExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, MemberExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, CoersionExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, CallExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, GetExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, SetExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, UnaryExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, BinaryExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ConditionalExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, AssignmentExpressionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ListNode* node ) {
throw;
}
// Statements
virtual Value* evaluate( Context& cx, StatementListNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, EmptyStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ExpressionStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, AnnotatedBlockNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, LabeledStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, IfStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, SwitchStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, CaseLabelNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, DoStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, WhileStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ForInStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ForStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, WithStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ContinueStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, BreakStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ReturnStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ThrowStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, TryStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, CatchClauseNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, FinallyClauseNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, UseStatementNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, IncludeStatementNode* node ) {
throw;
}
// Definitions
virtual Value* evaluate( Context& cx, ImportDefinitionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ImportBindingNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, AnnotatedDefinitionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, AttributeListNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ExportDefinitionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ExportBindingNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, VariableDefinitionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, VariableBindingNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, TypedVariableNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, FunctionDefinitionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, FunctionDeclarationNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, FunctionNameNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, FunctionSignatureNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ParameterNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, OptionalParameterNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ClassDefinitionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ClassDeclarationNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, InheritanceNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, NamespaceDefinitionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, PackageDefinitionNode* node ) {
throw;
}
virtual Value* evaluate( Context& cx, ProgramNode* node ) {
throw;
}
};
}
}
#endif // Evaluator_h
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,88 +0,0 @@
/**
* The base Node class.
*/
#ifndef Node_h
#define Node_h
namespace esc {
namespace v1 {
class Evaluator;
class Value;
class Context;
struct Node {
int position;
char local_var_index;
Node() {
}
Node( int position ) {
this->position = position;
}
virtual Value* evaluate( Context& cx, Evaluator* evaluator ) {
return (Value*) 0;
}
Node* first() {
return this;
}
Node* last() {
return this;
}
Node* pos(int p) {
position = p;
return this;
}
int pos() {
return position;
}
#if 0
private static final boolean debug = false;
Block block;
Store store;
boolean isLeader;
public void markLeader() throws Exception {
if( debug ) {
Debugger.trace( "Node.markLeader() with this = " + this );
//if(this instanceof AnnotatedBlockNode) throw new Exception("blah");
}
isLeader=true;
}
public boolean isLeader() {
return isLeader;
}
public boolean isBranch() {
return false;
}
public Node[] getTargets() {
return null;
}
public String toString() {
return isLeader ? "*"+block+":" : ""+block+":";
}
#endif
};
}
}
#endif // Node_h
/*
* The end.
*/

View File

@@ -1,46 +0,0 @@
/*
* The value class from which all other values derive.
*/
#include "NodeFactory.h"
namespace esc {
namespace v1 {
std::vector<Node*>* NodeFactory::roots;
int NodeFactory::main(int argc, char* argv[]) {
NodeFactory::init();
NodeFactory::Identifier("a");
NodeFactory::QualifiedIdentifier(
NodeFactory::Identifier("public"),
NodeFactory::Identifier("b"));
NodeFactory::LiteralNull();
NodeFactory::LiteralBoolean((bool)1);
NodeFactory::LiteralArray(
NodeFactory::List(
NULL,
NodeFactory::LiteralNumber("one")));
NodeFactory::LiteralField(
NodeFactory::Identifier("a"),
NodeFactory::LiteralBoolean((bool)1));
NodeFactory::LiteralNumber("3.1415");
NodeFactory::LiteralObject(
NodeFactory::List(
NULL,
NodeFactory::LiteralField(
NodeFactory::Identifier("a"),
NodeFactory::LiteralBoolean((bool)1))));
return 0;
}
}
}
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,445 +0,0 @@
/*
* Creates parse tree nodes.
*/
#ifndef NodeFactory_h
#define NodeFactory_h
#include <vector>
#include <algorithm>
#include "Node.h"
#include "Nodes.h"
namespace esc {
namespace v1 {
struct NodeFactory {
/*
* Test driver
*/
static int main(int argc, char* argv[]);
/*
* roots is a vector of references to all the nodes allocated
* since the last call to clear().
*/
static std::vector<Node*>* roots;
static void init() {
NodeFactory::roots = new std::vector<Node*>();
}
static void clear_root(Node* root) {
delete root;
}
static void clear() {
std::for_each(roots->begin(),roots->end(),clear_root);
roots->clear();
delete roots;
}
// Nodes
static IdentifierNode* Identifier( std::string name ) {
IdentifierNode* node = new IdentifierNode(name,0/*in->positionOfMark()*/);
roots->push_back(node);
return node;
}
static QualifiedIdentifierNode* QualifiedIdentifier( Node* qualifier, IdentifierNode* identifier ) {
QualifiedIdentifierNode* node = new QualifiedIdentifierNode(qualifier,identifier,identifier->pos());
roots->push_back(node);
return node;
}
static LiteralNullNode* LiteralNull() {
LiteralNullNode* node = new LiteralNullNode();
roots->push_back(node);
return node;
}
static LiteralBooleanNode* LiteralBoolean(bool value) {
LiteralBooleanNode* node = new LiteralBooleanNode(value);
roots->push_back(node);
return node;
}
static LiteralArrayNode* LiteralArray( Node* elementlist ) {
LiteralArrayNode* node = new LiteralArrayNode(elementlist);
roots->push_back(node);
return node;
}
static LiteralFieldNode* LiteralField( Node* name, Node* value ) {
LiteralFieldNode* node = new LiteralFieldNode(name,value);
roots->push_back(node);
return node;
}
static LiteralNumberNode* LiteralNumber( std::string value ) {
LiteralNumberNode* node = new LiteralNumberNode(value);
roots->push_back(node);
return node;
}
static LiteralObjectNode* LiteralObject( Node* fieldlist ) {
LiteralObjectNode* node = new LiteralObjectNode(fieldlist);
roots->push_back(node);
return node;
}
static LiteralRegExpNode* LiteralRegExp( std::string value ) {
LiteralRegExpNode* node = new LiteralRegExpNode(value);
roots->push_back(node);
return node;
}
static LiteralStringNode* LiteralString( std::string value ) {
LiteralStringNode* node = new LiteralStringNode(value);
roots->push_back(node);
return node;
}
#if 0
static LiteralTypeNode* LiteralType( Type* type ) {
LiteralTypeNode* node = new LiteralTypeNode(type);
roots->push_back(node);
return node;
}
#endif
static LiteralUndefinedNode* LiteralUndefined() {
LiteralUndefinedNode* node = new LiteralUndefinedNode();
roots->push_back(node);
return node;
}
static ParenthesizedExpressionNode* ParenthesizedExpression( Node* expr ) {
ParenthesizedExpressionNode* node = new ParenthesizedExpressionNode(expr,0/*in->positionOfMark()*/);
roots->push_back(node);
return node;
}
static ParenthesizedListExpressionNode* ParenthesizedListExpression( Node* expr ) {
ParenthesizedListExpressionNode* node = new ParenthesizedListExpressionNode(expr);
roots->push_back(node);
return node;
}
static FunctionExpressionNode* FunctionExpression( Node* name, Node* signature, Node* body ) {
FunctionExpressionNode* node = new FunctionExpressionNode(name,signature,body);
roots->push_back(node);
return node;
}
static AnnotatedDefinitionNode* AnnotatedDefinition( Node* attributes, Node* definition ) {
AnnotatedDefinitionNode* node = new AnnotatedDefinitionNode(attributes,definition);
roots->push_back(node);
return node;
}
static AttributeListNode* AttributeList( Node* item, Node* list ) {
AttributeListNode* node = new AttributeListNode(item,list);
roots->push_back(node);
return node;
}
static UnitExpressionNode* UnitExpression( Node* value, Node* type ) {
UnitExpressionNode* node = new UnitExpressionNode(value,type);
roots->push_back(node);
return node;
}
static ThisExpressionNode* ThisExpression() {
ThisExpressionNode* node = new ThisExpressionNode();
roots->push_back(node);
return node;
}
static SuperExpressionNode* SuperExpression() {
SuperExpressionNode* node = new SuperExpressionNode();
roots->push_back(node);
return node;
}
static ListNode* List( ListNode* list, Node* item ) {
ListNode* node = new ListNode(list,item,item->pos());
roots->push_back(node);
return node;
}
static PostfixExpressionNode* PostfixExpression( int op, Node* expr ) {
PostfixExpressionNode* node = new PostfixExpressionNode(op,expr);
roots->push_back(node);
return node;
}
static NewExpressionNode* NewExpression( Node* member ) {
NewExpressionNode* node = new NewExpressionNode(member);
roots->push_back(node);
return node;
}
static ClassofExpressionNode* ClassofExpression( Node* base ) {
ClassofExpressionNode* node = new ClassofExpressionNode(base);
roots->push_back(node);
return node;
}
static CallExpressionNode* CallExpression( MemberExpressionNode* member, ListNode* args ) {
CallExpressionNode* node = new CallExpressionNode(member,args);
roots->push_back(node);
return node;
}
static GetExpressionNode* GetExpression( MemberExpressionNode* member ) {
GetExpressionNode* node = new GetExpressionNode(member);
roots->push_back(node);
return node;
}
static SetExpressionNode* SetExpression( Node* member, Node* args ) {
SetExpressionNode* node = new SetExpressionNode(member,args);
roots->push_back(node);
return node;
}
static IndexedMemberExpressionNode* IndexedMemberExpression( Node* base, Node* member ) {
IndexedMemberExpressionNode* node = new IndexedMemberExpressionNode(base,member,0/*in->positionOfMark()*/);
roots->push_back(node);
return node;
}
static MemberExpressionNode* MemberExpression( Node* base, Node* name ) {
MemberExpressionNode* node = new MemberExpressionNode(base,name,0/*in->positionOfMark()*/);
roots->push_back(node);
return node;
}
static CoersionExpressionNode* CoersionExpression( Node* expr, Node* type ) {
CoersionExpressionNode* node = new CoersionExpressionNode(expr,type,0/*in->positionOfMark()*/);
roots->push_back(node);
return node;
}
static UnaryExpressionNode* UnaryExpression( int op, Node* expr ) {
UnaryExpressionNode* node = new UnaryExpressionNode(op,expr);
roots->push_back(node);
return node;
}
static BinaryExpressionNode* BinaryExpression( int op, Node* lhs, Node* rhs ) {
BinaryExpressionNode* node = new BinaryExpressionNode(op,lhs,rhs);
roots->push_back(node);
return node;
}
static ConditionalExpressionNode* ConditionalExpression( Node* cond, Node* thenexpr, Node* elseexpr ) {
ConditionalExpressionNode* node = new ConditionalExpressionNode(cond,thenexpr,elseexpr);
roots->push_back(node);
return node;
}
static AssignmentExpressionNode* AssignmentExpression( Node* lhs, int op, Node* rhs ) {
AssignmentExpressionNode* node = new AssignmentExpressionNode(lhs,op,rhs);
roots->push_back(node);
return node;
}
static StatementListNode* StatementList( StatementListNode* list, Node* item ) {
StatementListNode* node = new StatementListNode(list,item);
roots->push_back(node);
return node;
}
static EmptyStatementNode* EmptyStatement() {
EmptyStatementNode* node = new EmptyStatementNode();
roots->push_back(node);
return node;
}
static ExpressionStatementNode* ExpressionStatement( Node* expr ) {
ExpressionStatementNode* node = new ExpressionStatementNode(expr);
roots->push_back(node);
return node;
}
static AnnotatedBlockNode* AnnotatedBlock( Node* attributes, Node* definition ) {
AnnotatedBlockNode* node = new AnnotatedBlockNode(attributes,definition);
roots->push_back(node);
return node;
}
static LabeledStatementNode* LabeledStatement( Node* label, Node* statement ) {
LabeledStatementNode* node = new LabeledStatementNode(label,statement);
roots->push_back(node);
return node;
}
static IfStatementNode* IfStatement( Node* test, Node* tblock, Node* eblock ) {
IfStatementNode* node = new IfStatementNode(test,tblock,eblock);
roots->push_back(node);
return node;
}
static SwitchStatementNode* SwitchStatement( Node* expr, StatementListNode* statements ) {
SwitchStatementNode* node = new SwitchStatementNode(expr,statements);
roots->push_back(node);
return node;
}
static CaseLabelNode* CaseLabel( Node* label ) {
CaseLabelNode* node = new CaseLabelNode(label);
roots->push_back(node);
return node;
}
static DoStatementNode* DoStatement( Node* block, Node* expr ) {
DoStatementNode* node = new DoStatementNode(block,expr);
roots->push_back(node);
return node;
}
static WhileStatementNode* WhileStatement( Node* expr, Node* statement ) {
WhileStatementNode* node = new WhileStatementNode(expr,statement);
roots->push_back(node);
return node;
}
static ForInStatementNode* ForInStatement( Node* expr1, Node* expr2, Node* statement ) {
ForInStatementNode* node = new ForInStatementNode(expr1,expr2,statement);
roots->push_back(node);
return node;
}
static ForStatementNode* ForStatement( Node* expr1, Node* expr2, Node* expr3, Node* statement ) {
ForStatementNode* node = new ForStatementNode(expr1,expr2,expr3,statement);
roots->push_back(node);
return node;
}
static WithStatementNode* WithStatement( Node* expr, Node* statement ) {
WithStatementNode* node = new WithStatementNode(expr,statement);
roots->push_back(node);
return node;
}
static ContinueStatementNode* ContinueStatement(Node* expr) {
ContinueStatementNode* node = new ContinueStatementNode(expr);
roots->push_back(node);
return node;
}
static BreakStatementNode* BreakStatement(Node* expr) {
BreakStatementNode* node = new BreakStatementNode(expr);
roots->push_back(node);
return node;
}
static ReturnStatementNode* ReturnStatement( Node* expr ) {
ReturnStatementNode* node = new ReturnStatementNode(expr);
roots->push_back(node);
return node;
}
static ThrowStatementNode* ThrowStatement(Node* list) {
ThrowStatementNode* node = new ThrowStatementNode(list);
roots->push_back(node);
return node;
}
static TryStatementNode* TryStatement(Node* tryblock, StatementListNode* catchlist, Node* finallyblock) {
TryStatementNode* node = new TryStatementNode(tryblock,catchlist,finallyblock);
roots->push_back(node);
return node;
}
static CatchClauseNode* CatchClause(Node* parameter, Node* block) {
CatchClauseNode* node = new CatchClauseNode(parameter,block);
roots->push_back(node);
return node;
}
static FinallyClauseNode* FinallyClause( Node* block ) {
FinallyClauseNode* node = new FinallyClauseNode(block);
roots->push_back(node);
return node;
}
static IncludeStatementNode* IncludeStatement( Node* list ) {
IncludeStatementNode* node = new IncludeStatementNode(list);
roots->push_back(node);
return node;
}
static UseStatementNode* UseStatement( Node* expr ) {
UseStatementNode* node = new UseStatementNode(expr);
roots->push_back(node);
return node;
}
static ImportDefinitionNode* ImportDefinition( Node* item, Node* list ) {
ImportDefinitionNode* node = new ImportDefinitionNode(item,list);
roots->push_back(node);
return node;
}
static ImportBindingNode* ImportBinding( Node* identifer, Node* item ) {
ImportBindingNode* node = new ImportBindingNode(identifer,item);
roots->push_back(node);
return node;
}
static ExportDefinitionNode* ExportDefinition( Node* list ) {
ExportDefinitionNode* node = new ExportDefinitionNode(list);
roots->push_back(node);
return node;
}
static ExportBindingNode* ExportBinding( Node* name, Node* value ) {
ExportBindingNode* node = new ExportBindingNode(name,value);
roots->push_back(node);
return node;
}
static VariableDefinitionNode* VariableDefinition( int kind, Node* list ) {
VariableDefinitionNode* node = new VariableDefinitionNode(kind,list,list->pos());
roots->push_back(node);
return node;
}
static VariableBindingNode* VariableBinding( Node* identifier, Node* initializer ) {
VariableBindingNode* node = new VariableBindingNode(identifier,initializer);
roots->push_back(node);
return node;
}
static TypedVariableNode* TypedVariable( Node* identifier, Node* type ) {
TypedVariableNode* node = new TypedVariableNode(identifier,type,type!=NULL?type->pos():identifier->pos());
roots->push_back(node);
return node;
}
static FunctionDefinitionNode* FunctionDefinition( Node* decl, Node* body ) {
FunctionDefinitionNode* node = new FunctionDefinitionNode(decl,body);
roots->push_back(node);
return node;
}
static FunctionDeclarationNode* FunctionDeclaration( Node* name, Node* signature ) {
FunctionDeclarationNode* node = new FunctionDeclarationNode(name,signature);
roots->push_back(node);
return node;
}
static FunctionNameNode* FunctionName( int kind, Node* name ) {
FunctionNameNode* node = new FunctionNameNode(kind,name);
roots->push_back(node);
return node;
}
static RestParameterNode* RestParameter( Node* expr ) {
RestParameterNode* node = new RestParameterNode(expr);
roots->push_back(node);
return node;
}
static ParameterNode* Parameter( Node* identifer, Node* type ) {
ParameterNode* node = new ParameterNode(identifer,type);
roots->push_back(node);
return node;
}
static OptionalParameterNode* OptionalParameter( Node* identifer, Node* init ) {
OptionalParameterNode* node = new OptionalParameterNode(identifer,init);
roots->push_back(node);
return node;
}
static NamedParameterNode* NamedParameter( Node* name, Node* parameter ) {
NamedParameterNode* node = new NamedParameterNode(name,parameter);
roots->push_back(node);
return node;
}
static ClassDeclarationNode* ClassDeclaration( Node* name ) {
ClassDeclarationNode* node = new ClassDeclarationNode(name);
roots->push_back(node);
return node;
}
static ClassDefinitionNode* ClassDefinition( Node* name, Node* interfaces, Node* statements ) {
ClassDefinitionNode* node = new ClassDefinitionNode(name,interfaces,statements);
roots->push_back(node);
return node;
}
static InheritanceNode* Inheritance( Node* baseclass, Node* interfaces ) {
InheritanceNode* node = new InheritanceNode(baseclass,interfaces);
roots->push_back(node);
return node;
}
static NamespaceDefinitionNode* NamespaceDefinition( Node* identifier, Node* list ) {
NamespaceDefinitionNode* node = new NamespaceDefinitionNode(identifier,list);
roots->push_back(node);
return node;
}
static LanguageDeclarationNode* LanguageDeclaration( Node* list ) {
LanguageDeclarationNode* node = new LanguageDeclarationNode(list);
roots->push_back(node);
return node;
}
static PackageDefinitionNode* PackageDefinition( Node* name, Node* block ) {
PackageDefinitionNode* node = new PackageDefinitionNode(name,block);
roots->push_back(node);
return node;
}
static ProgramNode* Program( Node* statements ) {
ProgramNode* node = new ProgramNode(statements);
roots->push_back(node);
return node;
}
};
}
}
#endif // NodeFactory_h
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,426 +0,0 @@
/*
* The value class from which all other values derive.
*/
#pragma warning ( disable : 4786 )
#include <string>
#include <map>
#include <algorithm>
#include "Context.h"
#include "Value.h"
#include "Type.h"
#include "Slot.h"
#include "ObjectValue.h"
#include "ReferenceValue.h"
#include "TypeValue.h"
namespace esc {
namespace v1 {
ObjectValue* ObjectValue::undefinedValue;
ObjectValue* ObjectValue::nullValue;
ObjectValue* ObjectValue::trueValue;
ObjectValue* ObjectValue::falseValue;
ObjectValue* ObjectValue::publicNamespace;
ObjectValue* ObjectValue::objectPrototype;
Slot default_slot;
void ObjectValue::init() {
ObjectValue::undefinedValue = new ObjectValue();
ObjectValue::nullValue = new ObjectValue();
ObjectValue::trueValue = new ObjectValue();
ObjectValue::falseValue = new ObjectValue();
ObjectValue::publicNamespace = new ObjectValue(TypeValue::namespaceType);
ObjectValue::objectPrototype = new ObjectValue();
}
void ObjectValue::fini() {
}
ObjectValue::ObjectValue()
: names(*new std::map<std::string,Qualifiers>()),
slots(*new std::vector<Slot>(3,default_slot)),
dyna_slots(*new std::vector<Slot>),
frozen_flag(false),
first_index(0) {
initInstance(0,0);
}
ObjectValue::ObjectValue(Builder& builder)
: names(*new std::map<std::string,Qualifiers>()),
slots(*new std::vector<Slot>(3,default_slot)),
dyna_slots(*new std::vector<Slot>),
frozen_flag(false),
first_index(0) {
initInstance(0,TypeValue::objectType);
Context cx;
builder.build(cx,this);
}
ObjectValue::ObjectValue(bool value)
: names(*new std::map<std::string,Qualifiers>()),
slots(*new std::vector<Slot>(3,default_slot)),
dyna_slots(*new std::vector<Slot>),
frozen_flag(false),
first_index(0) {
initInstance(TypeValue::booleanType->prototype,TypeValue::booleanType);
Context& cx = *new Context();
Slot* slot = getSlot(cx,first_index+SLOT_VALUE);
slot->intValue = value;
slot->type = TypeValue::booleanType;
slot->attrs = 0;
}
// Construct an object with a given prototype object.
ObjectValue::ObjectValue(ObjectValue* protoObject)
: names(*new std::map<std::string,Qualifiers>()),
slots(*new std::vector<Slot>(3,default_slot)),
dyna_slots(*new std::vector<Slot>),
frozen_flag(false),
first_index(protoObject->getLastSlotIndex()) {
initInstance(protoObject,TypeValue::objectType);
}
// Construct an object with a class defined.
ObjectValue::ObjectValue(TypeValue* classObject)
: names(*new std::map<std::string,Qualifiers>()),
slots(*new std::vector<Slot>(3,default_slot)),
dyna_slots(*new std::vector<Slot>),
frozen_flag(false),
first_index(classObject->prototype->getLastSlotIndex()) {
initInstance(classObject->prototype,classObject);
}
void ObjectValue::initInstance(ObjectValue* protoObject,TypeValue* classObject) {
Context& cx = *new Context();
Slot* slot;
slot = getSlot(cx,first_index+SLOT_PROTO);
slot->value = protoObject;
slot->type = TypeValue::objectType;
slot->attrs = 0;
slot = getSlot(cx,first_index+SLOT_CLASS);
slot->value = classObject;
slot->type = TypeValue::typeType;
slot->attrs = 0;
// Call the class object's builder method to initialize
// this instance.
if( classObject ) {
classObject->build(cx,this);
}
}
/*
* Scope methods
*/
/*
* Look for a property name in the object.
*/
bool ObjectValue::hasName(Context& cx, std::string name, Value* qualifier) {
Names::iterator nameit = names.find(name);
if( nameit == names.end() ) {
return (bool)0;
}
Qualifiers& qual = (*nameit).second;
return qual.find(qualifier) != qual.end();
}
Namespaces* ObjectValue::hasNames(Context& cx, std::string name, Namespaces* namespaces) {
Namespaces* hasNamespaces = new Namespaces();
Names::iterator nameit = names.find(name);
if( nameit == names.end() ) {
return (Namespaces*)0;
}
Qualifiers* quals = &(*nameit).second;
// For each member of namespaces, see if there
// is a matching qualifier.
for(int i = 0; i < namespaces->size(); i++ ) {
Value* qual = namespaces->at(i);
if( quals->find(qual) != quals->end() ) {
hasNamespaces->push_back(qual);
}
}
return hasNamespaces;
}
/*
* Get the slot for a property.
*
* WARNING:
* Before calling this method you must call hasName to ensure that
* the requested property exists.
*/
Slot* ObjectValue::get(Context& cx, std::string name, Value* qualifier) {
std::map<Value*,int>& prop = names[name];
int index = prop[qualifier];
return getSlot(cx,index);
}
/*
* Set the value of a property.
*/
int ObjectValue::define(Context& cx, std::string name, Value* qualifier, int index) {
// Get the property for name
std::map<std::string,Qualifiers>::iterator nameit = names.find(name);
// If there is one, then get the qualifier map for that name.
// Otherwise, create a qualifier map and a new property.
if( nameit == names.end() ) {
Qualifiers qualifiers;
names[name] = qualifiers;
}
// Add the qualifier to the qualifiers map, and set its value to index.
std::map<Value*,int>& prop = names[name];
prop[qualifier] = index;
return index;
}
/*
* Add a slot to this object. This object's fixed slots
* (that is, all slots added before freezeSlots is called)
* begin where the [[Prototype]] indexes end.
*
* If [[Prototype]] object has not been frozen or this
* object has been frozen, then addSlot allocates the
* slot in the dynamic slot space.
*/
int ObjectValue::addSlot(Context& cx) {
Slot slot;
int index;
if( proto(cx) && proto(cx)->isFixed() && !this->isFixed() ) {
index = first_index + slots.size();
slots.push_back(slot);
} else if( !this->isFixed() ) {
index = slots.size();
slots.push_back(slot);
} else {
index = -dyna_slots.size();
dyna_slots.push_back(slot);
}
return index;
}
/*
* Get the slot for an index. If it is a fixed slot
* it will have a positive value. dynamic slots have
* negative values.
*/
Slot* ObjectValue::getSlot(Context& cx, int index) {
Slot* slot;
if( ((unsigned)index) < first_index ) {
slot = proto(cx)->getSlot(cx,index);
} else if (index < 0) {
slot = &dyna_slots[-index];
} else {
slot = &slots[index-first_index];
}
return slot;
}
/*
* Get the slot index of a named property.
*
* Before calling this method you must call hasName to ensure that
* the requested property exists.
*/
int ObjectValue::getSlotIndex(Context& cx, std::string name, Value* qualifier) {
std::map<Value*,int>& prop = names[name];
int size = prop.size();
int index = prop[qualifier];
return index;
}
bool ObjectValue::isFixed() {
return frozen_flag;
}
int ObjectValue::getFirstSlotIndex() {
return first_index;
}
int ObjectValue::getLastSlotIndex() {
frozen_flag = true;
return first_index+slots.size()-1;
}
ObjectValue* ObjectValue::proto(Context& cx) {
return this->getSlot(cx,first_index+SLOT_PROTO)->objValue;
}
TypeValue* ObjectValue::getType(Context& cx) {
return reinterpret_cast<TypeValue*>(this->getSlot(cx,first_index+SLOT_CLASS)->objValue);
}
/*
* Test driver
*/
int ObjectValue::main(int argc, char* argv[]) {
Context& cx = *new Context();
ObjectValue ob;
ObjectValue q1,q2,q3;
int i1,i2,i3;
i1 = ob.addSlot(cx); // add a slot
i1 = ob.define(cx,"a",&q1,i1); // define a property
i2 = ob.addSlot(cx);
i2 = ob.define(cx,"a",&q2,i2);
i3 = ob.addSlot(cx);
i3 = ob.define(cx,"a",&q3,i2);
//ObjectValue v1,v2,v3;
ob.get(cx,"a",&q1)->intValue = 10;
ob.get(cx,"a",&q2)->intValue = 20;
int v3 = ob.get(cx,"a",&q3)->intValue;
Slot* s1 = ob.getSlot(cx,i1);
Slot* s2 = ob.getSlot(cx,i2);
Slot* s3 = ob.getSlot(cx,i3);
ObjectValue b((bool)1);
delete &cx;
testClass(argc,argv);
return 0;
}
// Test the case:
// class B { static var xg = 1; var xp = 2; }
// var b = new B;
// b.xi = 3;
// b.class.xg;
// b.xp;
// b.xi;
int ObjectValue::testClass(int argc, char* argv[]) {
Context cx;;
// Allocate the parts
ObjectValue global;
ObjectValue default_ns;
// Wire them together
int slot_index;
Slot* slot;
// Init the proto object
ObjectValue b_proto;
slot_index = b_proto.addSlot(cx); // add a slot
slot_index = b_proto.define(cx,"xp",&default_ns,slot_index); // define a property
slot = b_proto.getSlot(cx,slot_index);
slot->intValue = 10;
// Init the class object
TypeValue b_class;
slot_index = b_class.addSlot(cx); // add a slot
slot_index = b_class.define(cx,"xg",&default_ns,slot_index); // define a property
slot = b_class.getSlot(cx,slot_index);
slot->intValue = 30;
// Init the instance object
ObjectValue b_instance(b_proto);
int first_index = b_instance.getFirstSlotIndex();
slot = b_instance.getSlot(cx,first_index+SLOT_PROTO);
slot->value = &b_proto;
slot->type = TypeValue::objectType;
slot->attrs = 0;
slot_index = b_instance.define(cx,"class",&default_ns,first_index+SLOT_CLASS); // define a property
slot = b_instance.getSlot(cx,first_index+SLOT_CLASS);
slot->value = &b_class;
slot->type = TypeValue::typeType;
slot->attrs = 0;
slot_index = b_instance.addSlot(cx); // add a slot
slot_index = b_instance.define(cx,"xi",&default_ns,slot_index); // define a property
slot = b_instance.getSlot(cx,slot_index);
slot->intValue = 20;
slot_index = global.addSlot(cx); // add a slot
slot_index = global.define(cx,"b",&default_ns,slot_index); // define a property
slot = global.getSlot(cx,slot_index);
slot->objValue = &b_instance;
// Make and evaluate some references
// b.xp
ReferenceValue r1(&b_instance,"xp",&default_ns);
Slot* sp;
sp = r1.getSlot(cx);
int sp_index = r1.getSlotIndex();
sp = b_instance.getSlot(cx,sp_index);
// b.xi
ReferenceValue r2(&b_instance,"xi",&default_ns);
Slot* si = r2.getSlot(cx);
// b.class.xg
ReferenceValue r3(&b_instance,"class",&default_ns);
ObjectValue& vB = *((ObjectValue*)r3.getValue(cx));
ReferenceValue r4(&vB,"xg",&default_ns);
Slot* sg = r4.getSlot(cx);
return 0;
}
}
}
/*
* Written by Jeff Dyer
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,163 +0,0 @@
/*
* This class is the building block for all ECMA values. Object values
* are a sequence of instances linked through the [[Prototype]] slot.
* Classes are a sequence of instances of the sub-class TypeValue, also
* linked through the [[Prototype]] slot. Lookup of class and instance
* properties uses the same algorithm to find a name. Names are bound
* to slots. Slots contain values that are methods for accessing or
* computing program values (i.e running code.)
*
* An object consists of a table of names, and a vector of slots. The
* slots hold methods for accessing and computing values. An object
* also has a private data accessible to the methods and accessors of
* the object.
*
* All symbolic references to the properties of an object are bound
* to the method of a slot. Constant references to fixed, final prop-
* erties can be compiled to direct access of the data value. This
* is the case with access to private, final or global variables.
*
* The instance and class hierarchies built at compile-time can be
* compressed into a single instance prototype and class object for
* faster lookup and dispatch.
*/
#ifndef ObjectValue_h
#define ObjectValue_h
#pragma warning( disable : 4786 )
#include <map>
#include <vector>
#include <string>
#include "Value.h"
#include "Type.h"
#include "Slot.h"
namespace esc {
namespace v1 {
class Context;
class TypeValue;
class Builder;
enum {
SLOT_PROTO = 0,
SLOT_CLASS,
SLOT_VALUE,
};
typedef std::map<Value*,int> Qualifiers;
typedef std::map<std::string,Qualifiers> Names;
typedef std::vector<Slot> Slots;
typedef std::vector<Value*> Namespaces;
class ObjectValue : public Value {
private:
Names names; // Names table
Slots slots; // Slots table
Slots dyna_slots; // Slots table
bool frozen_flag;
int first_index;
public:
static ObjectValue* undefinedValue;
static ObjectValue* nullValue;
static ObjectValue* trueValue;
static ObjectValue* falseValue;
static ObjectValue* publicNamespace;
static ObjectValue* objectPrototype;
ObjectValue();
ObjectValue(ObjectValue* protoObject);
ObjectValue(TypeValue* classObject);
ObjectValue(Builder& builder);
ObjectValue(bool value);
void ObjectValue::initInstance(ObjectValue* protoObject,TypeValue* classObject);
virtual ~ObjectValue() {
//names.clear();
//slots.clear();
//dyna_slots.clear();
}
/* Initialize and finalize the class.
*/
static void init();
static void fini();
/* Define a property and associate it with slot_index
*/
int define(Context& cx, std::string name, Value* qualifier, int slot_index);
/* Get the slot index of a property name
*/
int getSlotIndex(Context& cx, std::string name, Value* qualifier);
/* Get the slot of a property name
*/
Slot* get(Context& cx, std::string name, Value* qualifier);
/* Check for a property
*/
bool hasName(Context& cx, std::string name, Value* qualifier);
/* Check for names that consist of an id and one of multiple
* namespaces. Return a vector of namespaces that match. This
* method is used for lookup of unqualified names.
*/
Namespaces* hasNames(Context& cx, std::string name, Namespaces* namespaces);
/* Add a slot to this object.
*/
int addSlot(Context& cx);
/* Get a slot for a slot index
*/
Slot* getSlot(Context& cx, int index);
/* Check if the object is fixed yet.
*/
bool isFixed();
/* Get the start index for slots in this object. The indicies of
* all the objects in a prototype chain are contiguous.
*/
int getFirstSlotIndex();
/* Get the last slot index allocated for this part of the
* instance. Calling this method has the side-effect of
* freezing the slot table. Thereafter, new slots are
* allocated in the dynamic slots table.
*/
int getLastSlotIndex();
/* Get the [[Prototype]] object
*/
ObjectValue* proto(Context& cx);
/* Get the [[Type]] object
*/
virtual TypeValue* getType(Context& context);
// main
static int main(int argc, char* argv[]);
static int testClass(int argc, char* argv[]);
};
}
}
#endif // ObjectValue_h
/*
* Written by Jeff Dyer
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,38 +0,0 @@
#ifndef Slot_h
#define Slot_h
/*
* A slot.
*/
namespace esc {
namespace v1 {
class Value;
class ObjectValue;
struct Slot {
int attrs;
TypeValue* type;
union {
Value* value;
ObjectValue* objValue; // (ReferenceValue, ListValue, ObjectValue)
int intValue;
char* strValue;
};
Slot() : attrs(0), type(0), value(0) {
}
//Block block;
//Store store;
};
}
}
#endif // Slot_h
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,35 +0,0 @@
#ifndef Type_h
#define Type_h
/**
* The interface for all types.
*/
#include <vector>
namespace esc {
namespace v1 {
class Value;
class Context;
class Type {
// virtual std::vector<Value*> values() = 0;
// virtual std::vector<Value*> converts() = 0;
// virtual void addSub(Type& type) = 0;
virtual bool includes(Context& cx, Value* value) = 0;
// virtual void setSuper(Type& type) = 0;
// virtual Type* getSuper() = 0;
// virtual Value* convert(Context& cx, Value& value) = 0;
// virtual Value* coerce(Context& cx, Value& value) = 0;
};
}
}
#endif // Type_h
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,18 +0,0 @@
/*
* The value class from which all other values derive.
*/
#include "Value.h"
#include "Type.h"
namespace esc {
namespace v1 {
}
}
/*
* Written by Jeff Dyer
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,30 +0,0 @@
#ifndef Value_h
#define Value_h
/*
* The value class from which all other values derive. Immediate
* children are ObjectValue, ReferenceValue, ListValue, and
* CompletionValue.
*/
namespace esc {
namespace v1 {
class Context;
class TypeValue;
class Value {
public:
virtual Value* getValue(Context& context) { return this; }
virtual TypeValue* getType(Context& context) { return (TypeValue*)0; }
};
}
}
#endif // Value_h
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,116 +0,0 @@
/*
* Global object builder
*/
#pragma warning ( disable : 4786 )
#include <string>
#include <map>
#include <algorithm>
#include "Context.h"
#include "Value.h"
#include "Type.h"
#include "Slot.h"
#include "Builder.h"
#include "GlobalObjectBuilder.h"
#include "TypeValue.h"
namespace esc {
namespace v1 {
void GlobalObjectBuilder::build(Context& cx, ObjectValue* ob) {
Slot* slot;
int slot_index;
// Never type
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"Never",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->objValue = new TypeValue();
// Null type
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"Null",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->objValue = new TypeValue();
// Boolean type
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"Boolean",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->objValue = new TypeValue();
// Number type
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"Number",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->objValue = new TypeValue();
// String type
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"String",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->objValue = new TypeValue();
// Function type
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"Function",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->objValue = new TypeValue();
// Array type
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"Boolean",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->objValue = new TypeValue();
// Type type
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"Array",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->objValue = new TypeValue();
// Unit type
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"Unit",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->objValue = new TypeValue();
// public namespace
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"public",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->value = ObjectValue::publicNamespace;
// print - (built-in) function
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"print",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->value = new ObjectValue(); // function: print
// version - (built-in) field
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"get version",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->intValue = 7; //value_count; // function: get version
slot_index = ob->addSlot(cx);
slot_index = ob->define(cx,"set version",ObjectValue::publicNamespace,slot_index);
slot = ob->getSlot(cx,slot_index);
slot->intValue = 7; //value_count++; // function: set version
}
}
}
/*
* Written by Jeff Dyer
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,35 +0,0 @@
#ifndef GlobalObjectConstructor_h
#define GlobalObjectConstructor_h
/*
* Constructs global objects
*/
#include <string>
#include <vector>
#include "Builder.h"
#include "ObjectValue.h"
namespace esc {
namespace v1 {
class GlobalObjectBuilder : public Builder {
public:
GlobalObjectBuilder() {
}
virtual void build(Context& cx, ObjectValue* ob);
};
}
}
#endif // GlobalObjectConstructor_h
/*
* Written by Jeff Dyer
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved
*/

View File

@@ -1,515 +0,0 @@
#pragma warning ( disable : 4786 )
#include "Nodes.h"
#include "ConstantEvaluator.h"
#include "NodeFactory.h"
#include "ReferenceValue.h"
#include "TypeValue.h"
#include "GlobalObjectBuilder.h"
namespace esc {
namespace v1 {
// Base node
Value* ConstantEvaluator::evaluate( Context& cx, Node* node ) {
throw;
}
/*
* Unqualified identifier
*
* STATUS
*
* NOTES
* An unqualified name can bind to a local variable, instance
* property, or global property. A local will result in a
* aload_n instruction. A instance property will result in a
* get_property method call. A global property will result in a
* get_property method call on the global object.
*/
Value* ConstantEvaluator::evaluate( Context& cx, IdentifierNode* node ) {
return new ReferenceValue((ObjectValue*)0,node->name,used_namespaces);
}
/*
* QualifiedIdentifierNode
*
* {qualifiers:QualifierListNode name:String}
*
* Semantics:
* 1. Evaluate qualifier.
* 2. Call GetValue(Result(1).
* 3. If Result(2) is not a namespace, then throw a TypeError.
* 4. Create a new Reference(null,Result2),name).
* 5. Return Result(4).
*/
Value* ConstantEvaluator::evaluate( Context& cx, QualifiedIdentifierNode* node ) {
Value* qualifier;
if( node->qualifier != (Node*)0 ) {
qualifier = node->qualifier->evaluate(cx,this);
qualifier = qualifier->getValue(cx);
}
if( qualifier == (Value*)0 ) {
//error();
throw;
}
else
if(!(TypeValue::namespaceType->includes(cx,qualifier)) ) {
//error();
throw;
}
return new ReferenceValue((ObjectValue*)0,node->name,qualifier);
}
/*
* CallExpression
*
* Semantics
* ---------
* 1 Evaluate MemberExpression.
* 2 Evaluate Arguments, producing an internal list of argument
* values (section 11.2.4).
* 3 Call GetValue(Result(1)).
* 4 If Type(Result(3)) is not Object, throw a TypeError exception.
* 5 If Result(3) does not implement the internal [[Call]] method,
* throw a TypeError exception.
* 6 If Type(Result(1)) is Reference, Result(6) is GetBase(Result(1)).
* Otherwise, Result(6) is null.
* 7 If Result(6) is an activation object, Result(7) is null.
* Otherwise, Result(7) is the same as Result(6).
* 8 Call the [[Call]] method on Result(3), providing Result(7)
* as the this value and providing the list Result(2) as the
* argument values.
* 9 Return Result(8).
*
*/
Value* ConstantEvaluator::evaluate( Context& cx, CallExpressionNode* node ) {
Value* val = node->member->evaluate(cx,this);
ReferenceValue* ref = dynamic_cast<ReferenceValue*>(val); // Forces the use of RTTI.
if( node->args ) {
node->args->evaluate(cx,this);
}
// Do typechecking. It is quite possible that this function has not
// yet been defined. In this case, all of the semantic actions must
// be performed at runtime.
if( ref->lookup(cx) ) {
/* If the function was found: The slot index is in
* ref->slot_index and the base object is presumed
* to be the top value on the operand stack (if base
* is set), otherwise it is the nth (ref->scope_index)
* object from the bottom of the scope stack. (0 is
* global.)
*
* Nothing to do here.
*/
}
node->ref = ref;
return ObjectValue::undefinedValue;
}
Value* ConstantEvaluator::evaluate( Context& cx, GetExpressionNode* node ) {
Value* val = node->member->evaluate(cx,this);
ReferenceValue* ref = dynamic_cast<ReferenceValue*>(val); // Forces the use of RTTI.
ref->name.insert(0,"get "); // Tweak the name to make it a getter reference.
// Do typechecking. It is quite possible that this function has not
// yet been defined. In this case, all of the semantic actions must
// be performed at runtime.
if( ref->lookup(cx) ) {
/* If the function was found: The slot index is in
* ref->slot_index and the base object is presumed
* to be the top value on the operand stack (if base
* is set), otherwise it is the nth (ref->scope_index)
* object from the bottom of the scope stack. (0 is
* global.)
*
* Nothing to do here.
*/
}
return node->ref = ref;
}
Value* ConstantEvaluator::evaluate( Context& cx, SetExpressionNode* node ) {
return 0;
}
Value* ConstantEvaluator::evaluate( Context& cx, ThisExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, LiteralBooleanNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, LiteralNumberNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, LiteralStringNode* node ) {
return ObjectValue::undefinedValue;
}
Value* ConstantEvaluator::evaluate( Context& cx, LiteralUndefinedNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, LiteralRegExpNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, UnitExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, FunctionExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ParenthesizedExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ParenthesizedListExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, LiteralObjectNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, LiteralFieldNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, LiteralArrayNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, PostfixExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, NewExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, IndexedMemberExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ClassofExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, MemberExpressionNode* node ) {
/* If the member expression has a base, evaluate it and try to
* bind it to its slot. If there it binds, then get the slot
* type and then the prototype of that type. The prototype will
* be the compile-time stand-in for the instance.
*/
ObjectValue* prototype = 0;
if( node->base ) {
Value* val = node->base->evaluate(cx,this);
ReferenceValue* ref = dynamic_cast<ReferenceValue*>(val); // Forces the use of RTTI.
Slot* slot = ref->getSlot(cx);
TypeValue* type = slot->type;
prototype = type->prototype;
}
ReferenceValue* ref = dynamic_cast<ReferenceValue*>(node->expr->evaluate(cx,this));
ref->setBase(prototype);
return ref;
}
Value* ConstantEvaluator::evaluate( Context& cx, CoersionExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, UnaryExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, BinaryExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ConditionalExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, AssignmentExpressionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ListNode* node ) {
if( node->list ) {
node->list->evaluate(cx,this);
}
if( node->item ) {
node->item->evaluate(cx,this);
}
return ObjectValue::undefinedValue;
}
// Statements
Value* ConstantEvaluator::evaluate( Context& cx, StatementListNode* node ) {
if( node->list ) {
node->list->evaluate(cx,this);
}
if( node->item ) {
node->item->evaluate(cx,this);
}
return ObjectValue::undefinedValue;
}
Value* ConstantEvaluator::evaluate( Context& cx, EmptyStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ExpressionStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, AnnotatedBlockNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, LabeledStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, IfStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, SwitchStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, CaseLabelNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, DoStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, WhileStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ForInStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ForStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, WithStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ContinueStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, BreakStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ReturnStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ThrowStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, TryStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, CatchClauseNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, FinallyClauseNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, UseStatementNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, IncludeStatementNode* node ) {
throw;
}
// Definitions
Value* ConstantEvaluator::evaluate( Context& cx, ImportDefinitionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ImportBindingNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, AnnotatedDefinitionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, AttributeListNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ExportDefinitionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ExportBindingNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, VariableDefinitionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, VariableBindingNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, TypedVariableNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, FunctionDefinitionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, FunctionDeclarationNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, FunctionNameNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, FunctionSignatureNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ParameterNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, OptionalParameterNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ClassDefinitionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ClassDeclarationNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, InheritanceNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, NamespaceDefinitionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, PackageDefinitionNode* node ) {
throw;
}
Value* ConstantEvaluator::evaluate( Context& cx, ProgramNode* node ) {
if( node->statements != (ProgramNode*)0 ) {
node->statements->evaluate(cx,this);
}
return (Value*)0;
}
/*
* Test driver
*/
int ConstantEvaluator::main(int argc, char* argv[]) {
Context cx;
Evaluator* evaluator = new ConstantEvaluator();
Builder* globalObjectBuilder = new GlobalObjectBuilder();
ObjectValue* globalPrototype = new ObjectValue(*globalObjectBuilder);
ObjectValue global = ObjectValue(globalPrototype);
cx.pushScope(&global); // first scope is always considered the global scope.
cx.used_namespaces.push_back(ObjectValue::publicNamespace);
Node* node;
Value* val;
// public::print
node = NodeFactory::QualifiedIdentifier(
NodeFactory::Identifier("public"),
NodeFactory::Identifier("print"));
val = node->evaluate(cx,evaluator);
val = val->getValue(cx);
// get version
node = NodeFactory::GetExpression(
NodeFactory::MemberExpression(0,
NodeFactory::Identifier("version")));
val = node->evaluate(cx,evaluator);
val = val->getValue(cx);
// print('hello')
node = NodeFactory::CallExpression(NodeFactory::MemberExpression(0,NodeFactory::Identifier("print")),0);
val = node->evaluate(cx,evaluator);
val = val->getValue(cx);
return 0;
}
}
}
/*
* Written by Jeff Dyer
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,125 +0,0 @@
/*
* ConstantEvaluator
*/
#ifndef ConstantEvaluator_h
#define ConstantEvaluator_h
#include <vector>
#include "Value.h"
#include "Context.h"
#include "Evaluator.h"
#include "ObjectValue.h"
//#include "ByteCodeFactory.h"
//#include "ClassFileConstants.h"
namespace esc {
namespace v1 {
class ConstantEvaluator : public Evaluator {
std::vector<Value*>* used_namespaces;
public:
/*
* Test driver
*/
static int main(int argc, char* argv[]);
// Base node
Value* evaluate( Context& cx, Node* node );
// 3rd Edition features
Value* evaluate( Context& cx, IdentifierNode* node );
Value* evaluate( Context& cx, ThisExpressionNode* node );
Value* evaluate( Context& cx, LiteralBooleanNode* node );
Value* evaluate( Context& cx, LiteralNumberNode* node );
Value* evaluate( Context& cx, LiteralStringNode* node );
Value* evaluate( Context& cx, LiteralUndefinedNode* node );
Value* evaluate( Context& cx, LiteralRegExpNode* node );
Value* evaluate( Context& cx, FunctionExpressionNode* node );
Value* evaluate( Context& cx, ParenthesizedExpressionNode* node );
Value* evaluate( Context& cx, ParenthesizedListExpressionNode* node );
Value* evaluate( Context& cx, LiteralObjectNode* node );
Value* evaluate( Context& cx, LiteralFieldNode* node );
Value* evaluate( Context& cx, LiteralArrayNode* node );
Value* evaluate( Context& cx, PostfixExpressionNode* node );
Value* evaluate( Context& cx, NewExpressionNode* node );
Value* evaluate( Context& cx, IndexedMemberExpressionNode* node );
Value* evaluate( Context& cx, MemberExpressionNode* node );
Value* evaluate( Context& cx, CallExpressionNode* node );
Value* evaluate( Context& cx, GetExpressionNode* node );
Value* evaluate( Context& cx, SetExpressionNode* node );
Value* evaluate( Context& cx, UnaryExpressionNode* node );
Value* evaluate( Context& cx, BinaryExpressionNode* node );
Value* evaluate( Context& cx, ConditionalExpressionNode* node );
Value* evaluate( Context& cx, AssignmentExpressionNode* node );
Value* evaluate( Context& cx, ListNode* node );
Value* evaluate( Context& cx, StatementListNode* node );
Value* evaluate( Context& cx, EmptyStatementNode* node );
Value* evaluate( Context& cx, ExpressionStatementNode* node );
Value* evaluate( Context& cx, AnnotatedBlockNode* node );
Value* evaluate( Context& cx, LabeledStatementNode* node );
Value* evaluate( Context& cx, IfStatementNode* node );
Value* evaluate( Context& cx, SwitchStatementNode* node );
Value* evaluate( Context& cx, CaseLabelNode* node );
Value* evaluate( Context& cx, DoStatementNode* node );
Value* evaluate( Context& cx, WhileStatementNode* node );
Value* evaluate( Context& cx, ForInStatementNode* node );
Value* evaluate( Context& cx, ForStatementNode* node );
Value* evaluate( Context& cx, WithStatementNode* node );
Value* evaluate( Context& cx, ContinueStatementNode* node );
Value* evaluate( Context& cx, BreakStatementNode* node );
Value* evaluate( Context& cx, ReturnStatementNode* node );
Value* evaluate( Context& cx, ThrowStatementNode* node );
Value* evaluate( Context& cx, TryStatementNode* node );
Value* evaluate( Context& cx, CatchClauseNode* node );
Value* evaluate( Context& cx, FinallyClauseNode* node );
Value* evaluate( Context& cx, AnnotatedDefinitionNode* node );
Value* evaluate( Context& cx, VariableDefinitionNode* node );
Value* evaluate( Context& cx, VariableBindingNode* node );
Value* evaluate( Context& cx, FunctionDefinitionNode* node );
Value* evaluate( Context& cx, FunctionDeclarationNode* node );
Value* evaluate( Context& cx, FunctionNameNode* node );
Value* evaluate( Context& cx, FunctionSignatureNode* node );
Value* evaluate( Context& cx, ParameterNode* node );
Value* evaluate( Context& cx, ProgramNode* node );
// 4th Edition features
Value* evaluate( Context& cx, QualifiedIdentifierNode* node );
Value* evaluate( Context& cx, UnitExpressionNode* node );
Value* evaluate( Context& cx, ClassofExpressionNode* node );
Value* evaluate( Context& cx, CoersionExpressionNode* node );
Value* evaluate( Context& cx, UseStatementNode* node );
Value* evaluate( Context& cx, IncludeStatementNode* node );
Value* evaluate( Context& cx, ImportDefinitionNode* node );
Value* evaluate( Context& cx, ImportBindingNode* node );
Value* evaluate( Context& cx, AttributeListNode* node );
Value* evaluate( Context& cx, ExportDefinitionNode* node );
Value* evaluate( Context& cx, ExportBindingNode* node );
Value* evaluate( Context& cx, TypedVariableNode* node );
Value* evaluate( Context& cx, OptionalParameterNode* node );
Value* evaluate( Context& cx, ClassDefinitionNode* node );
Value* evaluate( Context& cx, ClassDeclarationNode* node );
Value* evaluate( Context& cx, InheritanceNode* node );
Value* evaluate( Context& cx, NamespaceDefinitionNode* node );
Value* evaluate( Context& cx, PackageDefinitionNode* node );
};
}
}
#endif // ConstantEvaluator_h
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,215 +0,0 @@
/*
* ReferenceValue
*/
#pragma warning ( disable : 4786 )
#include <stack>
#include "ReferenceValue.h"
#include "TypeValue.h"
#include "ObjectValue.h"
#include "Context.h"
namespace esc {
namespace v1 {
ReferenceValue::ReferenceValue(ObjectValue* base, std::string name,
Value* qualifier)
: base(base), name(name), qualifier(qualifier),
used_namespaces((std::vector<Value*>*)0), slot((Slot*)0),
slot_index(0),scope_index(0) {
}
ReferenceValue::ReferenceValue(ObjectValue* base, std::string name,
std::vector<Value*>* used_namespaces)
: base(base), name(name), qualifier((Value*)0),
used_namespaces(used_namespaces), slot((Slot*)0),
slot_index(0),scope_index(0) {
}
Value* ReferenceValue::getValue(Context& cx) {
Slot* s = this->getSlot(cx);
if( s ) {
return s->value;
} else {
return (Value*)0;
}
}
Slot* ReferenceValue::getSlot(Context& cx) {
if( slot ) {
return slot;
}
if( lookup(cx) ) {
// lookup has the side-effect of binding
// this reference to its defining slot. So
// now just return it.
return this->slot;
} else {
return (Slot*)0;
}
}
/*
* Lookup qualified name in the given context.
*/
bool ReferenceValue::lookup(Context& cx) {
ObjectValue* obj;
if(!base) {
// If there is no base reference, search for the
// binding from the inside to the outside of the
// scope chain. Fix up this reference's base member
// and recurse.
std::stack<ObjectValue*> scopes = cx.getScopes();
int scope_index = 0;
while( scopes.size() ) {
this->base = scopes.top(); // Set the base value
if( this->lookup(cx) ) {
// Found one. Clear the temporary base value
// and set the scope index.
this->base = 0;
this->scope_index = scope_index;
break;
}
scopes.pop();
++scope_index;
}
} else {
// If there is a base reference, search for the
// binding in this object and then up the proto
// chain.
if(!qualifier) {
return this->lookupUnqualified(cx);
}
obj = base;
while(obj && !obj->hasName(cx,name,qualifier)) {
obj = obj->proto(cx);
}
if( !obj ) {
return false;
}
// Bind slot
this->slot_index = obj->getSlotIndex(cx,name,qualifier);
this->slot = obj->getSlot(cx,this->slot_index);
}
return true;
}
/*
* Lookup a name that has one of the used namespaces.
*
* 1 Traverse to root of proto chain, pushing all objects
* onto a temporary stack.
* 2 In lifo order, see if one or more of the qualified
* names represented by the name and the used qualfiers
* is in the top object on the stack. Repeat for all
* objects on the stack until one object with at least
* one match is found, or all objects have been searched.
* 3 Create a new set of namespaces that inclues all
* the qualifiers of all the names that matched in the
* previous step.
* 4 Starting with the most derived object, search to
* proto chain for one or more of the qualified names
* represented by the name and the new set of used
* qualifiers.
* 5 If the found set represents more than one slot, throw
* and error exception. Otherwise, return true.
* 6 If no matching names are found, return false.
*/
bool ReferenceValue::lookupUnqualified(Context& cx) {
// Search this object and up the inheritance chain
// to find the qualified name.
ObjectValue* obj = base;
// Push the protos onto a stack.
std::stack<ObjectValue*> protos;
while(obj) {
protos.push(obj);
obj = obj->proto(cx);
}
// Search the protos top-down for matching names.
Namespaces* namespaces = 0;
while(!protos.empty()) {
ObjectValue* obj = protos.top();
namespaces = obj->hasNames(cx,name,&cx.used_namespaces);
if( namespaces ) {
break;
}
protos.pop();
}
// If no namespaces, then no matches. Return false.
if( !namespaces ) {
return false;
}
// Search for the first object in the proto chain that
// matches the name and namespaces.
obj = base?base:cx.scope();
while(obj && !(obj->hasNames(cx,name,namespaces))) {
obj = obj->proto(cx);
}
if( !obj ) {
return false;
}
// Verify that all matched names point to a single slot.
int last_index = 0;
for( int i = 0; i < namespaces->size(); i++ ) {
Value* qualifier = namespaces->at(i);
int index = obj->getSlotIndex(cx,name,qualifier);
if( last_index!=0 && index!=last_index ) {
throw;
// error();
}
last_index = index;
}
// Bind slot
this->slot_index = last_index;
this->slot = obj->getSlot(cx,this->slot_index);
return true;
}
}
}
/*
* Written by Jeff Dyer
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,58 +0,0 @@
/*
* ReferenceValue
*/
#ifndef ReferenceValue_h
#define ReferenceValue_h
#pragma warning( disable : 4786 )
#include <string>
#include <vector>
#include "Value.h"
namespace esc {
namespace v1 {
struct Slot;
class ObjectValue;
class Context;
class ReferenceValue : public Value {
ObjectValue* base;
Value* qualifier;
std::vector<Value*>* used_namespaces;
Slot* slot;
int slot_index;
int scope_index;
public:
std::string name;
ReferenceValue(ObjectValue* base, std::string name, Value* qualifier);
ReferenceValue(ObjectValue* base, std::string name, std::vector<Value*>* used_namespaces);
bool lookup(Context& cx);
bool lookupUnqualified(Context& cx);
Slot* getSlot(Context& cx);
Value* getValue(Context& cx);
int getSlotIndex() { return slot_index; }
int getScopeIndex() { return scope_index; }
ReferenceValue* setBase(ObjectValue* base) { this->base = base; return this; }
// main
static int main(int argc, char* argv[]);
};
}
}
#endif // ReferenceValue_h
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,82 +0,0 @@
/*
* The value class from which all other values derive.
*/
#pragma warning ( disable : 4786 )
#include <string>
#include <map>
#include <algorithm>
#include "Context.h"
#include "Value.h"
#include "Type.h"
#include "Slot.h"
#include "Builder.h"
#include "TypeValue.h"
namespace esc {
namespace v1 {
bool TypeValue::isInitialized = false;
TypeValue* TypeValue::booleanType;
TypeValue* TypeValue::namespaceType;
TypeValue* TypeValue::objectType;
TypeValue* TypeValue::typeType;
void TypeValue::init() {
if( isInitialized ) {
return;
}
isInitialized = true;
booleanType = new TypeValue();
namespaceType = new TypeValue();
objectType = new TypeValue();
typeType = new TypeValue();
}
void TypeValue::fini() {
if( isInitialized ) {
delete typeType;
delete objectType;
delete namespaceType;
delete booleanType;
isInitialized = false;
}
}
bool TypeValue::includes(Context& cx, Value* value) {
TypeValue* type = value->getType(cx);
while( type ) {
if( type == this ) {
return true;
}
type = type->super(cx);
}
return false;
}
void TypeValue::build(Context& cx, ObjectValue* ob) {
}
TypeValue* TypeValue::super(Context& cx) {
return reinterpret_cast<TypeValue*>(this->proto(cx));
}
}
}
/*
* Written by Jeff Dyer
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

View File

@@ -1,58 +0,0 @@
#ifndef TypeValue_h
#define TypeValue_h
/**
* The interface for all types.
*/
#include <vector>
#include "Builder.h"
#include "ObjectValue.h"
namespace esc {
namespace v1 {
class TypeValue : public ObjectValue, public Type, public Builder {
static bool isInitialized;
public:
ObjectValue* prototype;
virtual bool includes(Context& cx, Value* value);
virtual void build(Context& cx, ObjectValue* ob);
TypeValue* super(Context& cx);
TypeValue() {
this->prototype = new ObjectValue();
}
static TypeValue* booleanType;
static TypeValue* namespaceType;
static TypeValue* objectType;
static TypeValue* typeType;
#if 0
virtual std::vector<Value*> values() {};
virtual std::vector<Value*> converts() {};
virtual void addSub(Type& type) {};
virtual void setSuper(Type& type) {};
virtual Type* getSuper(){};
virtual Value* convert(Context& cx, Value& value) {};
virtual Value* coerce(Context& cx, Value& value) {};
#endif
static void init();
static void fini();
};
}
}
#endif // TypeValue_h
/*
* Copyright (c) 1998-2001 by Mountain View Compiler Company
* All rights reserved.
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +0,0 @@
/*
* 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 Mountain View Compiler
* Company. Portions created by Mountain View Compiler Company are
* Copyright (C) 1998-2000 Mountain View Compiler Company. All
* Rights Reserved.
*
* Contributor(s):
* Jeff Dyer <jeff@compilercompany.com>
*/
package com.compilercompany.ecmascript;
import java.io.*;
/*
* Debugging tool.
*/
public final class Debugger {
public static PrintStream dbg = null;
private static boolean useSystemOut = false;
public static void setOutFile(String filename) {
try {
PrintStream out = new PrintStream( new FileOutputStream( filename ) );
System.setOut( out );
//System.setErr( outfile );
} catch ( Exception e ) {
e.printStackTrace();
}
}
public static void setErrFile(String filename) {
try {
PrintStream err = new PrintStream( new FileOutputStream( filename ) );
//System.setOut( out );
System.setErr( err );
} catch ( Exception e ) {
e.printStackTrace();
}
}
public static void setDbgFile(String filename) {
try {
if( dbg!=null) {
dbg.close();
}
dbg = new PrintStream( new FileOutputStream( filename ) );
//System.setOut( outfile );
//System.setErr( outfile );
} catch ( Exception e ) {
e.printStackTrace();
}
}
public static void trace( String str ) {
try {
if( useSystemOut )
System.out.println( str );
else {
if( dbg == null ) {
dbg = new PrintStream( new FileOutputStream( "debug.out" ) );
//System.setOut( outfile );
//System.setErr( outfile );
}
dbg.println( str );
}
}
catch( SecurityException e ) {
useSystemOut = true;
System.out.println( str );
}
catch( Exception e ) {
e.printStackTrace();
}
}
}
/*
* The end.
*/

View File

@@ -1,512 +0,0 @@
/*
* 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 Mountain View Compiler
* Company. Portions created by Mountain View Compiler Company are
* Copyright (C) 1998-2000 Mountain View Compiler Company. All
* Rights Reserved.
*
* Contributor(s):
* Jeff Dyer <jeff@compilercompany.com>
*/
/**
* Filters and buffers characters from a input reader.
*/
package com.compilercompany.es3c.v1;
import java.io.*;
public class InputBuffer implements CharacterClasses {
private static final boolean debug = false;
private static final boolean debug_nextchar = true;
private static final boolean debug_retract = false;
StringBuffer lineA = new StringBuffer();
StringBuffer lineB = new StringBuffer();
StringBuffer curr_line,prev_line;
int curr_line_offset,prev_line_offset;
int lineA_offset, lineB_offset;
private StringBuffer text;
private int[] line_breaks = new int[1000];
Reader in;
PrintStream err;
String origin;
int pos;
int colPos, lnNum=-1; // <0,0> is the position of the first character.
public static PrintStream out;
public static void setOut(String filename) throws Exception {
out = new PrintStream( new FileOutputStream(filename) );
}
public static void main(String[] args) {
test_retract();
test_markandcopy();
test_getLineText();
}
public InputBuffer( Reader in, PrintStream err, String origin ) {
this(in,err,origin,0);
}
public InputBuffer( Reader in, PrintStream err, String origin, int pos ) {
this.in = in;
this.err = err;
this.origin = origin;
this.pos = pos;
this.text = new StringBuffer();
}
/**
* read()
*
* Read the next character from the input reader and store it in a buffer
* of the full text.
*/
private int read() throws Exception {
int c = in.read();
text.append((char)c);
pos++;
return c;
}
/**
* text()
*/
public String source() {
return text.toString();
}
/**
* nextchar() --
*
* The basic function of nextchar() is to fetch the next character,
* in the input array, increment next and return the fetched character.
*
* To simplify the Scanner, this method also does the following:
* 1. normalizes certain special characters to a common character.
* 2. skips unicode format control characters (category Cf).
* 3. keeps track of line breaks, line position and line number.
* 4. treats <cr>+<lf> as a single line terminator.
* 5. returns 0 when the end of input is reached.
*/
public final int nextchar() throws Exception {
int c = -1;
// If the last character was at the end of a line,
// then swap buffers and fill the new one with characters
// from the input reader.
if( curr_line==null || colPos==curr_line.length() ) {
lnNum++;
colPos=0;
// If the current character is a newline, then read
// the next line of input into the other input buffer.
if( curr_line == lineA ) {
if( lineB == null ) {
lineB = new StringBuffer();
lineB_offset = pos;
}
curr_line = lineB; curr_line_offset = lineB_offset;
prev_line = lineA; prev_line_offset = lineA_offset;
lineA = null;
} else {
if( lineA == null ) {
lineA = new StringBuffer();
lineA_offset = pos;
}
curr_line = lineA; curr_line_offset = lineA_offset;
prev_line = lineB; prev_line_offset = lineB_offset;
lineB = null;
}
while(c != '\n' && c != 0) {
c = read();
if( false ) {
Debugger.trace( "c = " + c );
}
// Skip Unicode 3.0 format-control (general category Cf in
// Unicode Character Database) characters.
while(true) {
switch(c) {
case 0x070f: // SYRIAC ABBREVIATION MARK
case 0x180b: // MONGOLIAN FREE VARIATION SELECTOR ONE
case 0x180c: // MONGOLIAN FREE VARIATION SELECTOR TWO
case 0x180d: // MONGOLIAN FREE VARIATION SELECTOR THREE
case 0x180e: // MONGOLIAN VOWEL SEPARATOR
case 0x200c: // ZERO WIDTH NON-JOINER
case 0x200d: // ZERO WIDTH JOINER
case 0x200e: // LEFT-TO-RIGHT MARK
case 0x200f: // RIGHT-TO-LEFT MARK
case 0x202a: // LEFT-TO-RIGHT EMBEDDING
case 0x202b: // RIGHT-TO-LEFT EMBEDDING
case 0x202c: // POP DIRECTIONAL FORMATTING
case 0x202d: // LEFT-TO-RIGHT OVERRIDE
case 0x202e: // RIGHT-TO-LEFT OVERRIDE
case 0x206a: // INHIBIT SYMMETRIC SWAPPING
case 0x206b: // ACTIVATE SYMMETRIC SWAPPING
case 0x206c: // INHIBIT ARABIC FORM SHAPING
case 0x206d: // ACTIVATE ARABIC FORM SHAPING
case 0x206e: // NATIONAL DIGIT SHAPES
case 0x206f: // NOMINAL DIGIT SHAPES
case 0xfeff: // ZERO WIDTH NO-BREAK SPACE
case 0xfff9: // INTERLINEAR ANNOTATION ANCHOR
case 0xfffa: // INTERLINEAR ANNOTATION SEPARATOR
case 0xfffb: // INTERLINEAR ANNOTATION TERMINATOR
c = read();
continue; // skip it.
default:
break;
}
break; // out of while loop.
}
if( c == 0x000a && prev_line.length()!=0 && prev_line.charAt(prev_line.length()-1) == 0x000d ) {
// If this is one of those funny double line terminators,
// Then ignore the second character by reading on.
line_breaks[lnNum] = pos; // adjust if forward.
c = read();
}
// Line terminators.
if( c == 0x000a ||
c == 0x000d ||
c == 0x2028 ||
c == 0x2029 ) {
curr_line.append((char)c);
c = '\n';
line_breaks[lnNum+1] = pos;
// White space
} else if( c == 0x0009 ||
c == 0x000b ||
c == 0x000c ||
c == 0x0020 ||
c == 0x00a0 ||
false /* other cat Zs' */ ) {
c = ' ';
curr_line.append((char)c);
// End of line
} else if( c == -1 ) {
c = 0;
curr_line.append((char)c);
// All other characters.
} else {
// Use c as is.
curr_line.append((char)c);
}
}
}
// Get the next character.
int ln = lnNum;
int col = colPos;
if( curr_line.length() != 0 && curr_line.charAt(colPos) == 0 ) {
c = 0;
colPos++;
} else if( colPos == curr_line.length()-1 ) {
c = '\n';
colPos++;
} else {
c = curr_line.charAt(colPos++);
}
if( out != null ) {
out.println("Ln " + ln + ", Col " + col + ": nextchar " + Integer.toHexString(c) + " = " + (char)c + " @ " + positionOfNext());
}
if( debug || debug_nextchar ) {
Debugger.trace("Ln " + ln + ", Col " + col + ": nextchar " + Integer.toHexString(c) + " = " + (char)c + " @ " + positionOfNext());
}
return c;
}
/**
* test_nextchar() --
* Return an indication of how nextchar() performs
* in various situations, relative to expectations.
*/
boolean test_nextchar() {
return true;
}
/**
* time_nextchar() --
* Return the milliseconds taken to do various ordinary
* tasks with nextchar().
*/
int time_nextchar() {
return 0;
}
/**
* retract
*
* Backup one character position in the input. If at the beginning
* of the line, then swap buffers and point to the last character
* in the other buffer.
*/
public final void retract() throws Exception {
colPos--;
if( colPos<0 ) {
if( curr_line == prev_line ) {
// Can only retract over one line.
throw new Exception("Can only retract past one line at a time.");
} else if( curr_line == lineA ) {
curr_line = lineB = prev_line;
} else {
curr_line = lineA = prev_line;
}
lnNum--;
colPos = curr_line.length()-1;
curr_line_offset = prev_line_offset;
}
if( debug || debug_retract ) {
Debugger.trace("Ln " + lnNum + ", Col " + colPos + ": retract");
}
return;
}
static boolean test_retract() {
Debugger.trace("test_retract");
Reader reader = new StringReader("abc\ndef\nghi");
try {
InputBuffer inbuf = new InputBuffer(reader,System.err,"test");
int c=-1;
for(int i=0;i<9;i++) {
c = inbuf.nextchar();
}
for(int i=0;i<3;i++) {
inbuf.retract();
c = inbuf.nextchar();
inbuf.retract();
}
while(c!=0) {
c = inbuf.nextchar();
}
} catch (Exception x) {
x.printStackTrace();
System.out.println(x);
}
return true;
}
/**
* classOfNext
*/
public byte classOfNext() {
// return the Unicode character class of the current
// character, which is pointed to by 'next-1'.
return CharacterClasses.data[curr_line.charAt(colPos-1)];
}
/**
* positionOfNext
*/
public int positionOfNext() {
return curr_line_offset+colPos-1;
}
/**
* positionOfMark
*/
public int positionOfMark() {
return line_breaks[markLn]+markCol-1;
}
/**
* mark
*/
int markCol;
int markLn;
public int mark() {
markLn = (lnNum==-1)?0:lnNum; // In case nextchar hasn't been called yet.
markCol = colPos;
if( debug ) {
Debugger.trace("Ln " + markLn + ", Col " + markCol + ": mark");
}
return markCol;
}
/**
* copy
*/
public String copy() throws Exception {
StringBuffer buf = new StringBuffer();
if( debug ) {
Debugger.trace("Ln " + lnNum + ", Col " + colPos + ": copy " + buf);
}
if(markLn!=lnNum || markCol>colPos) {
throw new Exception("Internal error: InputBuffer.copy() markLn = " + markLn + ", lnNum = " + lnNum + ", markCol = " +
markCol + ", colPos = " + colPos );
}
for (int i = markCol-1; i < colPos; i++) {
buf.append(curr_line.charAt(i));
}
return buf.toString();
}
static boolean test_markandcopy() {
Debugger.trace("test_copy");
Reader reader = new StringReader("abc\ndef\nghijklmnopqrst\nuvwxyz");
String s;
try {
InputBuffer inbuf = new InputBuffer(reader,System.err,"test");
int c=-1;
int i;
for(i=0;i<10;i++) {
c = inbuf.nextchar();
}
inbuf.mark();
for(;i<13;i++) {
c = inbuf.nextchar();
}
s = inbuf.copy();
if(s.equals("ijk")) {
Debugger.trace("1: passed: " + s);
} else {
Debugger.trace("1: failed: " + s);
}
while(c!=0) {
c = inbuf.nextchar();
}
s = inbuf.copy();
} catch (Exception x) {
s = x.getMessage();
//x.printStackTrace();
}
if(s.equals("Internal error: InputBuffer.copy() markLn = 2, lnNum = 3, markCol = 2, colPos = 6")) {
Debugger.trace("2: passed: " + s);
} else {
Debugger.trace("2: failed: " + s);
}
return true;
}
public String getLineText(int pos) {
int i,len;
for(i = 0; line_breaks[i] <= pos && i <= lnNum; i++)
;
int offset = line_breaks[i-1];
for(len = offset ; (text.charAt(len)!=(char)-1 &&
text.charAt(len)!=0x0a &&
text.charAt(len)!=0x0d &&
text.charAt(len)!=0x2028 &&
text.charAt(len)!=0x2029) ; len++) {
}
return text.toString().substring(offset,len);
}
static boolean test_getLineText() {
Debugger.trace("test_getLineText");
Reader reader = new StringReader("abc\ndef\nghi");
try {
InputBuffer inbuf = new InputBuffer(reader,System.err,"test");
int c=-1;
for(int i=0;i<9;i++) {
c = inbuf.nextchar();
}
for(int i=0;i<3;i++) {
inbuf.retract();
c = inbuf.nextchar();
inbuf.retract();
}
while(c!=0) {
c = inbuf.nextchar();
}
for(int i=0;i<inbuf.text.length()-1;i++) {
Debugger.trace("text @ " + i + " " + inbuf.getLineText(i));
}
} catch (Exception x) {
x.printStackTrace();
System.out.println(x);
}
return true;
}
public int getColPos(int pos) {
//Debugger.trace("pos " + pos);
int i,len;
for(i = 0; line_breaks[i] <= pos && i <= lnNum; i++)
;
int offset = line_breaks[i-1];
//Debugger.trace("offset " + offset);
return pos-offset;
}
public int getLnNum(int pos) {
int i;
for(i = 0; line_breaks[i] <= pos && i <= lnNum; i++)
;
return i-1;
}
}
/*
* The end.
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,397 +0,0 @@
package com.compilercompany.es3c.v1;
/*
* The states of the scanner.
*/
interface States {
/**
**/
public static final int start_state = 0;
public static final int error_state = start_state-1;
public static final int minusminus_state = start_state+1;
public static final int minusequal_state = minusminus_state +1;
public static final int minus_state = minusequal_state +1;
public static final int notequal_state = minus_state +1;
public static final int not_state = notequal_state +1;
public static final int remainderequal_state = not_state +1;
public static final int remainder_state = remainderequal_state +1;
public static final int logicaland_state = remainder_state +1;
public static final int logicalandassign_state = logicaland_state +1;
public static final int andequal_state = logicalandassign_state +1;
public static final int and_state = andequal_state +1;
public static final int leftparen_state = and_state +1;
public static final int rightparen_state = leftparen_state +1;
public static final int starequal_state = rightparen_state +1;
public static final int star_state = starequal_state +1;
public static final int comma_state = star_state +1;
public static final int dot_state = comma_state +1;
public static final int doubledot_state = dot_state +1;
public static final int tripledot_state = doubledot_state +1;
public static final int slashequal_state = tripledot_state +1;
public static final int slash_state = slashequal_state +1;
public static final int colon_state = slash_state +1;
public static final int doublecolon_state = colon_state+1;
public static final int semicolon_state = doublecolon_state+1;
public static final int questionmark_state = semicolon_state +1;
public static final int leftbracket_state = questionmark_state +1;
public static final int rightbracket_state = leftbracket_state +1;
public static final int bitwisexorassign_state = rightbracket_state +1;
public static final int bitwisexor_state = bitwisexorassign_state+1;
public static final int logicalxor_state = bitwisexor_state+1;
public static final int logicalxorassign_state = logicalxor_state+1;
public static final int leftbrace_state = logicalxorassign_state+1;
public static final int logicalor_state = leftbrace_state+1;
public static final int logicalorassign_state = logicalor_state+1;
public static final int orequal_state = logicalorassign_state +1;
public static final int or_state = orequal_state +1;
public static final int rightbrace_state = or_state +1;
public static final int squiggle_state = rightbrace_state +1;
public static final int plusplus_state = squiggle_state +1;
public static final int plusequal_state = plusplus_state +1;
public static final int plus_state = plusequal_state +1;
public static final int leftshiftequal_state = plus_state +1;
public static final int leftshift_state = leftshiftequal_state +1;
public static final int lessthanorequal_state = leftshift_state +1;
public static final int lessthan_state = lessthanorequal_state +1;
public static final int equal_state = lessthan_state +1;
public static final int equalequal_state = equal_state +1;
public static final int greaterthanorequal_state = equalequal_state +1;
public static final int rightshiftequal_state = greaterthanorequal_state +1;
public static final int unsignedrightshift_state = rightshiftequal_state +1;
public static final int unsignedrightshiftequal_state = unsignedrightshift_state +1;
public static final int rightshift_state = unsignedrightshiftequal_state+1;
public static final int greaterthan_state = rightshift_state +1;
public static final int A_state = greaterthan_state +1;
public static final int N_state = A_state +1;
public static final int AA_state = N_state +1;
public static final int AN_state = AA_state +1;
public static final int singlequote_state = AN_state +1;
public static final int doublequote_state = singlequote_state +1;
public static final int zero_state = doublequote_state +1;
public static final int decimalinteger_state = zero_state +1;
public static final int decimal_state = decimalinteger_state +1;
public static final int exponent_state = decimal_state +1;
public static final int hexinteger_state = exponent_state +1;
public static final int octalinteger_state = hexinteger_state +1;
public static final int slashregexp_state = octalinteger_state +1;
public static final int slashdiv_state = slashregexp_state +1;
public static final int regexp_state = slashdiv_state +1;
public static final int regexpg_state = regexp_state +1;
public static final int regexpi_state = regexpg_state +1;
public static final int regexpm_state = regexpi_state +1;
public static final int regexpgi_state = regexpm_state +1;
public static final int regexpgm_state = regexpgi_state +1;
public static final int regexpim_state = regexpgm_state +1;
public static final int regexpgim_state = regexpim_state +1;
public static final int pound_state = regexpgim_state +1;
public static final int ampersand_state = pound_state +1;
public static final int arrow_state = ampersand_state +1;
public static final int a_state = arrow_state+1;
public static final int ab_state = a_state+1;
public static final int abs_state = ab_state+1;
public static final int abst_state = abs_state+1;
public static final int abstr_state = abst_state+1;
public static final int abstra_state = abstr_state+1;
public static final int abstrac_state = abstra_state+1;
public static final int abstract_state = abstrac_state+1;
public static final int at_state = abstract_state +1;
public static final int att_state = at_state+1;
public static final int attr_state = att_state+1;
public static final int attri_state = attr_state+1;
public static final int attrib_state = attri_state+1;
public static final int attribu_state = attrib_state+1;
public static final int attribut_state = attribu_state+1;
public static final int attribute_state = attribut_state+1;
public static final int b_state = attribute_state+1;
public static final int bo_state = b_state+1;
public static final int boo_state = bo_state+1;
public static final int bool_state = boo_state+1;
public static final int boole_state = bool_state+1;
public static final int boolea_state = boole_state+1;
public static final int boolean_state = boolea_state+1;
public static final int br_state = boolean_state+1;
public static final int bre_state = br_state+1;
public static final int brea_state = bre_state+1;
public static final int break_state = brea_state+1;
public static final int by_state = break_state+1;
public static final int byt_state = by_state+1;
public static final int byte_state = byt_state+1;
public static final int c_state = byte_state+1;
public static final int ca_state = c_state+1;
public static final int cas_state = ca_state+1;
public static final int case_state = cas_state+1;
public static final int cat_state = case_state+1;
public static final int catc_state = cat_state+1;
public static final int catch_state = catc_state+1;
public static final int ch_state = catch_state+1;
public static final int cha_state = ch_state+1;
public static final int char_state = cha_state+1;
public static final int cl_state = char_state+1;
public static final int cla_state = cl_state+1;
public static final int clas_state = cla_state+1;
public static final int class_state = clas_state+1;
public static final int co_state = class_state+1;
public static final int con_state = co_state+1;
public static final int cont_state = con_state+1;
public static final int conti_state = cont_state+1;
public static final int contin_state = conti_state+1;
public static final int continu_state = contin_state+1;
public static final int continue_state = continu_state+1;
public static final int cons_state = continue_state+1;
public static final int const_state = cons_state+1;
public static final int constr_state = const_state+1;
public static final int constru_state = constr_state+1;
public static final int construc_state = constru_state+1;
public static final int construct_state = construc_state+1;
public static final int constructo_state = construct_state+1;
public static final int constructor_state = constructo_state+1;
public static final int d_state = constructor_state+1;
public static final int de_state = d_state+1;
public static final int deb_state = de_state+1;
public static final int debu_state = deb_state+1;
public static final int debug_state = debu_state+1;
public static final int debugg_state = debug_state+1;
public static final int debugge_state = debugg_state+1;
public static final int debugger_state = debugge_state+1;
public static final int def_state = debugger_state+1;
public static final int defa_state = def_state+1;
public static final int defau_state = defa_state+1;
public static final int defaul_state = defau_state+1;
public static final int default_state = defaul_state+1;
public static final int del_state = default_state+1;
public static final int dele_state = del_state+1;
public static final int delet_state = dele_state+1;
public static final int delete_state = delet_state+1;
public static final int do_state = delete_state+1;
public static final int dou_state = do_state+1;
public static final int doub_state = dou_state+1;
public static final int doubl_state = doub_state+1;
public static final int double_state = doubl_state+1;
public static final int e_state = double_state+1;
public static final int el_state = e_state+1;
public static final int els_state = el_state+1;
public static final int else_state = els_state+1;
public static final int en_state = else_state+1;
public static final int enu_state = en_state+1;
public static final int enum_state = enu_state+1;
public static final int ev_state = enum_state+1;
public static final int eva_state = ev_state+1;
public static final int eval_state = eva_state+1;
public static final int ex_state = eval_state+1;
public static final int exp_state = ex_state+1;
public static final int expo_state = exp_state+1;
public static final int expor_state = expo_state+1;
public static final int export_state = expor_state+1;
public static final int ext_state = export_state+1;
public static final int exte_state = ext_state+1;
public static final int exten_state = exte_state+1;
public static final int extend_state = exten_state+1;
public static final int extends_state = extend_state+1;
public static final int f_state = extends_state+1;
public static final int fa_state = f_state+1;
public static final int fal_state = fa_state+1;
public static final int fals_state = fal_state+1;
public static final int false_state = fals_state+1;
public static final int fi_state = false_state+1;
public static final int fin_state = fi_state+1;
public static final int fina_state = fin_state+1;
public static final int final_state = fina_state+1;
public static final int finall_state = final_state+1;
public static final int finally_state = finall_state+1;
public static final int fl_state = finally_state+1;
public static final int flo_state = fl_state+1;
public static final int floa_state = flo_state+1;
public static final int float_state = floa_state+1;
public static final int fo_state = float_state+1;
public static final int for_state = fo_state+1;
public static final int fu_state = for_state+1;
public static final int fun_state = fu_state+1;
public static final int func_state = fun_state+1;
public static final int funct_state = func_state+1;
public static final int functi_state = funct_state+1;
public static final int functio_state = functi_state+1;
public static final int function_state = functio_state+1;
public static final int g_state = function_state+1;
public static final int go_state = g_state+1;
public static final int got_state = go_state+1;
public static final int goto_state = got_state+1;
public static final int i_state = goto_state+1;
public static final int if_state = i_state+1;
public static final int im_state = if_state+1;
public static final int imp_state = im_state+1;
public static final int impl_state = imp_state+1;
public static final int imple_state = impl_state+1;
public static final int implem_state = imple_state+1;
public static final int impleme_state = implem_state+1;
public static final int implemen_state = impleme_state+1;
public static final int implement_state = implemen_state+1;
public static final int implements_state = implement_state+1;
public static final int impo_state = implements_state+1;
public static final int impor_state = impo_state+1;
public static final int import_state = impor_state+1;
public static final int in_state = import_state+1;
public static final int inc_state = in_state+1;
public static final int incl_state = inc_state+1;
public static final int inclu_state = incl_state+1;
public static final int includ_state = inclu_state+1;
public static final int include_state = includ_state+1;
public static final int ins_state = include_state+1;
public static final int inst_state = ins_state+1;
public static final int insta_state = inst_state+1;
public static final int instan_state = insta_state+1;
public static final int instanc_state = instan_state+1;
public static final int instance_state = instanc_state+1;
public static final int instanceo_state = instance_state+1;
public static final int instanceof_state = instanceo_state+1;
public static final int int_state = instanceof_state+1;
public static final int inte_state = int_state+1;
public static final int inter_state = inte_state+1;
public static final int interf_state = inter_state+1;
public static final int interfa_state = interf_state+1;
public static final int interfac_state = interfa_state+1;
public static final int interface_state = interfac_state+1;
public static final int l_state = interface_state+1;
public static final int lo_state = l_state+1;
public static final int lon_state = lo_state+1;
public static final int long_state = lon_state+1;
public static final int n_state = long_state+1;
public static final int na_state = n_state+1;
public static final int nam_state = na_state+1;
public static final int name_state = nam_state+1;
public static final int names_state = name_state+1;
public static final int namesp_state = names_state+1;
public static final int namespa_state = namesp_state+1;
public static final int namespac_state = namespa_state+1;
public static final int namespace_state = namespac_state+1;
public static final int nat_state = namespace_state+1;
public static final int nati_state = nat_state+1;
public static final int nativ_state = nati_state+1;
public static final int native_state = nativ_state+1;
public static final int ne_state = native_state+1;
public static final int new_state = ne_state+1;
public static final int nu_state = new_state+1;
public static final int nul_state = nu_state+1;
public static final int null_state = nul_state+1;
public static final int r_state = null_state+1;
public static final int re_state = r_state+1;
public static final int ret_state = re_state+1;
public static final int retu_state = ret_state+1;
public static final int retur_state = retu_state+1;
public static final int return_state = retur_state +1;
public static final int p_state = return_state +1;
public static final int pa_state = p_state +1;
public static final int pac_state = pa_state +1;
public static final int pack_state = pac_state +1;
public static final int packa_state = pack_state +1;
public static final int packag_state = packa_state +1;
public static final int package_state = packag_state +1;
public static final int pr_state = package_state +1;
public static final int pri_state = pr_state +1;
public static final int priv_state = pri_state +1;
public static final int priva_state = priv_state +1;
public static final int privat_state = priva_state +1;
public static final int private_state = privat_state +1;
public static final int pro_state = private_state +1;
public static final int prot_state = pro_state +1;
public static final int prote_state = prot_state +1;
public static final int protec_state = prote_state +1;
public static final int protect_state = protec_state +1;
public static final int protecte_state = protect_state +1;
public static final int protected_state = protecte_state +1;
public static final int pu_state = protected_state +1;
public static final int pub_state = pu_state +1;
public static final int publ_state = pub_state +1;
public static final int publi_state = publ_state +1;
public static final int public_state = publi_state +1;
public static final int s_state = public_state +1;
public static final int sh_state = s_state +1;
public static final int sho_state = sh_state +1;
public static final int shor_state = sho_state +1;
public static final int short_state = shor_state +1;
public static final int st_state = short_state +1;
public static final int sta_state = st_state +1;
public static final int stat_state = sta_state +1;
public static final int stati_state = stat_state +1;
public static final int static_state = stati_state +1;
public static final int su_state = static_state +1;
public static final int sup_state = su_state +1;
public static final int supe_state = sup_state +1;
public static final int super_state = supe_state +1;
public static final int sw_state = super_state +1;
public static final int swi_state = sw_state +1;
public static final int swit_state = swi_state +1;
public static final int switc_state = swit_state +1;
public static final int switch_state = switc_state +1;
public static final int sy_state = switch_state +1;
public static final int syn_state = sy_state +1;
public static final int sync_state = syn_state +1;
public static final int synch_state = sync_state +1;
public static final int synchr_state = synch_state +1;
public static final int synchro_state = synchr_state +1;
public static final int synchron_state = synchro_state +1;
public static final int synchroni_state = synchron_state +1;
public static final int synchroniz_state = synchroni_state +1;
public static final int synchronize_state = synchroniz_state +1;
public static final int synchronized_state = synchronize_state +1;
public static final int t_state = synchronized_state+1;
public static final int th_state = t_state +1;
public static final int thi_state = th_state +1;
public static final int this_state = thi_state +1;
public static final int thr_state = this_state +1;
public static final int thro_state = thr_state +1;
public static final int throw_state = thro_state +1;
public static final int throws_state = throw_state +1;
public static final int tr_state = throws_state +1;
public static final int tra_state = tr_state +1;
public static final int tran_state = tra_state +1;
public static final int trans_state = tran_state +1;
public static final int transi_state = trans_state +1;
public static final int transie_state = transi_state +1;
public static final int transien_state = transie_state +1;
public static final int transient_state = transien_state +1;
public static final int tru_state = transient_state +1;
public static final int true_state = tru_state +1;
public static final int try_state = true_state +1;
public static final int ty_state = try_state +1;
public static final int typ_state = ty_state +1;
public static final int type_state = typ_state +1;
public static final int typeo_state = type_state +1;
public static final int typeof_state = typeo_state +1;
public static final int u_state = typeof_state +1;
public static final int us_state = u_state+1;
public static final int use_state = us_state+1;
public static final int v_state = use_state+1;
public static final int va_state = v_state +1;
public static final int var_state = va_state +1;
public static final int vo_state = var_state +1;
public static final int vol_state = vo_state +1;
public static final int vola_state = vol_state +1;
public static final int volat_state = vola_state +1;
public static final int volati_state = volat_state +1;
public static final int volatil_state = volati_state +1;
public static final int volatile_state = volatil_state +1;
public static final int voi_state = volatile_state +1;
public static final int void_state = voi_state +1;
public static final int w_state = void_state +1;
public static final int wh_state = w_state +1;
public static final int whi_state = wh_state +1;
public static final int whil_state = whi_state +1;
public static final int while_state = whil_state +1;
public static final int wi_state = while_state +1;
public static final int wit_state = wi_state +1;
public static final int with_state = wit_state +1;
public static final int blockcomment_state = with_state+1;
public static final int blockcommentstar_state = blockcomment_state+1;
public static final int linecomment_state = blockcommentstar_state+1;
public static final int eol_state = linecomment_state+1;
}
/*
* The end.
*/

View File

@@ -1,61 +0,0 @@
package com.compilercompany.es3c.v1;
/**
* Represents token instances: literals and identifiers.
*
* This file implements the class Token that is used to carry
* information from the Scanner to the Parser.
*/
import java.util.Vector;
public final class Token implements Tokens {
int tokenClass;
String lexeme;
public Token( int tokenClass, String lexeme ) {
this.tokenClass = tokenClass;
this.lexeme = lexeme;
}
public final int getTokenClass() {
return tokenClass;
}
public final String getTokenText() {
if( tokenClass == stringliteral_token ) {
// erase quotes.
return lexeme.substring(1,lexeme.length()-1);
}
return lexeme;
}
public final String getTokenSource() {
return lexeme;
}
public static String getTokenClassName( int token_class ) {
return tokenClassNames[-1*token_class];
}
/**
* main()
*
* Unit test driver. Execute the command 'java Token' at the
* shell to verify this class' basic functionality.
*/
public static void main(String[] args) {
System.out.println("Token begin");
for(int i = 0; i>=stringliteral_token;i--) {
System.out.println(tokenClassNames[-1*i]);
}
System.out.println("Token end");
}
}
/*
* The end.
*/

View File

@@ -1,303 +0,0 @@
package com.compilercompany.es3c.v1;
/*
* Defines token classes and their print names.
*
* This interface defines values for each token class that occurs in
* ECMAScript 4. All but numericliteral, stringliteral, regexpliteral, and
* identifier are singleton and therefore a fully described by their
* token class defined here. The other four however can have an infinite number
* of instances each with a unique identifier and associated instance
* data. We use positive identifiers to signify instances of these
* token classes so that the instance data can be stored in an array,
* or set of arrays with the token value specifying its index.
*/
public interface Tokens {
/**
* Token class values are negative, and token instances are positive so
* that their values can point to their instance data in an array.
*/
public static final int first_token = -1;
public static final int eos_token = first_token-0;
public static final int minus_token = first_token - 1;
public static final int minusminus_token = minus_token - 1;
public static final int not_token = minusminus_token - 1;
public static final int notequals_token = not_token - 1;
public static final int strictnotequals_token = notequals_token - 1;
public static final int pound_token = strictnotequals_token - 1;
public static final int modulus_token = pound_token - 1;
public static final int modulusassign_token = modulus_token - 1;
public static final int bitwiseand_token = modulusassign_token - 1;
public static final int logicaland_token = bitwiseand_token - 1;
public static final int logicalandassign_token = logicaland_token - 1;
public static final int bitwiseandassign_token = logicalandassign_token - 1;
public static final int leftparen_token = bitwiseandassign_token - 1;
public static final int rightparen_token = leftparen_token - 1;
public static final int mult_token = rightparen_token - 1;
public static final int multassign_token = mult_token - 1;
public static final int comma_token = multassign_token - 1;
public static final int dot_token = comma_token - 1;
public static final int doubledot_token = dot_token - 1;
public static final int tripledot_token = doubledot_token - 1;
public static final int div_token = tripledot_token - 1;
public static final int divassign_token = div_token - 1;
public static final int colon_token = divassign_token - 1;
public static final int doublecolon_token = colon_token - 1;
public static final int semicolon_token = doublecolon_token - 1;
public static final int questionmark_token = semicolon_token - 1;
public static final int ampersand_token = questionmark_token - 1;
public static final int leftbracket_token = ampersand_token - 1;
public static final int rightbracket_token = leftbracket_token - 1 ;
public static final int bitwisexor_token = rightbracket_token - 1;
public static final int logicalxor_token = bitwisexor_token - 1;
public static final int logicalxorassign_token = logicalxor_token - 1;
public static final int bitwisexorassign_token = logicalxorassign_token - 1;
public static final int leftbrace_token = bitwisexorassign_token - 1;
public static final int bitwiseor_token = leftbrace_token - 1;
public static final int logicalor_token = bitwiseor_token - 1;
public static final int logicalorassign_token = logicalor_token - 1;
public static final int bitwiseorassign_token = logicalorassign_token - 1;
public static final int rightbrace_token = bitwiseorassign_token - 1;
public static final int bitwisenot_token = rightbrace_token - 1;
public static final int plus_token = bitwisenot_token - 1;
public static final int plusplus_token = plus_token - 1;
public static final int plusassign_token = plusplus_token - 1;
public static final int lessthan_token = plusassign_token - 1;
public static final int leftshift_token = lessthan_token - 1;
public static final int leftshiftassign_token = leftshift_token - 1;
public static final int lessthanorequals_token = leftshiftassign_token - 1;
public static final int assign_token = lessthanorequals_token - 1;
public static final int minusassign_token = assign_token - 1;
public static final int equals_token = minusassign_token - 1;
public static final int strictequals_token = equals_token - 1;
public static final int greaterthan_token = strictequals_token - 1;
public static final int arrow_token = greaterthan_token - 1;
public static final int greaterthanorequals_token = arrow_token - 1;
public static final int rightshift_token = greaterthanorequals_token - 1;
public static final int rightshiftassign_token = rightshift_token - 1;
public static final int unsignedrightshift_token = rightshiftassign_token - 1;
public static final int unsignedrightshiftassign_token = unsignedrightshift_token - 1;
public static final int abstract_token = unsignedrightshiftassign_token - 1;
public static final int attribute_token = abstract_token - 1;
public static final int boolean_token = attribute_token - 1;
public static final int break_token = boolean_token - 1;
public static final int byte_token = break_token - 1;
public static final int case_token = byte_token - 1;
public static final int catch_token = case_token - 1;
public static final int char_token = catch_token - 1;
public static final int class_token = char_token - 1;
public static final int const_token = class_token - 1;
public static final int constructor_token = const_token - 1;
public static final int continue_token = constructor_token - 1;
public static final int debugger_token = continue_token - 1;
public static final int default_token = debugger_token - 1;
public static final int delete_token = default_token - 1;
public static final int do_token = delete_token - 1;
public static final int double_token = do_token - 1;
public static final int else_token = double_token - 1;
public static final int enum_token = else_token - 1;
public static final int eval_token = enum_token - 1;
public static final int export_token = eval_token - 1;
public static final int extends_token = export_token - 1;
public static final int false_token = extends_token - 1;
public static final int final_token = false_token - 1;
public static final int finally_token = final_token - 1;
public static final int float_token = finally_token - 1;
public static final int for_token = float_token - 1;
public static final int function_token = for_token - 1;
public static final int get_token = function_token - 1;
public static final int goto_token = get_token - 1;
public static final int if_token = goto_token - 1;
public static final int implements_token = if_token - 1;
public static final int import_token = implements_token - 1;
public static final int in_token = import_token - 1;
public static final int include_token = in_token - 1;
public static final int instanceof_token = include_token - 1;
public static final int int_token = instanceof_token - 1;
public static final int interface_token = int_token - 1;
public static final int long_token = interface_token - 1;
public static final int namespace_token = long_token - 1;
public static final int native_token = namespace_token - 1;
public static final int new_token = native_token - 1;
public static final int null_token = new_token - 1;
public static final int package_token = null_token - 1;
public static final int private_token = package_token - 1;
public static final int protected_token = private_token - 1;
public static final int public_token = protected_token - 1;
public static final int return_token = public_token - 1;
public static final int set_token = return_token - 1;
public static final int short_token = set_token - 1;
public static final int static_token = short_token - 1;
public static final int super_token = static_token - 1;
public static final int switch_token = super_token - 1;
public static final int synchronized_token = switch_token - 1;
public static final int this_token = synchronized_token - 1;
public static final int throw_token = this_token - 1;
public static final int throws_token = throw_token - 1;
public static final int transient_token = throws_token - 1;
public static final int true_token = transient_token - 1;
public static final int try_token = true_token - 1;
public static final int typeof_token = try_token - 1;
public static final int use_token = typeof_token - 1;
public static final int var_token = use_token - 1;
public static final int void_token = var_token - 1;
public static final int volatile_token = void_token - 1;
public static final int while_token = volatile_token - 1;
public static final int with_token = while_token - 1;
public static final int identifier_token = with_token - 1;
public static final int numberliteral_token = identifier_token - 1;
public static final int regexpliteral_token = numberliteral_token - 1;
public static final int stringliteral_token = regexpliteral_token - 1;
public static final int eol_token = stringliteral_token - 1;
public static final int empty_token = eol_token - 1;
public static final int error_token = empty_token - 1;
public static final int last_token = empty_token - 1;
public static final String[] tokenClassNames = {
"<unused index>",
"<eos>",
"minus_token",
"minusminus_token",
"not_token",
"notequals_token",
"strictnotequals_token",
"pound_token",
"modulus_token",
"modulusassign_token",
"bitwiseand_token",
"logicaland_token",
"logicalandassign_token",
"bitwiseandassign_token",
"leftparen_token",
"rightparen_token",
"mult_token",
"multassign_token",
"comma_token",
"dot_token",
"doubledot_token",
"tripledot_token",
"div_token",
"divassign_token",
"colon_token",
"doublecolon_token",
"semicolon_token",
"questionmark_token",
"ampersand_token",
"leftbracket_token",
"rightbracket_token",
"bitwisexor_token",
"logicalxor_token",
"logicalxorassign_token",
"bitwisexorassign_token",
"leftbrace_token",
"bitwiseor_token",
"logicalor_token",
"logicalorassign_token",
"bitwiseorassign_token",
"rightbrace_token",
"bitwisenot_token",
"plus_token",
"plusplus_token",
"plusassign_token",
"lessthan_token",
"leftshift_token",
"leftshiftassign_token",
"lessthanorequals_token",
"assign_token",
"minusassign_token",
"equals_token",
"strictequals_token",
"greaterthan_token",
"arrow_token",
"greaterthanorequals_token",
"rightshift_token",
"rightshiftassign_token",
"unsignedrightshift_token",
"unsignedrightshiftassign_token",
"abstract_token",
"attribute_token",
"boolean_token",
"break_token",
"byte_token",
"case_token",
"catch_token",
"char_token",
"class_token",
"const_token",
"constructor_token",
"continue_token",
"debugger_token",
"default_token",
"delete_token",
"do_token",
"double_token",
"else_token",
"enum_token",
"eval_token",
"export_token",
"extends_token",
"false_token",
"final_token",
"finally_token",
"float_token",
"for_token",
"function_token",
"get_token",
"goto_token",
"if_token",
"implements_token",
"import_token",
"in_token",
"include_token",
"instanceof_token",
"int_token",
"interface_token",
"long_token",
"namespace_token",
"native_token",
"new_token",
"null_token",
"package_token",
"private_token",
"protected_token",
"public_token",
"return_token",
"set_token",
"short_token",
"static_token",
"super_token",
"switch_token",
"synchronized_token",
"this_token",
"throw_token",
"throws_token",
"transient_token",
"true_token",
"try_token",
"typeof_token",
"use_token",
"var_token",
"void_token",
"volatile_token",
"while_token",
"with_token",
"identifier_token",
"numberliteral_token",
"regexpliteral_token",
"stringliteral_token",
"<eol>",
"<empty>",
"<error>"
};
}
/*
* The end.
*/

View File

@@ -1,194 +0,0 @@
/*
* 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 Mountain View Compiler
* Company. Portions created by Mountain View Compiler Company are
* Copyright (C) 1998-2000 Mountain View Compiler Company. All
* Rights Reserved.
*
* Contributor(s):
* Jeff Dyer <jeff@compilercompany.com>
*/
import com.compilercompany.ecmascript.*;
import java.io.*;
/*
* The main driver.
*/
public class Main {
String[] classes;
/**
* Entry point.
*/
public static void main(String[] args) {
new Main(args).run();
System.exit(0);
}
/**
* Parse options.
*/
private static boolean traceInput = false;
private static boolean traceLexer = false;
private static boolean traceParser = false;
private static boolean doASM = false;
private static boolean debug = false;
public Main(String[] args) {
if (args.length == 0) {
System.out.println("Wrong args, read the 'readme' and try again");
}
/* Default values for options, overridden by user options. */
int i = 0;
for (; i < args.length; i++) {
if (args[i].equals("-i")||args[i].equals("-input")) {
traceInput = true;
} else if (args[i].equals("-l")||args[i].equals("-lexer")) {
traceLexer = true;
} else if (args[i].equals("-p")||args[i].equals("-parser")) {
traceParser = true;
} else if (args[i].equals("-d")||args[i].equals("-debug")) {
debug = true;
} else if (args[i].equals("-a")||args[i].equals("-asm")) {
doASM = true;
} else if (args[i].charAt(0) == '-') {
System.out.println("Unknown.option "+ args[i]);
} else {
break; /* The rest must be classes. */
}
}
/*
* Grab the rest of argv[] ... this must be the classes.
*/
classes = new String[args.length - i];
System.arraycopy(args, i, classes, 0, args.length - i);
if (classes.length == 0) {
System.out.println("No script specified");
}
}
public void run() {
try {
compile("",classes);
} catch (Exception x) {
x.printStackTrace();
}
}
static final void compile(String name, String[] input) throws Exception {
Debugger.trace( "begin testEvaluator: " + name );
String result;
Node node;
Value type;
Evaluator evaluator;
Value value = UndefinedValue.undefinedValue;
Class pc = Parser.class;
Class[] args = new Class[0];
Parser parser;
long t=0;
ObjectValue global = null;
int errorCount=0;
for( int i = 0; i < input.length; i++ ) {
try {
if( traceInput ) {
InputBuffer.setOut(input[i]+".inp");
} if( traceLexer ) {
Scanner.setOut(input[i]+".lex");
} if( debug ) {
Debugger.setDbgFile( input[i]+".dbg" );
}
Debugger.setErrFile( input[i]+".err" );
FileInputStream srcfile = new FileInputStream( input[i] );
InputStreamReader reader = new InputStreamReader( srcfile );
Context context = new Context();
global = new ObjectValue("__systemGlobal", new GlobalObject());
context.pushScope(global);
parser = new Parser(reader);
Evaluator cevaluator = new ConstantEvaluator();
t = System.currentTimeMillis();
node = parser.parseProgram();
errorCount = parser.errorCount();
if( errorCount == 0 ) {
if( traceParser ) {
Debugger.trace("setting parser output to " + input[i]);
JSILGenerator.setOut( input[i]+".par" );
node.evaluate(context,new JSILGenerator(false));
}
//Evaluator evaluator;
context.setEvaluator(new BlockEvaluator());
node.evaluate(context, context.getEvaluator());
//JSILGenerator.setOut( input[i]+".blocks" );
//context.setEvaluator(new JSILGenerator(false));
//node.evaluate(context, context.getEvaluator());
context.setEvaluator(new ConstantEvaluator());
value = node.evaluate(context, context.getEvaluator());
context.setEvaluator(new JSILGenerator(doASM));
JSILGenerator.setOut( input[i]+".jsil" );
node.evaluate(context, context.getEvaluator());
errorCount = context.errorCount();
}
t = System.currentTimeMillis() - t;
//Debugger.trace(""+global);
System.out.println(input[i] + ": "+ errorCount +" errors [" + Long.toString(t) + " msec]");
} catch( Exception x ) {
x.printStackTrace();
t = System.currentTimeMillis() - t;
System.out.println(input[i] + ": internal error" );
}
//Debugger.trace( " " + i + " passed in " + Long.toString(t) +
// " msec: [" + input[i] + "] = " + result );
}
}
}
/*
* The end.
*/

View File

@@ -1,15 +0,0 @@
/*
* Not used.
*/
package com.compilercompany.es3c.v1;
interface Attributes {
static final int ReadOnly = 0x00000001;
static final int DontDelete = 0x00000002;
static final int DontEnum = 0x00000004;
}
/*
* The end.
*/

View File

@@ -1,31 +0,0 @@
package com.compilercompany.es3c.v1;
/**
* Represents a basic block for flow analysis.
*/
public class Block {
Node entry, exit;
int n;
Block(int n) {
this.n = n;
}
void setEntry( Node entry ) {
this.entry = entry;
}
void setExit( Node exit ) {
this.exit = exit;
}
public String toString() {
return "B"+n/*+"( " + entry + ", " + exit + " )"*/;
}
}
/*
* The end.
*/

View File

@@ -1,214 +0,0 @@
package com.compilercompany.es3c.v1;
import java.util.Stack;
import java.util.Vector;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* Context used during semantic analysis.
*/
public class Context {
private static final boolean debug = true;
Evaluator evaluator;
Stack scopeStack;
Stack classStack;
Scope global;
Hashtable predecessors = new Hashtable();
Hashtable D;
int indent = 0;
int errors = 0;
public int errorCount() {
return errors;
}
String getIndent() {
StringBuffer str = new StringBuffer();
for (int i = 0; i < indent; i++) {
str.append('\t');
}
return str.toString();
}
/**
*
*/
static InputBuffer in;
public static InputBuffer getInput() {
return in;
}
public static void init(InputBuffer input) {
in=input;
}
/**
*
*/
public Evaluator getEvaluator() {
return evaluator;
}
public void setEvaluator(Evaluator evaluator) {
this.evaluator=evaluator;
}
/**
* The bottom of the stack.
*/
Scope getGlobal() {
return global;
}
/**
* The top of the scope stack.
*/
Scope getLocal() {
return (Scope) scopeStack.peek();
}
/**
* Make the given scope the new innermost scope.
*/
public Scope pushScope(Scope scope) {
if( scopeStack==null ) {
scopeStack = new Stack();
global = scope;
}
scopeStack.push(scope);
return scope;
}
/**
* Pop the top scope off the stack.
*/
public void popScope() {
if( scopeStack==null ) {
return;
}
scopeStack.pop();
return;
}
/**
* Make the given scope the new innermost scope.
*/
void enterClass(Scope scope) {
pushScope(scope);
if( classStack==null ) {
classStack = new Stack();
}
classStack.push(scope);
return;
}
void exitClass() {
classStack.pop();
popScope();
return;
}
Scope getThisClass() {
if(classStack.size()==0) {
return global;
} else {
return (Scope) classStack.peek();
}
}
/**
* The immediate outer.
*/
Scope nextScope(Scope scope) {
Scope next;
int index = scopeStack.indexOf(scope);
if(index==0) {
next = null;
} else {
next = (Scope) scopeStack.elementAt(index-1);
}
return next;
}
private Block thisBlock;
Vector blocks = new Vector();
int blockCount;
void enterBlock(Node entry) throws Exception {
if( debug ) {
Debugger.trace("Context.enterBlock() with entry = " + entry );
//Thread.dumpStack();
//if(entry instanceof AnnotatedBlockNode) throw new Exception("blah");
}
if( thisBlock!=null ) {
throw new Exception("Entering block before exiting previous block.");
}
thisBlock = new Block(blockCount++);
thisBlock.setEntry(entry);
blocks.addElement(thisBlock);
}
Block getBlock() {
return thisBlock;
}
void setBlock(Block b) {
thisBlock=b;
}
void exitBlock(Node exit) {
if( debug ) {
Debugger.trace("Context.exitBlock() with exit = " + exit );
}
if(thisBlock!=null) {
thisBlock.setExit(exit);
thisBlock = null;
}
}
/**
* Get all basic blocks in the current program.
*/
public Vector getBlocks() {
return blocks;
}
/**
* Add an edge.
*/
void addEdge(Block b1, Block b2) {
if( debug ) {
Debugger.trace("Context.addEdge() with b1 = " + b1 + ", b2 = " + b2 );
}
Vector preds = (Vector) predecessors.get(b2);
if( preds == null ) {
preds = new Vector();
preds.addElement(b1);
predecessors.put(b2,preds);
} else if( !preds.contains(b1) ) {
preds.addElement(b1);
}
}
public String toString() { return "context( " + scopeStack + ", " + global + " )"; }
}
/*
* The end.
*/

View File

@@ -1,16 +0,0 @@
package com.compilercompany.es3c.v1;
/**
* Not used.
**/
public interface Errors {
static final String syntaxPart1_error = "Error at: ";
static final String syntaxPart2_error = " Expecting a ";
}
/*
* The end.
*/

View File

@@ -1,243 +0,0 @@
package com.compilercompany.es3c.v1;
/**
* The base visitor object extended by semantic evaluators.
*
* This is a visitor that is used by the compiler for various forms for
* evaluation of a parse tree (e.g. a type evaluator might compute the
* static type of an expression.)
*/
public class Evaluator {
Value evaluate( Context context, Node node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
// Expression evaluators
Value evaluate( Context context, ThisExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, IdentifierNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, QualifiedIdentifierNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, LiteralBooleanNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, LiteralNullNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, LiteralNumberNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, LiteralStringNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, LiteralUndefinedNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, LiteralRegExpNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, UnitExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, FunctionExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ParenthesizedExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ParenthesizedListExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, LiteralObjectNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, LiteralFieldNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, LiteralArrayNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, PostfixExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, NewExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, IndexedMemberExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ClassofExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, MemberExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, CoersionExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, CallExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, UnaryExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, BinaryExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ConditionalExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, AssignmentExpressionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ListNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
// Statements
Value evaluate( Context context, StatementListNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, EmptyStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ExpressionStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, AnnotatedBlockNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, LabeledStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, IfStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, SwitchStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, CaseLabelNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, DoStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, WhileStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ForInStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ForStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, WithStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ContinueStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, BreakStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ReturnStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ThrowStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, TryStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, CatchClauseNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, FinallyClauseNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, UseStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, IncludeStatementNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
// Definitions
Value evaluate( Context context, ImportDefinitionNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, ImportBindingNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, AnnotatedDefinitionNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, AttributeListNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, ExportDefinitionNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, ExportBindingNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, VariableDefinitionNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, VariableBindingNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, TypedVariableNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, FunctionDefinitionNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, FunctionDeclarationNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, FunctionNameNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, FunctionSignatureNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, ParameterNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, OptionalParameterNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, ClassDefinitionNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, ClassDeclarationNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, InheritanceNode node ) throws Exception {
throw new Exception( "synthesis unspecified for node = " + node );
}
Value evaluate( Context context, NamespaceDefinitionNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, PackageDefinitionNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
Value evaluate( Context context, ProgramNode node ) throws Exception {
throw new Exception( "evaluation unspecified for node = " + node );
}
}
/*
* The end.
*/

View File

@@ -1,18 +0,0 @@
package com.compilercompany.es3c.v1;
/**
* Interface that object initializers implement.
*
* This interface is implemented by objects that can build
* instances of the Value class. For example, there is an
* object class that implements this interface for the
* system global object.
*/
interface Init {
void init( Value ob ) throws Exception;
}
/*
* The end.
*/

View File

@@ -1,64 +0,0 @@
package com.compilercompany.es3c.v1;
/**
* The base Node class.
*/
public class Node {
private static final boolean debug = false;
Block block;
int position;
Store store;
public Node() {
}
public Node( int position ) {
this.position = position;
}
public Value evaluate( Context context, Evaluator evaluator ) throws Exception {
return null;
}
boolean isLeader;
public void markLeader() throws Exception {
if( debug ) {
Debugger.trace( "Node.markLeader() with this = " + this );
//if(this instanceof AnnotatedBlockNode) throw new Exception("blah");
}
isLeader=true;
}
public boolean isLeader() {
return isLeader;
}
public boolean isBranch() {
return false;
}
public Node[] getTargets() {
return null;
}
public Node first() {
return this;
}
public Node last() {
return this;
}
public Node pos(int p) {
position = p;
return this;
}
public int pos() {
return position;
}
public String toString() {
return isLeader ? "*"+block+":" : ""+block+":";
}
}
/*
* The end.
*/

View File

@@ -1,273 +0,0 @@
/*
* Creates parse tree nodes.
*/
package com.compilercompany.es3c.v1;
public final class NodeFactory {
private static final boolean debug = false;
static private InputBuffer in;
static void init(InputBuffer input) {
in = input;
}
static IdentifierNode Identifier( String name ) {
if( debug ) {
Debugger.trace("" + in.positionOfMark() + ": Identifier " + name );
}
return new IdentifierNode(name,in.positionOfMark());
}
static QualifiedIdentifierNode QualifiedIdentifier( Node qualifier, IdentifierNode identifier ) {
if( debug ) {
Debugger.trace("" + in.positionOfMark() + ": QualifiedIdentifier " + identifier);
}
return new QualifiedIdentifierNode(qualifier,identifier,identifier.pos());
}
static LiteralNullNode LiteralNull() {
return new LiteralNullNode();
}
static LiteralBooleanNode LiteralBoolean(boolean value) {
return new LiteralBooleanNode(value);
}
static LiteralArrayNode LiteralArray( Node elementlist ) {
return new LiteralArrayNode(elementlist);
}
static LiteralFieldNode LiteralField( Node name, Node value ) {
return new LiteralFieldNode(name,value);
}
static LiteralNumberNode LiteralNumber( String value ) {
return new LiteralNumberNode(value);
}
static LiteralObjectNode LiteralObject( Node fieldlist ) {
return new LiteralObjectNode(fieldlist);
}
static LiteralRegExpNode LiteralRegExp( String value ) {
return new LiteralRegExpNode(value);
}
static LiteralStringNode LiteralString( String value ) {
return new LiteralStringNode(value);
}
static LiteralTypeNode LiteralType( Type type ) {
return new LiteralTypeNode(type);
}
static LiteralUndefinedNode LiteralUndefined() {
return new LiteralUndefinedNode();
}
static ParenthesizedExpressionNode ParenthesizedExpression( Node expr ) {
return new ParenthesizedExpressionNode(expr,in.positionOfMark());
}
static ParenthesizedListExpressionNode ParenthesizedListExpression( Node expr ) {
return new ParenthesizedListExpressionNode(expr);
}
static FunctionExpressionNode FunctionExpression( Node name, Node signature, Node body ) {
return new FunctionExpressionNode(name,signature,body);
}
static AnnotatedDefinitionNode AnnotatedDefinition( Node attributes, Node definition ) {
return new AnnotatedDefinitionNode(attributes,definition);
}
static AttributeListNode AttributeList( Node item, Node list ) {
return new AttributeListNode(item,list);
}
static UnitExpressionNode UnitExpression( Node value, Node type ) {
return new UnitExpressionNode(value,type);
}
static ThisExpressionNode ThisExpression() {
return new ThisExpressionNode();
}
static SuperExpressionNode SuperExpression() {
return new SuperExpressionNode();
}
static ListNode List( Node list, Node item ) {
return new ListNode(list,item,item.pos());
}
static PostfixExpressionNode PostfixExpression( int op, Node expr ) {
return new PostfixExpressionNode(op,expr);
}
static NewExpressionNode NewExpression( Node member ) {
return new NewExpressionNode(member);
}
static ClassofExpressionNode ClassofExpression( Node base ) {
if( debug ) {
Debugger.trace("base = " + base);
}
return new ClassofExpressionNode(base);
}
static CallExpressionNode CallExpression( Node member, Node args ) {
return new CallExpressionNode(member,args);
}
static IndexedMemberExpressionNode IndexedMemberExpression( Node base, Node member ) {
return new IndexedMemberExpressionNode(base,member,in.positionOfMark());
}
static MemberExpressionNode MemberExpression( Node base, Node name ) {
return new MemberExpressionNode(base,name,in.positionOfMark());
}
static CoersionExpressionNode CoersionExpression( Node expr, Node type ) {
return new CoersionExpressionNode(expr,type,in.positionOfMark());
}
static UnaryExpressionNode UnaryExpression( int op, Node expr ) {
return new UnaryExpressionNode(op,expr);
}
static BinaryExpressionNode BinaryExpression( int op, Node lhs, Node rhs ) {
return new BinaryExpressionNode(op,lhs,rhs);
}
static ConditionalExpressionNode ConditionalExpression( Node cond, Node thenexpr, Node elseexpr ) {
return new ConditionalExpressionNode(cond,thenexpr,elseexpr);
}
static AssignmentExpressionNode AssignmentExpression( Node lhs, int op, Node rhs ) {
return new AssignmentExpressionNode(lhs,op,rhs);
}
static StatementListNode StatementList( StatementListNode list, Node item ) {
return new StatementListNode(list,item);
}
static EmptyStatementNode EmptyStatement() {
return new EmptyStatementNode();
}
static ExpressionStatementNode ExpressionStatement( Node expr ) {
return new ExpressionStatementNode(expr);
}
static AnnotatedBlockNode AnnotatedBlock( Node attributes, Node definition ) {
return new AnnotatedBlockNode(attributes,definition);
}
static LabeledStatementNode LabeledStatement( Node label, Node statement ) {
return new LabeledStatementNode(label,statement);
}
static IfStatementNode IfStatement( Node test, Node tblock, Node eblock ) {
return new IfStatementNode(test,tblock,eblock);
}
static SwitchStatementNode SwitchStatement( Node expr, StatementListNode statements ) {
return new SwitchStatementNode(expr,statements);
}
static CaseLabelNode CaseLabel( Node label ) {
return new CaseLabelNode(label);
}
static DoStatementNode DoStatement( Node block, Node expr ) {
return new DoStatementNode(block,expr);
}
static WhileStatementNode WhileStatement( Node expr, Node statement ) {
return new WhileStatementNode(expr,statement);
}
static ForInStatementNode ForInStatement( Node expr1, Node expr2, Node statement ) {
return new ForInStatementNode(expr1,expr2,statement);
}
static ForStatementNode ForStatement( Node expr1, Node expr2, Node expr3, Node statement ) {
return new ForStatementNode(expr1,expr2,expr3,statement);
}
static WithStatementNode WithStatement( Node expr, Node statement ) {
return new WithStatementNode(expr,statement);
}
static ContinueStatementNode ContinueStatement(Node expr) {
return new ContinueStatementNode(expr);
}
static BreakStatementNode BreakStatement(Node expr) {
return new BreakStatementNode(expr);
}
static ReturnStatementNode ReturnStatement( Node expr ) {
return new ReturnStatementNode(expr);
}
static ThrowStatementNode ThrowStatement(Node list) {
return new ThrowStatementNode(list);
}
static TryStatementNode TryStatement(Node tryblock, StatementListNode catchlist, Node finallyblock) {
return new TryStatementNode(tryblock,catchlist,finallyblock);
}
static CatchClauseNode CatchClause(Node parameter, Node block) {
return new CatchClauseNode(parameter,block);
}
static FinallyClauseNode FinallyClause( Node block ) {
return new FinallyClauseNode(block);
}
static IncludeStatementNode IncludeStatement( Node list ) {
return new IncludeStatementNode(list);
}
static UseStatementNode UseStatement( Node expr ) {
return new UseStatementNode(expr);
}
static ImportDefinitionNode ImportDefinition( Node item, Node list ) {
return new ImportDefinitionNode(item,list);
}
static ImportBindingNode ImportBinding( Node identifer, Node item ) {
return new ImportBindingNode(identifer,item);
}
static ExportDefinitionNode ExportDefinition( Node list ) {
return new ExportDefinitionNode(list);
}
static ExportBindingNode ExportBinding( Node name, Node value ) {
return new ExportBindingNode(name,value);
}
static VariableDefinitionNode VariableDefinition( int kind, Node list ) {
return new VariableDefinitionNode(kind,list,list.pos());
}
static VariableBindingNode VariableBinding( Node identifier, Node initializer ) {
return new VariableBindingNode(identifier,initializer);
}
static TypedVariableNode TypedVariable( Node identifier, Node type ) {
if( debug ) {
Debugger.trace("" + in.positionOfMark() + ": TypedVariable " + type );
}
return new TypedVariableNode(identifier,type,type!=null?type.pos():identifier.pos());
}
static FunctionDefinitionNode FunctionDefinition( Node decl, Node body ) {
return new FunctionDefinitionNode(decl,body);
}
static FunctionDeclarationNode FunctionDeclaration( Node name, Node signature ) {
return new FunctionDeclarationNode(name,signature);
}
static FunctionNameNode FunctionName( int kind, Node name ) {
return new FunctionNameNode(kind,name);
}
static RestParameterNode RestParameter( Node expr ) {
return new RestParameterNode(expr);
}
static ParameterNode Parameter( Node identifer, Node type ) {
return new ParameterNode(identifer,type);
}
static OptionalParameterNode OptionalParameter( Node identifer, Node init ) {
return new OptionalParameterNode(identifer,init);
}
static NamedParameterNode NamedParameter( Node name, Node parameter ) {
return new NamedParameterNode(name,parameter);
}
static ClassDeclarationNode ClassDeclaration( Node name ) {
return new ClassDeclarationNode(name);
}
static ClassDefinitionNode ClassDefinition( Node name, Node interfaces, Node statements ) {
return new ClassDefinitionNode(name,interfaces,statements);
}
static InheritanceNode Inheritance( Node baseclass, Node interfaces ) {
return new InheritanceNode(baseclass,interfaces);
}
static InterfaceDeclarationNode InterfaceDeclaration( Node name ) {
return new InterfaceDeclarationNode(name);
}
static InterfaceDefinitionNode InterfaceDefinition( Node name, Node interfaces, Node statements ) {
return new InterfaceDefinitionNode(name,interfaces,statements);
}
static NamespaceDefinitionNode NamespaceDefinition( Node identifier, Node list ) {
return new NamespaceDefinitionNode(identifier,list);
}
static LanguageDeclarationNode LanguageDeclaration( Node list ) {
return new LanguageDeclarationNode(list);
}
static PackageDefinitionNode PackageDefinition( Node name, Node block ) {
return new PackageDefinitionNode(name,block);
}
static ProgramNode Program( Node statements ) {
return new ProgramNode(statements);
}
/*
static Node () {
return new Node();
}
*/
}
/*
* The end.
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +0,0 @@
package com.compilercompany.es3c.v1;
/**
* A scope, which contains slots.
*/
public interface Scope {
Slot get(Value namespace, String name) throws Exception;
Slot add(Value namespace, String name ) throws Exception;
boolean has(Value namespace, String name) throws Exception;
}
/*
* The end.
*/

View File

@@ -1,21 +0,0 @@
package com.compilercompany.es3c.v1;
/**
* A slot.
*/
public class Slot {
Value attrs;
Value type;
Value value;
Block block;
Store store;
public String toString() {
return "{ "+attrs+", "+type+", "+value+", "+store+" }";
}
}
/*
* The end.
*/

View File

@@ -1,23 +0,0 @@
package com.compilercompany.es3c.v1;
/**
* Represents an abstract unit of storage.
*/
public class Store {
Scope scope;
int index;
Store(Scope scope, int index) {
this.scope = scope;
this.index = index;
}
public String toString() {
return "store( " + index + " )";
}
}
/*
* The end.
*/

View File

@@ -1,20 +0,0 @@
package com.compilercompany.es3c.v1;
/**
* The interfaces for all types.
*/
public interface Type extends Init {
Object[] values();
Type[] converts();
void addSub(Type type);
boolean includes(Value value);
void setSuper(Type type);
Type getSuper();
Value convert(Context context, Value value) throws Exception;
Value coerce(Context context, Value value) throws Exception;
}
/*
* The end.
*/

View File

@@ -1,92 +0,0 @@
package com.compilercompany.es3c.v1;
import java.util.Hashtable;
import java.util.Vector;
/**
* The value class from which all other values derive.
*/
abstract public class Value implements Scope {
private static final boolean debug = false;
public Value type;
public Value getValue(Context context) throws Exception { return this; }
public Value getType(Context context) throws Exception { return type; }
/*
Hashtable defaultNames = new Hashtable();
Hashtable namespaces = new Hashtable();
Hashtable attributes = new Hashtable();
*/
public boolean has(Value namespace, String name) throws Exception {
throw new Exception("Constructor object expected in new expression");
/*
Hashtable names;
if( namespace == null ) {
names = defaultNames;
} else {
names = (Hashtable) namespaces.get(namespace);
}
return names.containsKey(name);
*/
}
public Slot get(Value namespace, String name) throws Exception {
throw new Exception("Constructor object expected in new expression");
/*
if(debug) {
Debugger.trace("ObjectValue.get() with namespaces="+namespaces+", namespace="+namespace+", name="+name);
}
Hashtable names;
if( namespace == null ) {
names = defaultNames;
} else {
names = (Hashtable) namespaces.get(namespace);
}
return (Slot) names.get(name);
*/
}
public Slot add(Value namespace, String name) throws Exception {
throw new Exception("Constructor object expected in new expression");
/*
if( debug ) {
Debugger.trace("ObjectType.add() with this = " + this + " namespace = " + namespace + " name = " + name);
}
Hashtable names;
if( namespace == null ) {
names = defaultNames;
} else {
names = (Hashtable) namespaces.get(namespace);
if( names==null ) {
names = new Hashtable();
namespaces.put(namespace,names);
}
}
Slot slot = new Slot();
names.put(name,slot);
return slot;
*/
}
int size() {
return 0;
}
public Value construct(Context context, Value args) throws Exception {
throw new Exception("Constructor object expected in new expression");
}
public Value call(Context context, Value args) throws Exception {
throw new Exception("Callable object expected in call expression");
}
}
/*
* The end.
*/

Some files were not shown because too many files have changed in this diff Show More