Compare commits
11 Commits
regalloc_c
...
RHAPSODY_N
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e69cd99b45 | ||
|
|
b1d544cd8e | ||
|
|
14c0be343d | ||
|
|
62660d5bab | ||
|
|
a5eb8ff006 | ||
|
|
2566e331ff | ||
|
|
0eb4adf962 | ||
|
|
1e6d0edc0a | ||
|
|
327d6871b4 | ||
|
|
f0e366ddda | ||
|
|
56d28c2510 |
@@ -1,134 +0,0 @@
|
||||
/* -*- 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
|
||||
@@ -1,195 +0,0 @@
|
||||
/* -*- 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
|
||||
@@ -1,159 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,283 +0,0 @@
|
||||
/* -*- 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
|
||||
@@ -1,284 +0,0 @@
|
||||
/* -*- 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));
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
/* -*- 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
|
||||
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,97 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,213 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,258 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,87 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,163 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,301 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,40 +0,0 @@
|
||||
#! 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)
|
||||
@@ -1,392 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,155 +0,0 @@
|
||||
/* -*- 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;
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/* -*- 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_
|
||||
|
||||
@@ -1,355 +0,0 @@
|
||||
/* -*- 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
|
||||
@@ -1,117 +0,0 @@
|
||||
// -*- 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_
|
||||
@@ -1,104 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,168 +0,0 @@
|
||||
// -*- 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_
|
||||
@@ -1,270 +0,0 @@
|
||||
/* -*- 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
|
||||
@@ -1,269 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,239 +0,0 @@
|
||||
/* -*- 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_
|
||||
@@ -1,186 +0,0 @@
|
||||
/* -*- 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();
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/* -*- 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_ */
|
||||
@@ -1,116 +0,0 @@
|
||||
/* -*- 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 ®A == ®B;}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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_
|
||||
105
mozilla/nsprpub/Makefile
Normal file
105
mozilla/nsprpub/Makefile
Normal file
@@ -0,0 +1,105 @@
|
||||
#! gmake
|
||||
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
MOD_DEPTH = .
|
||||
|
||||
DIRS = config pr lib
|
||||
|
||||
ifdef MOZILLA_CLIENT
|
||||
PR_CLIENT_BUILD = 1
|
||||
PR_CLIENT_BUILD_UNIX = 1
|
||||
endif
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
#
|
||||
# The -ll option of zip converts CR LF to LF.
|
||||
#
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ZIP_ASCII_OPT = -ll
|
||||
endif
|
||||
|
||||
ifdef PR_CLIENT_BUILD
|
||||
export::
|
||||
rm -r -f $(DIST)/../public/nspr
|
||||
ifdef PR_CLIENT_BUILD_UNIX
|
||||
rm -f $(DIST)/lib/libnspr.a
|
||||
rm -f $(DIST)/bin/libnspr.$(DLL_SUFFIX)
|
||||
endif
|
||||
endif
|
||||
|
||||
release::
|
||||
echo $(BUILD_NUMBER) > $(RELEASE_DIR)/$(BUILD_NUMBER)/version.df
|
||||
@if test -f imports.df; then \
|
||||
echo "cp -f imports.df $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df"; \
|
||||
cp -f imports.df $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df; \
|
||||
else \
|
||||
echo "echo > $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df"; \
|
||||
echo > $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df; \
|
||||
fi
|
||||
cd $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \
|
||||
rm -rf META-INF; mkdir META-INF; cd META-INF; \
|
||||
echo "Manifest-Version: 1.0" > MANIFEST.MF; \
|
||||
echo "" >> MANIFEST.MF; \
|
||||
cd ..; rm -f mdbinary.jar; zip -r mdbinary.jar META-INF lib; \
|
||||
rm -rf META-INF; \
|
||||
cd include; \
|
||||
rm -rf META-INF; mkdir META-INF; cd META-INF; \
|
||||
echo "Manifest-Version: 1.0" > MANIFEST.MF; \
|
||||
echo "" >> MANIFEST.MF; \
|
||||
cd ..; rm -f mdheader.jar; zip $(ZIP_ASCII_OPT) -r mdheader.jar *; \
|
||||
rm -rf META-INF
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
@if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); then \
|
||||
rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
|
||||
echo "making directory /m/dist/$(MOD_NAME)/$(BUILD_NUMBER)"; \
|
||||
config/prmkdir.bat $(MDIST_DOS)\\$(MOD_NAME)\\$(BUILD_NUMBER); \
|
||||
fi
|
||||
@if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME); then \
|
||||
rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \
|
||||
echo "making directory /m/dist/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME)"; \
|
||||
config/prmkdir.bat $(MDIST_DOS)\\$(MOD_NAME)\\$(BUILD_NUMBER)\\$(OBJDIR_NAME); \
|
||||
fi
|
||||
else
|
||||
@if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); then \
|
||||
rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
|
||||
echo "making directory /m/dist/$(MOD_NAME)/$(BUILD_NUMBER)"; \
|
||||
$(NSINSTALL) -D $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
|
||||
chmod 775 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
|
||||
fi
|
||||
@if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME); then \
|
||||
rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \
|
||||
echo "making directory /m/dist/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME)"; \
|
||||
$(NSINSTALL) -D $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \
|
||||
chmod 775 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \
|
||||
fi
|
||||
endif
|
||||
cd $(RELEASE_DIR)/$(BUILD_NUMBER); \
|
||||
cp -f version.df imports.df $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
|
||||
chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/version.df; \
|
||||
chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/imports.df; \
|
||||
cd $(OBJDIR_NAME); \
|
||||
cp -f mdbinary.jar $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \
|
||||
chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/mdbinary.jar; \
|
||||
cd include; \
|
||||
cp -f mdheader.jar $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \
|
||||
chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/mdheader.jar
|
||||
|
||||
depend:
|
||||
@echo "NSPR20 has no dependencies. Skipped."
|
||||
99
mozilla/nsprpub/config/AIX.mk
Normal file
99
mozilla/nsprpub/config/AIX.mk
Normal file
@@ -0,0 +1,99 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for AIX.
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
#
|
||||
# XXX
|
||||
# Temporary define for the Client; to be removed when binary release is used
|
||||
#
|
||||
ifdef MOZILLA_CLIENT
|
||||
CLASSIC_NSPR = 1
|
||||
endif
|
||||
|
||||
#
|
||||
# There are three implementation strategies available on AIX:
|
||||
# pthreads, classic, and pthreads-user. The default is pthreads.
|
||||
#
|
||||
ifeq ($(CLASSIC_NSPR),1)
|
||||
PTHREADS_USER =
|
||||
USE_PTHREADS =
|
||||
IMPL_STRATEGY = _CLASSIC
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
else
|
||||
ifeq ($(PTHREADS_USER),1)
|
||||
USE_PTHREADS =
|
||||
IMPL_STRATEGY = _PTH_USER
|
||||
else
|
||||
USE_PTHREADS = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# XXX
|
||||
# Temporary define for the Client; to be removed when binary release is used
|
||||
#
|
||||
ifdef MOZILLA_CLIENT
|
||||
IMPL_STRATEGY =
|
||||
endif
|
||||
|
||||
ifeq ($(CLASSIC_NSPR),1)
|
||||
CC = xlC
|
||||
CCC = xlC
|
||||
else
|
||||
CC = xlC_r
|
||||
CCC = xlC_r
|
||||
endif
|
||||
|
||||
CPU_ARCH = rs6000
|
||||
|
||||
RANLIB = ranlib
|
||||
|
||||
OS_CFLAGS = -qro -qroconst -DAIX -DSYSV
|
||||
ifeq ($(CC),xlC_r)
|
||||
OS_CFLAGS += -qarch=com
|
||||
endif
|
||||
|
||||
ifeq ($(OS_RELEASE),4.1)
|
||||
OS_CFLAGS += -DAIX4_1
|
||||
else
|
||||
DSO_LDOPTS = -brtl -bM:SRE -bnoentry -bexpall
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
ifeq ($(OS_RELEASE),4.3)
|
||||
OS_CFLAGS += -DAIX4_3
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Special link info for constructing AIX programs. On AIX we have to
|
||||
# statically link programs that use NSPR into a single .o, rewriting the
|
||||
# calls to select to call "aix". Once that is done we then can
|
||||
# link that .o with a .o built in nspr which implements the system call.
|
||||
#
|
||||
ifneq ($(OS_RELEASE),4.1)
|
||||
AIX_LINK_OPTS = -brtl -bnso -berok
|
||||
else
|
||||
AIX_LINK_OPTS = -bnso -berok
|
||||
#AIX_LINK_OPTS = -bnso -berok -brename:.select,.wrap_select -brename:.poll,.wrap_poll -bI:/usr/lib/syscalls.exp
|
||||
endif
|
||||
|
||||
AIX_WRAP = $(DIST)/lib/aixwrap.o
|
||||
AIX_TMP = $(OBJDIR)/_aix_tmp.o
|
||||
45
mozilla/nsprpub/config/BSD_OS.mk
Normal file
45
mozilla/nsprpub/config/BSD_OS.mk
Normal file
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for BSDI Unix for x86.
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
#CC = gcc -Wall -Wno-format
|
||||
#CCC = g++
|
||||
CC = shlicc2
|
||||
CCC = shlicc2
|
||||
RANLIB = ranlib
|
||||
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
OS_CFLAGS = -DBSDI -DHAVE_STRERROR -D__386BSD__ -DNEED_BSDREGEX -Di386
|
||||
OS_LIBS = -lcompat -ldl
|
||||
|
||||
ifeq ($(OS_RELEASE),2.1)
|
||||
OS_CFLAGS += -DBSDI_2
|
||||
endif
|
||||
|
||||
G++INCLUDES = -I/usr/include/g++
|
||||
|
||||
CPU_ARCH = x86
|
||||
|
||||
NOSUCHFILE = /no-such-file
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
DSO_LDOPTS = -r
|
||||
50
mozilla/nsprpub/config/FreeBSD.mk
Normal file
50
mozilla/nsprpub/config/FreeBSD.mk
Normal file
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for FreeBSD
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
RANLIB = ranlib
|
||||
|
||||
OS_REL_CFLAGS = -mno-486 -Di386
|
||||
CPU_ARCH = x86
|
||||
|
||||
OS_CFLAGS = $(DSO_CFLAGS) $(OS_REL_CFLAGS) -ansi -Wall -pipe -DFREEBSD -DHAVE_STRERROR -DHAVE_BSD_FLOCK -D_PR_NEED_POLL
|
||||
|
||||
ifeq ($(USE_PTHREADS),1)
|
||||
OS_LIBS = -lc_r
|
||||
# XXX probably should define _THREAD_SAFE too.
|
||||
DEFINES += -D_PR_NEED_FAKE_POLL
|
||||
else
|
||||
OS_LIBS = -lc
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
endif
|
||||
|
||||
ARCH = freebsd
|
||||
|
||||
DSO_CFLAGS = -fPIC
|
||||
DSO_LDOPTS = -Bshareable
|
||||
DSO_LDFLAGS =
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
|
||||
G++INCLUDES = -I/usr/include/g++
|
||||
155
mozilla/nsprpub/config/HP-UX.mk
Normal file
155
mozilla/nsprpub/config/HP-UX.mk
Normal file
@@ -0,0 +1,155 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for HP-UX
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
DLL_SUFFIX = sl
|
||||
|
||||
CC = cc -Ae
|
||||
CCC = CC
|
||||
RANLIB = echo
|
||||
|
||||
CPU_ARCH = hppa
|
||||
|
||||
OS_CFLAGS = +ESlit $(DSO_CFLAGS) -DHPUX -D$(CPU_ARCH) -D_HPUX_SOURCE
|
||||
|
||||
#
|
||||
# The header netdb.h on HP-UX 9 does not declare h_errno.
|
||||
# On 10.10 and 10.20, netdb.h declares h_errno only if
|
||||
# _XOPEN_SOURCE_EXTENDED is defined. So we need to declare
|
||||
# h_errno ourselves.
|
||||
#
|
||||
ifeq ($(basename $(OS_RELEASE)),A.09)
|
||||
OS_CFLAGS += -D_PR_NEED_H_ERRNO
|
||||
endif
|
||||
ifeq (,$(filter-out B.10.10 B.10.20,$(OS_RELEASE)))
|
||||
OS_CFLAGS += -D_PR_NEED_H_ERRNO
|
||||
endif
|
||||
|
||||
#
|
||||
# XXX
|
||||
# Temporary define for the Client; to be removed when binary release is used
|
||||
#
|
||||
ifdef MOZILLA_CLIENT
|
||||
CLASSIC_NSPR = 1
|
||||
endif
|
||||
|
||||
#
|
||||
# On HP-UX 9, the default (and only) implementation strategy is
|
||||
# classic nspr.
|
||||
#
|
||||
# On HP-UX 10.10 and 10.20, the default implementation strategy is
|
||||
# pthreads (actually DCE threads). Classic nspr is also available.
|
||||
#
|
||||
# On HP-UX 10.30 and 11.00, the default implementation strategy is
|
||||
# pthreads. Classic nspr and pthreads-user are also available.
|
||||
#
|
||||
ifeq ($(basename $(OS_RELEASE)),A.09)
|
||||
OS_CFLAGS += -DHPUX9
|
||||
DEFAULT_IMPL_STRATEGY = _CLASSIC
|
||||
endif
|
||||
|
||||
ifeq ($(OS_RELEASE),B.10.01)
|
||||
OS_CFLAGS += -DHPUX10
|
||||
DEFAULT_IMPL_STRATEGY = _CLASSIC
|
||||
endif
|
||||
|
||||
ifeq ($(OS_RELEASE),B.10.10)
|
||||
OS_CFLAGS += -DHPUX10 -DHPUX10_10
|
||||
DEFAULT_IMPL_STRATEGY = _PTH
|
||||
endif
|
||||
|
||||
ifeq ($(OS_RELEASE),B.10.20)
|
||||
OS_CFLAGS += -DHPUX10 -DHPUX10_20
|
||||
DEFAULT_IMPL_STRATEGY = _PTH
|
||||
endif
|
||||
|
||||
#
|
||||
# On 10.30 and 11.00, we use the new ANSI C++ compiler aCC.
|
||||
#
|
||||
|
||||
ifeq ($(OS_RELEASE),B.10.30)
|
||||
CCC = /opt/aCC/bin/aCC
|
||||
OS_CFLAGS += +DAportable +DS1.1 -DHPUX10 -DHPUX10_30
|
||||
DEFAULT_IMPL_STRATEGY = _PTH
|
||||
endif
|
||||
|
||||
# 11.00 is similar to 10.30.
|
||||
ifeq ($(OS_RELEASE),B.11.00)
|
||||
CCC = /opt/aCC/bin/aCC
|
||||
OS_CFLAGS += +DAportable +DS1.1 -DHPUX10 -DHPUX11
|
||||
DEFAULT_IMPL_STRATEGY = _PTH
|
||||
endif
|
||||
|
||||
ifeq ($(DEFAULT_IMPL_STRATEGY),_CLASSIC)
|
||||
CLASSIC_NSPR = 1
|
||||
endif
|
||||
|
||||
ifeq ($(DEFAULT_IMPL_STRATEGY),_PTH)
|
||||
USE_PTHREADS = 1
|
||||
ifeq ($(CLASSIC_NSPR),1)
|
||||
USE_PTHREADS =
|
||||
IMPL_STRATEGY = _CLASSIC
|
||||
endif
|
||||
ifeq ($(PTHREADS_USER),1)
|
||||
USE_PTHREADS =
|
||||
IMPL_STRATEGY = _PTH_USER
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# XXX
|
||||
# Temporary define for the Client; to be removed when binary release is used
|
||||
#
|
||||
ifdef MOZILLA_CLIENT
|
||||
IMPL_STRATEGY =
|
||||
endif
|
||||
|
||||
ifeq ($(CLASSIC_NSPR),1)
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
endif
|
||||
|
||||
#
|
||||
# To use the true pthread (kernel thread) library on 10.30 and
|
||||
# 11.00, we should define _POSIX_C_SOURCE to be 199506L.
|
||||
# The _REENTRANT macro is deprecated.
|
||||
#
|
||||
|
||||
ifdef USE_PTHREADS
|
||||
ifeq (,$(filter-out B.10.10 B.10.20,$(OS_RELEASE)))
|
||||
OS_CFLAGS += -D_REENTRANT -D_PR_DCETHREADS
|
||||
else
|
||||
OS_CFLAGS += -D_POSIX_C_SOURCE=199506L
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef PTHREADS_USER
|
||||
OS_CFLAGS += -D_POSIX_C_SOURCE=199506L
|
||||
endif
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
|
||||
DSO_LDOPTS = -b
|
||||
DSO_LDFLAGS =
|
||||
# +Z generates position independent code for use in shared libraries.
|
||||
DSO_CFLAGS = +Z
|
||||
|
||||
HAVE_PURIFY = 1
|
||||
114
mozilla/nsprpub/config/IRIX.mk
Normal file
114
mozilla/nsprpub/config/IRIX.mk
Normal file
@@ -0,0 +1,114 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for IRIX
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
#
|
||||
# The default implementation strategy for Irix is classic nspr.
|
||||
#
|
||||
ifeq ($(USE_PTHREADS),1)
|
||||
IMPL_STRATEGY = _PTH
|
||||
endif
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
CC = gcc
|
||||
COMPILER_TAG = _gcc
|
||||
AS = $(CC) -x assembler-with-cpp
|
||||
ODD_CFLAGS = -Wall -Wno-format
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER = -O6
|
||||
endif
|
||||
else
|
||||
CC = cc
|
||||
CCC = CC
|
||||
ODD_CFLAGS = -fullwarn -xansi
|
||||
ifdef BUILD_OPT
|
||||
|
||||
ifeq ($(USE_N32),1)
|
||||
OPTIMIZER = -O -OPT:Olimit=4000
|
||||
else
|
||||
OPTIMIZER = -O -Olimit 4000
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
# For 6.x machines, include this flag
|
||||
ifeq (6.,$(findstring 6.,$(OS_RELEASE)))
|
||||
ifeq ($(USE_N32),1)
|
||||
ODD_CFLAGS += -n32 -exceptions -woff 1209,1642,3201
|
||||
COMPILER_TAG = _n32
|
||||
else
|
||||
ODD_CFLAGS += -32 -multigot
|
||||
endif
|
||||
else
|
||||
ODD_CFLAGS += -xgot
|
||||
endif
|
||||
endif
|
||||
|
||||
ODD_CFLAGS += -DSVR4 -DIRIX
|
||||
|
||||
|
||||
CPU_ARCH = mips
|
||||
|
||||
RANLIB = /bin/true
|
||||
|
||||
# For purify
|
||||
# XXX: should always define _SGI_MP_SOURCE
|
||||
NOMD_OS_CFLAGS = $(ODD_CFLAGS) -D_SGI_MP_SOURCE
|
||||
|
||||
ifeq ($(OS_RELEASE),5.3)
|
||||
OS_CFLAGS += -DIRIX5_3
|
||||
endif
|
||||
|
||||
ifeq ($(OS_RELEASE),6.2)
|
||||
OS_CFLAGS += -DIRIX6_2
|
||||
endif
|
||||
|
||||
ifeq ($(OS_RELEASE),6.3)
|
||||
OS_CFLAGS += -DIRIX6_3
|
||||
endif
|
||||
|
||||
ifndef NO_MDUPDATE
|
||||
OS_CFLAGS += $(NOMD_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
|
||||
else
|
||||
OS_CFLAGS += $(NOMD_OS_CFLAGS)
|
||||
endif
|
||||
|
||||
# catch unresolved symbols
|
||||
ifeq ($(basename $(OS_RELEASE)),6)
|
||||
SHLIB_LD_OPTS = -no_unresolved
|
||||
endif
|
||||
|
||||
ifeq ($(USE_N32),1)
|
||||
SHLIB_LD_OPTS += -n32
|
||||
endif
|
||||
|
||||
MKSHLIB = $(LD) $(SHLIB_LD_OPTS) -rdata_shared -shared -soname $(@:$(OBJDIR)/%.so=%.so)
|
||||
|
||||
HAVE_PURIFY = 1
|
||||
|
||||
DSO_LDOPTS = -elf -shared -all
|
||||
|
||||
ifdef DSO_BACKEND
|
||||
DSO_LDOPTS += -soname $(DSO_NAME)
|
||||
|
||||
|
||||
endif
|
||||
112
mozilla/nsprpub/config/Linux.mk
Normal file
112
mozilla/nsprpub/config/Linux.mk
Normal file
@@ -0,0 +1,112 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
######################################################################
|
||||
# Config stuff for Linux (all architectures)
|
||||
######################################################################
|
||||
|
||||
######################################################################
|
||||
# Version-independent
|
||||
######################################################################
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
#
|
||||
# The default implementation strategy for Linux is classic nspr.
|
||||
#
|
||||
ifeq ($(USE_PTHREADS),1)
|
||||
IMPL_STRATEGY = _PTH
|
||||
DEFINES += -D_REENTRANT
|
||||
else
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
endif
|
||||
|
||||
ifeq (86,$(findstring 86,$(OS_TEST)))
|
||||
CPU_ARCH := x86
|
||||
else
|
||||
CPU_ARCH := $(OS_TEST)
|
||||
CPU_ARCH_TAG = _$(CPU_ARCH)
|
||||
endif
|
||||
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
RANLIB = ranlib
|
||||
|
||||
OS_INCLUDES =
|
||||
G++INCLUDES = -I/usr/include/g++
|
||||
|
||||
PLATFORM_FLAGS = -ansi -Wall -pipe -DLINUX -Dlinux
|
||||
PORT_FLAGS = -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR
|
||||
|
||||
OS_CFLAGS = $(DSO_CFLAGS) $(PLATFORM_FLAGS) $(PORT_FLAGS)
|
||||
|
||||
######################################################################
|
||||
# Version-specific stuff
|
||||
######################################################################
|
||||
|
||||
ifeq ($(CPU_ARCH),alpha)
|
||||
PLATFORM_FLAGS += -DLINUX1_2 -D_ALPHA_ -D__alpha
|
||||
PORT_FLAGS += -D_XOPEN_SOURCE
|
||||
endif
|
||||
ifeq ($(CPU_ARCH),ppc)
|
||||
PLATFORM_FLAGS += -DMKLINUX -DLINUX1_2
|
||||
OS_INCLUDES += -I/usr/local/include
|
||||
endif
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
PLATFORM_FLAGS += -DLINUX1_2
|
||||
endif
|
||||
ifeq ($(CPU_ARCH),x86)
|
||||
PLATFORM_FLAGS += -mno-486 -DLINUX1_2 -Di386
|
||||
PORT_FLAGS += -D_XOPEN_SOURCE
|
||||
endif
|
||||
ifeq ($(CPU_ARCH),m68k)
|
||||
#
|
||||
# gcc on Linux/m68k either has a bug or triggers a code-sequence
|
||||
# bug in the 68060 which causes gcc to crash. The simplest way to
|
||||
# avoid this is to enable a minimum level of optimization.
|
||||
#
|
||||
ifndef BUILD_OPT
|
||||
OPTIMIZER += -O
|
||||
endif
|
||||
PLATFORM_FLAGS += -m68020-40 -DLINUX1_2
|
||||
endif
|
||||
|
||||
# These are CPU_ARCH independent
|
||||
ifeq ($(basename $(OS_RELEASE)),2.0)
|
||||
PLATFORM_FLAGS += -DLINUX2_0
|
||||
endif
|
||||
|
||||
#
|
||||
# Linux ppc and 2.0 have shared libraries.
|
||||
#
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS) -soname $(@:$(OBJDIR)/%.so=%.so)
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER = -O2
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
# Overrides for defaults in config.mk (or wherever)
|
||||
######################################################################
|
||||
|
||||
######################################################################
|
||||
# Other
|
||||
######################################################################
|
||||
|
||||
DSO_CFLAGS = -fPIC
|
||||
DSO_LDOPTS = -shared
|
||||
DSO_LDFLAGS =
|
||||
40
mozilla/nsprpub/config/Makefile
Normal file
40
mozilla/nsprpub/config/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
#! gmake
|
||||
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
MOD_DEPTH = ..
|
||||
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
CSRCS = nsinstall.c pathsub.c
|
||||
|
||||
PLSRCS = nfspwd.pl
|
||||
|
||||
ifneq ($(OS_ARCH),WINNT)
|
||||
PROGRAM = $(OBJDIR)/nsinstall
|
||||
TARGETS = $(PROGRAM) $(PLSRCS:.pl=)
|
||||
endif
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
# Redefine MAKE_OBJDIR for just this directory
|
||||
define MAKE_OBJDIR
|
||||
if test ! -d $(@D); then rm -rf $(@D); mkdir $(@D); fi
|
||||
endef
|
||||
|
||||
export:: $(TARGETS)
|
||||
75
mozilla/nsprpub/config/NCR.mk
Normal file
75
mozilla/nsprpub/config/NCR.mk
Normal file
@@ -0,0 +1,75 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for NCR SVR4 MP-RAS
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
###
|
||||
NS_USE_NATIVE = 1
|
||||
|
||||
# NS_USE_GCC = 1
|
||||
|
||||
export PATH:=$(PATH):/opt/ncc/bin
|
||||
###
|
||||
|
||||
RANLIB = true
|
||||
GCC_FLAGS_EXTRA = -pipe
|
||||
|
||||
DEFINES += -DSVR4 -DSYSV -DHAVE_STRERROR -DNCR -D_PR_LOCAL_THREADS_ONLY
|
||||
|
||||
ifdef NS_USE_NATIVE
|
||||
CC = cc
|
||||
CCC = ncc
|
||||
OS_CFLAGS = -Hnocopyr
|
||||
#OS_LIBS = -L/opt/ncc/lib
|
||||
else
|
||||
#OS_LIBS =
|
||||
endif
|
||||
|
||||
CCC = g++
|
||||
|
||||
#OS_LIBS += -lsocket -lnsl -ldl -lc
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
#DSO_LDOPTS = -G -z defs
|
||||
DSO_LDOPTS = -G
|
||||
|
||||
CPU_ARCH = x86
|
||||
ARCH = ncr
|
||||
|
||||
NOSUCHFILE = /no-such-file
|
||||
|
||||
# now take care of default GCC (rus@5/5/97)
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
# if gcc-settings are redefined already - don't touch it
|
||||
#
|
||||
ifeq (,$(findstring gcc, $(CC)))
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
CXX = g++
|
||||
COMPILER_TAG = _gcc
|
||||
# always use -fPIC - some makefiles are still broken and don't distinguish
|
||||
# situation when they build shared and static libraries
|
||||
CFLAGS += -fPIC -Wall $(GCC_FLAGS_EXTRA)
|
||||
#OS_LIBS += -L/usr/local/lib -lstdc++ -lg++ -lgcc
|
||||
endif
|
||||
endif
|
||||
###
|
||||
|
||||
45
mozilla/nsprpub/config/NEC.mk
Normal file
45
mozilla/nsprpub/config/NEC.mk
Normal file
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for NEC Mips SYSV
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
CPU_ARCH = mips
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
else
|
||||
CC = $(NSDEPTH)/build/hcc -Xa -KGnum=0 -KOlimit=4000
|
||||
CCC = g++
|
||||
endif
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
|
||||
RANLIB = /bin/true
|
||||
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
OS_CFLAGS = $(ODD_CFLAGS) -DSVR4 -D__SVR4 -DNEC -Dnec_ews -DHAVE_STRERROR
|
||||
OS_LIBS = -lsocket -lnsl -ldl $(LDOPTIONS)
|
||||
LDOPTIONS = -lc -L/usr/ucblib -lucb
|
||||
|
||||
NOSUCHFILE = /no-such-file
|
||||
|
||||
DSO_LDOPTS = -G
|
||||
59
mozilla/nsprpub/config/NEWS-OS.mk
Normal file
59
mozilla/nsprpub/config/NEWS-OS.mk
Normal file
@@ -0,0 +1,59 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
######################################################################
|
||||
# Config stuff for Sony NEWS-OS
|
||||
######################################################################
|
||||
|
||||
######################################################################
|
||||
# Version-independent
|
||||
######################################################################
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
ARCH := sony
|
||||
CPU_ARCH := mips
|
||||
|
||||
CC = cc
|
||||
CCC = CC
|
||||
RANLIB = /bin/true
|
||||
|
||||
OS_INCLUDES = -I/usr/include
|
||||
G++INCLUDES =
|
||||
#OS_LIBS = -lsocket -lnsl -lgen -lresolv
|
||||
|
||||
PLATFORM_FLAGS = -Xa -fullwarn -DSONY
|
||||
PORT_FLAGS = -DSYSV -DSVR4 -D__svr4 -D__svr4__ -D_PR_LOCAL_THREADS_ONLY
|
||||
|
||||
OS_CFLAGS = $(PLATFORM_FLAGS) $(PORT_FLAGS)
|
||||
|
||||
######################################################################
|
||||
# Version-specific stuff
|
||||
######################################################################
|
||||
|
||||
######################################################################
|
||||
# Overrides for defaults in config.mk (or wherever)
|
||||
######################################################################
|
||||
|
||||
######################################################################
|
||||
# Other
|
||||
######################################################################
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
|
||||
DSO_LDOPTS = -G
|
||||
DSO_LDFLAGS =
|
||||
87
mozilla/nsprpub/config/OS2.mk
Normal file
87
mozilla/nsprpub/config/OS2.mk
Normal file
@@ -0,0 +1,87 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Configuration common to all (supported) versions of OS/2
|
||||
#
|
||||
# OS_CFLAGS is the command line options for the compiler when
|
||||
# building the .DLL object files.
|
||||
# OS_EXE_CFLAGS is the command line options for the compiler
|
||||
# when building the .EXE object files; this is for the test
|
||||
# programs.
|
||||
# the macro OS_CFLAGS is set to OS_EXE_CFLAGS inside of the
|
||||
# makefile for the pr/tests directory. ... Hack.
|
||||
|
||||
|
||||
#
|
||||
# On OS/2 we proudly support gbash...
|
||||
#
|
||||
SHELL = GBASH.EXE
|
||||
|
||||
CC = icc -q -DXP_OS2 -N10
|
||||
CCC = icc -q -DXP_OS2 -DOS2=4 -N10
|
||||
LINK = flipper ilink
|
||||
AR = flipper ilibo //noignorecase //nologo $@
|
||||
RANLIB = echo
|
||||
BSDECHO = echo
|
||||
NSINSTALL = nsinstall
|
||||
INSTALL = $(NSINSTALL)
|
||||
MAKE_OBJDIR = mkdir $(OBJDIR)
|
||||
IMPLIB = flipper implib -nologo -noignorecase
|
||||
FILTER = flipper cppfilt -q
|
||||
RC = rc.exe
|
||||
|
||||
GARBAGE =
|
||||
|
||||
XP_DEFINE = -DXP_PC
|
||||
OBJ_SUFFIX = obj
|
||||
LIB_SUFFIX = lib
|
||||
DLL_SUFFIX = dll
|
||||
|
||||
OS_CFLAGS = -I. -W3 -gm -gd+ -sd- -su4 -ge-
|
||||
OS_EXE_CFLAGS = -I. -W3 -gm -gd+ -sd- -su4
|
||||
AR_EXTRA_ARGS = ,,
|
||||
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER = -O+ -Oi
|
||||
DEFINES = -UDEBUG -U_DEBUG -DNDEBUG
|
||||
DLLFLAGS = -DLL -OUT:$@ -MAP:$(@:.dll=.map)
|
||||
OBJDIR_TAG = _OPT
|
||||
else
|
||||
OPTIMIZER = -Ti+
|
||||
DEFINES = -DDEBUG -D_DEBUG -UNDEBUG
|
||||
DLLFLAGS = -DEBUG -DLL -OUT:$@ -MAP:$(@:.dll=.map)
|
||||
OBJDIR_TAG = _DBG
|
||||
LDFLAGS = -DEBUG
|
||||
endif
|
||||
|
||||
DEFINES += -DOS2=4 -DBSD_SELECT
|
||||
DEFINES += -D_X86_
|
||||
DEFINES += -D_PR_GLOBAL_THREADS_ONLY
|
||||
|
||||
# Name of the binary code directories
|
||||
ifeq ($(CPU_ARCH),x386)
|
||||
ifdef MOZ_LITE
|
||||
OBJDIR_NAME = $(subst OS2,NAV,$(OS_CONFIG))$(OBJDIR_TAG).OBJ
|
||||
else
|
||||
OBJDIR_NAME = $(OS_CONFIG)$(OBJDIR_TAG).OBJ
|
||||
endif
|
||||
else
|
||||
OBJDIR_NAME = $(OS_CONFIG)$(CPU_ARCH)$(OBJDIR_TAG).OBJ
|
||||
endif
|
||||
|
||||
OS_DLLFLAGS = -nologo -DLL -FREE -NOE
|
||||
93
mozilla/nsprpub/config/OSF1.mk
Normal file
93
mozilla/nsprpub/config/OSF1.mk
Normal file
@@ -0,0 +1,93 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for DEC OSF/1
|
||||
#
|
||||
|
||||
#
|
||||
# The Bourne shell (sh) on OSF1 doesn't handle "set -e" correctly,
|
||||
# which we use to stop LOOP_OVER_DIRS submakes as soon as any
|
||||
# submake fails. So we use the Korn shell instead.
|
||||
#
|
||||
SHELL = /usr/bin/ksh
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
#
|
||||
# XXX
|
||||
# Temporary define for the Client; to be removed when binary release is used
|
||||
#
|
||||
ifdef MOZILLA_CLIENT
|
||||
CLASSIC_NSPR = 1
|
||||
endif
|
||||
|
||||
#
|
||||
# On OSF1 V3.2, classic nspr is the default (and only) implementation
|
||||
# strategy.
|
||||
#
|
||||
# On OSF1 V4.0, pthreads is the default implementation strategy.
|
||||
# Classic nspr is also available.
|
||||
#
|
||||
ifneq ($(OS_RELEASE),V3.2)
|
||||
USE_PTHREADS = 1
|
||||
ifeq ($(CLASSIC_NSPR), 1)
|
||||
USE_PTHREADS =
|
||||
IMPL_STRATEGY := _CLASSIC
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# XXX
|
||||
# Temporary define for the Client; to be removed when binary release is used
|
||||
#
|
||||
ifdef MOZILLA_CLIENT
|
||||
IMPL_STRATEGY =
|
||||
endif
|
||||
|
||||
CC = cc $(NON_LD_FLAGS) -std -readonly_strings
|
||||
# The C++ compiler cxx has -readonly_strings on by default.
|
||||
CCC = cxx
|
||||
|
||||
RANLIB = /bin/true
|
||||
|
||||
CPU_ARCH = alpha
|
||||
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER += -Olimit 4000
|
||||
endif
|
||||
|
||||
NON_LD_FLAGS = -ieee_with_inexact
|
||||
|
||||
OS_CFLAGS = -DOSF1 -D_REENTRANT -taso
|
||||
|
||||
ifeq ($(OS_RELEASE),V3.2)
|
||||
OS_CFLAGS += -DOSF1V3
|
||||
endif
|
||||
|
||||
ifeq ($(OS_RELEASE),V4.0)
|
||||
OS_CFLAGS += -DOSF1V4
|
||||
endif
|
||||
|
||||
ifeq ($(USE_PTHREADS),1)
|
||||
OS_CFLAGS += -pthread
|
||||
endif
|
||||
|
||||
# The command to build a shared library on OSF1.
|
||||
MKSHLIB = ld -shared -all -expect_unresolved "*"
|
||||
DSO_LDOPTS = -shared
|
||||
56
mozilla/nsprpub/config/Rhapsody.mk
Normal file
56
mozilla/nsprpub/config/Rhapsody.mk
Normal file
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for Rhapsody5.0
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
#
|
||||
# The default implementation strategy for Rhapsody is classic nspr.
|
||||
#
|
||||
ifeq ($(USE_CTHREADS),1)
|
||||
IMPL_STRATEGY = _CTH
|
||||
DEFINES += -D_PR_GLOBAL_THREADS_ONLY -D_PR_NO_CTHREAD_KEY_T
|
||||
else
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
endif
|
||||
|
||||
DEFINES += -D_PR_NEED_FAKE_POLL
|
||||
|
||||
|
||||
CC = cc
|
||||
CCC = cc++
|
||||
RANLIB = ranlib
|
||||
|
||||
OS_REL_CFLAGS = -Dppc
|
||||
CPU_ARCH = ppc
|
||||
|
||||
#OS_REL_CFLAGS = -mno-486 -Di386
|
||||
#CPU_ARCH = x86
|
||||
|
||||
OS_CFLAGS = $(DSO_CFLAGS) $(OS_REL_CFLAGS) -pipe -DRHAPSODY -DHAVE_STRERROR -DHAVE_BSD_FLOCK
|
||||
|
||||
ARCH = rhapsody
|
||||
|
||||
#DSO_CFLAGS = -fPIC
|
||||
#DSO_LDOPTS = -Bshareable
|
||||
#DSO_LDFLAGS =
|
||||
|
||||
MKSHLIB = $(CC) -arch ppc -dynamiclib -compatibility_version 1 -current_version 1
|
||||
DLL_SUFFIX = dylib
|
||||
74
mozilla/nsprpub/config/SCOOS.mk
Normal file
74
mozilla/nsprpub/config/SCOOS.mk
Normal file
@@ -0,0 +1,74 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SCO OpenServer for x86.
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
CC = cc -b elf -KPIC
|
||||
CCC = g++ -b elf -I/usr/local/lib/g++-include
|
||||
# CCC = $(DEPTH)/build/hcpp +.cpp +w
|
||||
RANLIB = /bin/true
|
||||
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
#
|
||||
# -DSCO_PM - Policy Manager AKA: SCO Licensing
|
||||
# -DSCO - Changes to Netscape source (consistent with AIX, LINUX, etc..)
|
||||
# -Dsco - Needed for /usr/include/X11/*
|
||||
#
|
||||
OS_CFLAGS = -DSCO_SV -DSYSV -D_SVID3 -DHAVE_STRERROR -D_PR_NEED_H_ERRNO -DSCO_PM -DSCO -Dsco
|
||||
#OS_LIBS = -lpmapi -lsocket -lc
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
|
||||
XINC = /usr/include/X11
|
||||
MOTIFLIB = -lXm
|
||||
INCLUDES += -I$(XINC)
|
||||
|
||||
CPU_ARCH = x86
|
||||
GFX_ARCH = x
|
||||
ARCH = sco
|
||||
|
||||
LOCALE_MAP = $(DEPTH)/cmd/xfe/intl/sco.lm
|
||||
EN_LOCALE = C
|
||||
DE_LOCALE = de_DE.ISO8859-1
|
||||
FR_LOCALE = fr_FR.ISO8859-1
|
||||
JP_LOCALE = ja
|
||||
SJIS_LOCALE = ja_JP.SJIS
|
||||
KR_LOCALE = ko_KR.EUC
|
||||
CN_LOCALE = zh
|
||||
TW_LOCALE = zh
|
||||
I2_LOCALE = i2
|
||||
|
||||
LOC_LIB_DIR = /usr/lib/X11
|
||||
|
||||
NOSUCHFILE = /no-such-file
|
||||
|
||||
BSDECHO = /bin/echo
|
||||
|
||||
#
|
||||
# These defines are for building unix plugins
|
||||
#
|
||||
BUILD_UNIX_PLUGINS = 1
|
||||
#DSO_LDOPTS = -b elf -G -z defs
|
||||
DSO_LDOPTS = -b elf -G
|
||||
DSO_LDFLAGS = -nostdlib -L/lib -L/usr/lib -lXm -lXt -lX11 -lgen
|
||||
|
||||
# Used for Java compiler
|
||||
EXPORT_FLAGS = -W l,-Bexport
|
||||
74
mozilla/nsprpub/config/SINIX.mk
Normal file
74
mozilla/nsprpub/config/SINIX.mk
Normal file
@@ -0,0 +1,74 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SNI SINIX-N (aka ReliantUNIX)
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
# use gcc -tf-
|
||||
NS_USE_GCC = 1
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
## gcc-2.7.2 homebrewn
|
||||
CC = gcc
|
||||
COMPILER_TAG = _gcc
|
||||
CCC = g++
|
||||
AS = $(CC) -x assembler-with-cpp
|
||||
LD = gld
|
||||
ODD_CFLAGS = -pipe -Wall -Wno-format
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER = -O
|
||||
#OPTIMIZER = -O6
|
||||
endif
|
||||
MKSHLIB = $(LD) -G -h $(@:$(OBJDIR)/%.so=%.so)
|
||||
DSO_LDOPTS = -G -Xlinker -Blargedynsym
|
||||
else
|
||||
## native compiler (CDS++ 1.0)
|
||||
CC = /usr/bin/cc
|
||||
CCC = /usr/bin/CC
|
||||
AS = /usr/bin/cc
|
||||
#ODD_CFLAGS = -fullwarn -xansi
|
||||
ODD_CFLAGS =
|
||||
ifdef BUILD_OPT
|
||||
#OPTIMIZER = -Olimit 4000
|
||||
OPTIMIZER = -O -F Olimit,4000
|
||||
endif
|
||||
MKSHLIB = $(CC) -G -h $(@:$(OBJDIR)/%.so=%.so)
|
||||
DSO_LDOPTS = -G -W l,-Blargedynsym
|
||||
endif
|
||||
|
||||
ODD_CFLAGS += -DSVR4 -DSNI -DRELIANTUNIX -D_SVID_GETTOD
|
||||
|
||||
CPU_ARCH = mips
|
||||
|
||||
RANLIB = /bin/true
|
||||
|
||||
# For purify
|
||||
NOMD_OS_CFLAGS = $(ODD_CFLAGS)
|
||||
|
||||
# we do not have -MDupdate ...
|
||||
OS_CFLAGS = $(NOMD_OS_CFLAGS)
|
||||
OS_LIBS = -lsocket -lnsl -lresolv -lgen -ldl -lc $(UCBLIB)
|
||||
UCBLIB = -L/usr/ucblib -lucb
|
||||
NOSUCHFILE = /no-such-file
|
||||
|
||||
HAVE_PURIFY = 0
|
||||
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
OS_CFLAGS = $(ODD_CFLAGS) -DSVR4 -DSNI -Dsinix
|
||||
26
mozilla/nsprpub/config/SunOS.mk
Normal file
26
mozilla/nsprpub/config/SunOS.mk
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SunOS.
|
||||
# 4 and 5 are vastly different, so we use 2 different files.
|
||||
#
|
||||
ifeq ($(basename $(OS_RELEASE)),4.1)
|
||||
include $(MOD_DEPTH)/config/SunOS4.mk
|
||||
else
|
||||
include $(MOD_DEPTH)/config/SunOS5.mk
|
||||
endif
|
||||
48
mozilla/nsprpub/config/SunOS4.mk
Normal file
48
mozilla/nsprpub/config/SunOS4.mk
Normal file
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SunOS4.1
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
# SunOS 4 _requires_ that shared libs have a version number.
|
||||
# XXX FIXME: Version number should use NSPR_VERSION_NUMBER?
|
||||
DLL_SUFFIX = so.1.0
|
||||
|
||||
CC = gcc
|
||||
COMPILER_TAG = _gcc
|
||||
|
||||
RANLIB = ranlib
|
||||
|
||||
CPU_ARCH = sparc
|
||||
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
# Purify doesn't like -MDupdate
|
||||
NOMD_OS_CFLAGS = -Wall -Wno-format -DSUNOS4
|
||||
OS_CFLAGS = $(DSO_CFLAGS) $(NOMD_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
|
||||
HAVE_PURIFY = 1
|
||||
|
||||
NOSUCHFILE = /no-such-file
|
||||
|
||||
DSO_LDOPTS =
|
||||
# -fPIC generates position-independent code for use in a shared library.
|
||||
DSO_CFLAGS = -fPIC
|
||||
162
mozilla/nsprpub/config/SunOS5.mk
Normal file
162
mozilla/nsprpub/config/SunOS5.mk
Normal file
@@ -0,0 +1,162 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SunOS 5.x on sparc and x86
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
#
|
||||
# XXX
|
||||
# Temporary define for the Client; to be removed when binary release is used
|
||||
#
|
||||
ifdef MOZILLA_CLIENT
|
||||
LOCAL_THREADS_ONLY = 1
|
||||
ifndef NS_USE_NATIVE
|
||||
NS_USE_GCC = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# The default implementation strategy on Solaris is global threads only.
|
||||
# Local threads only and pthreads are also available.
|
||||
#
|
||||
ifeq ($(USE_PTHREADS),1)
|
||||
IMPL_STRATEGY = _PTH
|
||||
else
|
||||
ifeq ($(LOCAL_THREADS_ONLY),1)
|
||||
IMPL_STRATEGY = _LOCAL
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
else
|
||||
DEFINES += -D_PR_GLOBAL_THREADS_ONLY
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# XXX
|
||||
# Temporary define for the Client; to be removed when binary release is used
|
||||
#
|
||||
ifdef MOZILLA_CLIENT
|
||||
IMPL_STRATEGY =
|
||||
endif
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
CC = gcc -Wall
|
||||
CCC = g++ -Wall
|
||||
#
|
||||
# XXX
|
||||
# Temporary define for the Client; to be removed when binary release is used
|
||||
#
|
||||
ifdef MOZILLA_CLIENT
|
||||
#COMPILER_TAG = _gcc
|
||||
else
|
||||
COMPILER_TAG = _gcc
|
||||
endif
|
||||
#ASFLAGS += -x assembler-with-cpp
|
||||
ifdef NO_MDUPDATE
|
||||
OS_CFLAGS = $(NOMD_OS_CFLAGS)
|
||||
else
|
||||
OS_CFLAGS = $(NOMD_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
|
||||
endif
|
||||
else
|
||||
CC = cc -xstrconst
|
||||
CCC = CC -Qoption cg -xstrconst
|
||||
ASFLAGS += -Wa,-P
|
||||
OS_CFLAGS = $(NOMD_OS_CFLAGS)
|
||||
#
|
||||
# If we are building for a release, we want to put all symbol
|
||||
# tables in the debug executable or share library instead of
|
||||
# the .o files, so that our clients can run dbx on the debug
|
||||
# library without having the .o files around.
|
||||
#
|
||||
ifdef BUILD_NUMBER
|
||||
ifndef BUILD_OPT
|
||||
OS_CFLAGS += -xs
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
RANLIB = echo
|
||||
|
||||
OS_DEFINES = -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS
|
||||
|
||||
ifeq ($(OS_TEST),i86pc)
|
||||
CPU_ARCH = x86
|
||||
CPU_ARCH_TAG = _i86pc
|
||||
OS_DEFINES += -Di386
|
||||
else
|
||||
CPU_ARCH = sparc
|
||||
endif
|
||||
|
||||
ifeq (5.5,$(findstring 5.5,$(OS_RELEASE)))
|
||||
OS_DEFINES += -DSOLARIS2_5
|
||||
SOL_CFLAGS = -D_SVID_GETTOD
|
||||
endif
|
||||
|
||||
ifeq ($(OS_RELEASE),5.6)
|
||||
SOL_CFLAGS = -D_SVID_GETTOD
|
||||
endif
|
||||
|
||||
ifneq ($(LOCAL_THREADS_ONLY),1)
|
||||
OS_DEFINES += -D_REENTRANT
|
||||
endif
|
||||
|
||||
# Purify doesn't like -MDupdate
|
||||
NOMD_OS_CFLAGS = $(DSO_CFLAGS) $(OS_DEFINES) $(SOL_CFLAGS)
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
|
||||
# ld options:
|
||||
# -G: produce a shared object
|
||||
# -z defs: no unresolved symbols allowed
|
||||
DSO_LDOPTS = -G
|
||||
|
||||
# -KPIC generates position independent code for use in shared libraries.
|
||||
# (Similarly for -fPIC in case of gcc.)
|
||||
ifdef NS_USE_GCC
|
||||
DSO_CFLAGS = -fPIC
|
||||
else
|
||||
DSO_CFLAGS = -KPIC
|
||||
endif
|
||||
|
||||
HAVE_PURIFY = 1
|
||||
|
||||
NOSUCHFILE = /no-such-file
|
||||
|
||||
#
|
||||
# Library of atomic functions for UltraSparc systems
|
||||
#
|
||||
# The nspr makefiles build ULTRASPARC_LIBRARY (which contains assembly language
|
||||
# implementation of the nspr atomic functions for UltraSparc systems) in addition
|
||||
# to libnspr.so. (The actual name of the library is
|
||||
# lib$(ULTRASPARC_LIBRARY)$(MOD_VERSION).so
|
||||
#
|
||||
# The actual name of the filter-library, recorded in libnspr.so, is set to the
|
||||
# value of $(ULTRASPARC_FILTER_LIBRARY).
|
||||
# For an application to use the assembly-language implementation, a link should be
|
||||
# made so that opening ULTRASPARC_FILTER_LIBRARY results in opening
|
||||
# ULTRASPARC_LIBRARY. This indirection requires the user to explicitly set up
|
||||
# library for use on UltraSparc systems, thereby helping to avoid using it by
|
||||
# accident on non-UltraSparc systems.
|
||||
# The directory containing the ultrasparc libraries should be in LD_LIBRARY_PATH.
|
||||
#
|
||||
ifeq ($(OS_TEST),sun4u)
|
||||
ULTRASPARC_LIBRARY = ultrasparc
|
||||
ULTRASPARC_FILTER_LIBRARY = libatomic.so
|
||||
DSO_LDOPTS += -f $(ULTRASPARC_FILTER_LIBRARY)
|
||||
endif
|
||||
70
mozilla/nsprpub/config/UNIX.mk
Normal file
70
mozilla/nsprpub/config/UNIX.mk
Normal file
@@ -0,0 +1,70 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
XP_DEFINE = -DXP_UNIX
|
||||
OBJ_SUFFIX = o
|
||||
LIB_SUFFIX = a
|
||||
DLL_SUFFIX = so
|
||||
AR = ar cr $@
|
||||
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER = -O
|
||||
DEFINES = -UDEBUG -DNDEBUG
|
||||
OBJDIR_TAG = _OPT
|
||||
else
|
||||
OPTIMIZER = -g
|
||||
DEFINES = -DDEBUG -UNDEBUG -DDEBUG_$(shell whoami)
|
||||
OBJDIR_TAG = _DBG
|
||||
endif
|
||||
|
||||
# Name of the binary code directories
|
||||
OBJDIR_NAME = $(OS_CONFIG)$(CPU_ARCH_TAG)$(COMPILER_TAG)$(IMPL_STRATEGY)$(OBJDIR_TAG).OBJ
|
||||
|
||||
MKDEPEND_DIR = $(DEPTH)/config/mkdepend
|
||||
MKDEPEND = $(MKDEPEND_DIR)/$(OBJDIR_NAME)/mkdepend
|
||||
MKDEPENDENCIES = $(OBJDIR)/depend.mk
|
||||
|
||||
####################################################################
|
||||
#
|
||||
# One can define the makefile variable NSDISTMODE to control
|
||||
# how files are published to the 'dist' directory. If not
|
||||
# defined, the default is "install using relative symbolic
|
||||
# links". The two possible values are "copy", which copies files
|
||||
# but preserves source mtime, and "absolute_symlink", which
|
||||
# installs using absolute symbolic links. The "absolute_symlink"
|
||||
# option requires NFSPWD.
|
||||
#
|
||||
####################################################################
|
||||
|
||||
NSINSTALL = $(MOD_DEPTH)/config/$(OBJDIR_NAME)/nsinstall
|
||||
|
||||
ifeq ($(NSDISTMODE),copy)
|
||||
# copy files, but preserve source mtime
|
||||
INSTALL = $(NSINSTALL) -t
|
||||
else
|
||||
ifeq ($(NSDISTMODE),absolute_symlink)
|
||||
# install using absolute symbolic links
|
||||
INSTALL = $(NSINSTALL) -L `$(NFSPWD)`
|
||||
else
|
||||
# install using relative symbolic links
|
||||
INSTALL = $(NSINSTALL) -R
|
||||
endif
|
||||
endif
|
||||
|
||||
define MAKE_OBJDIR
|
||||
if test ! -d $(@D); then rm -rf $(@D); $(NSINSTALL) -D $(@D); fi
|
||||
endef
|
||||
38
mozilla/nsprpub/config/UNIXWARE.mk
Normal file
38
mozilla/nsprpub/config/UNIXWARE.mk
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SCO UnixWare
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/UNIX.mk
|
||||
|
||||
CC = $(NSDEPTH)/build/hcc
|
||||
CCC = $(NSDEPTH)/build/hcpp
|
||||
|
||||
RANLIB = true
|
||||
|
||||
DEFINES += -D_PR_LOCAL_THREADS_ONLY
|
||||
OS_CFLAGS = -DSVR4 -DSYSV -DUNIXWARE
|
||||
|
||||
MKSHLIB = $(LD) $(DSO_LDOPTS)
|
||||
DSO_LDOPTS = -G
|
||||
|
||||
CPU_ARCH = x86
|
||||
ARCH = sco
|
||||
|
||||
NOSUCHFILE = /no-such-file
|
||||
139
mozilla/nsprpub/config/WIN32.mk
Normal file
139
mozilla/nsprpub/config/WIN32.mk
Normal file
@@ -0,0 +1,139 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Configuration common to all versions of Windows NT
|
||||
# and Windows 95.
|
||||
#
|
||||
|
||||
#
|
||||
# Client build: make sure we use the shmsdos.exe under $(MOZ_TOOLS).
|
||||
# $(MOZ_TOOLS_FLIPPED) is $(MOZ_TOOLS) with all the backslashes
|
||||
# flipped, so that gmake won't interpret them as escape characters.
|
||||
#
|
||||
ifdef PR_CLIENT_BUILD_WINDOWS
|
||||
SHELL = $(MOZ_TOOLS_FLIPPED)/bin/shmsdos.exe
|
||||
endif
|
||||
|
||||
CC = cl
|
||||
CCC = cl
|
||||
LINK = link
|
||||
AR = lib -NOLOGO -OUT:"$@"
|
||||
RANLIB = echo
|
||||
BSDECHO = echo
|
||||
NSINSTALL = nsinstall
|
||||
INSTALL = $(NSINSTALL)
|
||||
define MAKE_OBJDIR
|
||||
if test ! -d $(@D); then rm -rf $(@D); $(NSINSTALL) -D $(@D); fi
|
||||
endef
|
||||
RC = rc.exe
|
||||
|
||||
GARBAGE = $(OBJDIR)/vc20.pdb $(OBJDIR)/vc40.pdb
|
||||
|
||||
XP_DEFINE = -DXP_PC
|
||||
OBJ_SUFFIX = obj
|
||||
LIB_SUFFIX = lib
|
||||
DLL_SUFFIX = dll
|
||||
|
||||
OS_CFLAGS = -W3 -nologo -GF -Gy
|
||||
|
||||
ifdef MOZ_PROF
|
||||
|
||||
#
|
||||
# compile with debug symbols, but without DEBUG code and ASSERTs
|
||||
#
|
||||
ifdef USE_DEBUG_RTL
|
||||
OS_CFLAGS += -MDd
|
||||
else
|
||||
OS_CFLAGS += -MD
|
||||
endif
|
||||
OPTIMIZER = -Od -Z7
|
||||
#OPTIMIZER = -Zi -Fd$(OBJDIR)/ -Od
|
||||
DEFINES = -UDEBUG -U_DEBUG -DNDEBUG
|
||||
DLLFLAGS = -DEBUG -DEBUGTYPE:CV -OUT:"$@"
|
||||
OBJDIR_TAG = _DBG
|
||||
LDFLAGS = -DEBUG -DEBUGTYPE:CV
|
||||
|
||||
else
|
||||
|
||||
ifdef BUILD_OPT
|
||||
OS_CFLAGS += -MD
|
||||
OPTIMIZER = -O2
|
||||
DEFINES = -UDEBUG -U_DEBUG -DNDEBUG
|
||||
DLLFLAGS = -OUT:"$@"
|
||||
OBJDIR_TAG = _OPT
|
||||
else
|
||||
#
|
||||
# Define USE_DEBUG_RTL if you want to use the debug runtime library
|
||||
# (RTL) in the debug build
|
||||
#
|
||||
ifdef USE_DEBUG_RTL
|
||||
OS_CFLAGS += -MDd
|
||||
else
|
||||
OS_CFLAGS += -MD
|
||||
endif
|
||||
OPTIMIZER = -Od -Z7
|
||||
#OPTIMIZER = -Zi -Fd$(OBJDIR)/ -Od
|
||||
DEFINES = -DDEBUG -D_DEBUG -UNDEBUG
|
||||
DLLFLAGS = -DEBUG -DEBUGTYPE:CV -OUT:"$@"
|
||||
OBJDIR_TAG = _DBG
|
||||
LDFLAGS = -DEBUG -DEBUGTYPE:CV
|
||||
endif
|
||||
endif
|
||||
|
||||
DEFINES += -DWIN32
|
||||
ifeq ($(OS_TARGET),WINNT)
|
||||
#
|
||||
# Win NT needs -GT so that fibers can work
|
||||
#
|
||||
OS_CFLAGS += -GT
|
||||
DEFINES += -DWINNT
|
||||
else
|
||||
DEFINES += -DWIN95 -D_PR_GLOBAL_THREADS_ONLY
|
||||
endif
|
||||
|
||||
ifeq ($(CPU_ARCH),x386)
|
||||
DEFINES += -D_X86_
|
||||
else
|
||||
ifeq ($(CPU_ARCH),MIPS)
|
||||
DEFINES += -D_MIPS_
|
||||
else
|
||||
ifeq ($(CPU_ARCH),ALPHA)
|
||||
DEFINES += -D_ALPHA_=1
|
||||
else
|
||||
CPU_ARCH = processor_is_undefined
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Name of the binary code directories
|
||||
|
||||
ifeq ($(CPU_ARCH),x386)
|
||||
CPU_ARCH_TAG =
|
||||
else
|
||||
CPU_ARCH_TAG = $(CPU_ARCH)
|
||||
endif
|
||||
|
||||
ifdef USE_DEBUG_RTL
|
||||
OBJDIR_SUFFIX = OBJD
|
||||
else
|
||||
OBJDIR_SUFFIX = OBJ
|
||||
endif
|
||||
|
||||
OBJDIR_NAME = $(OS_CONFIG)$(CPU_ARCH_TAG)$(OBJDIR_TAG).$(OBJDIR_SUFFIX)
|
||||
|
||||
OS_DLLFLAGS = -nologo -DLL -SUBSYSTEM:WINDOWS -PDB:NONE
|
||||
22
mozilla/nsprpub/config/WIN95.mk
Normal file
22
mozilla/nsprpub/config/WIN95.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for WIN95
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/WIN32.mk
|
||||
22
mozilla/nsprpub/config/WINNT.mk
Normal file
22
mozilla/nsprpub/config/WINNT.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for WINNT
|
||||
#
|
||||
|
||||
include $(MOD_DEPTH)/config/WIN32.mk
|
||||
200
mozilla/nsprpub/config/arch.mk
Normal file
200
mozilla/nsprpub/config/arch.mk
Normal file
@@ -0,0 +1,200 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# Master "Core Components" macros for getting the OS architecture #
|
||||
#######################################################################
|
||||
|
||||
#
|
||||
# Important internal static macros
|
||||
#
|
||||
|
||||
OS_ARCH := $(subst /,_,$(shell uname -s))
|
||||
OS_RELEASE := $(shell uname -r)
|
||||
OS_TEST := $(shell uname -m)
|
||||
|
||||
#
|
||||
# Tweak the default OS_ARCH and OS_RELEASE macros as needed.
|
||||
#
|
||||
ifeq ($(OS_ARCH),AIX)
|
||||
OS_RELEASE := $(shell uname -v).$(shell uname -r)
|
||||
endif
|
||||
ifeq ($(OS_ARCH),BSD_386)
|
||||
OS_ARCH := BSD_OS
|
||||
endif
|
||||
ifeq ($(OS_ARCH),IRIX64)
|
||||
OS_ARCH := IRIX
|
||||
endif
|
||||
ifeq ($(OS_ARCH),UNIX_SV)
|
||||
ifneq ($(findstring NCR,$(shell grep NCR /etc/bcheckrc | head -1 )),)
|
||||
OS_ARCH := NCR
|
||||
else
|
||||
OS_ARCH := UNIXWARE
|
||||
OS_RELEASE := $(shell uname -v)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(OS_ARCH),ncr)
|
||||
OS_ARCH := NCR
|
||||
endif
|
||||
# This is the only way to correctly determine the actual OS version on NCR boxes.
|
||||
ifeq ($(OS_ARCH),NCR)
|
||||
OS_RELEASE := $(shell awk '{print $$3}' /etc/.relid | sed 's/^\([0-9]\)\(.\)\(..\)\(.*\)$$/\2.\3/')
|
||||
endif
|
||||
ifeq ($(OS_ARCH),UNIX_System_V)
|
||||
OS_ARCH := NEC
|
||||
endif
|
||||
ifeq ($(OS_ARCH),SCO_SV)
|
||||
OS_ARCH := SCOOS
|
||||
OS_RELEASE := 5.0
|
||||
endif
|
||||
ifeq ($(OS_ARCH),SINIX-N)
|
||||
OS_ARCH := SINIX
|
||||
endif
|
||||
# SINIX changes name to ReliantUNIX with 5.43
|
||||
ifeq ($(OS_ARCH),ReliantUNIX-N)
|
||||
OS_ARCH := SINIX
|
||||
endif
|
||||
ifeq ($(OS_ARCH),UnixWare)
|
||||
OS_ARCH := UNIXWARE
|
||||
OS_RELEASE := $(shell uname -v)
|
||||
endif
|
||||
|
||||
#
|
||||
# Handle FreeBSD 2.2-STABLE and Linux 2.0.30-osfmach3
|
||||
#
|
||||
|
||||
ifeq (,$(filter-out Linux FreeBSD,$(OS_ARCH)))
|
||||
OS_RELEASE := $(shell echo $(OS_RELEASE) | sed 's/-.*//')
|
||||
endif
|
||||
|
||||
#
|
||||
# Distinguish between OSF1 V4.0B and V4.0D
|
||||
#
|
||||
|
||||
ifeq ($(OS_ARCH)$(OS_RELEASE),OSF1V4.0)
|
||||
OS_VERSION := $(shell uname -v)
|
||||
ifeq ($(OS_VERSION),564)
|
||||
OS_RELEASE := V4.0B
|
||||
endif
|
||||
ifeq ($(OS_VERSION),878)
|
||||
OS_RELEASE := V4.0D
|
||||
endif
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
# Master "Core Components" macros for getting the OS target #
|
||||
#######################################################################
|
||||
|
||||
#
|
||||
# Note: OS_TARGET should be specified on the command line for gmake.
|
||||
# When OS_TARGET=WIN95 is specified, then a Windows 95 target is built.
|
||||
# The difference between the Win95 target and the WinNT target is that
|
||||
# the WinNT target uses Windows NT specific features not available
|
||||
# in Windows 95. The Win95 target will run on Windows NT, but (supposedly)
|
||||
# at lesser performance (the Win95 target uses threads; the WinNT target
|
||||
# uses fibers).
|
||||
#
|
||||
# When OS_TARGET=WIN16 is specified, then a Windows 3.11 (16bit) target
|
||||
# is built. See: win16_3.11.mk for lots more about the Win16 target.
|
||||
#
|
||||
# If OS_TARGET is not specified, it defaults to $(OS_ARCH), i.e., no
|
||||
# cross-compilation.
|
||||
#
|
||||
|
||||
#
|
||||
# The following hack allows one to build on a WIN95 machine (as if
|
||||
# s/he were cross-compiling on a WINNT host for a WIN95 target).
|
||||
# It also accomodates for MKS's uname.exe. If you never intend
|
||||
# to do development on a WIN95 machine, you don't need this hack.
|
||||
#
|
||||
ifeq ($(OS_ARCH),WIN95)
|
||||
OS_ARCH := WINNT
|
||||
OS_TARGET := WIN95
|
||||
endif
|
||||
ifeq ($(OS_ARCH),Windows_95)
|
||||
OS_ARCH := Windows_NT
|
||||
OS_TARGET := WIN95
|
||||
endif
|
||||
ifeq ($(OS_ARCH), OS2)
|
||||
OS_ARCH := WINNT
|
||||
OS_TARGET := OS2
|
||||
endif
|
||||
|
||||
#
|
||||
# On WIN32, we also define the variable CPU_ARCH.
|
||||
#
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
CPU_ARCH := $(shell uname -p)
|
||||
ifeq ($(CPU_ARCH),I386)
|
||||
CPU_ARCH = x386
|
||||
endif
|
||||
else
|
||||
#
|
||||
# If uname -s returns "Windows_NT", we assume that we are using
|
||||
# the uname.exe in MKS toolkit.
|
||||
#
|
||||
# The -r option of MKS uname only returns the major version number.
|
||||
# So we need to use its -v option to get the minor version number.
|
||||
# Moreover, it doesn't have the -p option, so we need to use uname -m.
|
||||
#
|
||||
ifeq ($(OS_ARCH), Windows_NT)
|
||||
OS_ARCH = WINNT
|
||||
OS_MINOR_RELEASE := $(shell uname -v)
|
||||
ifeq ($(OS_MINOR_RELEASE),00)
|
||||
OS_MINOR_RELEASE = 0
|
||||
endif
|
||||
OS_RELEASE := $(OS_RELEASE).$(OS_MINOR_RELEASE)
|
||||
CPU_ARCH := $(shell uname -m)
|
||||
#
|
||||
# MKS's uname -m returns "586" on a Pentium machine.
|
||||
#
|
||||
ifneq (,$(findstring 86,$(CPU_ARCH)))
|
||||
CPU_ARCH = x386
|
||||
endif
|
||||
else
|
||||
#
|
||||
# If uname -s returns "CYGWIN32/NT", we assume that we are using
|
||||
# the uname.exe in the GNU-Win32 tools.
|
||||
#
|
||||
ifeq ($(OS_ARCH), CYGWIN32_NT)
|
||||
OS_ARCH = WINNT
|
||||
CPU_ARCH := $(shell uname -m)
|
||||
#
|
||||
# GNU-Win32's uname -m returns "i686" on a Pentium Pro machine.
|
||||
#
|
||||
ifneq (,$(findstring 86,$(CPU_ARCH)))
|
||||
CPU_ARCH = x386
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef OS_TARGET
|
||||
OS_TARGET := $(OS_ARCH)
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET), WIN95)
|
||||
OS_RELEASE := 4.0
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET), WIN16)
|
||||
OS_RELEASE :=
|
||||
# OS_RELEASE := _3.11
|
||||
endif
|
||||
|
||||
OS_CONFIG := $(OS_TARGET)$(OS_RELEASE)
|
||||
116
mozilla/nsprpub/config/config.mk
Normal file
116
mozilla/nsprpub/config/config.mk
Normal file
@@ -0,0 +1,116 @@
|
||||
#! gmake
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# Configuration information for building in the NSPR source module
|
||||
|
||||
# Define an include-at-most-once-flag
|
||||
NSPR_CONFIG_MK = 1
|
||||
|
||||
include $(MOD_DEPTH)/config/module.df
|
||||
|
||||
include $(MOD_DEPTH)/config/arch.mk
|
||||
|
||||
ifndef NSDEPTH
|
||||
NSDEPTH = $(MOD_DEPTH)/..
|
||||
endif
|
||||
|
||||
#
|
||||
# Default command macros; can be overridden in <arch>.mk.
|
||||
#
|
||||
# XXX FIXME: I removed CCF and LINKEXE.
|
||||
AS = $(CC)
|
||||
ASFLAGS = $(CFLAGS)
|
||||
PURIFY = purify $(PURIFYOPTIONS)
|
||||
LINK_DLL = $(LINK) $(OS_DLLFLAGS) $(DLLFLAGS)
|
||||
NFSPWD = $(MOD_DEPTH)/config/nfspwd
|
||||
|
||||
LIBNSPR = $(DIST)/lib/libnspr.$(LIB_SUFFIX)
|
||||
PURELIBNSPR = $(DIST)/lib/libpurenspr.$(LIB_SUFFIX)
|
||||
|
||||
CFLAGS = $(OPTIMIZER) $(OS_CFLAGS) $(XP_DEFINE) $(DEFINES) $(INCLUDES) \
|
||||
$(XCFLAGS)
|
||||
# For purify
|
||||
NOMD_CFLAGS = $(OPTIMIZER) $(NOMD_OS_CFLAGS) $(XP_DEFINE) $(DEFINES) $(INCLUDES) \
|
||||
$(XCFLAGS)
|
||||
|
||||
include $(MOD_DEPTH)/config/$(OS_TARGET).mk
|
||||
|
||||
# Figure out where the binary code lives.
|
||||
BUILD = $(OBJDIR_NAME)
|
||||
OBJDIR = $(OBJDIR_NAME)
|
||||
DIST = $(NSDEPTH)/dist/$(OBJDIR_NAME)
|
||||
ifeq ($(MOZ_BITS),16)
|
||||
MOZ_INCL = $(NSDEPTH)/dist/public/win16
|
||||
MOZ_DIST = $(NSDEPTH)/dist/WIN16D_D.OBJ
|
||||
endif
|
||||
|
||||
VPATH = $(OBJDIR)
|
||||
DEPENDENCIES = $(OBJDIR)/.md
|
||||
|
||||
ifdef BUILD_DEBUG_GC
|
||||
DEFINES += -DDEBUG_GC
|
||||
endif
|
||||
|
||||
GARBAGE += $(DEPENDENCIES) core $(wildcard core.[0-9]*)
|
||||
|
||||
####################################################################
|
||||
#
|
||||
# The NSPR-specific configuration
|
||||
#
|
||||
####################################################################
|
||||
|
||||
OS_CFLAGS += -DFORCE_PR_LOG
|
||||
|
||||
ifeq ($(_PR_NO_CLOCK_TIMER),1)
|
||||
OS_CFLAGS += -D_PR_NO_CLOCK_TIMER
|
||||
endif
|
||||
|
||||
ifeq ($(USE_PTHREADS), 1)
|
||||
OS_CFLAGS += -D_PR_PTHREADS -UHAVE_CVAR_BUILT_ON_SEM
|
||||
endif
|
||||
|
||||
ifeq ($(PTHREADS_USER), 1)
|
||||
OS_CFLAGS += -DPTHREADS_USER -UHAVE_CVAR_BUILT_ON_SEM
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CTHREADS), 1)
|
||||
OS_CFLAGS += -D_PR_CTHREADS
|
||||
endif
|
||||
|
||||
ifeq ($(USE_IPV6),1)
|
||||
OS_CFLAGS += -D_PR_INET6
|
||||
endif
|
||||
|
||||
####################################################################
|
||||
#
|
||||
# Configuration for the release process
|
||||
#
|
||||
####################################################################
|
||||
|
||||
MDIST = /m/dist
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
MDIST = //helium/dist
|
||||
MDIST_DOS = \\\\helium\\dist
|
||||
endif
|
||||
|
||||
# RELEASE_DIR is ns/dist/<module name>
|
||||
|
||||
RELEASE_DIR = $(NSDEPTH)/dist/release/$(MOD_NAME)
|
||||
|
||||
RELEASE_INCLUDE_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/include
|
||||
RELEASE_LIB_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/lib
|
||||
139
mozilla/nsprpub/config/libc_r.h
Normal file
139
mozilla/nsprpub/config/libc_r.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/* libc_r.h -- macros, defines, etc. to make using reentrant libc calls */
|
||||
/* a bit easier. This was initially done for AIX pthreads, */
|
||||
/* but should be usable for anyone... */
|
||||
|
||||
/* Most of these use locally defined space instead of static library space. */
|
||||
/* Because of this, we use the _INIT_R to declare/allocate space (stack), */
|
||||
/* and the plain routines to actually do it..._WARNING_: avoid allocating */
|
||||
/* memory wherever possible. Memory allocation is fairly expensive, at */
|
||||
/* least on AIX...use arrays instead (which allocate from the stack.) */
|
||||
/* I know the names are a bit strange, but I wanted to be fairly certain */
|
||||
/* that we didn't have any namespace corruption...in general, the inits are */
|
||||
/* R_<name>_INIT_R(), and the actual calls are R_<name>_R(). */
|
||||
|
||||
#ifndef _LIBC_R_H
|
||||
#define _LIBC_R_H
|
||||
|
||||
/************/
|
||||
/* strtok */
|
||||
/************/
|
||||
#define R_STRTOK_INIT_R() \
|
||||
char *r_strtok_r=NULL
|
||||
|
||||
#define R_STRTOK_R(return,source,delim) \
|
||||
return=strtok_r(source,delim,&r_strtok_r)
|
||||
|
||||
#define R_STRTOK_NORET_R(source,delim) \
|
||||
strtok_r(source,delim,&r_strtok_r)
|
||||
|
||||
/**************/
|
||||
/* strerror */
|
||||
/**************/
|
||||
#define R_MAX_STRERROR_LEN_R 8192 /* Straight from limits.h */
|
||||
|
||||
#define R_STRERROR_INIT_R() \
|
||||
char r_strerror_r[R_MAX_STRERROR_LEN_R]
|
||||
|
||||
#define R_STRERROR_R(val) \
|
||||
strerror_r(val,r_strerror_r,R_MAX_STRERROR_LEN_R)
|
||||
|
||||
/*****************/
|
||||
/* time things */
|
||||
/*****************/
|
||||
#define R_ASCTIME_INIT_R() \
|
||||
char r_asctime_r[26]
|
||||
|
||||
#define R_ASCTIME_R(val) \
|
||||
asctime_r(val,r_asctime_r)
|
||||
|
||||
#define R_CTIME_INIT_R() \
|
||||
char r_ctime_r[26]
|
||||
|
||||
#define R_CTIME_R(val) \
|
||||
ctime_r(val,r_ctime_r)
|
||||
|
||||
#define R_GMTIME_INIT_R() \
|
||||
struct tm r_gmtime_r
|
||||
|
||||
#define R_GMTIME_R(time) \
|
||||
gmtime_r(time,&r_gmtime_r)
|
||||
|
||||
#define R_LOCALTIME_INIT_R() \
|
||||
struct tm r_localtime_r
|
||||
|
||||
#define R_LOCALTIME_R(val) \
|
||||
localtime_r(val,&r_localtime_r)
|
||||
|
||||
/***********/
|
||||
/* crypt */
|
||||
/***********/
|
||||
#include <crypt.h>
|
||||
#define R_CRYPT_INIT_R() \
|
||||
CRYPTD r_cryptd_r; \
|
||||
bzero(&r_cryptd_r,sizeof(CRYPTD))
|
||||
|
||||
#define R_CRYPT_R(pass,salt) \
|
||||
crypt_r(pass,salt,&r_cryptd_r)
|
||||
|
||||
/**************/
|
||||
/* pw stuff */
|
||||
/**************/
|
||||
#define R_MAX_PW_LEN_R 1024
|
||||
/* The following must be after the last declaration, but */
|
||||
/* before the first bit of code... */
|
||||
#define R_GETPWNAM_INIT_R(pw_ptr) \
|
||||
struct passwd r_getpwnam_pw_r; \
|
||||
char r_getpwnam_line_r[R_MAX_PW_LEN_R]; \
|
||||
pw_ptr = &r_getpwnam_pw_r
|
||||
|
||||
#define R_GETPWNAM_R(name) \
|
||||
getpwnam_r(name,&r_getpwnam_pw_r,r_getpwnam_line_r,R_MAX_PW_LEN_R)
|
||||
|
||||
/*******************/
|
||||
/* gethost stuff */
|
||||
/*******************/
|
||||
#define R_GETHOSTBYADDR_INIT_R() \
|
||||
struct hostent r_gethostbyaddr_r; \
|
||||
struct hostent_data r_gethostbyaddr_data_r
|
||||
|
||||
#define R_GETHOSTBYADDR_R(addr,len,type,xptr_ent) \
|
||||
bzero(&r_gethostbyaddr_r,sizeof(struct hostent)); \
|
||||
bzero(&r_gethostbyaddr_data_r,sizeof(struct hostent_data)); \
|
||||
xptr_ent = &r_gethostbyaddr_r; \
|
||||
if (gethostbyaddr_r(addr,len,type, \
|
||||
&r_gethostbyaddr_r,&r_gethostbyaddr_data_r) == -1) { \
|
||||
xptr_ent = NULL; \
|
||||
}
|
||||
|
||||
#define R_GETHOSTBYNAME_INIT_R() \
|
||||
struct hostent r_gethostbyname_r; \
|
||||
struct hostent_data r_gethostbyname_data_r
|
||||
|
||||
#define R_GETHOSTBYNAME_R(name,xptr_ent) \
|
||||
bzero(&r_gethostbyname_r,sizeof(struct hostent)); \
|
||||
bzero(&r_gethostbyname_data_r,sizeof(struct hostent_data)); \
|
||||
xptr_ent = &r_gethostbyname_r; \
|
||||
if (gethostbyname_r(name, \
|
||||
&r_gethostbyname_r,&r_gethostbyname_data_r) == -1) { \
|
||||
xptr_ent = NULL; \
|
||||
}
|
||||
|
||||
#endif /* _LIBC_R_H */
|
||||
23
mozilla/nsprpub/config/module.df
Normal file
23
mozilla/nsprpub/config/module.df
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# Module description file
|
||||
#
|
||||
# A module is also called a component or a subsystem.
|
||||
|
||||
MOD_NAME = nspr20
|
||||
MOD_VERSION = 21
|
||||
30
mozilla/nsprpub/config/nfspwd.pl
Normal file
30
mozilla/nsprpub/config/nfspwd.pl
Normal file
@@ -0,0 +1,30 @@
|
||||
#! perl
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
require "fastcwd.pl";
|
||||
|
||||
$_ = &fastcwd;
|
||||
if (m@^/[uh]/@o || s@^/tmp_mnt/@/@o) {
|
||||
print("$_\n");
|
||||
} elsif ((($user, $rest) = m@^/usr/people/(\w+)/(.*)@o)
|
||||
&& readlink("/u/$user") eq "/usr/people/$user") {
|
||||
print("/u/$user/$rest\n");
|
||||
} else {
|
||||
chop($host = `hostname`);
|
||||
print("/h/$host$_\n");
|
||||
}
|
||||
336
mozilla/nsprpub/config/nsinstall.c
Normal file
336
mozilla/nsprpub/config/nsinstall.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Netscape portable install command.
|
||||
**
|
||||
** Brendan Eich, 7/20/95
|
||||
*/
|
||||
#include <stdio.h> /* OSF/1 requires this before grp.h, so put it first */
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "pathsub.h"
|
||||
|
||||
#define HAVE_LCHOWN
|
||||
|
||||
#if defined(AIX) || defined(BSDI) || defined(HPUX) || defined(LINUX) || defined(SUNOS4) || defined(SCO) || defined(UNIXWARE) || defined(RHAPSODY)
|
||||
#undef HAVE_LCHOWN
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Does getcwd() take NULL as the first argument and malloc
|
||||
* the result buffer?
|
||||
*/
|
||||
#if !defined(RHAPSODY)
|
||||
#define GETCWD_CAN_MALLOC
|
||||
#endif
|
||||
|
||||
#ifdef LINUX
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
#if defined(SCO) || defined(UNIXWARE) || defined(SNI) || defined(NCR) || defined(NEC)
|
||||
#if !defined(S_ISLNK) && defined(S_IFLNK)
|
||||
#define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(SNI)
|
||||
extern int fchmod(int fildes, mode_t mode);
|
||||
#endif
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
|
||||
" %*s [-DdltR] file [file ...] directory\n",
|
||||
program, strlen(program), "");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static int
|
||||
mkdirs(char *path, mode_t mode)
|
||||
{
|
||||
char *cp;
|
||||
struct stat sb;
|
||||
|
||||
while (*path == '/' && path[1] == '/')
|
||||
path++;
|
||||
while ((cp = strrchr(path, '/')) && cp[1] == '\0')
|
||||
*cp = '\0';
|
||||
if (cp && cp != path) {
|
||||
*cp = '\0';
|
||||
if ((lstat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
|
||||
mkdirs(path, mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
*cp = '/';
|
||||
}
|
||||
return mkdir(path, mode);
|
||||
}
|
||||
|
||||
static uid_t
|
||||
touid(char *owner)
|
||||
{
|
||||
struct passwd *pw;
|
||||
uid_t uid;
|
||||
char *cp;
|
||||
|
||||
pw = getpwnam(owner);
|
||||
if (pw)
|
||||
return pw->pw_uid;
|
||||
uid = strtol(owner, &cp, 0);
|
||||
if (uid == 0 && cp == owner)
|
||||
fail("cannot find uid for %s", owner);
|
||||
return uid;
|
||||
}
|
||||
|
||||
static gid_t
|
||||
togid(char *group)
|
||||
{
|
||||
struct group *gr;
|
||||
gid_t gid;
|
||||
char *cp;
|
||||
|
||||
gr = getgrnam(group);
|
||||
if (gr)
|
||||
return gr->gr_gid;
|
||||
gid = strtol(group, &cp, 0);
|
||||
if (gid == 0 && cp == group)
|
||||
fail("cannot find gid for %s", group);
|
||||
return gid;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists, fromfd, tofd, cc, wc;
|
||||
mode_t mode = 0755;
|
||||
char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *bp, buf[BUFSIZ];
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
struct stat sb, tosb;
|
||||
struct utimbuf utb;
|
||||
|
||||
program = argv[0];
|
||||
cwd = linkname = linkprefix = owner = group = 0;
|
||||
onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'C':
|
||||
cwd = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
onlydir = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dodir = 1;
|
||||
break;
|
||||
case 'l':
|
||||
dolink = 1;
|
||||
break;
|
||||
case 'L':
|
||||
linkprefix = optarg;
|
||||
lplen = strlen(linkprefix);
|
||||
dolink = 1;
|
||||
break;
|
||||
case 'R':
|
||||
dolink = dorelsymlink = 1;
|
||||
break;
|
||||
case 'm':
|
||||
mode = strtoul(optarg, &cp, 8);
|
||||
if (mode == 0 && cp == optarg)
|
||||
usage();
|
||||
break;
|
||||
case 'o':
|
||||
owner = optarg;
|
||||
break;
|
||||
case 'g':
|
||||
group = optarg;
|
||||
break;
|
||||
case 't':
|
||||
dotimes = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc < 2 - onlydir)
|
||||
usage();
|
||||
|
||||
todir = argv[argc-1];
|
||||
if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
|
||||
mkdirs(todir, 0777) < 0) {
|
||||
fail("cannot make directory %s", todir);
|
||||
}
|
||||
if (onlydir)
|
||||
return 0;
|
||||
|
||||
if (!cwd) {
|
||||
#ifdef GETCWD_CAN_MALLOC
|
||||
cwd = getcwd(0, PATH_MAX);
|
||||
#else
|
||||
cwd = malloc(PATH_MAX + 1);
|
||||
cwd = getcwd(cwd, PATH_MAX);
|
||||
#endif
|
||||
}
|
||||
xchdir(todir);
|
||||
#ifdef GETCWD_CAN_MALLOC
|
||||
todir = getcwd(0, PATH_MAX);
|
||||
#else
|
||||
todir = malloc(PATH_MAX + 1);
|
||||
todir = getcwd(todir, PATH_MAX);
|
||||
#endif
|
||||
tdlen = strlen(todir);
|
||||
xchdir(cwd);
|
||||
tdlen = strlen(todir);
|
||||
|
||||
uid = owner ? touid(owner) : -1;
|
||||
gid = group ? togid(group) : -1;
|
||||
|
||||
while (--argc > 0) {
|
||||
name = *argv++;
|
||||
len = strlen(name);
|
||||
base = xbasename(name);
|
||||
bnlen = strlen(base);
|
||||
toname = (char*)xmalloc(tdlen + 1 + bnlen + 1);
|
||||
sprintf(toname, "%s/%s", todir, base);
|
||||
exists = (lstat(toname, &tosb) == 0);
|
||||
|
||||
if (dodir) {
|
||||
/* -d means create a directory, always */
|
||||
if (exists && !S_ISDIR(tosb.st_mode)) {
|
||||
(void) unlink(toname);
|
||||
exists = 0;
|
||||
}
|
||||
if (!exists && mkdir(toname, mode) < 0)
|
||||
fail("cannot make directory %s", toname);
|
||||
if ((owner || group) && chown(toname, uid, gid) < 0)
|
||||
fail("cannot change owner of %s", toname);
|
||||
} else if (dolink) {
|
||||
if (*name == '/') {
|
||||
/* source is absolute pathname, link to it directly */
|
||||
linkname = 0;
|
||||
} else {
|
||||
if (linkprefix) {
|
||||
/* -L implies -l and prefixes names with a $cwd arg. */
|
||||
len += lplen + 1;
|
||||
linkname = (char*)xmalloc(len + 1);
|
||||
sprintf(linkname, "%s/%s", linkprefix, name);
|
||||
} else if (dorelsymlink) {
|
||||
/* Symlink the relative path from todir to source name. */
|
||||
linkname = (char*)xmalloc(PATH_MAX);
|
||||
|
||||
if (*todir == '/') {
|
||||
/* todir is absolute: skip over common prefix. */
|
||||
lplen = relatepaths(todir, cwd, linkname);
|
||||
strcpy(linkname + lplen, name);
|
||||
} else {
|
||||
/* todir is named by a relative path: reverse it. */
|
||||
reversepath(todir, name, len, linkname);
|
||||
xchdir(cwd);
|
||||
}
|
||||
|
||||
len = strlen(linkname);
|
||||
}
|
||||
name = linkname;
|
||||
}
|
||||
|
||||
/* Check for a pre-existing symlink with identical content. */
|
||||
if (exists &&
|
||||
(!S_ISLNK(tosb.st_mode) ||
|
||||
readlink(toname, buf, sizeof buf) != len ||
|
||||
strncmp(buf, name, len) != 0)) {
|
||||
(void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
|
||||
exists = 0;
|
||||
}
|
||||
if (!exists && symlink(name, toname) < 0)
|
||||
fail("cannot make symbolic link %s", toname);
|
||||
#ifdef HAVE_LCHOWN
|
||||
if ((owner || group) && lchown(toname, uid, gid) < 0)
|
||||
fail("cannot change owner of %s", toname);
|
||||
#endif
|
||||
|
||||
if (linkname) {
|
||||
free(linkname);
|
||||
linkname = 0;
|
||||
}
|
||||
} else {
|
||||
/* Copy from name to toname, which might be the same file. */
|
||||
fromfd = open(name, O_RDONLY);
|
||||
if (fromfd < 0 || fstat(fromfd, &sb) < 0)
|
||||
fail("cannot access %s", name);
|
||||
if (exists && (!S_ISREG(tosb.st_mode) || access(toname, W_OK) < 0))
|
||||
(void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
|
||||
tofd = open(toname, O_CREAT | O_WRONLY, 0666);
|
||||
if (tofd < 0)
|
||||
fail("cannot create %s", toname);
|
||||
|
||||
bp = buf;
|
||||
while ((cc = read(fromfd, bp, sizeof buf)) > 0) {
|
||||
while ((wc = write(tofd, bp, cc)) > 0) {
|
||||
if ((cc -= wc) == 0)
|
||||
break;
|
||||
bp += wc;
|
||||
}
|
||||
if (wc < 0)
|
||||
fail("cannot write to %s", toname);
|
||||
}
|
||||
if (cc < 0)
|
||||
fail("cannot read from %s", name);
|
||||
|
||||
if (ftruncate(tofd, sb.st_size) < 0)
|
||||
fail("cannot truncate %s", toname);
|
||||
if (dotimes) {
|
||||
utb.actime = sb.st_atime;
|
||||
utb.modtime = sb.st_mtime;
|
||||
if (utime(toname, &utb) < 0)
|
||||
fail("cannot set times of %s", toname);
|
||||
}
|
||||
if (fchmod(tofd, mode) < 0)
|
||||
fail("cannot change mode of %s", toname);
|
||||
if ((owner || group) && fchown(tofd, uid, gid) < 0)
|
||||
fail("cannot change owner of %s", toname);
|
||||
|
||||
/* Must check for delayed (NFS) write errors on close. */
|
||||
if (close(tofd) < 0)
|
||||
fail("cannot write to %s", toname);
|
||||
close(fromfd);
|
||||
}
|
||||
|
||||
free(toname);
|
||||
}
|
||||
|
||||
free(cwd);
|
||||
free(todir);
|
||||
return 0;
|
||||
}
|
||||
219
mozilla/nsprpub/config/pathsub.c
Normal file
219
mozilla/nsprpub/config/pathsub.c
Normal file
@@ -0,0 +1,219 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Pathname subroutines.
|
||||
**
|
||||
** Brendan Eich, 8/29/95
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "pathsub.h"
|
||||
#ifdef USE_REENTRANT_LIBC
|
||||
#include "libc_r.h"
|
||||
#endif /* USE_REENTRANT_LIBC */
|
||||
|
||||
char *program;
|
||||
|
||||
void
|
||||
fail(char *format, ...)
|
||||
{
|
||||
int error;
|
||||
va_list ap;
|
||||
|
||||
#ifdef USE_REENTRANT_LIBC
|
||||
R_STRERROR_INIT_R();
|
||||
#endif
|
||||
|
||||
error = errno;
|
||||
fprintf(stderr, "%s: ", program);
|
||||
va_start(ap, format);
|
||||
vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
if (error)
|
||||
|
||||
#ifdef USE_REENTRANT_LIBC
|
||||
R_STRERROR_R(errno);
|
||||
fprintf(stderr, ": %s", r_strerror_r);
|
||||
#else
|
||||
fprintf(stderr, ": %s", strerror(errno));
|
||||
#endif
|
||||
|
||||
putc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *
|
||||
getcomponent(char *path, char *name)
|
||||
{
|
||||
if (*path == '\0')
|
||||
return 0;
|
||||
if (*path == '/') {
|
||||
*name++ = '/';
|
||||
} else {
|
||||
do {
|
||||
*name++ = *path++;
|
||||
} while (*path != '/' && *path != '\0');
|
||||
}
|
||||
*name = '\0';
|
||||
while (*path == '/')
|
||||
path++;
|
||||
return path;
|
||||
}
|
||||
|
||||
#ifdef UNIXWARE
|
||||
/* Sigh. The static buffer in Unixware's readdir is too small. */
|
||||
struct dirent * readdir(DIR *d)
|
||||
{
|
||||
static struct dirent *buf = NULL;
|
||||
#define MAX_PATH_LEN 1024
|
||||
|
||||
|
||||
if(buf == NULL)
|
||||
buf = (struct dirent *) malloc(sizeof(struct dirent) + MAX_PATH_LEN)
|
||||
;
|
||||
return(readdir_r(d, buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
char *
|
||||
ino2name(ino_t ino, char *dir)
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *ep;
|
||||
char *name;
|
||||
|
||||
dp = opendir("..");
|
||||
if (!dp)
|
||||
fail("cannot read parent directory");
|
||||
for (;;) {
|
||||
if (!(ep = readdir(dp)))
|
||||
fail("cannot find current directory");
|
||||
if (ep->d_ino == ino)
|
||||
break;
|
||||
}
|
||||
name = xstrdup(ep->d_name);
|
||||
closedir(dp);
|
||||
return name;
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc(size_t size)
|
||||
{
|
||||
void *p = malloc(size);
|
||||
if (!p)
|
||||
fail("cannot allocate %u bytes", size);
|
||||
return p;
|
||||
}
|
||||
|
||||
char *
|
||||
xstrdup(char *s)
|
||||
{
|
||||
return strcpy((char*)xmalloc(strlen(s) + 1), s);
|
||||
}
|
||||
|
||||
char *
|
||||
xbasename(char *path)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
while ((cp = strrchr(path, '/')) && cp[1] == '\0')
|
||||
*cp = '\0';
|
||||
if (!cp) return path;
|
||||
return cp + 1;
|
||||
}
|
||||
|
||||
void
|
||||
xchdir(char *dir)
|
||||
{
|
||||
if (chdir(dir) < 0)
|
||||
fail("cannot change directory to %s", dir);
|
||||
}
|
||||
|
||||
int
|
||||
relatepaths(char *from, char *to, char *outpath)
|
||||
{
|
||||
char *cp, *cp2;
|
||||
int len;
|
||||
char buf[NAME_MAX];
|
||||
|
||||
assert(*from == '/' && *to == '/');
|
||||
for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
while (cp[-1] != '/')
|
||||
cp--, cp2--;
|
||||
if (cp - 1 == to) {
|
||||
/* closest common ancestor is /, so use full pathname */
|
||||
len = strlen(strcpy(outpath, to));
|
||||
if (outpath[len] != '/') {
|
||||
outpath[len++] = '/';
|
||||
outpath[len] = '\0';
|
||||
}
|
||||
} else {
|
||||
len = 0;
|
||||
while ((cp2 = getcomponent(cp2, buf)) != 0) {
|
||||
strcpy(outpath + len, "../");
|
||||
len += 3;
|
||||
}
|
||||
while ((cp = getcomponent(cp, buf)) != 0) {
|
||||
sprintf(outpath + len, "%s/", buf);
|
||||
len += strlen(outpath + len);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
reversepath(char *inpath, char *name, int len, char *outpath)
|
||||
{
|
||||
char *cp, *cp2;
|
||||
char buf[NAME_MAX];
|
||||
struct stat sb;
|
||||
|
||||
cp = strcpy(outpath + PATH_MAX - (len + 1), name);
|
||||
cp2 = inpath;
|
||||
while ((cp2 = getcomponent(cp2, buf)) != 0) {
|
||||
if (strcmp(buf, ".") == 0)
|
||||
continue;
|
||||
if (strcmp(buf, "..") == 0) {
|
||||
if (stat(".", &sb) < 0)
|
||||
fail("cannot stat current directory");
|
||||
name = ino2name(sb.st_ino, "..");
|
||||
len = strlen(name);
|
||||
cp -= len + 1;
|
||||
strcpy(cp, name);
|
||||
cp[len] = '/';
|
||||
free(name);
|
||||
xchdir("..");
|
||||
} else {
|
||||
cp -= 3;
|
||||
strncpy(cp, "../", 3);
|
||||
xchdir(buf);
|
||||
}
|
||||
}
|
||||
strcpy(outpath, cp);
|
||||
}
|
||||
59
mozilla/nsprpub/config/pathsub.h
Normal file
59
mozilla/nsprpub/config/pathsub.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 pathsub_h___
|
||||
#define pathsub_h___
|
||||
/*
|
||||
** Pathname subroutines.
|
||||
**
|
||||
** Brendan Eich, 8/29/95
|
||||
*/
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if SUNOS4
|
||||
#include "../pr/include/md/sunos4.h"
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Just prevent stupidity
|
||||
*/
|
||||
#undef NAME_MAX
|
||||
#define NAME_MAX 256
|
||||
|
||||
extern char *program;
|
||||
|
||||
extern void fail(char *format, ...);
|
||||
extern char *getcomponent(char *path, char *name);
|
||||
extern char *ino2name(ino_t ino, char *dir);
|
||||
extern void *xmalloc(size_t size);
|
||||
extern char *xstrdup(char *s);
|
||||
extern char *xbasename(char *path);
|
||||
extern void xchdir(char *dir);
|
||||
|
||||
/* Relate absolute pathnames from and to returning the result in outpath. */
|
||||
extern int relatepaths(char *from, char *to, char *outpath);
|
||||
|
||||
/* XXX changes current working directory -- caveat emptor */
|
||||
extern void reversepath(char *inpath, char *name, int len, char *outpath);
|
||||
|
||||
#endif /* pathsub_h___ */
|
||||
18
mozilla/nsprpub/config/prmkdir.bat
Executable file
18
mozilla/nsprpub/config/prmkdir.bat
Executable file
@@ -0,0 +1,18 @@
|
||||
REM
|
||||
REM The contents of this file are subject to the Netscape Public License
|
||||
REM Version 1.0 (the "NPL"); you may not use this file except in
|
||||
REM compliance with the NPL. You may obtain a copy of the NPL at
|
||||
REM http://www.mozilla.org/NPL/
|
||||
REM
|
||||
REM Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
REM WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
REM for the specific language governing rights and limitations under the
|
||||
REM NPL.
|
||||
REM
|
||||
REM The Initial Developer of this code under the NPL is Netscape
|
||||
REM Communications Corporation. Portions created by Netscape are
|
||||
REM Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
REM Reserved.
|
||||
REM
|
||||
|
||||
mkdir %1
|
||||
367
mozilla/nsprpub/config/rules.mk
Normal file
367
mozilla/nsprpub/config/rules.mk
Normal file
@@ -0,0 +1,367 @@
|
||||
#! gmake
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
################################################################################
|
||||
# We have a 4 pass build process:
|
||||
#
|
||||
# Pass 1. export - Create generated headers and stubs. Publish public headers to
|
||||
# dist/<arch>/include.
|
||||
#
|
||||
# Pass 2. libs - Create libraries. Publish libraries to dist/<arch>/lib.
|
||||
#
|
||||
# Pass 3. all - Create programs.
|
||||
#
|
||||
# Pass 4. install - Publish programs to dist/<arch>/bin.
|
||||
#
|
||||
# Parameters to this makefile (set these before including):
|
||||
#
|
||||
# a)
|
||||
# TARGETS -- the target to create
|
||||
# (defaults to $LIBRARY $PROGRAM)
|
||||
# b)
|
||||
# DIRS -- subdirectories for make to recurse on
|
||||
# (the 'all' rule builds $TARGETS $DIRS)
|
||||
# c)
|
||||
# CSRCS -- .c files to compile
|
||||
# (used to define $OBJS)
|
||||
# d)
|
||||
# PROGRAM -- the target program name to create from $OBJS
|
||||
# ($OBJDIR automatically prepended to it)
|
||||
# e)
|
||||
# LIBRARY -- the target library name to create from $OBJS
|
||||
# ($OBJDIR automatically prepended to it)
|
||||
#
|
||||
################################################################################
|
||||
|
||||
ifndef NSPR_CONFIG_MK
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
endif
|
||||
|
||||
#
|
||||
# This makefile contains rules for building the following kinds of
|
||||
# libraries:
|
||||
# - LIBRARY: a static (archival) library
|
||||
# - SHARED_LIBRARY: a shared (dynamic link) library
|
||||
# - IMPORT_LIBRARY: an import library, used only on Windows and OS/2
|
||||
# - PURE_LIBRARY: a library for Purify
|
||||
#
|
||||
# The names of these libraries can be generated by simply specifying
|
||||
# LIBRARY_NAME and LIBRARY_VERSION.
|
||||
#
|
||||
|
||||
ifdef LIBRARY_NAME
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
|
||||
#
|
||||
# Win16 and OS/2 require library names conforming to the 8.3 rule.
|
||||
# other platforms do not.
|
||||
#
|
||||
ifeq (,$(filter-out WIN16 OS2,$(OS_TARGET)))
|
||||
LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)_s.lib
|
||||
SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).dll
|
||||
IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).lib
|
||||
else
|
||||
LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_s.lib
|
||||
SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).dll
|
||||
IMPORT_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).lib
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX)
|
||||
ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
|
||||
SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_shr.a
|
||||
else
|
||||
SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
|
||||
endif
|
||||
ifdef HAVE_PURIFY
|
||||
ifdef DSO_BACKEND
|
||||
PURE_LIBRARY = $(OBJDIR)/purelib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
|
||||
else
|
||||
PURE_LIBRARY = $(OBJDIR)/purelib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX)
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef TARGETS
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY)
|
||||
else
|
||||
TARGETS = $(LIBRARY) $(SHARED_LIBRARY)
|
||||
ifdef HAVE_PURIFY
|
||||
TARGETS += $(PURE_LIBRARY)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# OBJS is the list of object files. It can be constructed by
|
||||
# specifying CSRCS (list of C source files) and ASFILES (list
|
||||
# of assembly language source files).
|
||||
#
|
||||
|
||||
ifndef OBJS
|
||||
OBJS = $(addprefix $(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \
|
||||
$(addprefix $(OBJDIR)/,$(ASFILES:.s=.$(OBJ_SUFFIX)))
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET), WIN16)
|
||||
comma := ,
|
||||
empty :=
|
||||
space := $(empty) $(empty)
|
||||
W16OBJS = $(subst $(space),$(comma)$(space),$(strip $(OBJS)))
|
||||
W16TEMP =$(OS_LIBS) $(EXTRA_LIBS)
|
||||
ifeq ($(strip $(W16TEMP)),)
|
||||
W16LIBS =
|
||||
else
|
||||
W16LIBS = library $(subst $(space),$(comma)$(space),$(strip $(W16TEMP)))
|
||||
endif
|
||||
W16DEF = $(notdir $(basename $(SHARED_LIBRARY))).DEF
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
ifneq ($(OS_TARGET), WIN16)
|
||||
ifneq ($(OS_TARGET), OS2)
|
||||
OBJS += $(RES)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ALL_TRASH = $(TARGETS) $(OBJS) $(OBJDIR) LOGS TAGS $(GARBAGE) \
|
||||
$(NOSUCHFILE) \
|
||||
so_locations
|
||||
|
||||
ifdef DIRS
|
||||
LOOP_OVER_DIRS = \
|
||||
@for d in $(DIRS); do \
|
||||
if test -d $$d; then \
|
||||
set -e; \
|
||||
echo "cd $$d; $(MAKE) $@"; \
|
||||
$(MAKE) -C $$d $@; \
|
||||
set +e; \
|
||||
else \
|
||||
echo "Skipping non-directory $$d..."; \
|
||||
fi; \
|
||||
done
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
all:: export libs install
|
||||
|
||||
export::
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
libs::
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
install::
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
clean::
|
||||
rm -rf $(OBJS) so_locations $(NOSUCHFILE)
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
clobber::
|
||||
rm -f $(OBJS) $(TARGETS) $(GARBAGE) so_locations $(NOSUCHFILE)
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
realclean clobber_all::
|
||||
rm -rf $(wildcard *.OBJ *.OBJD) dist $(ALL_TRASH)
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
release:: export
|
||||
ifdef RELEASE_LIBS
|
||||
@echo "Copying libraries to release directory"
|
||||
@if test -z "$(BUILD_NUMBER)"; then \
|
||||
echo "BUILD_NUMBER must be defined"; \
|
||||
false; \
|
||||
fi
|
||||
@if test ! -d $(RELEASE_LIB_DIR); then \
|
||||
rm -f $(RELEASE_LIB_DIR); \
|
||||
$(NSINSTALL) -D $(RELEASE_LIB_DIR);\
|
||||
fi
|
||||
cp $(RELEASE_LIBS) $(RELEASE_LIB_DIR)
|
||||
endif
|
||||
ifdef RELEASE_HEADERS
|
||||
@echo "Copying header files to release directory"
|
||||
@if test -z "$(BUILD_NUMBER)"; then \
|
||||
echo "BUILD_NUMBER must be defined"; \
|
||||
false; \
|
||||
fi
|
||||
@if test ! -d $(RELEASE_HEADERS_DEST); then \
|
||||
rm -rf $(RELEASE_HEADERS_DEST); \
|
||||
$(NSINSTALL) -D $(RELEASE_HEADERS_DEST);\
|
||||
fi
|
||||
cp $(RELEASE_HEADERS) $(RELEASE_HEADERS_DEST)
|
||||
endif
|
||||
+$(LOOP_OVER_DIRS)
|
||||
|
||||
alltags:
|
||||
rm -f TAGS tags
|
||||
find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs etags -a
|
||||
find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs ctags -a
|
||||
|
||||
$(NFSPWD):
|
||||
cd $(@D); $(MAKE) $(@F)
|
||||
|
||||
$(PROGRAM): $(OBJS)
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
$(CC) $(OBJS) -Fe$@ -link $(LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS)
|
||||
else
|
||||
$(CC) -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS)
|
||||
endif
|
||||
|
||||
$(LIBRARY): $(OBJS)
|
||||
@$(MAKE_OBJDIR)
|
||||
rm -f $@
|
||||
$(AR) $(OBJS) $(AR_EXTRA_ARGS)
|
||||
$(RANLIB) $@
|
||||
|
||||
ifeq ($(OS_TARGET), WIN16)
|
||||
$(IMPORT_LIBRARY): $(SHARED_LIBRARY)
|
||||
wlib $(OS_LIB_FLAGS) $@ +$(SHARED_LIBRARY)
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET), OS2)
|
||||
$(IMPORT_LIBRARY): $(SHARED_LIBRARY)
|
||||
$(IMPLIB) $@ $(SHARED_LIBRARY).def
|
||||
endif
|
||||
|
||||
$(SHARED_LIBRARY): $(OBJS)
|
||||
@$(MAKE_OBJDIR)
|
||||
rm -f $@
|
||||
ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
|
||||
echo "#!" > $(OBJDIR)/lib$(LIBRARY_NAME)_syms
|
||||
nm -B -C -g $(OBJS) \
|
||||
| awk '/ [T,D] / {print $$3}' \
|
||||
| sed -e 's/^\.//' \
|
||||
| sort -u >> $(OBJDIR)/lib$(LIBRARY_NAME)_syms
|
||||
$(LD) $(XCFLAGS) -o $@ $(OBJS) -bE:$(OBJDIR)/lib$(LIBRARY_NAME)_syms \
|
||||
-bM:SRE -bnoentry $(OS_LIBS) $(EXTRA_LIBS)
|
||||
|
||||
else
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
ifeq ($(OS_TARGET), WIN16)
|
||||
echo system windows dll initinstance >w16link
|
||||
echo option map >>w16link
|
||||
echo option oneautodata >>w16link
|
||||
echo option heapsize=32K >>w16link
|
||||
echo option $(OS_DLL_OPTION) >>w16link
|
||||
echo debug $(DEBUGTYPE) all >>w16link
|
||||
echo name $@ >>w16link
|
||||
echo file >>w16link
|
||||
echo $(W16OBJS) >>w16link
|
||||
echo $(W16IMPORTS) >>w16link
|
||||
echo $(W16LIBS) >>w16link
|
||||
echo $(W16_EXPORTS) >>w16link
|
||||
echo libfile libentry >>w16link
|
||||
$(LINK) @w16link.
|
||||
rm w16link
|
||||
else
|
||||
ifeq ($(OS_TARGET), OS2)
|
||||
# append ( >> ) doesn't seem to be working under OS/2 gmake. Run through OS/2 shell instead.
|
||||
@cmd /C "echo LIBRARY $(notdir $(basename $(SHARED_LIBRARY))) INITINSTANCE TERMINSTANCE >$@.def"
|
||||
@cmd /C "echo PROTMODE >>$@.def"
|
||||
@cmd /C "echo CODE LOADONCALL MOVEABLE DISCARDABLE >>$@.def"
|
||||
@cmd /C "echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >>$@.def"
|
||||
@cmd /C "echo EXPORTS >>$@.def"
|
||||
@cmd /C "$(FILTER) -B -P $(LIBRARY) >> $@.def"
|
||||
$(LINK_DLL) -MAP $(DLLBASE) $(OS_LIBS) $(EXTRA_LIBS) $(OBJS) $@.def
|
||||
else
|
||||
$(LINK_DLL) -MAP $(DLLBASE) $(OS_LIBS) $(EXTRA_LIBS) $(OBJS)
|
||||
endif
|
||||
endif
|
||||
else
|
||||
$(MKSHLIB) -o $@ $(OBJS) $(EXTRA_LIBS) $(OS_LIBS)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(PURE_LIBRARY):
|
||||
rm -f $@
|
||||
ifneq ($(OS_ARCH), WINNT)
|
||||
$(AR) $(OBJS)
|
||||
endif
|
||||
$(RANLIB) $@
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
$(RES): $(RESNAME)
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(OS_TARGET),OS2)
|
||||
$(RC) -DOS2 -r $(RESNAME) $(RES)
|
||||
else
|
||||
$(RC) -Fo$(RES) $(RESNAME)
|
||||
endif
|
||||
@echo $(RES) finished
|
||||
endif
|
||||
|
||||
$(OBJDIR)/%.$(OBJ_SUFFIX): %.cpp
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
$(CCC) -Fo$@ -c $(CFLAGS) $<
|
||||
else
|
||||
$(CCC) -o $@ -c $(CFLAGS) $<
|
||||
endif
|
||||
|
||||
WCCFLAGS1 = $(subst /,\\,$(CFLAGS))
|
||||
WCCFLAGS2 = $(subst -I,-i=,$(WCCFLAGS1))
|
||||
WCCFLAGS3 = $(subst -D,-d,$(WCCFLAGS2))
|
||||
$(OBJDIR)/%.$(OBJ_SUFFIX): %.c
|
||||
@$(MAKE_OBJDIR)
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
ifeq ($(OS_TARGET), WIN16)
|
||||
# $(MOD_DEPTH)/config/w16opt $(WCCFLAGS3)
|
||||
echo $(WCCFLAGS3) >w16wccf
|
||||
$(CC) -zq -fo$(OBJDIR)\\$*.$(OBJ_SUFFIX) @w16wccf $*.c
|
||||
rm w16wccf
|
||||
else
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $*.c
|
||||
endif
|
||||
else
|
||||
$(CC) -o $@ -c $(CFLAGS) $*.c
|
||||
endif
|
||||
|
||||
$(OBJDIR)/%.$(OBJ_SUFFIX): %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(AS) -o $@ $(ASFLAGS) -c $*.s
|
||||
|
||||
%.i: %.c
|
||||
$(CC) -C -E $(CFLAGS) $< > $*.i
|
||||
|
||||
%: %.pl
|
||||
rm -f $@; cp $*.pl $@; chmod +x $@
|
||||
|
||||
################################################################################
|
||||
# Special gmake rules.
|
||||
################################################################################
|
||||
|
||||
#
|
||||
# Re-define the list of default suffixes, so gmake won't have to churn through
|
||||
# hundreds of built-in suffix rules for stuff we don't need.
|
||||
#
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .a .$(OBJ_SUFFIX) .c .cpp .s .h .i .pl
|
||||
|
||||
#
|
||||
# Fake targets. Always run these rules, even if a file/directory with that
|
||||
# name already exists.
|
||||
#
|
||||
.PHONY: all alltags clean export install libs realclean release
|
||||
99
mozilla/nsprpub/config/win16.mk
Normal file
99
mozilla/nsprpub/config/win16.mk
Normal file
@@ -0,0 +1,99 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# win16_3.11.mk -- Make configuration for Win16
|
||||
#
|
||||
# This file configures gmake to build the Win16 variant of
|
||||
# NSPR 2.0. This file has the function of two files commonly
|
||||
# used on other platforms, for example: winnt.mk and
|
||||
# winnt4.0.mk. ... The packaging is easier and there is only
|
||||
# one variant of the Win16 target.
|
||||
#
|
||||
# Win16 is built using the Watcom C/C++ version 11.0
|
||||
# compiler. You gotta set up the compiler first. Follow the
|
||||
# directions in the manual (Ha! ... really, its not a
|
||||
# problem). The Watcom compiler depends on a few environment
|
||||
# variables; these environment variables define where the
|
||||
# compiler components are installed; they must be set before
|
||||
# running the make.
|
||||
#
|
||||
# Notes:
|
||||
# OS_CFLAGS is the command line options for the compiler when
|
||||
# building the .DLL object files.
|
||||
# OS_EXE_CFLAGS is the command line options for the compiler
|
||||
# when building the .EXE object files; this is for the test
|
||||
# programs.
|
||||
# the macro OS_CFLAGS is set to OS_EXE_CFLAGS inside of the
|
||||
# makefile for the pr/tests directory. ... Hack.
|
||||
#
|
||||
# USE_WATCOM_DEBUG_DATA environment variable causes the
|
||||
# watcom compiler flag to be set to -hw (otherwise
|
||||
# it is set to -hc (codeview debug data)) for debug builds.
|
||||
#
|
||||
|
||||
# -- configuration -----------------------------------------
|
||||
|
||||
CC = wcc
|
||||
CCC = wcl
|
||||
LINK = wlink
|
||||
AR = wlib -q $@
|
||||
RC = wrc.exe /r /dWIN16=1 /bt=windows
|
||||
RANLIB = echo
|
||||
BSDECHO = echo
|
||||
NSINSTALL = nsinstall
|
||||
INSTALL = $(NSINSTALL)
|
||||
MAKE_OBJDIR = mkdir $(OBJDIR)
|
||||
|
||||
XP_DEFINE = -DXP_PC
|
||||
OBJ_SUFFIX = obj
|
||||
LIB_SUFFIX = lib
|
||||
DLL_SUFFIX = dll
|
||||
|
||||
ifdef BUILD_OPT
|
||||
OBJDIR_TAG = _O
|
||||
OPTIMIZER = -oneatx -oh -oi -ei -3 -fpi87 -fp3 -s
|
||||
else
|
||||
ifdef USE_WATCOM_DEBUG_DATA
|
||||
OPTIMIZER = -d2 -hw -s -DDEBUG
|
||||
DEBUGTYPE = watcom
|
||||
else
|
||||
OPTIMIZER = -d2 -hc -s -DDEBUG
|
||||
DEBUGTYPE = codeview
|
||||
endif
|
||||
OBJDIR_TAG = _D
|
||||
endif
|
||||
|
||||
# XXX FIXME: I doubt we use this. It is redundant with
|
||||
# SHARED_LIBRARY.
|
||||
ifdef DLL
|
||||
DLL := $(addprefix $(OBJDIR)/, $(DLL))
|
||||
endif
|
||||
|
||||
|
||||
CPU_ARCH = x386
|
||||
OS_CFLAGS = -ml -3 -bd -zc -zu -bt=windows -d_X86_ -dWIN16 -d_WINDLL
|
||||
OS_EXE_CFLAGS = -ml -3 -bt=windows -d_X86_ -dWIN16
|
||||
OS_LIB_FLAGS = -c -iro -n
|
||||
|
||||
# Name of the binary code directories
|
||||
OBJDIR_NAME = $(OS_CONFIG)$(OBJDIR_TAG).OBJ
|
||||
|
||||
OS_DLL_OPTION = CASEEXACT
|
||||
OS_DLLFLAGS =
|
||||
OS_LIBS =
|
||||
W16_EXPORTS = #
|
||||
32
mozilla/nsprpub/lib/Makefile
Normal file
32
mozilla/nsprpub/lib/Makefile
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ..
|
||||
|
||||
export NSPR20=1
|
||||
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
DIRS = ds libc msgc
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
install:: export
|
||||
108
mozilla/nsprpub/lib/ds/Makefile
Normal file
108
mozilla/nsprpub/lib/ds/Makefile
Normal file
@@ -0,0 +1,108 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../..
|
||||
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
# Disable optimization of the nspr on SunOS4.1.3
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
ifeq ($(OS_RELEASE),4.1.3_U1)
|
||||
OPTIMIZER =
|
||||
endif
|
||||
endif
|
||||
|
||||
INCLUDES = -I$(DIST)/include/private -I$(DIST)/include
|
||||
|
||||
CSRCS = \
|
||||
plarena.c \
|
||||
plevent.c \
|
||||
plhash.c \
|
||||
$(NULL)
|
||||
|
||||
HEADERS = \
|
||||
plarenas.h \
|
||||
plarena.h \
|
||||
plevent.h \
|
||||
plhash.h \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
ifeq (,$(filter-out WIN16 OS2,$(OS_TARGET)))
|
||||
# OS_CFLAGS = $(OS_EXE_CFLAGS)
|
||||
EXTRA_LIBS = $(DIST)/lib/nspr$(MOD_VERSION).lib
|
||||
else
|
||||
DLLBASE=/BASE:0x30000000
|
||||
RES=$(OBJDIR)/ds.res
|
||||
RESNAME=$(MOD_DEPTH)/pr/src/nspr.rc
|
||||
OS_LIBS = user32.lib
|
||||
EXTRA_LIBS = $(DIST)/lib/libnspr$(MOD_VERSION).lib
|
||||
endif
|
||||
else
|
||||
ifeq ($(OS_ARCH), AIX)
|
||||
ifeq ($(CLASSIC_NSPR),1)
|
||||
OS_LIBS += -lc
|
||||
else
|
||||
OS_LIBS += -lc_r
|
||||
endif
|
||||
endif
|
||||
ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
|
||||
EXTRA_LIBS = -L$(DIST)/lib -lnspr$(MOD_VERSION)_shr
|
||||
else
|
||||
EXTRA_LIBS = -L$(DIST)/lib -lnspr$(MOD_VERSION)
|
||||
endif
|
||||
endif
|
||||
|
||||
# On NCR and SCO_SV, we can't link with extra libraries when
|
||||
# we build a shared library. If we do so, the linker doesn't
|
||||
# complain, but we would run into weird problems at run-time.
|
||||
# Therefore on these platforms, we link just the .o files.
|
||||
ifeq ($(OS_ARCH),NCR)
|
||||
EXTRA_LIBS =
|
||||
endif
|
||||
ifeq ($(OS_ARCH),SCO_SV)
|
||||
EXTRA_LIBS =
|
||||
endif
|
||||
|
||||
LIBRARY_NAME = plds
|
||||
LIBRARY_VERSION = $(MOD_VERSION)
|
||||
|
||||
RELEASE_HEADERS = $(HEADERS)
|
||||
RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
|
||||
RELEASE_LIBS = $(TARGETS)
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
#
|
||||
# The Client build wants the shared libraries in $(DIST)/bin,
|
||||
# so we also install them there.
|
||||
#
|
||||
|
||||
export:: $(TARGETS)
|
||||
$(INSTALL) -m 444 $(HEADERS) $(DIST)/include
|
||||
$(INSTALL) -m 444 $(TARGETS) $(DIST)/lib
|
||||
$(INSTALL) -m 444 $(SHARED_LIBRARY) $(DIST)/bin
|
||||
ifeq ($(MOZ_BITS),16)
|
||||
$(INSTALL) -m 444 $(HEADERS) $(MOZ_INCL)
|
||||
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
|
||||
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
|
||||
endif
|
||||
|
||||
install:: export
|
||||
|
||||
299
mozilla/nsprpub/lib/ds/plarena.c
Normal file
299
mozilla/nsprpub/lib/ds/plarena.c
Normal file
@@ -0,0 +1,299 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "plarena.h"
|
||||
#include "prmem.h"
|
||||
#include "prbit.h"
|
||||
#include "prlog.h"
|
||||
|
||||
static PLArena *arena_freelist;
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
static PLArenaStats *arena_stats_list;
|
||||
|
||||
#define COUNT(pool,what) (pool)->stats.what++
|
||||
#else
|
||||
#define COUNT(pool,what) /* nothing */
|
||||
#endif
|
||||
|
||||
#define PL_ARENA_DEFAULT_ALIGN sizeof(double)
|
||||
|
||||
PR_IMPLEMENT(void) PL_InitArenaPool(
|
||||
PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (name)
|
||||
#endif
|
||||
|
||||
if (align == 0)
|
||||
align = PL_ARENA_DEFAULT_ALIGN;
|
||||
pool->mask = PR_BITMASK(PR_CeilingLog2(align));
|
||||
pool->first.next = NULL;
|
||||
pool->first.base = pool->first.avail = pool->first.limit =
|
||||
(PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1);
|
||||
pool->current = &pool->first;
|
||||
pool->arenasize = size;
|
||||
#ifdef PL_ARENAMETER
|
||||
memset(&pool->stats, 0, sizeof pool->stats);
|
||||
pool->stats.name = strdup(name);
|
||||
pool->stats.next = arena_stats_list;
|
||||
arena_stats_list = &pool->stats;
|
||||
#endif
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb)
|
||||
{
|
||||
PLArena **ap, *a, *b;
|
||||
PRUint32 sz;
|
||||
void *p;
|
||||
|
||||
PR_ASSERT((nb & pool->mask) == 0);
|
||||
#if defined(WIN16)
|
||||
if (nb >= 60000U)
|
||||
return 0;
|
||||
#endif /* WIN16 */
|
||||
ap = &arena_freelist;
|
||||
for (a = pool->current; a->avail + nb > a->limit; pool->current = a) {
|
||||
if (a->next) { /* move to next arena */
|
||||
a = a->next;
|
||||
continue;
|
||||
}
|
||||
while ((b = *ap) != 0) { /* reclaim a free arena */
|
||||
if (b->limit - b->base == pool->arenasize) {
|
||||
*ap = b->next;
|
||||
b->next = 0;
|
||||
a = a->next = b;
|
||||
COUNT(pool, nreclaims);
|
||||
goto claim;
|
||||
}
|
||||
ap = &b->next;
|
||||
}
|
||||
sz = PR_MAX(pool->arenasize, nb); /* allocate a new arena */
|
||||
sz += sizeof *a + pool->mask; /* header and alignment slop */
|
||||
b = (PLArena*)PR_MALLOC(sz);
|
||||
if (!b)
|
||||
return 0;
|
||||
a = a->next = b;
|
||||
a->next = 0;
|
||||
a->limit = (PRUword)a + sz;
|
||||
PL_COUNT_ARENA(pool,++);
|
||||
COUNT(pool, nmallocs);
|
||||
claim:
|
||||
a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1);
|
||||
}
|
||||
p = (void *)a->avail;
|
||||
a->avail += nb;
|
||||
return p;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void *) PL_ArenaGrow(
|
||||
PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr)
|
||||
{
|
||||
void *newp;
|
||||
|
||||
PL_ARENA_ALLOCATE(newp, pool, size + incr);
|
||||
if (newp)
|
||||
memcpy(newp, p, size);
|
||||
return newp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free tail arenas linked after head, which may not be the true list head.
|
||||
* Reset pool->current to point to head in case it pointed at a tail arena.
|
||||
*/
|
||||
static void FreeArenaList(PLArenaPool *pool, PLArena *head, PRBool reallyFree)
|
||||
{
|
||||
PLArena **ap, *a;
|
||||
|
||||
ap = &head->next;
|
||||
a = *ap;
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
|
||||
a->avail = a->base;
|
||||
PL_CLEAR_UNUSED(a);
|
||||
} while ((a = a->next) != 0);
|
||||
a = *ap;
|
||||
#endif
|
||||
|
||||
if (reallyFree) {
|
||||
do {
|
||||
*ap = a->next;
|
||||
PL_CLEAR_ARENA(a);
|
||||
PL_COUNT_ARENA(pool,--);
|
||||
PR_DELETE(a);
|
||||
} while ((a = *ap) != 0);
|
||||
} else {
|
||||
/* Insert the whole arena chain at the front of the freelist. */
|
||||
do {
|
||||
ap = &(*ap)->next;
|
||||
} while (*ap);
|
||||
*ap = arena_freelist;
|
||||
arena_freelist = a;
|
||||
head->next = 0;
|
||||
}
|
||||
|
||||
pool->current = head;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaRelease(PLArenaPool *pool, char *mark)
|
||||
{
|
||||
PLArena *a;
|
||||
|
||||
for (a = pool->first.next; a; a = a->next) {
|
||||
if (PR_UPTRDIFF(mark, a) < PR_UPTRDIFF(a->avail, a)) {
|
||||
a->avail = (PRUword)PL_ARENA_ALIGN(pool, mark);
|
||||
FreeArenaList(pool, a, PR_TRUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_FreeArenaPool(PLArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first, PR_FALSE);
|
||||
COUNT(pool, ndeallocs);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_FinishArenaPool(PLArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first, PR_TRUE);
|
||||
#ifdef PL_ARENAMETER
|
||||
{
|
||||
PLArenaStats *stats, **statsp;
|
||||
|
||||
if (pool->stats.name)
|
||||
PR_DELETE(pool->stats.name);
|
||||
for (statsp = &arena_stats_list; (stats = *statsp) != 0;
|
||||
statsp = &stats->next) {
|
||||
if (stats == &pool->stats) {
|
||||
*statsp = stats->next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_CompactArenaPool(PLArenaPool *ap)
|
||||
{
|
||||
#if XP_MAC
|
||||
#pragma unused (ap)
|
||||
#if 0
|
||||
PRArena *curr = &(ap->first);
|
||||
while (curr) {
|
||||
reallocSmaller(curr, curr->avail - (uprword_t)curr);
|
||||
curr->limit = curr->avail;
|
||||
curr = curr->next;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaFinish()
|
||||
{
|
||||
PLArena *a, *next;
|
||||
|
||||
for (a = arena_freelist; a; a = next) {
|
||||
next = a->next;
|
||||
PR_DELETE(a);
|
||||
}
|
||||
arena_freelist = NULL;
|
||||
}
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
PR_IMPLEMENT(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb)
|
||||
{
|
||||
pool->stats.nallocs++;
|
||||
pool->stats.nbytes += nb;
|
||||
if (nb > pool->stats.maxalloc)
|
||||
pool->stats.maxalloc = nb;
|
||||
pool->stats.variance += nb * nb;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaCountInplaceGrowth(
|
||||
PLArenaPool *pool, PRUint32 size, PRUint32 incr)
|
||||
{
|
||||
pool->stats.ninplace++;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaCountGrowth(
|
||||
PLArenaPool *pool, PRUint32 size, PRUint32 incr)
|
||||
{
|
||||
pool->stats.ngrows++;
|
||||
pool->stats.nbytes += incr;
|
||||
pool->stats.variance -= size * size;
|
||||
size += incr;
|
||||
if (size > pool->stats.maxalloc)
|
||||
pool->stats.maxalloc = size;
|
||||
pool->stats.variance += size * size;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark)
|
||||
{
|
||||
pool->stats.nreleases++;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark)
|
||||
{
|
||||
pool->stats.nfastrels++;
|
||||
}
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
PR_IMPLEMENT(void) PL_DumpArenaStats(FILE *fp)
|
||||
{
|
||||
PLArenaStats *stats;
|
||||
double mean, variance;
|
||||
|
||||
for (stats = arena_stats_list; stats; stats = stats->next) {
|
||||
if (stats->nallocs != 0) {
|
||||
mean = (double)stats->nbytes / stats->nallocs;
|
||||
variance = fabs(stats->variance / stats->nallocs - mean * mean);
|
||||
} else {
|
||||
mean = variance = 0;
|
||||
}
|
||||
|
||||
fprintf(fp, "\n%s allocation statistics:\n", stats->name);
|
||||
fprintf(fp, " number of arenas: %u\n", stats->narenas);
|
||||
fprintf(fp, " number of allocations: %u\n", stats->nallocs);
|
||||
fprintf(fp, " number of free arena reclaims: %u\n", stats->nreclaims);
|
||||
fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs);
|
||||
fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs);
|
||||
fprintf(fp, " number of allocation growths: %u\n", stats->ngrows);
|
||||
fprintf(fp, " number of in-place growths: %u\n", stats->ninplace);
|
||||
fprintf(fp, "number of released allocations: %u\n", stats->nreleases);
|
||||
fprintf(fp, " number of fast releases: %u\n", stats->nfastrels);
|
||||
fprintf(fp, " total bytes allocated: %u\n", stats->nbytes);
|
||||
fprintf(fp, " mean allocation size: %g\n", mean);
|
||||
fprintf(fp, " standard deviation: %g\n", sqrt(variance));
|
||||
fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc);
|
||||
}
|
||||
}
|
||||
#endif /* PL_ARENAMETER */
|
||||
193
mozilla/nsprpub/lib/ds/plarena.h
Normal file
193
mozilla/nsprpub/lib/ds/plarena.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 plarena_h___
|
||||
#define plarena_h___
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*
|
||||
* Also supports LIFO allocation (PL_ARENA_MARK/PL_ARENA_RELEASE).
|
||||
*/
|
||||
#include "prtypes.h"
|
||||
#include "plarenas.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct PLArena PLArena;
|
||||
|
||||
struct PLArena {
|
||||
PLArena *next; /* next arena for this lifetime */
|
||||
PRUword base; /* aligned base address, follows this header */
|
||||
PRUword limit; /* one beyond last byte in arena */
|
||||
PRUword avail; /* points to next available byte */
|
||||
};
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
typedef struct PLArenaStats PLArenaStats;
|
||||
|
||||
struct PLArenaStats {
|
||||
PLArenaStats *next; /* next in arenaStats list */
|
||||
char *name; /* name for debugging */
|
||||
PRUint32 narenas; /* number of arenas in pool */
|
||||
PRUint32 nallocs; /* number of PL_ARENA_ALLOCATE() calls */
|
||||
PRUint32 nreclaims; /* number of reclaims from freeArenas */
|
||||
PRUint32 nmallocs; /* number of malloc() calls */
|
||||
PRUint32 ndeallocs; /* number of lifetime deallocations */
|
||||
PRUint32 ngrows; /* number of PL_ARENA_GROW() calls */
|
||||
PRUint32 ninplace; /* number of in-place growths */
|
||||
PRUint32 nreleases; /* number of PL_ARENA_RELEASE() calls */
|
||||
PRUint32 nfastrels; /* number of "fast path" releases */
|
||||
PRUint32 nbytes; /* total bytes allocated */
|
||||
PRUint32 maxalloc; /* maximum allocation size in bytes */
|
||||
PRFloat64 variance; /* size variance accumulator */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct PLArenaPool {
|
||||
PLArena first; /* first arena in pool list */
|
||||
PLArena *current; /* arena from which to allocate space */
|
||||
PRUint32 arenasize; /* net exact size of a new arena */
|
||||
PRUword mask; /* alignment mask (power-of-2 - 1) */
|
||||
#ifdef PL_ARENAMETER
|
||||
PLArenaStats stats;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* If the including .c file uses only one power-of-2 alignment, it may define
|
||||
* PL_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions
|
||||
* per ALLOCATE and GROW.
|
||||
*/
|
||||
#ifdef PL_ARENA_CONST_ALIGN_MASK
|
||||
#define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + PL_ARENA_CONST_ALIGN_MASK) \
|
||||
& ~PL_ARENA_CONST_ALIGN_MASK)
|
||||
|
||||
#define PL_INIT_ARENA_POOL(pool, name, size) \
|
||||
PL_InitArenaPool(pool, name, size, PL_ARENA_CONST_ALIGN_MASK + 1)
|
||||
#else
|
||||
#define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + (pool)->mask) & ~(pool)->mask)
|
||||
#endif
|
||||
|
||||
#define PL_ARENA_ALLOCATE(p, pool, nb) \
|
||||
PR_BEGIN_MACRO \
|
||||
PLArena *_a = (pool)->current; \
|
||||
PRUint32 _nb = PL_ARENA_ALIGN(pool, nb); \
|
||||
PRUword _p = _a->avail; \
|
||||
PRUword _q = _p + _nb; \
|
||||
if (_q > _a->limit) \
|
||||
_p = (PRUword)PL_ArenaAllocate(pool, _nb); \
|
||||
else \
|
||||
_a->avail = _q; \
|
||||
p = (void *)_p; \
|
||||
PL_ArenaCountAllocation(pool, nb); \
|
||||
PR_END_MACRO
|
||||
|
||||
#define PL_ARENA_GROW(p, pool, size, incr) \
|
||||
PR_BEGIN_MACRO \
|
||||
PLArena *_a = (pool)->current; \
|
||||
PRUint32 _incr = PL_ARENA_ALIGN(pool, incr); \
|
||||
PRUword _p = _a->avail; \
|
||||
PRUword _q = _p + _incr; \
|
||||
if (_p == (PRUword)(p) + PL_ARENA_ALIGN(pool, size) && \
|
||||
_q <= _a->limit) { \
|
||||
_a->avail = _q; \
|
||||
PL_ArenaCountInplaceGrowth(pool, size, incr); \
|
||||
} else { \
|
||||
p = PL_ArenaGrow(pool, p, size, incr); \
|
||||
} \
|
||||
PL_ArenaCountGrowth(pool, size, incr); \
|
||||
PR_END_MACRO
|
||||
|
||||
#define PL_ARENA_MARK(pool) ((void *) (pool)->current->avail)
|
||||
#define PR_UPTRDIFF(p,q) ((PRUword)(p) - (PRUword)(q))
|
||||
|
||||
#ifdef DEBUG
|
||||
#define PL_FREE_PATTERN 0xDA
|
||||
#define PL_CLEAR_UNUSED(a) (PR_ASSERT((a)->avail <= (a)->limit), \
|
||||
memset((void*)(a)->avail, PL_FREE_PATTERN, \
|
||||
(a)->limit - (a)->avail))
|
||||
#define PL_CLEAR_ARENA(a) memset((void*)(a), PL_FREE_PATTERN, \
|
||||
(a)->limit - (PRUword)(a))
|
||||
#else
|
||||
#define PL_CLEAR_UNUSED(a)
|
||||
#define PL_CLEAR_ARENA(a)
|
||||
#endif
|
||||
|
||||
#define PL_ARENA_RELEASE(pool, mark) \
|
||||
PR_BEGIN_MACRO \
|
||||
char *_m = (char *)(mark); \
|
||||
PLArena *_a = (pool)->current; \
|
||||
if (PR_UPTRDIFF(_m, _a) <= PR_UPTRDIFF(_a->avail, _a)) { \
|
||||
_a->avail = (PRUword)PL_ARENA_ALIGN(pool, _m); \
|
||||
PL_CLEAR_UNUSED(_a); \
|
||||
PL_ArenaCountRetract(pool, _m); \
|
||||
} else { \
|
||||
PL_ArenaRelease(pool, _m); \
|
||||
} \
|
||||
PL_ArenaCountRelease(pool, _m); \
|
||||
PR_END_MACRO
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
#define PL_COUNT_ARENA(pool,op) ((pool)->stats.narenas op)
|
||||
#else
|
||||
#define PL_COUNT_ARENA(pool,op)
|
||||
#endif
|
||||
|
||||
#define PL_ARENA_DESTROY(pool, a, pnext) \
|
||||
PR_BEGIN_MACRO \
|
||||
PL_COUNT_ARENA(pool,--); \
|
||||
if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
|
||||
*(pnext) = (a)->next; \
|
||||
PL_CLEAR_ARENA(a); \
|
||||
free(a); \
|
||||
(a) = 0; \
|
||||
PR_END_MACRO
|
||||
|
||||
#ifdef PL_ARENAMETER
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
PR_EXTERN(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaCountInplaceGrowth(
|
||||
PLArenaPool *pool, PRUint32 size, PRUint32 incr);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaCountGrowth(
|
||||
PLArenaPool *pool, PRUint32 size, PRUint32 incr);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark);
|
||||
|
||||
PR_EXTERN(void) PL_DumpArenaStats(FILE *fp);
|
||||
|
||||
#else /* !PL_ARENAMETER */
|
||||
|
||||
#define PL_ArenaCountAllocation(ap, nb) /* nothing */
|
||||
#define PL_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */
|
||||
#define PL_ArenaCountGrowth(ap, size, incr) /* nothing */
|
||||
#define PL_ArenaCountRelease(ap, mark) /* nothing */
|
||||
#define PL_ArenaCountRetract(ap, mark) /* nothing */
|
||||
|
||||
#endif /* !PL_ARENAMETER */
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* plarena_h___ */
|
||||
95
mozilla/nsprpub/lib/ds/plarenas.h
Normal file
95
mozilla/nsprpub/lib/ds/plarenas.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
#if defined(PLARENAS_H)
|
||||
#else /* defined(PLARENAS_H) */
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct PLArenaPool PLArenaPool;
|
||||
|
||||
/*
|
||||
** Allocate an arena pool as specified by the parameters.
|
||||
**
|
||||
** This is equivelant to allocating the space yourself and then
|
||||
** calling PL_InitArenaPool().
|
||||
**
|
||||
** This function may fail (and return a NULL) for a variety of
|
||||
** reasons. The reason for a particular failure can be discovered
|
||||
** by calling PR_GetError().
|
||||
*/
|
||||
#if 0 /* Not implemented */
|
||||
PR_EXTERN(PLArenaPool*) PL_AllocArenaPool(
|
||||
const char *name, PRUint32 size, PRUint32 align);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Destroy an arena pool previously allocated by PL_AllocArenaPool().
|
||||
**
|
||||
** This function may fail if the arena is not empty and the caller
|
||||
** wishes to check for empty upon descruction.
|
||||
*/
|
||||
#if 0 /* Not implemented */
|
||||
PR_EXTERN(PRStatus) PL_DestroyArenaPool(PLArenaPool *pool, PRBool checkEmpty);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Initialize an arena pool with the given name for debugging and metering,
|
||||
** with a minimum size per arena of size bytes.
|
||||
**/
|
||||
PR_EXTERN(void) PL_InitArenaPool(
|
||||
PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align);
|
||||
|
||||
/*
|
||||
** Finish using arenas, freeing all memory associated with them.
|
||||
**/
|
||||
PR_EXTERN(void) PL_ArenaFinish(void);
|
||||
|
||||
/*
|
||||
** Free the arenas in pool. The user may continue to allocate from pool
|
||||
** after calling this function. There is no need to call PL_InitArenaPool()
|
||||
** again unless PL_FinishArenaPool(pool) has been called.
|
||||
**/
|
||||
PR_EXTERN(void) PL_FreeArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Free the arenas in pool and finish using it altogether.
|
||||
**/
|
||||
PR_EXTERN(void) PL_FinishArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Compact all of the arenas in a pool so that no space is wasted.
|
||||
**/
|
||||
PR_EXTERN(void) PL_CompactArenaPool(PLArenaPool *pool);
|
||||
|
||||
/*
|
||||
** Friend functions used by the PL_ARENA_*() macros.
|
||||
**/
|
||||
PR_EXTERN(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb);
|
||||
|
||||
PR_EXTERN(void *) PL_ArenaGrow(
|
||||
PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr);
|
||||
|
||||
PR_EXTERN(void) PL_ArenaRelease(PLArenaPool *pool, char *mark);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* defined(PLARENAS_H) */
|
||||
|
||||
/* plarenas */
|
||||
734
mozilla/nsprpub/lib/ds/plevent.c
Normal file
734
mozilla/nsprpub/lib/ds/plevent.c
Normal file
@@ -0,0 +1,734 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
#if defined(WIN16)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "plevent.h"
|
||||
#include "prmem.h"
|
||||
#include "prcmon.h"
|
||||
#include "prlog.h"
|
||||
#if !defined(WIN32)
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#if !defined(OS2)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(XP_MAC)
|
||||
#include <AppleEvents.h>
|
||||
#include "pprthred.h"
|
||||
#include "primpl.h"
|
||||
#else
|
||||
#include "private/pprthred.h"
|
||||
#include "private/primpl.h"
|
||||
#endif
|
||||
|
||||
static PRLogModuleInfo *event_lm = NULL;
|
||||
|
||||
/*******************************************************************************
|
||||
* Private Stuff
|
||||
******************************************************************************/
|
||||
|
||||
struct PLEventQueue {
|
||||
char* name;
|
||||
PRCList queue;
|
||||
PRMonitor* monitor;
|
||||
PRThread* handlerThread;
|
||||
#ifdef XP_UNIX
|
||||
PRInt32 eventPipe[2];
|
||||
PRPackedBool nativeNotifier;
|
||||
int notifyCount;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define PR_EVENT_PTR(_qp) \
|
||||
((PLEvent*) ((char*) (_qp) - offsetof(PLEvent, link)))
|
||||
|
||||
static PRStatus _pl_SetupNativeNotifier(PLEventQueue* self);
|
||||
static void _pl_CleanupNativeNotifier(PLEventQueue* self);
|
||||
static PRStatus _pl_NativeNotify(PLEventQueue* self);
|
||||
static PRStatus _pl_AcknowledgeNativeNotify(PLEventQueue* self);
|
||||
|
||||
|
||||
#if defined(_WIN32) || defined(WIN16)
|
||||
PLEventQueue * _pr_main_event_queue;
|
||||
UINT _pr_PostEventMsgId;
|
||||
HWND _pr_eventReceiverWindow;
|
||||
static char *_pr_eventWindowClass = "NSPR:EventWindow";
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Event Queue Operations
|
||||
******************************************************************************/
|
||||
|
||||
PR_IMPLEMENT(PLEventQueue*)
|
||||
PL_CreateEventQueue(char* name, PRThread* handlerThread)
|
||||
{
|
||||
PRStatus err;
|
||||
PLEventQueue* self = NULL;
|
||||
PRMonitor* mon = NULL;
|
||||
|
||||
if (event_lm == NULL)
|
||||
event_lm = PR_LOG_DEFINE("event");
|
||||
|
||||
self = PR_NEWZAP(PLEventQueue);
|
||||
if (self == NULL) return NULL;
|
||||
|
||||
mon = PR_NewNamedMonitor(name);
|
||||
if (mon == NULL) goto error;
|
||||
|
||||
self->name = name;
|
||||
self->monitor = mon;
|
||||
self->handlerThread = handlerThread;
|
||||
PR_INIT_CLIST(&self->queue);
|
||||
err = _pl_SetupNativeNotifier(self);
|
||||
if (err) goto error;
|
||||
|
||||
return self;
|
||||
|
||||
error:
|
||||
if (mon != NULL)
|
||||
PR_DestroyMonitor(mon);
|
||||
PR_DELETE(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRMonitor*)
|
||||
PL_GetEventQueueMonitor(PLEventQueue* self)
|
||||
{
|
||||
return self->monitor;
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
_pl_destroyEvent(PLEvent* event, void* data, PLEventQueue* queue)
|
||||
{
|
||||
#ifdef XP_MAC
|
||||
#pragma unused (data, queue)
|
||||
#endif
|
||||
PL_DequeueEvent(event, queue);
|
||||
PL_DestroyEvent(event);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_DestroyEventQueue(PLEventQueue* self)
|
||||
{
|
||||
PR_EnterMonitor(self->monitor);
|
||||
|
||||
/* destroy undelivered events */
|
||||
PL_MapEvents(self, _pl_destroyEvent, NULL);
|
||||
|
||||
_pl_CleanupNativeNotifier(self);
|
||||
|
||||
/* destroying the monitor also destroys the name */
|
||||
PR_ExitMonitor(self->monitor);
|
||||
PR_DestroyMonitor(self->monitor);
|
||||
PR_DELETE(self);
|
||||
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PL_PostEvent(PLEventQueue* self, PLEvent* event)
|
||||
{
|
||||
PRStatus err;
|
||||
PRMonitor* mon;
|
||||
|
||||
if (self == NULL)
|
||||
return PR_FAILURE;
|
||||
|
||||
mon = self->monitor;
|
||||
PR_EnterMonitor(mon);
|
||||
|
||||
/* insert event into thread's event queue: */
|
||||
if (event != NULL) {
|
||||
PR_APPEND_LINK(&event->link, &self->queue);
|
||||
}
|
||||
|
||||
/* notify even if event is NULL */
|
||||
err = _pl_NativeNotify(self);
|
||||
if (err != PR_SUCCESS) goto done;
|
||||
|
||||
/*
|
||||
* This may fall on deaf ears if we're really notifying the native
|
||||
* thread, and no one has called PL_WaitForEvent (or PL_EventLoop):
|
||||
*/
|
||||
err = PR_Notify(mon);
|
||||
|
||||
done:
|
||||
PR_ExitMonitor(mon);
|
||||
return err;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void*)
|
||||
PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event)
|
||||
{
|
||||
void* result;
|
||||
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
|
||||
PR_ASSERT(event != NULL);
|
||||
PR_CEnterMonitor(event);
|
||||
|
||||
if (PR_CurrentThread() == self->handlerThread) {
|
||||
/* Handle the case where the thread requesting the event handling
|
||||
is also the thread that's supposed to do the handling. */
|
||||
result = event->handler(event);
|
||||
}
|
||||
else {
|
||||
int inEventQueueMon = PR_GetMonitorEntryCount(self->monitor);
|
||||
int i, entryCount = self->monitor->entryCount;
|
||||
|
||||
event->synchronousResult = (void*)PR_TRUE;
|
||||
PR_PostEvent(self, event);
|
||||
/* We need to temporarily give up our event queue monitor if
|
||||
we're holding it, otherwise, the thread we're going to wait
|
||||
for notification from won't be able to enter it to process
|
||||
the event. */
|
||||
if (inEventQueueMon) {
|
||||
for (i = 0; i < entryCount; i++)
|
||||
PR_ExitMonitor(self->monitor);
|
||||
}
|
||||
PR_CWait(event, PR_INTERVAL_NO_TIMEOUT); /* wait for event to be handled or destroyed */
|
||||
if (inEventQueueMon) {
|
||||
for (i = 0; i < entryCount; i++)
|
||||
PR_EnterMonitor(self->monitor);
|
||||
}
|
||||
result = event->synchronousResult;
|
||||
event->synchronousResult = NULL;
|
||||
}
|
||||
|
||||
PR_CExitMonitor(event);
|
||||
|
||||
/* For synchronous events, they're destroyed here on the caller's
|
||||
thread before the result is returned. See PL_HandleEvent. */
|
||||
PL_DestroyEvent(event);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PLEvent*)
|
||||
PL_GetEvent(PLEventQueue* self)
|
||||
{
|
||||
PLEvent* event = NULL;
|
||||
PRStatus err;
|
||||
PRMonitor* mon;
|
||||
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
|
||||
mon = self->monitor;
|
||||
PR_EnterMonitor(mon);
|
||||
|
||||
err = _pl_AcknowledgeNativeNotify(self);
|
||||
if (err) goto done;
|
||||
|
||||
if (!PR_CLIST_IS_EMPTY(&self->queue)) {
|
||||
/* then grab the event and return it: */
|
||||
event = PR_EVENT_PTR(self->queue.next);
|
||||
PR_REMOVE_AND_INIT_LINK(&event->link);
|
||||
}
|
||||
|
||||
done:
|
||||
PR_ExitMonitor(mon);
|
||||
return event;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRBool)
|
||||
PL_EventAvailable(PLEventQueue* self)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
if (self == NULL)
|
||||
return PR_FALSE;
|
||||
|
||||
PR_EnterMonitor(self->monitor);
|
||||
|
||||
if (!PR_CLIST_IS_EMPTY(&self->queue))
|
||||
result = PR_TRUE;
|
||||
|
||||
PR_ExitMonitor(self->monitor);
|
||||
return result;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data)
|
||||
{
|
||||
PRCList* qp;
|
||||
|
||||
if (self == NULL)
|
||||
return;
|
||||
|
||||
PR_EnterMonitor(self->monitor);
|
||||
qp = self->queue.next;
|
||||
while (qp != &self->queue) {
|
||||
PLEvent* event = PR_EVENT_PTR(qp);
|
||||
qp = qp->next;
|
||||
(*fun)(event, data, self);
|
||||
}
|
||||
PR_ExitMonitor(self->monitor);
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
_pl_DestroyEventForOwner(PLEvent* event, void* owner, PLEventQueue* queue)
|
||||
{
|
||||
PR_ASSERT(PR_GetMonitorEntryCount(queue->monitor) > 0);
|
||||
if (event->owner == owner) {
|
||||
PR_LOG(event_lm, PR_LOG_DEBUG,
|
||||
("$$$ \tdestroying event %0x for owner %0x", event, owner));
|
||||
PL_DequeueEvent(event, queue);
|
||||
if (event->synchronousResult == (void*)PR_TRUE) {
|
||||
PR_CEnterMonitor(event);
|
||||
event->synchronousResult = NULL;
|
||||
PR_CNotify(event);
|
||||
PR_CExitMonitor(event);
|
||||
}
|
||||
else {
|
||||
PL_DestroyEvent(event);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PR_LOG(event_lm, PR_LOG_DEBUG,
|
||||
("$$$ \tskipping event %0x for owner %0x", event, owner));
|
||||
}
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_RevokeEvents(PLEventQueue* self, void* owner)
|
||||
{
|
||||
if (self == NULL)
|
||||
return;
|
||||
|
||||
PR_LOG_BEGIN(event_lm, PR_LOG_DEBUG,
|
||||
("$$$ revoking events for owner %0x", owner));
|
||||
|
||||
/*
|
||||
** First we enter the monitor so that no one else can post any events
|
||||
** to the queue:
|
||||
*/
|
||||
PR_EnterMonitor(self->monitor);
|
||||
PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ owner %0x, entered monitor", owner));
|
||||
|
||||
/*
|
||||
** Discard any pending events for this owner:
|
||||
*/
|
||||
PL_MapEvents(self, _pl_DestroyEventForOwner, owner);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
PRCList* qp = self->queue.next;
|
||||
while (qp != &self->queue) {
|
||||
PREvent* event = PR_EVENT_PTR(qp);
|
||||
qp = qp->next;
|
||||
PR_ASSERT(event->owner != owner);
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
PR_ExitMonitor(self->monitor);
|
||||
|
||||
PR_LOG_END(event_lm, PR_LOG_DEBUG,
|
||||
("$$$ revoking events for owner %0x", owner));
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_ProcessPendingEvents(PLEventQueue* self)
|
||||
{
|
||||
if (self == NULL)
|
||||
return;
|
||||
|
||||
while (PR_TRUE) {
|
||||
PLEvent* event = PL_GetEvent(self);
|
||||
if (event == NULL) return;
|
||||
|
||||
PR_LOG_BEGIN(event_lm, PR_LOG_DEBUG, ("$$$ processing event"));
|
||||
PL_HandleEvent(event);
|
||||
PR_LOG_END(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Event Operations
|
||||
******************************************************************************/
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_InitEvent(PLEvent* self, void* owner,
|
||||
PLHandleEventProc handler,
|
||||
PLDestroyEventProc destructor)
|
||||
{
|
||||
PR_INIT_CLIST(&self->link);
|
||||
self->handler = handler;
|
||||
self->destructor = destructor;
|
||||
self->owner = owner;
|
||||
self->synchronousResult = NULL;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void*)
|
||||
PL_GetEventOwner(PLEvent* self)
|
||||
{
|
||||
return self->owner;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_HandleEvent(PLEvent* self)
|
||||
{
|
||||
void* result;
|
||||
|
||||
if (self == NULL)
|
||||
return;
|
||||
|
||||
/* This event better not be on an event queue anymore. */
|
||||
PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));
|
||||
|
||||
result = (*self->handler)(self);
|
||||
if (NULL != self->synchronousResult) {
|
||||
PR_CEnterMonitor(self);
|
||||
self->synchronousResult = result;
|
||||
PR_CNotify(self); /* wake up the guy waiting for the result */
|
||||
PR_CExitMonitor(self);
|
||||
}
|
||||
else {
|
||||
/* For asynchronous events, they're destroyed by the event-handler
|
||||
thread. See PR_PostSynchronousEvent. */
|
||||
PL_DestroyEvent(self);
|
||||
}
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_DestroyEvent(PLEvent* self)
|
||||
{
|
||||
if (self == NULL)
|
||||
return;
|
||||
|
||||
/* This event better not be on an event queue anymore. */
|
||||
PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));
|
||||
|
||||
(*self->destructor)(self);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_DequeueEvent(PLEvent* self, PLEventQueue* queue)
|
||||
{
|
||||
#ifdef XP_MAC
|
||||
#pragma unused (queue)
|
||||
#endif
|
||||
if (self == NULL)
|
||||
return;
|
||||
|
||||
/* Only the owner is allowed to dequeue events because once the
|
||||
client has put it in the queue, they have no idea whether it's
|
||||
been processed and destroyed or not. */
|
||||
/* PR_ASSERT(queue->handlerThread == PR_CurrentThread());*/
|
||||
|
||||
PR_EnterMonitor(queue->monitor);
|
||||
|
||||
PR_ASSERT(!PR_CLIST_IS_EMPTY(&self->link));
|
||||
PR_REMOVE_AND_INIT_LINK(&self->link);
|
||||
|
||||
PR_ExitMonitor(queue->monitor);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Pure Event Queues
|
||||
*
|
||||
* For when you're only processing PLEvents and there is no native
|
||||
* select, thread messages, or AppleEvents.
|
||||
******************************************************************************/
|
||||
|
||||
PR_IMPLEMENT(PLEvent*)
|
||||
PL_WaitForEvent(PLEventQueue* self)
|
||||
{
|
||||
PLEvent* event;
|
||||
PRMonitor* mon;
|
||||
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
|
||||
mon = self->monitor;
|
||||
PR_EnterMonitor(mon);
|
||||
|
||||
while ((event = PL_GetEvent(self)) == NULL) {
|
||||
PRStatus err;
|
||||
PR_LOG_END(event_lm, PR_LOG_DEBUG, ("$$$ waiting for event"));
|
||||
err = PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
|
||||
if ((err == PR_FAILURE)
|
||||
&& (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break;
|
||||
}
|
||||
|
||||
PR_ExitMonitor(mon);
|
||||
return event;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_EventLoop(PLEventQueue* self)
|
||||
{
|
||||
if (self == NULL)
|
||||
return;
|
||||
|
||||
while (PR_TRUE) {
|
||||
PLEvent* event = PL_WaitForEvent(self);
|
||||
if (event == NULL) {
|
||||
/* This can only happen if the current thread is interrupted */
|
||||
return;
|
||||
}
|
||||
|
||||
PR_LOG_BEGIN(event_lm, PR_LOG_DEBUG, ("$$$ processing event"));
|
||||
PL_HandleEvent(event);
|
||||
PR_LOG_END(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Native Event Queues
|
||||
*
|
||||
* For when you need to call select, or WaitNextEvent, and yet also want
|
||||
* to handle PLEvents.
|
||||
******************************************************************************/
|
||||
|
||||
static PRStatus
|
||||
_pl_SetupNativeNotifier(PLEventQueue* self)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (self)
|
||||
#endif
|
||||
|
||||
PRInt32 err = 0;
|
||||
#if defined(XP_UNIX)
|
||||
err = pipe(self->eventPipe);
|
||||
#endif
|
||||
return err == 0 ? PR_SUCCESS : PR_FAILURE;
|
||||
}
|
||||
|
||||
static void
|
||||
_pl_CleanupNativeNotifier(PLEventQueue* self)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (self)
|
||||
#endif
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
close(self->eventPipe[0]);
|
||||
close(self->eventPipe[1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
_pl_NativeNotify(PLEventQueue* self)
|
||||
{
|
||||
#if defined(XP_UNIX)
|
||||
|
||||
# define NOTIFY_TOKEN 0xFA
|
||||
PRInt32 count;
|
||||
unsigned char buf[] = { NOTIFY_TOKEN };
|
||||
|
||||
count = write(self->eventPipe[1], buf, 1);
|
||||
self->notifyCount++;
|
||||
return (count == 1) ? PR_SUCCESS : PR_FAILURE;
|
||||
|
||||
#elif defined(XP_PC) && ( defined(WINNT) || defined(WIN95) || defined(WIN16))
|
||||
/*
|
||||
** Post a message to the NSPR window on the main thread requesting
|
||||
** it to process the pending events. This is only necessary for the
|
||||
** main event queue, since the main thread is waiting for OS events.
|
||||
*/
|
||||
if (self == _pr_main_event_queue) {
|
||||
PostMessage( _pr_eventReceiverWindow, _pr_PostEventMsgId,
|
||||
(WPARAM)0, (LPARAM)self);
|
||||
}
|
||||
return PR_SUCCESS;
|
||||
|
||||
#elif defined(XP_MAC)
|
||||
|
||||
#pragma unused (self)
|
||||
return PR_SUCCESS; /* XXX can fail? */
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
_pl_AcknowledgeNativeNotify(PLEventQueue* self)
|
||||
{
|
||||
#if defined(XP_UNIX)
|
||||
|
||||
PRInt32 count;
|
||||
unsigned char c;
|
||||
|
||||
if (self->notifyCount <= 0) return PR_SUCCESS;
|
||||
/* consume the byte NativeNotify put in our pipe: */
|
||||
count = read(self->eventPipe[0], &c, 1);
|
||||
self->notifyCount--;
|
||||
return ((count == 1 && c == NOTIFY_TOKEN) || count == 0)
|
||||
? PR_SUCCESS : PR_FAILURE;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (self)
|
||||
#endif
|
||||
|
||||
/* nothing to do on the other platforms */
|
||||
return PR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRInt32)
|
||||
PL_GetEventQueueSelectFD(PLEventQueue* self)
|
||||
{
|
||||
if (self == NULL)
|
||||
return -1;
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
return self->eventPipe[0];
|
||||
#else
|
||||
return -1; /* other platforms don't handle this (yet) */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined(WIN16) || defined(_WIN32)
|
||||
/*
|
||||
** Global Instance handle...
|
||||
** In Win32 this is the module handle of the DLL.
|
||||
**
|
||||
*/
|
||||
HINSTANCE _pr_hInstance;
|
||||
#endif
|
||||
|
||||
#if defined(WIN16)
|
||||
/*
|
||||
** Function LibMain() is required by Win16
|
||||
**
|
||||
*/
|
||||
int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
|
||||
WORD cbHeapSize, LPSTR lpszCmdLine )
|
||||
{
|
||||
_pr_hInstance = hInst;
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* WIN16 */
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
/*
|
||||
** Initialization routine for the NSPR DLL...
|
||||
*/
|
||||
|
||||
BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
|
||||
{
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
_pr_hInstance = hDLL;
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
_pr_hInstance = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(WIN16) || defined(_WIN32)
|
||||
PR_IMPLEMENT(PLEventQueue *)
|
||||
PL_GetMainEventQueue()
|
||||
{
|
||||
PR_ASSERT(_pr_main_event_queue);
|
||||
|
||||
return _pr_main_event_queue;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
#if defined(WIN16)
|
||||
__loadds
|
||||
#endif
|
||||
_md_EventReceiverProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (_pr_PostEventMsgId == uMsg )
|
||||
{
|
||||
PREventQueue *queue = (PREventQueue *)lParam;
|
||||
|
||||
PR_ASSERT(queue == PL_GetMainEventQueue());
|
||||
if (queue == PL_GetMainEventQueue())
|
||||
{
|
||||
PR_ProcessPendingEvents(queue);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_InitializeEventsLib(char *name)
|
||||
{
|
||||
WNDCLASS wc;
|
||||
|
||||
_pr_main_event_queue = PL_CreateEventQueue(name, PR_GetCurrentThread());
|
||||
|
||||
/* Register the windows message for NSPR Event notification */
|
||||
_pr_PostEventMsgId = RegisterWindowMessage("NSPR_PostEvent");
|
||||
|
||||
/* Register the class for the event receiver window */
|
||||
if (!GetClassInfo(_pr_hInstance, _pr_eventWindowClass, &wc)) {
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = _md_EventReceiverProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = _pr_hInstance;
|
||||
wc.hIcon = NULL;
|
||||
wc.hCursor = NULL;
|
||||
wc.hbrBackground = (HBRUSH) NULL;
|
||||
wc.lpszMenuName = (LPCSTR) NULL;
|
||||
wc.lpszClassName = _pr_eventWindowClass;
|
||||
RegisterClass(&wc);
|
||||
}
|
||||
|
||||
/* Create the event receiver window */
|
||||
_pr_eventReceiverWindow = CreateWindow(_pr_eventWindowClass,
|
||||
"NSPR:EventReceiver",
|
||||
0, 0, 0, 10, 10,
|
||||
NULL, NULL, _pr_hInstance,
|
||||
NULL);
|
||||
PR_ASSERT(_pr_eventReceiverWindow);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(WIN16)
|
||||
PR_IMPLEMENT(HWND)
|
||||
PR_GetEventReceiverWindow()
|
||||
{
|
||||
if(_pr_eventReceiverWindow != NULL)
|
||||
{
|
||||
return _pr_eventReceiverWindow;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
403
mozilla/nsprpub/lib/ds/plevent.h
Normal file
403
mozilla/nsprpub/lib/ds/plevent.h
Normal file
@@ -0,0 +1,403 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/**********************************************************************
|
||||
NSPL Events
|
||||
|
||||
Defining Events
|
||||
---------------
|
||||
|
||||
Events are essentially structures that represent argument lists for a
|
||||
function that will run on another thread. All event structures you
|
||||
define must include a PLEvent struct as their first field:
|
||||
|
||||
typedef struct MyEventType {
|
||||
PLEvent e;
|
||||
// arguments follow...
|
||||
int x;
|
||||
char* y;
|
||||
} MyEventType;
|
||||
|
||||
It is also essential that you establish a model of ownership for each
|
||||
argument passed in an event record, i.e. whether particular arguments
|
||||
will be deleted by the event destruction callback, or whether they
|
||||
only loaned to the event handler callback, and guaranteed to persist
|
||||
until the time at which the handler is called.
|
||||
|
||||
Sending Events
|
||||
--------------
|
||||
|
||||
Events are initialized by PL_InitEvent and can be sent via
|
||||
PL_PostEvent or PL_PostSynchronousEvent. Events can also have an
|
||||
owner. The owner of an event can revoke all the events in a given
|
||||
event-queue by calling PL_RevokeEvents. An owner might want
|
||||
to do this if, for instance, it is being destroyed, and handling the
|
||||
events after the owner's destruction would cause an error (e.g. an
|
||||
MWContext).
|
||||
|
||||
Since the act of initializing and posting an event must be coordinated
|
||||
with it's possible revocation, it is essential that the event-queue's
|
||||
monitor be entered surrounding the code that constructs, initializes
|
||||
and posts the event:
|
||||
|
||||
void postMyEvent(MyOwner* owner, int x, char* y)
|
||||
{
|
||||
MyEventType* event;
|
||||
|
||||
PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
|
||||
|
||||
// construct
|
||||
event = PR_NEW(MyEventType);
|
||||
if (event == NULL) goto done;
|
||||
|
||||
// initialize
|
||||
PL_InitEvent(event, owner,
|
||||
(PLHandleEventProc)handleMyEvent,
|
||||
(PLDestroyEventProc)destroyMyEvent);
|
||||
event->x = x;
|
||||
event->y = strdup(y);
|
||||
|
||||
// post
|
||||
PL_PostEvent(myQueue, &event->e);
|
||||
|
||||
done:
|
||||
PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
|
||||
}
|
||||
|
||||
If you don't call PL_InitEvent and PL_PostEvent within the
|
||||
event-queue's monitor, you'll get a big red assert.
|
||||
|
||||
Handling Events
|
||||
---------------
|
||||
|
||||
To handle an event you must write a callback that is passed the event
|
||||
record you defined containing the event's arguments:
|
||||
|
||||
void* handleMyEvent(MyEventType* event)
|
||||
{
|
||||
doit(event->x, event->y);
|
||||
return NULL; // you could return a value for a sync event
|
||||
}
|
||||
|
||||
Similarly for the destruction callback:
|
||||
|
||||
void destroyMyEvent(MyEventType* event)
|
||||
{
|
||||
free(event->y); // created by strdup
|
||||
free(event);
|
||||
}
|
||||
|
||||
Processing Events in Your Event Loop
|
||||
------------------------------------
|
||||
|
||||
If your main loop only processes events delivered to the event queue,
|
||||
things are rather simple. You just get the next event (which may
|
||||
block), and then handle it:
|
||||
|
||||
while (1) {
|
||||
event = PL_GetEvent(myQueue);
|
||||
PL_HandleEvent(event);
|
||||
}
|
||||
|
||||
However, if other things must be waited on, you'll need to obtain a
|
||||
file-descriptor that represents your event queue, and hand it to select:
|
||||
|
||||
fd = PL_GetEventQueueSelectFD(myQueue);
|
||||
...add fd to select set...
|
||||
while (select(...)) {
|
||||
if (...fd...) {
|
||||
PL_ProcessPendingEvents(myQueue);
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
Of course, with Motif and Windows it's more complicated than that, and
|
||||
on Mac it's completely different, but you get the picture.
|
||||
|
||||
Revoking Events
|
||||
---------------
|
||||
If at any time an owner of events is about to be destroyed, you must
|
||||
take steps to ensure that no one tries to use the event queue after
|
||||
the owner is gone (or a crash may result). You can do this by either
|
||||
processing all the events in the queue before destroying the owner:
|
||||
|
||||
{
|
||||
...
|
||||
PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
|
||||
PL_ProcessPendingEvents(myQueue);
|
||||
DestroyMyOwner(owner);
|
||||
PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
|
||||
...
|
||||
}
|
||||
|
||||
or by revoking the events that are in the queue for that owner. This
|
||||
removes them from the queue and calls their destruction callback:
|
||||
|
||||
{
|
||||
...
|
||||
PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
|
||||
PL_RevokeEvents(myQueue, owner);
|
||||
DestroyMyOwner(owner);
|
||||
PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
|
||||
...
|
||||
}
|
||||
|
||||
In either case it is essential that you be in the event-queue's monitor
|
||||
to ensure that all events are removed from the queue for that owner,
|
||||
and to ensure that no more events will be delivered for that owner.
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef prevent_h___
|
||||
#define prevent_h___
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prclist.h"
|
||||
#include "prthread.h"
|
||||
#include "prmon.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
/* Typedefs */
|
||||
|
||||
typedef struct PLEvent PLEvent;
|
||||
typedef struct PLEventQueue PLEventQueue;
|
||||
|
||||
/*******************************************************************************
|
||||
* Event Queue Operations
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
** Creates a new event queue. Returns NULL on failure.
|
||||
*/
|
||||
PR_EXTERN(PLEventQueue*)
|
||||
PL_CreateEventQueue(char* name, PRThread* handlerThread);
|
||||
|
||||
/*
|
||||
** Destroys an event queue.
|
||||
*/
|
||||
PR_EXTERN(void)
|
||||
PL_DestroyEventQueue(PLEventQueue* self);
|
||||
|
||||
/*
|
||||
** Returns the monitor associated with an event queue. This monitor is
|
||||
** selectable. The monitor should be entered to protect against anyone
|
||||
** calling PL_RevokeEvents while the event is trying to be constructed
|
||||
** and delivered.
|
||||
*/
|
||||
PR_EXTERN(PRMonitor*)
|
||||
PL_GetEventQueueMonitor(PLEventQueue* self);
|
||||
|
||||
#define PL_ENTER_EVENT_QUEUE_MONITOR(queue) \
|
||||
PR_EnterMonitor(PL_GetEventQueueMonitor(queue))
|
||||
|
||||
#define PL_EXIT_EVENT_QUEUE_MONITOR(queue) \
|
||||
PR_ExitMonitor(PL_GetEventQueueMonitor(queue))
|
||||
|
||||
/*
|
||||
** Posts an event to an event queue, waking up any threads waiting for an
|
||||
** event. If event is NULL, notification still occurs, but no event will
|
||||
** be available.
|
||||
**
|
||||
** Any events delivered by this routine will be destroyed by PL_HandleEvent
|
||||
** when it is called (by the event-handling thread).
|
||||
*/
|
||||
PR_EXTERN(PRStatus)
|
||||
PL_PostEvent(PLEventQueue* self, PLEvent* event);
|
||||
|
||||
/*
|
||||
** Like PL_PostEvent, this routine posts an event to the event handling
|
||||
** thread, but does so synchronously, waiting for the result. The result
|
||||
** which is the value of the handler routine is returned.
|
||||
**
|
||||
** Any events delivered by this routine will be not be destroyed by
|
||||
** PL_HandleEvent, but instead will be destroyed just before the result is
|
||||
** returned (by the current thread).
|
||||
*/
|
||||
PR_EXTERN(void*)
|
||||
PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event);
|
||||
|
||||
/*
|
||||
** Gets an event from an event queue. Returns NULL if no event is
|
||||
** available.
|
||||
*/
|
||||
PR_EXTERN(PLEvent*)
|
||||
PL_GetEvent(PLEventQueue* self);
|
||||
|
||||
/*
|
||||
** Returns true if there is an event available for PL_GetEvent.
|
||||
*/
|
||||
PR_EXTERN(PRBool)
|
||||
PL_EventAvailable(PLEventQueue* self);
|
||||
|
||||
/*
|
||||
** This is the type of the function that must be passed to PL_MapEvents
|
||||
** (see description below).
|
||||
*/
|
||||
typedef void
|
||||
(PR_CALLBACK *PLEventFunProc)(PLEvent* event, void* data, PLEventQueue* queue);
|
||||
|
||||
/*
|
||||
** Applies a function to every event in the event queue. This can be used
|
||||
** to selectively handle, filter, or remove events. The data pointer is
|
||||
** passed to each invocation of the function fun.
|
||||
*/
|
||||
PR_EXTERN(void)
|
||||
PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data);
|
||||
|
||||
/*
|
||||
** This routine walks an event queue and destroys any event whose owner is
|
||||
** the owner specified. The == operation is used to compare owners.
|
||||
*/
|
||||
PR_EXTERN(void)
|
||||
PL_RevokeEvents(PLEventQueue* self, void* owner);
|
||||
|
||||
/*
|
||||
** This routine processes all pending events in the event queue. It can be
|
||||
** called from the thread's main event-processing loop whenever the event
|
||||
** queue's selectFD is ready (returned by PL_GetEventQueueSelectFD).
|
||||
*/
|
||||
PR_EXTERN(void)
|
||||
PL_ProcessPendingEvents(PLEventQueue* self);
|
||||
|
||||
/*******************************************************************************
|
||||
* Pure Event Queues
|
||||
*
|
||||
* For when you're only processing PLEvents and there is no native
|
||||
* select, thread messages, or AppleEvents.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
** Blocks until an event can be returned from the event queue. This routine
|
||||
** may return NULL if the current thread is interrupted.
|
||||
*/
|
||||
PR_EXTERN(PLEvent*)
|
||||
PL_WaitForEvent(PLEventQueue* self);
|
||||
|
||||
/*
|
||||
** One stop shopping if all you're going to do is process PLEvents. Just
|
||||
** call this and it loops forever processing events as they arrive. It will
|
||||
** terminate when your thread is interrupted or dies.
|
||||
*/
|
||||
PR_EXTERN(void)
|
||||
PL_EventLoop(PLEventQueue* self);
|
||||
|
||||
/*******************************************************************************
|
||||
* Native Event Queues
|
||||
*
|
||||
* For when you need to call select, or WaitNextEvent, and yet also want
|
||||
* to handle PLEvents.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
** This routine allows you to grab the file descriptor associated with an
|
||||
** event queue and use it in the readFD set of select. Useful for platforms
|
||||
** that support select, and must wait on other things besides just PLEvents.
|
||||
*/
|
||||
PR_EXTERN(PRInt32)
|
||||
PL_GetEventQueueSelectFD(PLEventQueue* self);
|
||||
|
||||
/*******************************************************************************
|
||||
* Event Operations
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
** The type of an event handler function. This function is passed as an
|
||||
** initialization argument to PL_InitEvent, and called by
|
||||
** PL_HandleEvent. If the event is called synchronously, a void* result
|
||||
** may be returned (otherwise any result will be ignored).
|
||||
*/
|
||||
typedef void*
|
||||
(PR_CALLBACK *PLHandleEventProc)(PLEvent* self);
|
||||
|
||||
/*
|
||||
** The type of an event destructor function. This function is passed as
|
||||
** an initialization argument to PL_InitEvent, and called by
|
||||
** PL_DestroyEvent.
|
||||
*/
|
||||
typedef void
|
||||
(PR_CALLBACK *PLDestroyEventProc)(PLEvent* self);
|
||||
|
||||
/*
|
||||
** Initializes an event. Usually events are embedded in a larger event
|
||||
** structure which holds event-specific data, so this is an initializer
|
||||
** for that embedded part of the structure.
|
||||
*/
|
||||
PR_EXTERN(void)
|
||||
PL_InitEvent(PLEvent* self, void* owner,
|
||||
PLHandleEventProc handler,
|
||||
PLDestroyEventProc destructor);
|
||||
|
||||
/*
|
||||
** Returns the owner of an event.
|
||||
*/
|
||||
PR_EXTERN(void*)
|
||||
PL_GetEventOwner(PLEvent* self);
|
||||
|
||||
/*
|
||||
** Handles an event, calling the event's handler routine.
|
||||
*/
|
||||
PR_EXTERN(void)
|
||||
PL_HandleEvent(PLEvent* self);
|
||||
|
||||
/*
|
||||
** Destroys an event, calling the event's destructor.
|
||||
*/
|
||||
PR_EXTERN(void)
|
||||
PL_DestroyEvent(PLEvent* self);
|
||||
|
||||
/*
|
||||
** Removes an event from an event queue.
|
||||
*/
|
||||
PR_EXTERN(void)
|
||||
PL_DequeueEvent(PLEvent* self, PLEventQueue* queue);
|
||||
|
||||
#if defined(_WIN32) || defined(WIN16)
|
||||
PR_EXTERN(HWND)
|
||||
PR_GetEventReceiverWindow();
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Private Stuff
|
||||
******************************************************************************/
|
||||
|
||||
struct PLEvent {
|
||||
PRCList link;
|
||||
PLHandleEventProc handler;
|
||||
PLDestroyEventProc destructor;
|
||||
void* owner;
|
||||
void* synchronousResult;
|
||||
/* other fields follow... */
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
** Returns the event queue associated with the main thread. Note that
|
||||
** the event queue is now created by NSPR.
|
||||
*/
|
||||
#ifdef XP_PC
|
||||
PR_EXTERN(PLEventQueue *)
|
||||
PL_GetMainEventQueue(void);
|
||||
PR_EXTERN(void)
|
||||
PL_InitializeEventsLib(char *name);
|
||||
#endif /* XP_PC */
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* prevent_h___ */
|
||||
477
mozilla/nsprpub/lib/ds/plhash.c
Normal file
477
mozilla/nsprpub/lib/ds/plhash.c
Normal file
@@ -0,0 +1,477 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PL hash table package.
|
||||
*/
|
||||
#include "plhash.h"
|
||||
#include "prbit.h"
|
||||
#include "prlog.h"
|
||||
#include "prmem.h"
|
||||
#include "prtypes.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Compute the number of buckets in ht */
|
||||
#define NBUCKETS(ht) (1 << (PL_HASH_BITS - (ht)->shift))
|
||||
|
||||
/* The smallest table has 16 buckets */
|
||||
#define MINBUCKETSLOG2 4
|
||||
#define MINBUCKETS (1 << MINBUCKETSLOG2)
|
||||
|
||||
/* Compute the maximum entries given n buckets that we will tolerate, ~90% */
|
||||
#define OVERLOADED(n) ((n) - ((n) >> 3))
|
||||
|
||||
/* Compute the number of entries below which we shrink the table by half */
|
||||
#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
|
||||
|
||||
/*
|
||||
** Stubs for default hash allocator ops.
|
||||
*/
|
||||
static void * PR_CALLBACK
|
||||
DefaultAllocTable(void *pool, PRSize size)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
return PR_MALLOC(size);
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
DefaultFreeTable(void *pool, void *item)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
PR_DELETE(item);
|
||||
}
|
||||
|
||||
static PLHashEntry * PR_CALLBACK
|
||||
DefaultAllocEntry(void *pool, const void *key)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool,key)
|
||||
#endif
|
||||
|
||||
return PR_NEW(PLHashEntry);
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
DefaultFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
|
||||
{
|
||||
#if defined(XP_MAC)
|
||||
#pragma unused (pool)
|
||||
#endif
|
||||
|
||||
if (flag == HT_FREE_ENTRY)
|
||||
PR_DELETE(he);
|
||||
}
|
||||
|
||||
static PLHashAllocOps defaultHashAllocOps = {
|
||||
DefaultAllocTable, DefaultFreeTable,
|
||||
DefaultAllocEntry, DefaultFreeEntry
|
||||
};
|
||||
|
||||
PR_IMPLEMENT(PLHashTable *)
|
||||
PL_NewHashTable(PRUint32 n, PLHashFunction keyHash,
|
||||
PLHashComparator keyCompare, PLHashComparator valueCompare,
|
||||
PLHashAllocOps *allocOps, void *allocPriv)
|
||||
{
|
||||
PLHashTable *ht;
|
||||
PRUint32 nb;
|
||||
|
||||
if (n <= MINBUCKETS) {
|
||||
n = MINBUCKETSLOG2;
|
||||
} else {
|
||||
n = PR_CeilingLog2(n);
|
||||
if ((PRInt32)n < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!allocOps) allocOps = &defaultHashAllocOps;
|
||||
|
||||
ht = (PLHashTable*)((*allocOps->allocTable)(allocPriv, sizeof *ht));
|
||||
if (!ht)
|
||||
return 0;
|
||||
memset(ht, 0, sizeof *ht);
|
||||
ht->shift = PL_HASH_BITS - n;
|
||||
n = 1 << n;
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
if (n > 16000) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return 0;
|
||||
}
|
||||
#endif /* WIN16 */
|
||||
nb = n * sizeof(PLHashEntry *);
|
||||
ht->buckets = (PLHashEntry**)((*allocOps->allocTable)(allocPriv, nb));
|
||||
if (!ht->buckets) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return 0;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
ht->keyHash = keyHash;
|
||||
ht->keyCompare = keyCompare;
|
||||
ht->valueCompare = valueCompare;
|
||||
ht->allocOps = allocOps;
|
||||
ht->allocPriv = allocPriv;
|
||||
return ht;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_HashTableDestroy(PLHashTable *ht)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
PLHashEntry *he, *next;
|
||||
PLHashAllocOps *allocOps = ht->allocOps;
|
||||
void *allocPriv = ht->allocPriv;
|
||||
|
||||
n = NBUCKETS(ht);
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = ht->buckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
(*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht->buckets);
|
||||
#ifdef DEBUG
|
||||
memset(ht, 0xDB, sizeof *ht);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
}
|
||||
|
||||
/*
|
||||
** Multiplicative hash, from Knuth 6.4.
|
||||
*/
|
||||
#define GOLDEN_RATIO 0x9E3779B9U
|
||||
|
||||
PR_IMPLEMENT(PLHashEntry **)
|
||||
PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key)
|
||||
{
|
||||
PLHashEntry *he, **hep, **hep0;
|
||||
PLHashNumber h;
|
||||
|
||||
#ifdef HASHMETER
|
||||
ht->nlookups++;
|
||||
#endif
|
||||
h = keyHash * GOLDEN_RATIO;
|
||||
h >>= ht->shift;
|
||||
hep = hep0 = &ht->buckets[h];
|
||||
while ((he = *hep) != 0) {
|
||||
if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) {
|
||||
/* Move to front of chain if not already there */
|
||||
if (hep != hep0) {
|
||||
*hep = he->next;
|
||||
he->next = *hep0;
|
||||
*hep0 = he;
|
||||
}
|
||||
return hep0;
|
||||
}
|
||||
hep = &he->next;
|
||||
#ifdef HASHMETER
|
||||
ht->nsteps++;
|
||||
#endif
|
||||
}
|
||||
return hep;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PLHashEntry *)
|
||||
PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep,
|
||||
PLHashNumber keyHash, const void *key, void *value)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
PLHashEntry *he, *next, **oldbuckets;
|
||||
PRUint32 nb;
|
||||
|
||||
/* Grow the table if it is overloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (ht->nentries >= OVERLOADED(n)) {
|
||||
#ifdef HASHMETER
|
||||
ht->ngrows++;
|
||||
#endif
|
||||
ht->shift--;
|
||||
oldbuckets = ht->buckets;
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
if (2 * n > 16000)
|
||||
return 0;
|
||||
#endif /* WIN16 */
|
||||
nb = 2 * n * sizeof(PLHashEntry *);
|
||||
ht->buckets = (PLHashEntry**)
|
||||
((*ht->allocOps->allocTable)(ht->allocPriv, nb));
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return 0;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = PL_HashTableRawLookup(ht, he->keyHash, he->key);
|
||||
PR_ASSERT(*hep == 0);
|
||||
he->next = 0;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
hep = PL_HashTableRawLookup(ht, keyHash, key);
|
||||
}
|
||||
|
||||
/* Make a new key value entry */
|
||||
he = (*ht->allocOps->allocEntry)(ht->allocPriv, key);
|
||||
if (!he)
|
||||
return 0;
|
||||
he->keyHash = keyHash;
|
||||
he->key = key;
|
||||
he->value = value;
|
||||
he->next = *hep;
|
||||
*hep = he;
|
||||
ht->nentries++;
|
||||
return he;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PLHashEntry *)
|
||||
PL_HashTableAdd(PLHashTable *ht, const void *key, void *value)
|
||||
{
|
||||
PLHashNumber keyHash;
|
||||
PLHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = PL_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) != 0) {
|
||||
/* Hit; see if values match */
|
||||
if ((*ht->valueCompare)(he->value, value)) {
|
||||
/* key,value pair is already present in table */
|
||||
return he;
|
||||
}
|
||||
if (he->value)
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE);
|
||||
he->value = value;
|
||||
return he;
|
||||
}
|
||||
return PL_HashTableRawAdd(ht, hep, keyHash, key, value);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he)
|
||||
{
|
||||
PRUint32 i, n;
|
||||
PLHashEntry *next, **oldbuckets;
|
||||
PRUint32 nb;
|
||||
|
||||
*hep = he->next;
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY);
|
||||
|
||||
/* Shrink table if it's underloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (--ht->nentries < UNDERLOADED(n)) {
|
||||
#ifdef HASHMETER
|
||||
ht->nshrinks++;
|
||||
#endif
|
||||
ht->shift++;
|
||||
oldbuckets = ht->buckets;
|
||||
nb = n * sizeof(PLHashEntry*) / 2;
|
||||
ht->buckets = (PLHashEntry**)(
|
||||
(*ht->allocOps->allocTable)(ht->allocPriv, nb));
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = PL_HashTableRawLookup(ht, he->keyHash, he->key);
|
||||
PR_ASSERT(*hep == 0);
|
||||
he->next = 0;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
}
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRBool)
|
||||
PL_HashTableRemove(PLHashTable *ht, const void *key)
|
||||
{
|
||||
PLHashNumber keyHash;
|
||||
PLHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = PL_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) == 0)
|
||||
return PR_FALSE;
|
||||
|
||||
/* Hit; remove element */
|
||||
PL_HashTableRawRemove(ht, hep, he);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void *)
|
||||
PL_HashTableLookup(PLHashTable *ht, const void *key)
|
||||
{
|
||||
PLHashNumber keyHash;
|
||||
PLHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = PL_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) != 0) {
|
||||
return he->value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Iterate over the entries in the hash table calling func for each
|
||||
** entry found. Stop if "f" says to (return value & PR_ENUMERATE_STOP).
|
||||
** Return a count of the number of elements scanned.
|
||||
*/
|
||||
PR_IMPLEMENT(int)
|
||||
PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg)
|
||||
{
|
||||
PLHashEntry *he, **hep;
|
||||
PRUint32 i, nbuckets;
|
||||
int rv, n = 0;
|
||||
PLHashEntry *todo = 0;
|
||||
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
hep = &ht->buckets[i];
|
||||
while ((he = *hep) != 0) {
|
||||
rv = (*f)(he, n, arg);
|
||||
n++;
|
||||
if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) {
|
||||
*hep = he->next;
|
||||
if (rv & HT_ENUMERATE_REMOVE) {
|
||||
he->next = todo;
|
||||
todo = he;
|
||||
}
|
||||
} else {
|
||||
hep = &he->next;
|
||||
}
|
||||
if (rv & HT_ENUMERATE_STOP) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
hep = &todo;
|
||||
while ((he = *hep) != 0) {
|
||||
PL_HashTableRawRemove(ht, hep, he);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
#ifdef HASHMETER
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_HashTableDumpMeter(PLHashTable *ht, PLHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
double mean, variance;
|
||||
PRUint32 nchains, nbuckets;
|
||||
PRUint32 i, n, maxChain, maxChainLen;
|
||||
PLHashEntry *he;
|
||||
|
||||
variance = 0;
|
||||
nchains = 0;
|
||||
maxChainLen = 0;
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
he = ht->buckets[i];
|
||||
if (!he)
|
||||
continue;
|
||||
nchains++;
|
||||
for (n = 0; he; he = he->next)
|
||||
n++;
|
||||
variance += n * n;
|
||||
if (n > maxChainLen) {
|
||||
maxChainLen = n;
|
||||
maxChain = i;
|
||||
}
|
||||
}
|
||||
mean = (double)ht->nentries / nchains;
|
||||
variance = fabs(variance / nchains - mean * mean);
|
||||
|
||||
fprintf(fp, "\nHash table statistics:\n");
|
||||
fprintf(fp, " number of lookups: %u\n", ht->nlookups);
|
||||
fprintf(fp, " number of entries: %u\n", ht->nentries);
|
||||
fprintf(fp, " number of grows: %u\n", ht->ngrows);
|
||||
fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
|
||||
fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
|
||||
/ ht->nlookups);
|
||||
fprintf(fp, "mean hash chain length: %g\n", mean);
|
||||
fprintf(fp, " standard deviation: %g\n", sqrt(variance));
|
||||
fprintf(fp, " max hash chain length: %u\n", maxChainLen);
|
||||
fprintf(fp, " max hash chain: [%u]\n", maxChain);
|
||||
|
||||
for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
|
||||
if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT)
|
||||
break;
|
||||
}
|
||||
#endif /* HASHMETER */
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = PL_HashTableEnumerateEntries(ht, dump, fp);
|
||||
#ifdef HASHMETER
|
||||
PL_HashTableDumpMeter(ht, dump, fp);
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PLHashNumber)
|
||||
PL_HashString(const void *key)
|
||||
{
|
||||
PLHashNumber h;
|
||||
const PRUint8 *s;
|
||||
|
||||
h = 0;
|
||||
for (s = (const PRUint8*)key; *s; s++)
|
||||
h = (h >> 28) ^ (h << 4) ^ *s;
|
||||
return h;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
PL_CompareStrings(const void *v1, const void *v2)
|
||||
{
|
||||
return strcmp((const char*)v1, (const char*)v2) == 0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
PL_CompareValues(const void *v1, const void *v2)
|
||||
{
|
||||
return v1 == v2;
|
||||
}
|
||||
131
mozilla/nsprpub/lib/ds/plhash.h
Normal file
131
mozilla/nsprpub/lib/ds/plhash.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 plhash_h___
|
||||
#define plhash_h___
|
||||
/*
|
||||
* API to portable hash table code.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct PLHashEntry PLHashEntry;
|
||||
typedef struct PLHashTable PLHashTable;
|
||||
typedef PRUint32 PLHashNumber;
|
||||
#define PL_HASH_BITS 32
|
||||
typedef PLHashNumber (PR_CALLBACK *PLHashFunction)(const void *key);
|
||||
typedef PRIntn (PR_CALLBACK *PLHashComparator)(const void *v1, const void *v2);
|
||||
typedef PRIntn (PR_CALLBACK *PLHashEnumerator)(PLHashEntry *he, PRIntn i, void *arg);
|
||||
|
||||
/* Flag bits in PLHashEnumerator's return value */
|
||||
#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
|
||||
#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
|
||||
#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
|
||||
#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */
|
||||
|
||||
typedef struct PLHashAllocOps {
|
||||
void * (PR_CALLBACK *allocTable)(void *pool, PRSize size);
|
||||
void (PR_CALLBACK *freeTable)(void *pool, void *item);
|
||||
PLHashEntry * (PR_CALLBACK *allocEntry)(void *pool, const void *key);
|
||||
void (PR_CALLBACK *freeEntry)(void *pool, PLHashEntry *he, PRUintn flag);
|
||||
} PLHashAllocOps;
|
||||
|
||||
#define HT_FREE_VALUE 0 /* just free the entry's value */
|
||||
#define HT_FREE_ENTRY 1 /* free value and entire entry */
|
||||
|
||||
struct PLHashEntry {
|
||||
PLHashEntry *next; /* hash chain linkage */
|
||||
PLHashNumber keyHash; /* key hash function result */
|
||||
const void *key; /* ptr to opaque key */
|
||||
void *value; /* ptr to opaque value */
|
||||
};
|
||||
|
||||
struct PLHashTable {
|
||||
PLHashEntry **buckets; /* vector of hash buckets */
|
||||
PRUint32 nentries; /* number of entries in table */
|
||||
PRUint32 shift; /* multiplicative hash shift */
|
||||
PLHashFunction keyHash; /* key hash function */
|
||||
PLHashComparator keyCompare; /* key comparison function */
|
||||
PLHashComparator valueCompare; /* value comparison function */
|
||||
PLHashAllocOps *allocOps; /* allocation operations */
|
||||
void *allocPriv; /* allocation private data */
|
||||
#ifdef HASHMETER
|
||||
PRUint32 nlookups; /* total number of lookups */
|
||||
PRUint32 nsteps; /* number of hash chains traversed */
|
||||
PRUint32 ngrows; /* number of table expansions */
|
||||
PRUint32 nshrinks; /* number of table contractions */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new hash table.
|
||||
* If allocOps is null, use default allocator ops built on top of malloc().
|
||||
*/
|
||||
PR_EXTERN(PLHashTable *)
|
||||
PL_NewHashTable(PRUint32 n, PLHashFunction keyHash,
|
||||
PLHashComparator keyCompare, PLHashComparator valueCompare,
|
||||
PLHashAllocOps *allocOps, void *allocPriv);
|
||||
|
||||
PR_EXTERN(void)
|
||||
PL_HashTableDestroy(PLHashTable *ht);
|
||||
|
||||
/* Low level access methods */
|
||||
PR_EXTERN(PLHashEntry **)
|
||||
PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key);
|
||||
|
||||
PR_EXTERN(PLHashEntry *)
|
||||
PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, PLHashNumber keyHash,
|
||||
const void *key, void *value);
|
||||
|
||||
PR_EXTERN(void)
|
||||
PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he);
|
||||
|
||||
/* Higher level access methods */
|
||||
PR_EXTERN(PLHashEntry *)
|
||||
PL_HashTableAdd(PLHashTable *ht, const void *key, void *value);
|
||||
|
||||
PR_EXTERN(PRBool)
|
||||
PL_HashTableRemove(PLHashTable *ht, const void *key);
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg);
|
||||
|
||||
PR_EXTERN(void *)
|
||||
PL_HashTableLookup(PLHashTable *ht, const void *key);
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp);
|
||||
|
||||
/* General-purpose C string hash function. */
|
||||
PR_EXTERN(PLHashNumber)
|
||||
PL_HashString(const void *key);
|
||||
|
||||
/* Compare strings using strcmp(), return true if equal. */
|
||||
PR_EXTERN(int)
|
||||
PL_CompareStrings(const void *v1, const void *v2);
|
||||
|
||||
/* Stub function just returns v1 == v2 */
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_CompareValues(const void *v1, const void *v2);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* plhash_h___ */
|
||||
32
mozilla/nsprpub/lib/libc/Makefile
Normal file
32
mozilla/nsprpub/lib/libc/Makefile
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../..
|
||||
|
||||
export NSPR20=1
|
||||
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
DIRS = include src
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
install:: export
|
||||
20
mozilla/nsprpub/lib/libc/README
Normal file
20
mozilla/nsprpub/lib/libc/README
Normal file
@@ -0,0 +1,20 @@
|
||||
NSPR 2.0 libc functions
|
||||
-----------------------
|
||||
|
||||
Last edited: AOF 04 March 1997
|
||||
|
||||
This directory contains various libc-types of functions. All functions in
|
||||
this directory are platform independent, thread friendly (both safe and
|
||||
efficient). They are contributed from various sources, though the contri-
|
||||
butions are monitored by the NSPR group (mailto:freier).
|
||||
|
||||
All API items exported by these functions will contain the same three
|
||||
character prefix, "PL_" (Portable Library). Internal function names
|
||||
that are not exported (static) are of little concern, though some caution
|
||||
must be used on those elements that are 'extern' but not really intended
|
||||
to be part of the API. Those should all have a prefix of "_PL_" (is that
|
||||
legal?).
|
||||
|
||||
The responsibility for contributions in this area are distributed among
|
||||
all interested parties.
|
||||
|
||||
37
mozilla/nsprpub/lib/libc/include/Makefile
Normal file
37
mozilla/nsprpub/lib/libc/include/Makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../../..
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
RELEASE_HEADERS = $(HEADERS)
|
||||
RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
export:: $(HEADERS)
|
||||
$(INSTALL) -m 444 $(HEADERS) $(DIST)/include
|
||||
ifeq ($(MOZ_BITS),16)
|
||||
$(INSTALL) -m 444 $(HEADERS) $(MOZ_INCL)
|
||||
endif
|
||||
|
||||
install:: export
|
||||
|
||||
7
mozilla/nsprpub/lib/libc/include/README
Normal file
7
mozilla/nsprpub/lib/libc/include/README
Normal file
@@ -0,0 +1,7 @@
|
||||
NSPR 2.0 libc functions
|
||||
-----------------------
|
||||
|
||||
Last edited: AOF 04 March 1997
|
||||
|
||||
This directory contains the API for various libc-types of functions.
|
||||
|
||||
79
mozilla/nsprpub/lib/libc/include/plbase64.h
Normal file
79
mozilla/nsprpub/lib/libc/include/plbase64.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 _plbase64_h
|
||||
#define _plbase64_h
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* PL_Base64Encode
|
||||
*
|
||||
* This routine encodes the data pointed to by the "src" parameter using the
|
||||
* base64 algorithm, and returns a pointer to the result. If the "srclen"
|
||||
* parameter is not zero, it specifies the length of the source data. If it
|
||||
* is zero, the source data is assumed to be null-terminated, and PL_strlen
|
||||
* is used to determine the source length. If the "dest" parameter is not
|
||||
* null, it is assumed to point to a buffer of sufficient size (which may be
|
||||
* calculated: ((srclen + 2)/3)*4) into which the encoded data is placed
|
||||
* (without any termination). If the "dest" parameter is null, a buffer is
|
||||
* allocated from the heap to hold the encoded data, and the result *will*
|
||||
* be terminated with an extra null character. It is the caller's
|
||||
* responsibility to free the result when it is allocated. A null is returned
|
||||
* if the allocation fails.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_Base64Encode
|
||||
(
|
||||
const char *src,
|
||||
PRUint32 srclen,
|
||||
char *dest
|
||||
);
|
||||
|
||||
/*
|
||||
* PL_Base64Decode
|
||||
*
|
||||
* This routine decodes the data pointed to by the "src" parameter using
|
||||
* the base64 algorithm, and returns a pointer to the result. The source
|
||||
* may either include or exclude any trailing '=' characters. If the
|
||||
* "srclen" parameter is not zero, it specifies the length of the source
|
||||
* data. If it is zero, PL_strlen will be used to determine the source
|
||||
* length. If the "dest" parameter is not null, it is assumed to point to
|
||||
* a buffer of sufficient size (which may be calculated: (srclen * 3)/4
|
||||
* when srclen includes the '=' characters) into which the decoded data
|
||||
* is placed (without any termination). If the "dest" parameter is null,
|
||||
* a buffer is allocated from the heap to hold the decoded data, and the
|
||||
* result *will* be terminated with an extra null character. It is the
|
||||
* caller's responsibility to free the result when it is allocated. A null
|
||||
* is retuned if the allocation fails, or if the source is not well-coded.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_Base64Decode
|
||||
(
|
||||
const char *src,
|
||||
PRUint32 srclen,
|
||||
char *dest
|
||||
);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* _plbase64_h */
|
||||
47
mozilla/nsprpub/lib/libc/include/plerror.h
Normal file
47
mozilla/nsprpub/lib/libc/include/plerror.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** File: plerror.h
|
||||
** Description: Simple routine to print translate the calling thread's
|
||||
** error numbers and print them.
|
||||
*/
|
||||
|
||||
#if defined(PLERROR_H)
|
||||
#else
|
||||
#define PLERROR_H
|
||||
|
||||
#include "prio.h"
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
/*
|
||||
** Print the messages to "syserr" prepending 'msg' if not NULL.
|
||||
*/
|
||||
PR_EXTERN(void) PL_PrintError(const char *msg);
|
||||
|
||||
/*
|
||||
** Print the messages to specified output file prepending 'msg' if not NULL.
|
||||
*/
|
||||
PR_EXTERN(void) PL_FPrintError(PRFileDesc *output, const char *msg);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* defined(PLERROR_H) */
|
||||
|
||||
/* plerror.h */
|
||||
62
mozilla/nsprpub/lib/libc/include/plgetopt.h
Normal file
62
mozilla/nsprpub/lib/libc/include/plgetopt.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** File: plgetopt.h
|
||||
** Description: utilities to parse argc/argv
|
||||
*/
|
||||
|
||||
#if defined(PLGETOPT_H_)
|
||||
#else
|
||||
#define PLGETOPT_H_
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct PLOptionInternal PLOptionInternal;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PL_OPT_OK, /* all's well with the option */
|
||||
PL_OPT_EOL, /* end of options list */
|
||||
PL_OPT_BAD /* invalid option (and value) */
|
||||
} PLOptStatus;
|
||||
|
||||
typedef struct PLOptState
|
||||
{
|
||||
char option; /* the name of the option */
|
||||
const char *value; /* the value of that option | NULL */
|
||||
|
||||
PLOptionInternal *internal; /* private processing state */
|
||||
|
||||
} PLOptState;
|
||||
|
||||
PR_EXTERN(PLOptState*) PL_CreateOptState(
|
||||
PRIntn argc, char **argv, const char *options);
|
||||
|
||||
PR_EXTERN(void) PL_DestroyOptState(PLOptState *opt);
|
||||
|
||||
PR_EXTERN(PLOptStatus) PL_GetNextOpt(PLOptState *opt);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* defined(PLGETOPT_H_) */
|
||||
|
||||
/* plgetopt.h */
|
||||
|
||||
89
mozilla/nsprpub/lib/libc/include/plresolv.h
Normal file
89
mozilla/nsprpub/lib/libc/include/plresolv.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* plresolv.h - asynchronous name resolution using DNS
|
||||
*/
|
||||
|
||||
#ifndef _PLRESOLV_H_
|
||||
#define _PLRESOLV_H_
|
||||
|
||||
/*
|
||||
** THIS IS WORK IN PROGRESS. DO NOT ATTEMPT TO USE ANY PORTION OF THIS
|
||||
** API UNTIL THIS MESSAGE NO LONGER EXISTS. IF YOU DO, THEN YOU SURRENDER
|
||||
** THE RIGHT TO COMPLAIN ABOUT ANY CONTENT.
|
||||
*/
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
|
||||
#include <prtypes.h>
|
||||
#include <prnetdb.h>
|
||||
|
||||
NSPR_BEGIN_EXTERN_C
|
||||
|
||||
#define PL_RESOLVE_MAXHOSTENTBUF 1024
|
||||
#define PL_RESOLVE_DEFAULT_TIMEOUT 0
|
||||
|
||||
/* Error return codes */
|
||||
#define PL_RESOLVE_OK 0
|
||||
#define PL_RESOLVE_EWINIT 1 /* Failed to initialize window */
|
||||
#define PL_RESOLVE_EMAKE 2 /* Failed to create request */
|
||||
#define PL_RESOLVE_ELAUNCH 3 /* Error launching Async request */
|
||||
#define PL_RESOLVE_ETIMEDOUT 4 /* Request timed-out */
|
||||
#define PL_RESOLVE_EINVAL 5 /* Invalid argument */
|
||||
#define PL_RESOLVE_EOVERFLOW 6 /* Buffer Overflow */
|
||||
#define PL_RESOLVE_EUNKNOWN 7 /* berzerk error */
|
||||
|
||||
/* ----------- Function Prototypes ----------------*/
|
||||
|
||||
PR_EXTERN(PRStatus) PL_ResolveName(
|
||||
const char *name, unsigned char *buf,
|
||||
PRIntn bufsize, PRIntervalTime timeout,
|
||||
PRHostEnt *hostentry, PRIntervalTime *ttl);
|
||||
|
||||
PR_EXTERN(PRStatus) PL_ResolveAddr(
|
||||
const PRNetAddr *address, unsigned char *buf,
|
||||
PRIntn bufsize, PRIntervalTime timeout,
|
||||
PRHostEnt *hostentry, PRIntervalTime *ttl);
|
||||
|
||||
typedef struct PLResolveStats {
|
||||
int re_errors;
|
||||
int re_nu_look;
|
||||
int re_na_look;
|
||||
int re_replies;
|
||||
int re_requests;
|
||||
int re_resends;
|
||||
int re_sent;
|
||||
int re_timeouts;
|
||||
} PLResolveStats;
|
||||
|
||||
typedef struct PLResoveInfo {
|
||||
PRBool enabled;
|
||||
PRUint32 numNameLookups;
|
||||
PRUint32 numAddrLookups;
|
||||
PRUint32 numLookupsInProgress;
|
||||
PLResolveStats stats;
|
||||
} PLResoveInfo;
|
||||
|
||||
PR_EXTERN(void) PL_ResolveInfo(PLResoveInfo *info);
|
||||
|
||||
NSPR_END_EXTERN_C
|
||||
|
||||
#endif /* defined(XP_UNIX) */
|
||||
|
||||
#endif /* _PLRESOLV_H_ */
|
||||
428
mozilla/nsprpub/lib/libc/include/plstr.h
Normal file
428
mozilla/nsprpub/lib/libc/include/plstr.h
Normal file
@@ -0,0 +1,428 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 _plstr_h
|
||||
#define _plstr_h
|
||||
|
||||
/*
|
||||
* plstr.h
|
||||
*
|
||||
* This header file exports the API to the NSPR portable library or string-
|
||||
* handling functions.
|
||||
*
|
||||
* This API was not designed as an "optimal" or "ideal" string library; it
|
||||
* was based on the good ol' unix string.3 functions, and was written to
|
||||
*
|
||||
* 1) replace the libc functions, for cross-platform consistancy,
|
||||
* 2) complete the API on platforms lacking common functions (e.g.,
|
||||
* strcase*), and
|
||||
* 3) to implement some obvious "closure" functions that I've seen
|
||||
* people hacking around in our code.
|
||||
*
|
||||
* Point number three largely means that most functions have an "strn"
|
||||
* limited-length version, and all comparison routines have a non-case-
|
||||
* sensitive version available.
|
||||
*/
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
/*
|
||||
* PL_strlen
|
||||
*
|
||||
* Returns the length of the provided string, not including the trailing '\0'.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRUint32)
|
||||
PL_strlen(const char *str);
|
||||
|
||||
/*
|
||||
* PL_strnlen
|
||||
*
|
||||
* Returns the length of the provided string, not including the trailing '\0',
|
||||
* up to the indicated maximum. The string will not be examined beyond the
|
||||
* maximum; if no terminating '\0' is found, the maximum will be returned.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRUint32)
|
||||
PL_strnlen(const char *str, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strcpy
|
||||
*
|
||||
* Copies the source string, up to and including the trailing '\0', into the
|
||||
* destination buffer. It does not (can not) verify that the destination
|
||||
* buffer is large enough. It returns the "dest" argument.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strcpy(char *dest, const char *src);
|
||||
|
||||
/*
|
||||
* PL_strncpy
|
||||
*
|
||||
* Copies the source string into the destination buffer, up to and including
|
||||
* the trailing '\0' or up to and including the max'th character, whichever
|
||||
* comes first. It does not (can not) verify that the destination buffer is
|
||||
* large enough. If the source string is longer than the maximum length,
|
||||
* the result will *not* be null-terminated (JLRU).
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strncpy(char *dest, const char *src, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strncpyz
|
||||
*
|
||||
* Copies the source string into the destination buffer, up to and including
|
||||
* the trailing '\0' or up but not including the max'th character, whichever
|
||||
* comes first. It does not (can not) verify that the destination buffer is
|
||||
* large enough. The destination string is always terminated with a '\0',
|
||||
* unlike the traditional libc implementation. It returns the "dest" argument.
|
||||
*
|
||||
* NOTE: If you call this with a source "abcdefg" and a max of 5, the
|
||||
* destination will end up with "abcd\0" (i.e., it's strlen length will be 4)!
|
||||
*
|
||||
* This means you can do this:
|
||||
*
|
||||
* char buffer[ SOME_SIZE ];
|
||||
* PL_strncpyz(buffer, src, sizeof(buffer));
|
||||
*
|
||||
* and the result will be properly terminated.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strncpyz(char *dest, const char *src, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strdup
|
||||
*
|
||||
* Returns a pointer to a malloc'd extent of memory containing a duplicate
|
||||
* of the argument string. The size of the allocated extent is one greater
|
||||
* than the length of the argument string, because of the terminator. A
|
||||
* null argument, like a zero-length argument, will result in a pointer to
|
||||
* a one-byte extent containing the null value. This routine returns null
|
||||
* upon malloc failure.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strdup(const char *s);
|
||||
|
||||
/*
|
||||
* PL_strfree
|
||||
*
|
||||
* Free memory allocated by PL_strdup
|
||||
*/
|
||||
|
||||
PR_EXTERN(void)
|
||||
PL_strfree(char *s);
|
||||
|
||||
/*
|
||||
* PL_strndup
|
||||
*
|
||||
* Returns a pointer to a malloc'd extent of memory containing a duplicate
|
||||
* of the argument string, up to the maximum specified. If the argument
|
||||
* string has a length greater than the value of the specified maximum, the
|
||||
* return value will be a pointer to an extent of memory of length one
|
||||
* greater than the maximum specified. A null string, a zero-length string,
|
||||
* or a zero maximum will all result in a pointer to a one-byte extent
|
||||
* containing the null value. This routine returns null upon malloc failure.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strndup(const char *s, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strcat
|
||||
*
|
||||
* Appends a copy of the string pointed to by the second argument to the
|
||||
* end of the string pointed to by the first. The destination buffer is
|
||||
* not (can not be) checked for sufficient size. A null destination
|
||||
* argument returns null; otherwise, the first argument is returned.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strcat(char *dst, const char *src);
|
||||
|
||||
/*
|
||||
* PL_strncat
|
||||
*
|
||||
* Appends a copy of the string pointed to by the second argument, up to
|
||||
* the maximum size specified, to the end of the string pointed to by the
|
||||
* first. The destination buffer is not (can not be) checked for sufficient
|
||||
* size. A null destination argument returns null; otherwise, the first
|
||||
* argument is returned. If the maximum size limits the copy, then the
|
||||
* result will *not* be null-terminated (JLRU). A null destination
|
||||
* returns null; otherwise, the destination argument is returned.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strncat(char *dst, const char *src, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strcatn
|
||||
*
|
||||
* Appends a copy of the string pointed to by the third argument, to the
|
||||
* end of the string pointed to by the first. The second argument specifies
|
||||
* the maximum size of the destination buffer, including the null termination.
|
||||
* If the existing string in dst is longer than the max, no action is taken.
|
||||
* The resulting string will be null-terminated. A null destination returns
|
||||
* null; otherwise, the destination argument is returned.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strcatn(char *dst, PRUint32 max, const char *src);
|
||||
|
||||
/*
|
||||
* PL_strcmp
|
||||
*
|
||||
* Returns an integer, the sign of which -- positive, zero, or negative --
|
||||
* reflects the lexical sorting order of the two strings indicated. The
|
||||
* result is positive if the first string comes after the second. The
|
||||
* NSPR implementation is not i18n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_strcmp(const char *a, const char *b);
|
||||
|
||||
/*
|
||||
* PL_strncmp
|
||||
*
|
||||
* Returns an integer, the sign of which -- positive, zero, or negative --
|
||||
* reflects the lexical sorting order of the two strings indicated, up to
|
||||
* the maximum specified. The result is positive if the first string comes
|
||||
* after the second. The NSPR implementation is not i18n. If the maximum
|
||||
* is zero, only the existance or non-existance (pointer is null) of the
|
||||
* strings is compared.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_strncmp(const char *a, const char *b, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strcasecmp
|
||||
*
|
||||
* Returns an integer, the sign of which -- positive, zero or negative --
|
||||
* reflects the case-insensitive lexical sorting order of the two strings
|
||||
* indicated. The result is positive if the first string comes after the
|
||||
* second. The NSPR implementation is not i18n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_strcasecmp(const char *a, const char *b);
|
||||
|
||||
/*
|
||||
* PL_strncasecmp
|
||||
*
|
||||
* Returns an integer, the sign of which -- positive, zero or negative --
|
||||
* reflects the case-insensitive lexical sorting order of the first n characters
|
||||
* of the two strings indicated. The result is positive if the first string comes
|
||||
* after the second. The NSPR implementation is not i18n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
PL_strncasecmp(const char *a, const char *b, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strchr
|
||||
*
|
||||
* Returns a pointer to the first instance of the specified character in the
|
||||
* provided string. It returns null if the character is not found, or if the
|
||||
* provided string is null. The character may be the null character.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strchr(const char *s, char c);
|
||||
|
||||
/*
|
||||
* PL_strrchr
|
||||
*
|
||||
* Returns a pointer to the last instance of the specified character in the
|
||||
* provided string. It returns null if the character is not found, or if the
|
||||
* provided string is null. The character may be the null character.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strrchr(const char *s, char c);
|
||||
|
||||
/*
|
||||
* PL_strnchr
|
||||
*
|
||||
* Returns a pointer to the first instance of the specified character within the
|
||||
* first n characters of the provided string. It returns null if the character
|
||||
* is not found, or if the provided string is null. The character may be the
|
||||
* null character.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnchr(const char *s, char c, PRUint32 n);
|
||||
|
||||
/*
|
||||
* PL_strnrchr
|
||||
*
|
||||
* Returns a pointer to the last instance of the specified character within the
|
||||
* first n characters of the provided string. It returns null if the character is
|
||||
* not found, or if the provided string is null. The character may be the null
|
||||
* character.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnrchr(const char *s, char c, PRUint32 n);
|
||||
|
||||
/*
|
||||
* NOTE: Looking for strcasechr, strcaserchr, strncasechr, or strncaserchr?
|
||||
* Use strpbrk, strprbrk, strnpbrk or strnprbrk.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PL_strpbrk
|
||||
*
|
||||
* Returns a pointer to the first instance in the first string of any character
|
||||
* (not including the terminating null character) of the second string. It returns
|
||||
* null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strpbrk(const char *s, const char *list);
|
||||
|
||||
/*
|
||||
* PL_strprbrk
|
||||
*
|
||||
* Returns a pointer to the last instance in the first string of any character
|
||||
* (not including the terminating null character) of the second string. It returns
|
||||
* null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strprbrk(const char *s, const char *list);
|
||||
|
||||
/*
|
||||
* PL_strnpbrk
|
||||
*
|
||||
* Returns a pointer to the first instance (within the first n characters) of any
|
||||
* character (not including the terminating null character) of the second string.
|
||||
* It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnpbrk(const char *s, const char *list, PRUint32 n);
|
||||
|
||||
/*
|
||||
* PL_strnprbrk
|
||||
*
|
||||
* Returns a pointer to the last instance (within the first n characters) of any
|
||||
* character (not including the terminating null character) of the second string.
|
||||
* It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnprbrk(const char *s, const char *list, PRUint32 n);
|
||||
|
||||
/*
|
||||
* PL_strstr
|
||||
*
|
||||
* Returns a pointer to the first instance of the little string within the
|
||||
* big one. It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strstr(const char *big, const char *little);
|
||||
|
||||
/*
|
||||
* PL_strrstr
|
||||
*
|
||||
* Returns a pointer to the last instance of the little string within the big one.
|
||||
* It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strrstr(const char *big, const char *little);
|
||||
|
||||
/*
|
||||
* PL_strnstr
|
||||
*
|
||||
* Returns a pointer to the first instance of the little string within the first
|
||||
* n characters of the big one. It returns null if either string is null. It
|
||||
* returns null if the length of the little string is greater than n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnstr(const char *big, const char *little, PRUint32 n);
|
||||
|
||||
/*
|
||||
* PL_strnrstr
|
||||
*
|
||||
* Returns a pointer to the last instance of the little string within the first
|
||||
* n characters of the big one. It returns null if either string is null. It
|
||||
* returns null if the length of the little string is greater than n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strnrstr(const char *big, const char *little, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strcasestr
|
||||
*
|
||||
* Returns a pointer to the first instance of the little string within the big one,
|
||||
* ignoring case. It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strcasestr(const char *big, const char *little);
|
||||
|
||||
/*
|
||||
* PL_strcaserstr
|
||||
*
|
||||
* Returns a pointer to the last instance of the little string within the big one,
|
||||
* ignoring case. It returns null if either string is null.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strcaserstr(const char *big, const char *little);
|
||||
|
||||
/*
|
||||
* PL_strncasestr
|
||||
*
|
||||
* Returns a pointer to the first instance of the listtle string within the first
|
||||
* n characters of the big one, ignoring case. It returns null if either string is
|
||||
* null. It returns null if the length of the little string is greater than n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strncasestr(const char *big, const char *little, PRUint32 max);
|
||||
|
||||
/*
|
||||
* PL_strncaserstr
|
||||
*
|
||||
* Returns a pointer to the last instance of the little string within the first
|
||||
* n characters of the big one, ignoring case. It returns null if either string is
|
||||
* null. It returns null if the length of the little string is greater than n.
|
||||
*/
|
||||
|
||||
PR_EXTERN(char *)
|
||||
PL_strncaserstr(const char *big, const char *little, PRUint32 max);
|
||||
|
||||
/*
|
||||
* Things not (yet?) included: strspn/strcspn, strtok/strtok_r, strsep.
|
||||
* memchr, memcmp, memcpy, memccpy, index, rindex, bcmp, bcopy, bzero.
|
||||
* Any and all i18n/l10n stuff.
|
||||
*/
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* _plstr_h */
|
||||
105
mozilla/nsprpub/lib/libc/src/Makefile
Normal file
105
mozilla/nsprpub/lib/libc/src/Makefile
Normal file
@@ -0,0 +1,105 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../../..
|
||||
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
# Disable optimization of the nspr on SunOS4.1.3
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
ifeq ($(OS_RELEASE),4.1.3_U1)
|
||||
OPTIMIZER =
|
||||
endif
|
||||
endif
|
||||
|
||||
INCLUDES = -I$(DIST)/include
|
||||
|
||||
CSRCS =\
|
||||
strlen.c \
|
||||
strcpy.c \
|
||||
strdup.c \
|
||||
strcat.c \
|
||||
strcmp.c \
|
||||
strccmp.c \
|
||||
strchr.c \
|
||||
strpbrk.c \
|
||||
strstr.c \
|
||||
strcstr.c \
|
||||
base64.c \
|
||||
plerror.c \
|
||||
plgetopt.c \
|
||||
$(NULL)
|
||||
|
||||
LIBRARY_NAME = plc
|
||||
LIBRARY_VERSION = $(MOD_VERSION)
|
||||
|
||||
RELEASE_LIBS = $(TARGETS)
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifeq (,$(filter-out WIN16 OS2,$(OS_TARGET)))
|
||||
EXTRA_LIBS = $(DIST)/lib/nspr$(MOD_VERSION).lib
|
||||
else
|
||||
DLLBASE=/BASE:0x30000000
|
||||
RES=$(OBJDIR)/plc.res
|
||||
RESNAME=$(MOD_DEPTH)/pr/src/nspr.rc
|
||||
EXTRA_LIBS = $(DIST)/lib/libnspr$(MOD_VERSION).lib
|
||||
endif
|
||||
else
|
||||
ifeq ($(OS_ARCH), AIX)
|
||||
ifeq ($(CLASSIC_NSPR),1)
|
||||
OS_LIBS += -lc
|
||||
else
|
||||
OS_LIBS += -lc_r
|
||||
endif
|
||||
endif
|
||||
ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
|
||||
EXTRA_LIBS = -L$(DIST)/lib -lnspr$(MOD_VERSION)_shr
|
||||
else
|
||||
EXTRA_LIBS = -L$(DIST)/lib -lnspr$(MOD_VERSION)
|
||||
endif
|
||||
endif
|
||||
|
||||
# On NCR and SCO_SV, we can't link with extra libraries when
|
||||
# we build a shared library. If we do so, the linker doesn't
|
||||
# complain, but we would run into weird problems at run-time.
|
||||
# Therefore on these platforms, we link just the .o files.
|
||||
ifeq ($(OS_ARCH),NCR)
|
||||
EXTRA_LIBS =
|
||||
endif
|
||||
ifeq ($(OS_ARCH),SCO_SV)
|
||||
EXTRA_LIBS =
|
||||
endif
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
#
|
||||
# The Client build wants the shared libraries in $(DIST)/bin,
|
||||
# so we also install them there.
|
||||
#
|
||||
|
||||
export:: $(TARGETS)
|
||||
$(INSTALL) -m 444 $(TARGETS) $(DIST)/lib
|
||||
$(INSTALL) -m 444 $(SHARED_LIBRARY) $(DIST)/bin
|
||||
ifeq ($(MOZ_BITS),16)
|
||||
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
|
||||
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
|
||||
endif
|
||||
|
||||
install:: export
|
||||
|
||||
20
mozilla/nsprpub/lib/libc/src/README
Normal file
20
mozilla/nsprpub/lib/libc/src/README
Normal file
@@ -0,0 +1,20 @@
|
||||
NSPR 2.0 libc functions
|
||||
-----------------------
|
||||
|
||||
Last edited: AOF 04 March 1997
|
||||
|
||||
This directory contains various libc-types of functions. All functions in
|
||||
this directory are platform independent, thread friendly (both safe and
|
||||
efficient). They are contributed from various sources, though the contri-
|
||||
butions are monitored by the NSPR group (mailto:freier).
|
||||
|
||||
All API items exported by these functions will contain the same three
|
||||
character prefix, "PL_" (Portable Library). Internal function names
|
||||
that are not exported (static) are of little concern, though some caution
|
||||
must be used on those elements that are 'extern' but not really intended
|
||||
to be part of the API. Those should all have a prefix of "_PL_" (is that
|
||||
legal?).
|
||||
|
||||
The responsibility for contributions in this area are distributed among
|
||||
all interested parties.
|
||||
|
||||
403
mozilla/nsprpub/lib/libc/src/base64.c
Normal file
403
mozilla/nsprpub/lib/libc/src/base64.c
Normal file
@@ -0,0 +1,403 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plbase64.h"
|
||||
#include "prlog.h" /* For PR_NOT_REACHED */
|
||||
#include "prmem.h" /* for malloc / PR_MALLOC */
|
||||
#include "plstr.h" /* for PL_strlen */
|
||||
|
||||
static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static void
|
||||
encode3to4
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
PRUint32 b32 = (PRUint32)0;
|
||||
PRIntn i, j = 18;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
b32 <<= 8;
|
||||
b32 |= (PRUint32)src[i];
|
||||
}
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
dest[i] = base[ (PRUint32)((b32>>j) & 0x3F) ];
|
||||
j -= 6;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
encode2to4
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
|
||||
dest[1] = base[ (PRUint32)(((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)) ];
|
||||
dest[2] = base[ (PRUint32)((src[1] & 0x0F) << 2) ];
|
||||
dest[3] = (unsigned char)'=';
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
encode1to4
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
|
||||
dest[1] = base[ (PRUint32)((src[0] & 0x03) << 4) ];
|
||||
dest[2] = (unsigned char)'=';
|
||||
dest[3] = (unsigned char)'=';
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
encode
|
||||
(
|
||||
const unsigned char *src,
|
||||
PRUint32 srclen,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
while( srclen >= 3 )
|
||||
{
|
||||
encode3to4(src, dest);
|
||||
src += 3;
|
||||
dest += 4;
|
||||
srclen -= 3;
|
||||
}
|
||||
|
||||
switch( srclen )
|
||||
{
|
||||
case 2:
|
||||
encode2to4(src, dest);
|
||||
break;
|
||||
case 1:
|
||||
encode1to4(src, dest);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
PR_NOT_REACHED("coding error");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* PL_Base64Encode
|
||||
*
|
||||
* If the destination argument is NULL, a return buffer is
|
||||
* allocated, and the data therein will be null-terminated.
|
||||
* If the destination argument is not NULL, it is assumed to
|
||||
* be of sufficient size, and the contents will not be null-
|
||||
* terminated by this routine.
|
||||
*
|
||||
* Returns null if the allocation fails.
|
||||
*/
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_Base64Encode
|
||||
(
|
||||
const char *src,
|
||||
PRUint32 srclen,
|
||||
char *dest
|
||||
)
|
||||
{
|
||||
if( 0 == srclen )
|
||||
{
|
||||
srclen = PL_strlen(src);
|
||||
}
|
||||
|
||||
if( (char *)0 == dest )
|
||||
{
|
||||
PRUint32 destlen = ((srclen + 2)/3) * 4;
|
||||
dest = (char *)PR_MALLOC(destlen + 1);
|
||||
if( (char *)0 == dest )
|
||||
{
|
||||
return (char *)0;
|
||||
}
|
||||
dest[ destlen ] = (char)0; /* null terminate */
|
||||
}
|
||||
|
||||
encode((const unsigned char *)src, srclen, (unsigned char *)dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static PRInt32
|
||||
codetovalue
|
||||
(
|
||||
unsigned char c
|
||||
)
|
||||
{
|
||||
if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') )
|
||||
{
|
||||
return (PRInt32)(c - (unsigned char)'A');
|
||||
}
|
||||
else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') )
|
||||
{
|
||||
return ((PRInt32)(c - (unsigned char)'a') +26);
|
||||
}
|
||||
else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') )
|
||||
{
|
||||
return ((PRInt32)(c - (unsigned char)'0') +52);
|
||||
}
|
||||
else if( (unsigned char)'+' == c )
|
||||
{
|
||||
return (PRInt32)62;
|
||||
}
|
||||
else if( (unsigned char)'/' == c )
|
||||
{
|
||||
return (PRInt32)63;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
decode4to3
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
PRUint32 b32 = (PRUint32)0;
|
||||
PRInt32 bits;
|
||||
PRIntn i;
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
bits = codetovalue(src[i]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
b32 <<= 6;
|
||||
b32 |= bits;
|
||||
}
|
||||
|
||||
dest[0] = (unsigned char)((b32 >> 16) & 0xFF);
|
||||
dest[1] = (unsigned char)((b32 >> 8) & 0xFF);
|
||||
dest[2] = (unsigned char)((b32 ) & 0xFF);
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
decode3to2
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
PRUint32 b32 = (PRUint32)0;
|
||||
PRInt32 bits;
|
||||
PRUint32 ubits;
|
||||
|
||||
bits = codetovalue(src[0]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
b32 = (PRUint32)bits;
|
||||
b32 <<= 6;
|
||||
|
||||
bits = codetovalue(src[1]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
b32 |= (PRUint32)bits;
|
||||
b32 <<= 4;
|
||||
|
||||
bits = codetovalue(src[2]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
ubits = (PRUint32)bits;
|
||||
b32 |= (ubits >> 2);
|
||||
|
||||
dest[0] = (unsigned char)((b32 >> 8) & 0xFF);
|
||||
dest[1] = (unsigned char)((b32 ) & 0xFF);
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
decode2to1
|
||||
(
|
||||
const unsigned char *src,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
PRUint32 b32;
|
||||
PRUint32 ubits;
|
||||
PRInt32 bits;
|
||||
|
||||
bits = codetovalue(src[0]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
ubits = (PRUint32)bits;
|
||||
b32 = (ubits << 2);
|
||||
|
||||
bits = codetovalue(src[1]);
|
||||
if( bits < 0 )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
ubits = (PRUint32)bits;
|
||||
b32 |= (ubits >> 4);
|
||||
|
||||
dest[0] = (unsigned char)b32;
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
decode
|
||||
(
|
||||
const unsigned char *src,
|
||||
PRUint32 srclen,
|
||||
unsigned char *dest
|
||||
)
|
||||
{
|
||||
PRStatus rv;
|
||||
|
||||
while( srclen >= 4 )
|
||||
{
|
||||
rv = decode4to3(src, dest);
|
||||
if( PR_SUCCESS != rv )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
src += 4;
|
||||
dest += 3;
|
||||
srclen -= 4;
|
||||
}
|
||||
|
||||
switch( srclen )
|
||||
{
|
||||
case 3:
|
||||
rv = decode3to2(src, dest);
|
||||
break;
|
||||
case 2:
|
||||
rv = decode2to1(src, dest);
|
||||
break;
|
||||
case 1:
|
||||
rv = PR_FAILURE;
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
PR_NOT_REACHED("coding error");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* PL_Base64Decode
|
||||
*
|
||||
* If the destination argument is NULL, a return buffer is
|
||||
* allocated and the data therein will be null-terminated.
|
||||
* If the destination argument is not null, it is assumed
|
||||
* to be of sufficient size, and the data will not be null-
|
||||
* terminated by this routine.
|
||||
*
|
||||
* Returns null if the allocation fails, or if the source string is
|
||||
* not well-formed.
|
||||
*/
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_Base64Decode
|
||||
(
|
||||
const char *src,
|
||||
PRUint32 srclen,
|
||||
char *dest
|
||||
)
|
||||
{
|
||||
PRStatus status;
|
||||
PRBool allocated = PR_FALSE;
|
||||
|
||||
if( 0 == srclen )
|
||||
{
|
||||
srclen = PL_strlen(src);
|
||||
}
|
||||
|
||||
if( 0 == (srclen & 3) )
|
||||
{
|
||||
if( (char)'=' == src[ srclen-1 ] )
|
||||
{
|
||||
if( (char)'=' == src[ srclen-2 ] )
|
||||
{
|
||||
srclen -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
srclen -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (char *)0 == dest )
|
||||
{
|
||||
PRUint32 destlen = ((srclen * 3) / 4);
|
||||
dest = (char *)PR_MALLOC(destlen + 1);
|
||||
if( (char *)0 == dest )
|
||||
{
|
||||
return (char *)0;
|
||||
}
|
||||
dest[ destlen ] = (char)0; /* null terminate */
|
||||
allocated = PR_TRUE;
|
||||
}
|
||||
|
||||
status = decode((const unsigned char *)src, srclen, (unsigned char *)dest);
|
||||
if( PR_SUCCESS != status )
|
||||
{
|
||||
if( PR_TRUE == allocated )
|
||||
{
|
||||
PR_DELETE(dest);
|
||||
}
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
144
mozilla/nsprpub/lib/libc/src/plerror.c
Normal file
144
mozilla/nsprpub/lib/libc/src/plerror.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** File:plerror.c
|
||||
** Description: Simple routine to print translate the calling thread's
|
||||
** error numbers and print them to "syserr".
|
||||
*/
|
||||
|
||||
#include "plerror.h"
|
||||
|
||||
#include "prprf.h"
|
||||
#include "prerror.h"
|
||||
|
||||
PR_IMPLEMENT(void) PL_FPrintError(PRFileDesc *fd, const char *msg)
|
||||
{
|
||||
static const char *tags[] =
|
||||
{
|
||||
"PR_OUT_OF_MEMORY_ERROR",
|
||||
"PR_BAD_DESCRIPTOR_ERROR",
|
||||
"PR_WOULD_BLOCK_ERROR",
|
||||
"PR_ACCESS_FAULT_ERROR",
|
||||
"PR_INVALID_METHOD_ERROR",
|
||||
"PR_ILLEGAL_ACCESS_ERROR",
|
||||
"PR_UNKNOWN_ERROR",
|
||||
"PR_PENDING_INTERRUPT_ERROR",
|
||||
"PR_NOT_IMPLEMENTED_ERROR",
|
||||
"PR_IO_ERROR",
|
||||
"PR_IO_TIMEOUT_ERROR",
|
||||
"PR_IO_PENDING_ERROR",
|
||||
"PR_DIRECTORY_OPEN_ERROR",
|
||||
"PR_INVALID_ARGUMENT_ERROR",
|
||||
"PR_ADDRESS_NOT_AVAILABLE_ERROR",
|
||||
"PR_ADDRESS_NOT_SUPPORTED_ERROR",
|
||||
"PR_IS_CONNECTED_ERROR",
|
||||
"PR_BAD_ADDRESS_ERROR",
|
||||
"PR_ADDRESS_IN_USE_ERROR",
|
||||
"PR_CONNECT_REFUSED_ERROR",
|
||||
"PR_NETWORK_UNREACHABLE_ERROR",
|
||||
"PR_CONNECT_TIMEOUT_ERROR",
|
||||
"PR_NOT_CONNECTED_ERROR",
|
||||
"PR_LOAD_LIBRARY_ERROR",
|
||||
"PR_UNLOAD_LIBRARY_ERROR",
|
||||
"PR_FIND_SYMBOL_ERROR",
|
||||
"PR_INSUFFICIENT_RESOURCES_ERROR",
|
||||
"PR_DIRECTORY_LOOKUP_ERROR",
|
||||
"PR_TPD_RANGE_ERROR",
|
||||
"PR_PROC_DESC_TABLE_FULL_ERROR",
|
||||
"PR_SYS_DESC_TABLE_FULL_ERROR",
|
||||
"PR_NOT_SOCKET_ERROR",
|
||||
"PR_NOT_TCP_SOCKET_ERROR",
|
||||
"PR_SOCKET_ADDRESS_IS_BOUND_ERROR",
|
||||
"PR_NO_ACCESS_RIGHTS_ERROR",
|
||||
"PR_OPERATION_NOT_SUPPORTED_ERROR",
|
||||
"PR_PROTOCOL_NOT_SUPPORTED_ERROR",
|
||||
"PR_REMOTE_FILE_ERROR",
|
||||
"PR_BUFFER_OVERFLOW_ERROR",
|
||||
"PR_CONNECT_RESET_ERROR",
|
||||
"PR_RANGE_ERROR",
|
||||
"PR_DEADLOCK_ERROR",
|
||||
"PR_FILE_IS_LOCKED_ERROR",
|
||||
"PR_FILE_TOO_BIG_ERROR",
|
||||
"PR_NO_DEVICE_SPACE_ERROR",
|
||||
"PR_PIPE_ERROR",
|
||||
"PR_NO_SEEK_DEVICE_ERROR",
|
||||
"PR_IS_DIRECTORY_ERROR",
|
||||
"PR_LOOP_ERROR",
|
||||
"PR_NAME_TOO_LONG_ERROR",
|
||||
"PR_FILE_NOT_FOUND_ERROR",
|
||||
"PR_NOT_DIRECTORY_ERROR",
|
||||
"PR_READ_ONLY_FILESYSTEM_ERROR",
|
||||
"PR_DIRECTORY_NOT_EMPTY_ERROR",
|
||||
"PR_FILESYSTEM_MOUNTED_ERROR",
|
||||
"PR_NOT_SAME_DEVICE_ERROR",
|
||||
"PR_DIRECTORY_CORRUPTED_ERROR",
|
||||
"PR_FILE_EXISTS_ERROR",
|
||||
"PR_MAX_DIRECTORY_ENTRIES_ERROR",
|
||||
"PR_INVALID_DEVICE_STATE_ERROR",
|
||||
"PR_DEVICE_IS_LOCKED_ERROR",
|
||||
"PR_NO_MORE_FILES_ERROR",
|
||||
"PR_END_OF_FILE_ERROR",
|
||||
"PR_FILE_SEEK_ERROR",
|
||||
"PR_FILE_IS_BUSY_ERROR",
|
||||
"PR_IN_PROGRESS_ERROR",
|
||||
"PR_ALREADY_INITIATED_ERROR",
|
||||
"PR_GROUP_EMPTY_ERROR",
|
||||
"PR_INVALID_STATE_ERROR",
|
||||
"PR_MAX_ERROR"
|
||||
};
|
||||
|
||||
PRErrorCode error = PR_GetError();
|
||||
PRInt32 oserror = PR_GetOSError();
|
||||
PRIntn thoseIKnowAbout = sizeof(tags) / sizeof(char*);
|
||||
PRIntn lastError = PR_NSPR_ERROR_BASE + thoseIKnowAbout;
|
||||
|
||||
if (NULL != msg) PR_fprintf(fd, "%s: ", msg);
|
||||
if ((error < PR_NSPR_ERROR_BASE) || (error > lastError))
|
||||
PR_fprintf(
|
||||
fd, " (%d)OUT OF RANGE, oserror = %d\n", error, oserror);
|
||||
else
|
||||
PR_fprintf(
|
||||
fd, "%s(%d), oserror = %d\n",
|
||||
tags[error - PR_NSPR_ERROR_BASE], error, oserror);
|
||||
} /* PL_FPrintError */
|
||||
|
||||
PR_IMPLEMENT(void) PL_PrintError(const char *msg)
|
||||
{
|
||||
static PRFileDesc *fd = NULL;
|
||||
if (NULL == fd) fd = PR_GetSpecialFD(PR_StandardError);
|
||||
PL_FPrintError(fd, msg);
|
||||
} /* PL_PrintError */
|
||||
|
||||
#if defined(WIN16)
|
||||
/*
|
||||
** libmain() is a required function for win16
|
||||
**
|
||||
*/
|
||||
int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
|
||||
WORD cbHeapSize, LPSTR lpszCmdLine )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* WIN16 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* plerror.c */
|
||||
165
mozilla/nsprpub/lib/libc/src/plgetopt.c
Normal file
165
mozilla/nsprpub/lib/libc/src/plgetopt.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** File: plgetopt.c
|
||||
** Description: utilities to parse argc/argv
|
||||
*/
|
||||
|
||||
#include "prmem.h"
|
||||
#include "prlog.h"
|
||||
#include "prerror.h"
|
||||
#include "plstr.h"
|
||||
#include "plgetopt.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static char static_Nul = 0;
|
||||
|
||||
struct PLOptionInternal
|
||||
{
|
||||
const char *options; /* client options list specification */
|
||||
PRIntn argc; /* original number of arguments */
|
||||
char **argv; /* vector of pointers to arguments */
|
||||
PRIntn xargc; /* which one we're processing now */
|
||||
const char *xargv; /* where within *argv[xargc] */
|
||||
PRBool minus; /* do we already have the '-'? */
|
||||
};
|
||||
|
||||
/*
|
||||
** Create the state in which to parse the tokens.
|
||||
**
|
||||
** argc the sum of the number of options and their values
|
||||
** argv the options and their values
|
||||
** options vector of single character options w/ | w/o ':
|
||||
*/
|
||||
PR_IMPLEMENT(PLOptState*) PL_CreateOptState(
|
||||
PRIntn argc, char **argv, const char *options)
|
||||
{
|
||||
PLOptState *opt = NULL;
|
||||
if (NULL == options)
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
||||
else
|
||||
{
|
||||
opt = PR_NEWZAP(PLOptState);
|
||||
if (NULL == opt)
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
else
|
||||
{
|
||||
PLOptionInternal *internal = PR_NEW(PLOptionInternal);
|
||||
if (NULL == internal)
|
||||
{
|
||||
PR_DELETE(opt);
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
opt->option = 0;
|
||||
opt->value = NULL;
|
||||
opt->internal = internal;
|
||||
|
||||
internal->argc = argc;
|
||||
internal->argv = argv;
|
||||
internal->xargc = 0;
|
||||
internal->xargv = &static_Nul;
|
||||
internal->minus = PR_FALSE;
|
||||
internal->options = options;
|
||||
}
|
||||
}
|
||||
}
|
||||
return opt;
|
||||
} /* PL_CreateOptState */
|
||||
|
||||
/*
|
||||
** Destroy object created by CreateOptState()
|
||||
*/
|
||||
PR_IMPLEMENT(void) PL_DestroyOptState(PLOptState *opt)
|
||||
{
|
||||
PR_DELETE(opt->internal);
|
||||
PR_DELETE(opt);
|
||||
} /* PL_DestroyOptState */
|
||||
|
||||
PR_IMPLEMENT(PLOptStatus) PL_GetNextOpt(PLOptState *opt)
|
||||
{
|
||||
PLOptionInternal *internal = opt->internal;
|
||||
PRIntn cop, eoo = PL_strlen(internal->options);
|
||||
|
||||
/*
|
||||
** If the current xarg points to nul, advance to the next
|
||||
** element of the argv vector. If the vector index is equal
|
||||
** to argc, we're out of arguments, so return an EOL.
|
||||
** Note whether the first character of the new argument is
|
||||
** a '-' and skip by it if it is.
|
||||
*/
|
||||
while (0 == *internal->xargv)
|
||||
{
|
||||
internal->xargc += 1;
|
||||
if (internal->xargc >= internal->argc)
|
||||
{
|
||||
opt->option = 0;
|
||||
opt->value = NULL;
|
||||
return PL_OPT_EOL;
|
||||
}
|
||||
internal->xargv = internal->argv[internal->xargc];
|
||||
internal->minus = ('-' == *internal->xargv ? PR_TRUE : PR_FALSE); /* not it */
|
||||
if (internal->minus) internal->xargv += 1; /* and consume */
|
||||
}
|
||||
|
||||
/*
|
||||
** If we already have a '-' in hand, xargv points to the next
|
||||
** option. See if we can find a match in the list of possible
|
||||
** options supplied.
|
||||
*/
|
||||
|
||||
if (internal->minus)
|
||||
{
|
||||
for (cop = 0; cop < eoo; ++cop)
|
||||
{
|
||||
if (internal->options[cop] == *internal->xargv)
|
||||
{
|
||||
opt->option = *internal->xargv;
|
||||
internal->xargv += 1;
|
||||
/*
|
||||
** if options indicates that there's an associated
|
||||
** value, this argv is finished and the next is the
|
||||
** option's value.
|
||||
*/
|
||||
if (':' == internal->options[cop + 1])
|
||||
{
|
||||
PR_ASSERT(0 == *internal->xargv);
|
||||
opt->value = internal->argv[++(internal->xargc)];
|
||||
internal->xargv = &static_Nul;
|
||||
internal->minus = PR_FALSE;
|
||||
}
|
||||
else opt->value = NULL;
|
||||
return PL_OPT_OK;
|
||||
}
|
||||
}
|
||||
internal->xargv += 1; /* consume that option */
|
||||
return PL_OPT_BAD;
|
||||
}
|
||||
/*
|
||||
** No '-', so it must be a standalone value. The option is nul.
|
||||
*/
|
||||
opt->value = internal->argv[(internal->xargc)++];
|
||||
internal->xargv = &static_Nul;
|
||||
opt->option = 0;
|
||||
return PL_OPT_OK;
|
||||
} /* PL_GetNextOpt */
|
||||
|
||||
/* plgetopt.c */
|
||||
70
mozilla/nsprpub/lib/libc/src/strcat.c
Normal file
70
mozilla/nsprpub/lib/libc/src/strcat.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plstr.h"
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strcat(char *dest, const char *src)
|
||||
{
|
||||
char *rv;
|
||||
|
||||
if( (char *)0 == dest ) return (char *)0;
|
||||
if( (const char *)0 == src ) return dest;
|
||||
|
||||
for( rv = dest; *dest; dest++ )
|
||||
;
|
||||
|
||||
for( ; ((*dest = *src) != 0); dest++, src++ )
|
||||
;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strncat(char *dest, const char *src, PRUint32 max)
|
||||
{
|
||||
char *rv;
|
||||
|
||||
if( (char *)0 == dest ) return (char *)0;
|
||||
if( (const char *)0 == src ) return dest;
|
||||
if( 0 == max ) return dest;
|
||||
|
||||
for( rv = dest; *dest; dest++ )
|
||||
;
|
||||
|
||||
(void)PL_strncpy(dest, src, max);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strcatn(char *dest, PRUint32 max, const char *src)
|
||||
{
|
||||
char *rv;
|
||||
PRUint32 dl;
|
||||
|
||||
if( (char *)0 == dest ) return (char *)0;
|
||||
if( (const char *)0 == src ) return dest;
|
||||
|
||||
for( rv = dest, dl = 0; *dest; dest++, dl++ )
|
||||
;
|
||||
|
||||
if( max <= dl ) return rv;
|
||||
(void)PL_strncpyz(dest, src, max-dl);
|
||||
|
||||
return rv;
|
||||
}
|
||||
80
mozilla/nsprpub/lib/libc/src/strccmp.c
Normal file
80
mozilla/nsprpub/lib/libc/src/strccmp.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plstr.h"
|
||||
|
||||
static const unsigned char uc[] =
|
||||
{
|
||||
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
|
||||
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
|
||||
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
|
||||
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
|
||||
' ', '!', '"', '#', '$', '%', '&', '\'',
|
||||
'(', ')', '*', '+', ',', '-', '.', '/',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', ':', ';', '<', '=', '>', '?',
|
||||
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
||||
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
|
||||
'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
||||
'X', 'Y', 'Z', '{', '|', '}', '~', '\177'
|
||||
};
|
||||
|
||||
PR_IMPLEMENT(PRIntn)
|
||||
PL_strcasecmp(const char *a, const char *b)
|
||||
{
|
||||
const unsigned char *ua = (const unsigned char *)a;
|
||||
const unsigned char *ub = (const unsigned char *)b;
|
||||
|
||||
if( ((const char *)0 == a) || (const char *)0 == b )
|
||||
return (PRIntn)(a-b);
|
||||
|
||||
while( (uc[*ua] == uc[*ub]) && ('\0' != *a) )
|
||||
{
|
||||
a++;
|
||||
ua++;
|
||||
ub++;
|
||||
}
|
||||
|
||||
return (PRIntn)(uc[*ua] - uc[*ub]);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRIntn)
|
||||
PL_strncasecmp(const char *a, const char *b, PRUint32 max)
|
||||
{
|
||||
const unsigned char *ua = (const unsigned char *)a;
|
||||
const unsigned char *ub = (const unsigned char *)b;
|
||||
|
||||
if( ((const char *)0 == a) || (const char *)0 == b )
|
||||
return (PRIntn)(a-b);
|
||||
|
||||
while( max && (uc[*ua] == uc[*ub]) && ('\0' != *a) )
|
||||
{
|
||||
a++;
|
||||
ua++;
|
||||
ub++;
|
||||
max--;
|
||||
}
|
||||
|
||||
if( 0 == max ) return (PRIntn)0;
|
||||
|
||||
return (PRIntn)(uc[*ua] - uc[*ub]);
|
||||
}
|
||||
83
mozilla/nsprpub/lib/libc/src/strchr.c
Normal file
83
mozilla/nsprpub/lib/libc/src/strchr.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plstr.h"
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strchr(const char *s, char c)
|
||||
{
|
||||
if( (const char *)0 == s ) return (char *)0;
|
||||
|
||||
for( ; *s; s++ )
|
||||
if( *s == c )
|
||||
return (char *)s;
|
||||
|
||||
if( (char)0 == c ) return (char *)s;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strrchr(const char *s, char c)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if( (const char *)0 == s ) return (char *)0;
|
||||
|
||||
for( p = s; *p; p++ )
|
||||
;
|
||||
|
||||
for( ; p >= s; p-- )
|
||||
if( *p == c )
|
||||
return (char *)p;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strnchr(const char *s, char c, PRUint32 n)
|
||||
{
|
||||
if( (const char *)0 == s ) return (char *)0;
|
||||
|
||||
for( ; *s && n; s++, n-- )
|
||||
if( *s == c )
|
||||
return (char *)s;
|
||||
|
||||
if( ((char)0 == c) && ((char)0 == *s) && (n > 0)) return (char *)s;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strnrchr(const char *s, char c, PRUint32 n)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if( (const char *)0 == s ) return (char *)0;
|
||||
|
||||
for( p = s; *p && n; p++, n-- )
|
||||
;
|
||||
|
||||
if( ((char)0 == c) && ((char)0 == *p) && (n > 0) ) return (char *)p;
|
||||
|
||||
for( p--; p >= s; p-- )
|
||||
if( *p == c )
|
||||
return (char *)p;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
52
mozilla/nsprpub/lib/libc/src/strcmp.c
Normal file
52
mozilla/nsprpub/lib/libc/src/strcmp.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plstr.h"
|
||||
|
||||
PR_IMPLEMENT(PRIntn)
|
||||
PL_strcmp(const char *a, const char *b)
|
||||
{
|
||||
if( ((const char *)0 == a) || (const char *)0 == b )
|
||||
return (PRIntn)(a-b);
|
||||
|
||||
while( (*a == *b) && ('\0' != *a) )
|
||||
{
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return (PRIntn)(*((const unsigned char *)a) - *((const unsigned char *)b));
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRIntn)
|
||||
PL_strncmp(const char *a, const char *b, PRUint32 max)
|
||||
{
|
||||
if( ((const char *)0 == a) || (const char *)0 == b )
|
||||
return (PRIntn)(a-b);
|
||||
|
||||
while( max && (*a == *b) && ('\0' != *a) )
|
||||
{
|
||||
a++;
|
||||
b++;
|
||||
max--;
|
||||
}
|
||||
|
||||
if( 0 == max ) return (PRIntn)0;
|
||||
|
||||
return (PRIntn)(*((const unsigned char *)a) - *((const unsigned char *)b));
|
||||
}
|
||||
69
mozilla/nsprpub/lib/libc/src/strcpy.c
Normal file
69
mozilla/nsprpub/lib/libc/src/strcpy.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plstr.h"
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strcpy(char *dest, const char *src)
|
||||
{
|
||||
char *rv;
|
||||
|
||||
if( (char *)0 == dest ) return (char *)0;
|
||||
if( (const char *)0 == src ) return (char *)0;
|
||||
|
||||
for( rv = dest; ((*dest = *src) != 0); dest++, src++ )
|
||||
;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strncpy(char *dest, const char *src, PRUint32 max)
|
||||
{
|
||||
char *rv;
|
||||
|
||||
if( (char *)0 == dest ) return (char *)0;
|
||||
if( (const char *)0 == src ) return (char *)0;
|
||||
|
||||
for( rv = dest; max && ((*dest = *src) != 0); dest++, src++, max-- )
|
||||
;
|
||||
|
||||
#ifdef JLRU
|
||||
while( --max )
|
||||
*++dest = '\0';
|
||||
#endif /* JLRU */
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strncpyz(char *dest, const char *src, PRUint32 max)
|
||||
{
|
||||
char *rv;
|
||||
|
||||
if( (char *)0 == dest ) return (char *)0;
|
||||
if( (const char *)0 == src ) return (char *)0;
|
||||
if( 0 == max ) return (char *)0;
|
||||
|
||||
for( rv = dest, max--; max && ((*dest = *src) != 0); dest++, src++, max-- )
|
||||
;
|
||||
|
||||
*dest = '\0';
|
||||
|
||||
return rv;
|
||||
}
|
||||
104
mozilla/nsprpub/lib/libc/src/strcstr.c
Normal file
104
mozilla/nsprpub/lib/libc/src/strcstr.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plstr.h"
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strcasestr(const char *big, const char *little)
|
||||
{
|
||||
PRUint32 ll;
|
||||
|
||||
if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
|
||||
if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
|
||||
|
||||
ll = PL_strlen(little);
|
||||
|
||||
for( ; *big; big++ )
|
||||
/* obvious improvement available here */
|
||||
if( 0 == PL_strncasecmp(big, little, ll) )
|
||||
return (char *)big;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strcaserstr(const char *big, const char *little)
|
||||
{
|
||||
const char *p;
|
||||
PRUint32 ll;
|
||||
|
||||
if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
|
||||
if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
|
||||
|
||||
ll = PL_strlen(little);
|
||||
p = &big[ PL_strlen(big) - ll ];
|
||||
if( p < big ) return (char *)0;
|
||||
|
||||
for( ; p >= big; p-- )
|
||||
/* obvious improvement available here */
|
||||
if( 0 == PL_strncasecmp(p, little, ll) )
|
||||
return (char *)p;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strncasestr(const char *big, const char *little, PRUint32 max)
|
||||
{
|
||||
PRUint32 ll;
|
||||
|
||||
if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
|
||||
if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
|
||||
|
||||
ll = PL_strlen(little);
|
||||
if( ll > max ) return (char *)0;
|
||||
max -= ll;
|
||||
max++;
|
||||
|
||||
for( ; *big && max; big++, max-- )
|
||||
/* obvious improvement available here */
|
||||
if( 0 == PL_strncasecmp(big, little, ll) )
|
||||
return (char *)big;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strncaserstr(const char *big, const char *little, PRUint32 max)
|
||||
{
|
||||
const char *p;
|
||||
PRUint32 ll;
|
||||
|
||||
if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
|
||||
if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
|
||||
|
||||
ll = PL_strlen(little);
|
||||
|
||||
for( p = big; *p && max; p++, max-- )
|
||||
;
|
||||
|
||||
p -= ll;
|
||||
if( p < big ) return (char *)0;
|
||||
|
||||
for( ; p >= big; p-- )
|
||||
/* obvious improvement available here */
|
||||
if( 0 == PL_strncasecmp(p, little, ll) )
|
||||
return (char *)p;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
64
mozilla/nsprpub/lib/libc/src/strdup.c
Normal file
64
mozilla/nsprpub/lib/libc/src/strdup.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plstr.h"
|
||||
#include "prmem.h"
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strdup(const char *s)
|
||||
{
|
||||
char *rv;
|
||||
PRUint32 l;
|
||||
|
||||
l = PL_strlen(s);
|
||||
|
||||
rv = (char *)malloc(l+1);
|
||||
if( (char *)0 == rv ) return rv;
|
||||
|
||||
if( (const char *)0 == s )
|
||||
*rv = '\0';
|
||||
else
|
||||
(void)PL_strcpy(rv, s);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_strfree(char *s)
|
||||
{
|
||||
free(s);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strndup(const char *s, PRUint32 max)
|
||||
{
|
||||
char *rv;
|
||||
PRUint32 l;
|
||||
|
||||
l = PL_strnlen(s, max);
|
||||
|
||||
rv = (char *)malloc(l+1);
|
||||
if( (char *)0 == rv ) return rv;
|
||||
|
||||
if( (const char *)0 == s )
|
||||
*rv = '\0';
|
||||
else
|
||||
(void)PL_strncpyz(rv, s, l+1);
|
||||
|
||||
return rv;
|
||||
}
|
||||
50
mozilla/nsprpub/lib/libc/src/strlen.c
Normal file
50
mozilla/nsprpub/lib/libc/src/strlen.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plstr.h"
|
||||
#include "prtypes.h"
|
||||
#include "prlog.h"
|
||||
|
||||
PR_IMPLEMENT(PRUint32)
|
||||
PL_strlen(const char *str)
|
||||
{
|
||||
register const char *s;
|
||||
|
||||
if( (const char *)0 == str ) return 0;
|
||||
for( s = str; *s; s++ )
|
||||
;
|
||||
/* error checking in case we have a 64-bit platform -- make sure we dont
|
||||
* have ultra long strings that overflow a int32
|
||||
*/
|
||||
if (sizeof(PRUint32) < sizeof(PRUptrdiff))
|
||||
PR_ASSERT((s-str) < 2147483647);
|
||||
|
||||
return (PRUint32)(s - str);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRUint32)
|
||||
PL_strnlen(const char *str, PRUint32 max)
|
||||
{
|
||||
register const char *s;
|
||||
|
||||
if( (const char *)0 == str ) return 0;
|
||||
for( s = str; *s && max; s++, max-- )
|
||||
;
|
||||
|
||||
return (PRUint32)(s - str);
|
||||
}
|
||||
87
mozilla/nsprpub/lib/libc/src/strpbrk.c
Normal file
87
mozilla/nsprpub/lib/libc/src/strpbrk.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plstr.h"
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strpbrk(const char *s, const char *list)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0;
|
||||
|
||||
for( ; *s; s++ )
|
||||
for( p = list; *p; p++ )
|
||||
if( *s == *p )
|
||||
return (char *)s;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strprbrk(const char *s, const char *list)
|
||||
{
|
||||
const char *p;
|
||||
const char *r;
|
||||
|
||||
if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0;
|
||||
|
||||
for( r = s; *r; r++ )
|
||||
;
|
||||
|
||||
for( r--; r >= s; r-- )
|
||||
for( p = list; *p; p++ )
|
||||
if( *r == *p )
|
||||
return (char *)r;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strnpbrk(const char *s, const char *list, PRUint32 max)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0;
|
||||
|
||||
for( ; *s && max; s++, max-- )
|
||||
for( p = list; *p; p++ )
|
||||
if( *s == *p )
|
||||
return (char *)s;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strnprbrk(const char *s, const char *list, PRUint32 max)
|
||||
{
|
||||
const char *p;
|
||||
const char *r;
|
||||
|
||||
if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0;
|
||||
|
||||
for( r = s; *r && max; r++, max-- )
|
||||
;
|
||||
|
||||
for( r--; r >= s; r-- )
|
||||
for( p = list; *p; p++ )
|
||||
if( *r == *p )
|
||||
return (char *)r;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
104
mozilla/nsprpub/lib/libc/src/strstr.c
Normal file
104
mozilla/nsprpub/lib/libc/src/strstr.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 "plstr.h"
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strstr(const char *big, const char *little)
|
||||
{
|
||||
PRUint32 ll;
|
||||
|
||||
if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
|
||||
if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
|
||||
|
||||
ll = PL_strlen(little);
|
||||
|
||||
for( ; *big; big++ )
|
||||
if( *little == *big )
|
||||
if( 0 == PL_strncmp(big, little, ll) )
|
||||
return (char *)big;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strrstr(const char *big, const char *little)
|
||||
{
|
||||
const char *p;
|
||||
PRUint32 ll;
|
||||
|
||||
if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
|
||||
if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
|
||||
|
||||
ll = PL_strlen(little);
|
||||
p = &big[ PL_strlen(big) - ll ];
|
||||
if( p < big ) return (char *)0;
|
||||
|
||||
for( ; p >= big; p-- )
|
||||
if( *little == *p )
|
||||
if( 0 == PL_strncmp(p, little, ll) )
|
||||
return (char *)p;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strnstr(const char *big, const char *little, PRUint32 max)
|
||||
{
|
||||
PRUint32 ll;
|
||||
|
||||
if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
|
||||
if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
|
||||
|
||||
ll = PL_strlen(little);
|
||||
if( ll > max ) return (char *)0;
|
||||
max -= ll;
|
||||
max++;
|
||||
|
||||
for( ; *big && max; big++, max-- )
|
||||
if( *little == *big )
|
||||
if( 0 == PL_strncmp(big, little, ll) )
|
||||
return (char *)big;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(char *)
|
||||
PL_strnrstr(const char *big, const char *little, PRUint32 max)
|
||||
{
|
||||
const char *p;
|
||||
PRUint32 ll;
|
||||
|
||||
if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
|
||||
if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
|
||||
|
||||
ll = PL_strlen(little);
|
||||
|
||||
for( p = big; *p && max; p++, max-- )
|
||||
;
|
||||
|
||||
p -= ll;
|
||||
if( p < big ) return (char *)0;
|
||||
|
||||
for( ; p >= big; p-- )
|
||||
if( *little == *p )
|
||||
if( 0 == PL_strncmp(p, little, ll) )
|
||||
return (char *)p;
|
||||
|
||||
return (char *)0;
|
||||
}
|
||||
28
mozilla/nsprpub/lib/msgc/Makefile
Normal file
28
mozilla/nsprpub/lib/msgc/Makefile
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
MOD_DEPTH = ../..
|
||||
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
DIRS = include src tests
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
install:: export
|
||||
37
mozilla/nsprpub/lib/msgc/include/Makefile
Normal file
37
mozilla/nsprpub/lib/msgc/include/Makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../../..
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
EXPORT_HEADERS = prgc.h
|
||||
HEADERS = $(EXPORT_HEADERS) gcint.h
|
||||
|
||||
RELEASE_HEADERS = $(EXPORT_HEADERS)
|
||||
RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
export:: $(EXPORT_HEADERS)
|
||||
$(INSTALL) -m 444 $(EXPORT_HEADERS) $(DIST)/include
|
||||
ifeq ($(MOZ_BITS),16)
|
||||
$(INSTALL) -m 444 $(EXPORT_HEADERS) $(MOZ_INCL)
|
||||
endif
|
||||
|
||||
install:: export
|
||||
110
mozilla/nsprpub/lib/msgc/include/gcint.h
Normal file
110
mozilla/nsprpub/lib/msgc/include/gcint.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 gcint_h___
|
||||
#define gcint_h___
|
||||
|
||||
#include "prmon.h"
|
||||
#include "prgc.h"
|
||||
|
||||
extern PRLogModuleInfo *_pr_msgc_lm;
|
||||
extern GCInfo _pr_gcData;
|
||||
|
||||
#if defined(_WIN32) && !defined(DEBUG)
|
||||
#undef INLINE_LOCK
|
||||
#endif
|
||||
|
||||
#ifdef INLINE_LOCK
|
||||
#define LOCK_GC() EnterCriticalSection(&_pr_gcData.lock->mutexHandle)
|
||||
#define UNLOCK_GC() LeaveCriticalSection(&_pr_gcData.lock->mutexHandle)
|
||||
#else
|
||||
#define LOCK_GC() PR_EnterMonitor(_pr_gcData.lock)
|
||||
#define UNLOCK_GC() PR_ExitMonitor (_pr_gcData.lock)
|
||||
#define GC_IS_LOCKED() (PR_GetMonitorEntryCount(_pr_gcData.lock)!=0)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define _GCTRACE(x, y) if (_pr_gcData.flags & x) GCTrace y
|
||||
#else
|
||||
#define _GCTRACE(x, y)
|
||||
#endif
|
||||
|
||||
extern GCBeginGCHook *_pr_beginGCHook;
|
||||
extern void *_pr_beginGCHookArg;
|
||||
extern GCBeginGCHook *_pr_endGCHook;
|
||||
extern void *_pr_endGCHookArg;
|
||||
|
||||
extern GCBeginFinalizeHook *_pr_beginFinalizeHook;
|
||||
extern void *_pr_beginFinalizeHookArg;
|
||||
extern GCBeginFinalizeHook *_pr_endFinalizeHook;
|
||||
extern void *_pr_endFinalizeHookArg;
|
||||
|
||||
extern int _pr_do_a_dump;
|
||||
extern FILE *_pr_dump_file;
|
||||
|
||||
extern PRLogModuleInfo *_pr_gc_lm;
|
||||
|
||||
/*
|
||||
** Root finders. Root finders are used by the GC to find pointers into
|
||||
** the GC heap that are not contained in the GC heap.
|
||||
*/
|
||||
typedef struct RootFinderStr RootFinder;
|
||||
|
||||
struct RootFinderStr {
|
||||
RootFinder *next;
|
||||
GCRootFinder *func;
|
||||
char *name;
|
||||
void *arg;
|
||||
};
|
||||
extern RootFinder *_pr_rootFinders;
|
||||
|
||||
typedef struct CollectorTypeStr {
|
||||
GCType gctype;
|
||||
uint32 flags;
|
||||
} CollectorType;
|
||||
|
||||
#define GC_MAX_TYPES 256
|
||||
extern CollectorType *_pr_collectorTypes;
|
||||
|
||||
#define _GC_TYPE_BUSY 0x1
|
||||
#define _GC_TYPE_FINAL 0x2
|
||||
#define _GC_TYPE_WEAK 0x4
|
||||
|
||||
/* Slot in _pr_gcTypes used for free memory */
|
||||
#define FREE_MEMORY_TYPEIX 255
|
||||
|
||||
extern void _PR_InitGC(PRWord flags);
|
||||
extern void _MD_InitGC(void);
|
||||
extern void PR_CALLBACK _PR_ScanFinalQueue(void *notused);
|
||||
|
||||
/*
|
||||
** Grow the GC Heap.
|
||||
*/
|
||||
extern void *_MD_GrowGCHeap(PRUint32 *sizep);
|
||||
|
||||
/*
|
||||
** Extend the GC Heap.
|
||||
*/
|
||||
extern PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize);
|
||||
|
||||
/*
|
||||
** Free a GC segment.
|
||||
*/
|
||||
extern void _MD_FreeGCSegment(void *base, PRInt32 len);
|
||||
|
||||
#endif /* gcint_h___ */
|
||||
400
mozilla/nsprpub/lib/msgc/include/prgc.h
Normal file
400
mozilla/nsprpub/lib/msgc/include/prgc.h
Normal file
@@ -0,0 +1,400 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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 prgc_h___
|
||||
#define prgc_h___
|
||||
|
||||
/*
|
||||
** API to NSPR gc memory system.
|
||||
*/
|
||||
#include "prtypes.h"
|
||||
#include "prmon.h"
|
||||
#include "prthread.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(WIN16)
|
||||
#define GCPTR __far
|
||||
#else
|
||||
#define GCPTR
|
||||
#endif
|
||||
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
** Initialize the garbage collector.
|
||||
** "flags" is the trace flags (see below).
|
||||
** "initialHeapSize" is the initial size of the heap and may be zero
|
||||
** if the default is desired.
|
||||
** "segmentSize" is the size of each segment of memory added to the
|
||||
** heap when the heap is grown.
|
||||
*/
|
||||
PR_EXTERN(void) PR_InitGC(
|
||||
PRWord flags, PRInt32 initialHeapSize, PRInt32 segmentSize, PRThreadScope scope);
|
||||
|
||||
/*
|
||||
** Shuts down gc and frees up all memory associated with it.
|
||||
*/
|
||||
PR_EXTERN(void) PR_ShutdownGC(PRBool finalizeOnExit);
|
||||
|
||||
/*
|
||||
** This walk function will be called for every gc object in the
|
||||
** heap as it is walked. If it returns non-zero, the walk is terminated.
|
||||
*/
|
||||
typedef PRInt32 (*PRWalkFun)(void GCPTR* obj, void* data);
|
||||
|
||||
/*
|
||||
** GC Type record. This defines all of the GC operations used on a
|
||||
** particular object type. These structures are passed to
|
||||
** PR_RegisterType.
|
||||
*/
|
||||
typedef struct GCType {
|
||||
/*
|
||||
** Scan an object that is in the GC heap and call PR_LiveObject on
|
||||
** all of the pointers in it. If this slot is null then the object
|
||||
** won't be scanned (i.e. it has no embedded pointers).
|
||||
*/
|
||||
void (PR_CALLBACK *scan)(void GCPTR *obj);
|
||||
|
||||
/*
|
||||
** Finalize an object that has no references. This is called by the
|
||||
** GC after it has determined where the object debris is but before
|
||||
** it has moved the debris to the logical "free list". The object is
|
||||
** marked alive for this call and removed from the list of objects
|
||||
** that need finalization (finalization only happens once for an
|
||||
** object). If this slot is null then the object doesn't need
|
||||
** finalization.
|
||||
*/
|
||||
void (PR_CALLBACK *finalize)(void GCPTR *obj);
|
||||
|
||||
/*
|
||||
** Dump out an object during a PR_DumpGCHeap(). This is used as a
|
||||
** debugging tool.
|
||||
*/
|
||||
void (PR_CALLBACK *dump)(FILE *out, void GCPTR *obj, PRBool detailed, PRIntn indentLevel);
|
||||
|
||||
/*
|
||||
** Add object to summary table.
|
||||
*/
|
||||
void (PR_CALLBACK *summarize)(void GCPTR *obj, PRUint32 bytes);
|
||||
|
||||
/*
|
||||
** Free hook called by GC when the object is being freed.
|
||||
*/
|
||||
void (PR_CALLBACK *free)(void *obj);
|
||||
|
||||
/* Weak pointer support: If the object has a weak pointer (Note:
|
||||
at most one), this function is used to get the weak link's
|
||||
offset from the start of the body of a gc object */
|
||||
PRUint32 (PR_CALLBACK *getWeakLinkOffset)(void *obj);
|
||||
|
||||
/* Descriptive character for dumping this GCType */
|
||||
char kindChar;
|
||||
|
||||
/*
|
||||
** Walker routine. This routine should apply fun(obj->ptr, data)
|
||||
** for every gc pointer within the object.
|
||||
*/
|
||||
PRInt32 (PR_CALLBACK *walk)(void GCPTR *obj, PRWalkFun fun, void* data);
|
||||
} GCType;
|
||||
|
||||
/*
|
||||
** This data structure must be added as the hash table passed to
|
||||
** the summarize method of GCType.
|
||||
*/
|
||||
typedef struct PRSummaryEntry {
|
||||
void* clazz;
|
||||
PRInt32 instancesCount;
|
||||
PRInt32 totalSize;
|
||||
} PRSummaryEntry;
|
||||
|
||||
/*
|
||||
** This function pointer must be registered by users of nspr
|
||||
** to produce the finally summary after all object in the
|
||||
** heap have been visited.
|
||||
*/
|
||||
typedef void (PR_CALLBACK *PRSummaryPrinter)(FILE *out, void* closure);
|
||||
|
||||
PR_EXTERN(void) PR_CALLBACK PR_RegisterSummaryPrinter(PRSummaryPrinter fun, void* closure);
|
||||
|
||||
typedef void PR_CALLBACK GCRootFinder(void *arg);
|
||||
typedef void PR_CALLBACK GCBeginFinalizeHook(void *arg);
|
||||
typedef void PR_CALLBACK GCEndFinalizeHook(void *arg);
|
||||
typedef void PR_CALLBACK GCBeginGCHook(void *arg);
|
||||
typedef void PR_CALLBACK GCEndGCHook(void *arg);
|
||||
|
||||
typedef enum { PR_GCBEGIN, PR_GCEND } GCLockHookArg;
|
||||
|
||||
typedef void PR_CALLBACK GCLockHookFunc(GCLockHookArg arg1, void *arg2);
|
||||
|
||||
typedef struct GCLockHook GCLockHook;
|
||||
|
||||
struct GCLockHook {
|
||||
GCLockHookFunc* func;
|
||||
void* arg;
|
||||
GCLockHook* next;
|
||||
GCLockHook* prev;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Hooks which are called at the beginning and end of the GC process.
|
||||
** The begin hooks are called before the root finding step. The hooks are
|
||||
** called with threading disabled, so it is now allowed to re-enter the
|
||||
** kernel. The end hooks are called after the gc has finished but before
|
||||
** the finalizer has run.
|
||||
*/
|
||||
PR_EXTERN(void) PR_CALLBACK PR_SetBeginGCHook(GCBeginGCHook *hook, void *arg);
|
||||
PR_EXTERN(void) PR_CALLBACK PR_GetBeginGCHook(GCBeginGCHook **hook, void **arg);
|
||||
PR_EXTERN(void) PR_CALLBACK PR_SetEndGCHook(GCBeginGCHook *hook, void *arg);
|
||||
PR_EXTERN(void) PR_CALLBACK PR_GetEndGCHook(GCEndGCHook **hook, void **arg);
|
||||
|
||||
/*
|
||||
** Called before SuspendAll is called by dogc, so that GC thread can hold
|
||||
** all the locks before hand to avoid any deadlocks
|
||||
*/
|
||||
|
||||
/*
|
||||
PR_EXTERN(void) PR_SetGCLockHook(GCLockHook *hook, void *arg);
|
||||
PR_EXTERN(void) PR_GetGCLockHook(GCLockHook **hook, void **arg);
|
||||
*/
|
||||
|
||||
PR_EXTERN(int) PR_RegisterGCLockHook(GCLockHookFunc *hook, void *arg);
|
||||
|
||||
/*
|
||||
** Hooks which are called at the beginning and end of the GC finalization
|
||||
** process. After the GC has identified all of the dead objects in the
|
||||
** heap, it looks for objects that need finalization. Before it calls the
|
||||
** first finalization proc (see the GCType structure above) it calls the
|
||||
** begin hook. When it has finalized the last object it calls the end
|
||||
** hook.
|
||||
*/
|
||||
PR_EXTERN(void) PR_SetBeginFinalizeHook(GCBeginFinalizeHook *hook, void *arg);
|
||||
PR_EXTERN(void) PR_GetBeginFinalizeHook(GCBeginFinalizeHook **hook, void **arg);
|
||||
PR_EXTERN(void) PR_SetEndFinalizeHook(GCBeginFinalizeHook *hook, void *arg);
|
||||
PR_EXTERN(void) PR_GetEndFinalizeHook(GCEndFinalizeHook **hook, void **arg);
|
||||
|
||||
/*
|
||||
** Register a GC type. Return's the index into the GC internal type
|
||||
** table. The returned value is passed to PR_AllocMemory. After the call,
|
||||
** the "type" memory belongs to the GC (the caller must not free it or
|
||||
** change it).
|
||||
*/
|
||||
PR_EXTERN(PRInt32) PR_RegisterType(GCType *type);
|
||||
|
||||
/*
|
||||
** Register a root finder with the collector. The collector will call
|
||||
** these functions to identify all of the roots before collection
|
||||
** proceeds. "arg" is passed to the function when it is called.
|
||||
*/
|
||||
PR_EXTERN(PRStatus) PR_RegisterRootFinder(GCRootFinder func, char *name, void *arg);
|
||||
|
||||
/*
|
||||
** Allocate some GC'able memory. The object must be at least bytes in
|
||||
** size. The type index function for the object is specified. "flags"
|
||||
** specifies some control flags. If PR_ALLOC_CLEAN is set then the memory
|
||||
** is zero'd before being returned. If PR_ALLOC_DOUBLE is set then the
|
||||
** allocated memory is double aligned.
|
||||
**
|
||||
** Any memory cell that you store a pointer to something allocated by
|
||||
** this call must be findable by the GC. Use the PR_RegisterRootFinder to
|
||||
** register new places where the GC will look for pointers into the heap.
|
||||
** The GC already knows how to scan any NSPR threads or monitors.
|
||||
*/
|
||||
PR_EXTERN(PRWord GCPTR *)PR_AllocMemory(
|
||||
PRWord bytes, PRInt32 typeIndex, PRWord flags);
|
||||
PR_EXTERN(PRWord GCPTR *)PR_AllocSimpleMemory(
|
||||
PRWord bytes, PRInt32 typeIndex);
|
||||
|
||||
/*
|
||||
** This function can be used to cause PR_AllocMemory to always return
|
||||
** NULL. This may be useful in low memory situations when we're trying to
|
||||
** shutdown applets.
|
||||
*/
|
||||
PR_EXTERN(void) PR_EnableAllocation(PRBool yesOrNo);
|
||||
|
||||
/* flags bits */
|
||||
#define PR_ALLOC_CLEAN 0x1
|
||||
#define PR_ALLOC_DOUBLE 0x2
|
||||
#define PR_ALLOC_ZERO_HANDLE 0x4 /* XXX yes, it's a hack */
|
||||
|
||||
/*
|
||||
** Force a garbage collection right now. Return when it completes.
|
||||
*/
|
||||
PR_EXTERN(void) PR_GC(void);
|
||||
|
||||
/*
|
||||
** Force a finalization right now. Return when finalization has
|
||||
** completed. Finalization completes when there are no more objects
|
||||
** pending finalization. This does not mean there are no objects in the
|
||||
** gc heap that will need finalization should a collection be done after
|
||||
** this call.
|
||||
*/
|
||||
PR_EXTERN(void) PR_ForceFinalize(void);
|
||||
|
||||
/*
|
||||
** Dump the GC heap out to the given file. This will stop the system dead
|
||||
** in its tracks while it is occuring.
|
||||
*/
|
||||
PR_EXTERN(void) PR_DumpGCHeap(FILE *out, PRBool detailed);
|
||||
|
||||
/*
|
||||
** Wrapper for PR_DumpGCHeap
|
||||
*/
|
||||
PR_EXTERN(void) PR_DumpMemory(PRBool detailed);
|
||||
|
||||
/*
|
||||
** Dump summary of objects allocated.
|
||||
*/
|
||||
PR_EXTERN(void) PR_DumpMemorySummary(void);
|
||||
|
||||
/*
|
||||
** Dump the application heaps.
|
||||
*/
|
||||
PR_EXTERN(void) PR_DumpApplicationHeaps(void);
|
||||
|
||||
/*
|
||||
** Helper function used by dump routines to do the indentation in a
|
||||
** consistent fashion.
|
||||
*/
|
||||
PR_EXTERN(void) PR_DumpIndent(FILE *out, PRIntn indent);
|
||||
|
||||
/*
|
||||
** The GCInfo structure contains all of the GC state...
|
||||
**
|
||||
** busyMemory:
|
||||
** The amount of GC heap memory that is busy at this instant. Busy
|
||||
** doesn't mean alive, it just means that it has been
|
||||
** allocated. Immediately after a collection busy means how much is
|
||||
** alive.
|
||||
**
|
||||
** freeMemory:
|
||||
** The amount of GC heap memory that is as yet unallocated.
|
||||
**
|
||||
** allocMemory:
|
||||
** The sum of free and busy memory in the GC heap.
|
||||
**
|
||||
** maxMemory:
|
||||
** The maximum size that the GC heap is allowed to grow.
|
||||
**
|
||||
** lowSeg:
|
||||
** The lowest segment currently used in the GC heap.
|
||||
**
|
||||
** highSeg:
|
||||
** The highest segment currently used in the GC heap.
|
||||
** The lowSeg and highSeg members are used for a "quick test" of whether
|
||||
** a pointer falls within the GC heap. [ see GC_IN_HEAP(...) ]
|
||||
**
|
||||
** lock:
|
||||
** Monitor used for syncronization within the GC.
|
||||
**
|
||||
** finalizer:
|
||||
** Thread in which the GC finalizer is running.
|
||||
**
|
||||
** liveBlock:
|
||||
** Object scanning functions call through this function pointer to
|
||||
** register a potential block of pointers with the collector. (This is
|
||||
** currently not at all different than processRoot.)
|
||||
**
|
||||
** livePointer:
|
||||
** Object scanning functions call through this function pointer to
|
||||
** register a single pointer with the collector.
|
||||
**
|
||||
** processRootBlock:
|
||||
** When a root finder identifies a root it should call through this
|
||||
** function pointer so that the GC can process the root. The call takes
|
||||
** a base address and count which the gc will examine for valid heap
|
||||
** pointers.
|
||||
**
|
||||
** processRootPointer:
|
||||
** When a root finder identifies a root it should call through this
|
||||
** function pointer so that the GC can process the root. The call takes
|
||||
** a single pointer value.
|
||||
*/
|
||||
typedef struct GCInfoStr {
|
||||
PRWord flags; /* trace flags (see below) */
|
||||
PRWord busyMemory; /* memory in use right now */
|
||||
PRWord freeMemory; /* memory free right now */
|
||||
PRWord allocMemory; /* sum of busy & free memory */
|
||||
PRWord maxMemory; /* max memory we are allowed to allocate */
|
||||
PRWord *lowSeg; /* lowest segment in the GC heap */
|
||||
PRWord *highSeg; /* higest segment in the GC heap */
|
||||
|
||||
PRMonitor *lock;
|
||||
PRThread *finalizer;
|
||||
|
||||
void (PR_CALLBACK *liveBlock)(void **base, PRInt32 count);
|
||||
void (PR_CALLBACK *livePointer)(void *ptr);
|
||||
void (PR_CALLBACK *processRootBlock)(void **base, PRInt32 count);
|
||||
void (PR_CALLBACK *processRootPointer)(void *ptr);
|
||||
FILE* dumpOutput;
|
||||
#ifdef GCTIMINGHOOK
|
||||
void (*gcTimingHook)(int32 gcTime);
|
||||
#endif
|
||||
} GCInfo;
|
||||
|
||||
PR_EXTERN(GCInfo *) PR_GetGCInfo(void);
|
||||
PR_EXTERN(PRBool) PR_GC_In_Heap(void GCPTR *object);
|
||||
|
||||
/*
|
||||
** Simple bounds check to see if a pointer is anywhere near the GC heap.
|
||||
** Used to avoid calls to PR_ProcessRoot and PR_LiveObject by object
|
||||
** scanning code.
|
||||
*/
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
#define GC_IN_HEAP(_info, _p) (((PRWord*)(_p) >= (_info)->lowSeg) && \
|
||||
((PRWord*)(_p) < (_info)->highSeg))
|
||||
#else
|
||||
/*
|
||||
** The simple bounds check, above, doesn't work in Win16, because we don't
|
||||
** maintain: lowSeg == MIN(all segments) and highSeg == MAX(all segments).
|
||||
** So we have to do a little better.
|
||||
*/
|
||||
#define GC_IN_HEAP(_info, _p) PR_GC_In_Heap(_p)
|
||||
#endif
|
||||
|
||||
PR_EXTERN(PRWord) PR_GetObjectHeader(void *ptr);
|
||||
|
||||
PR_EXTERN(PRWord) PR_SetObjectHeader(void *ptr, PRWord newUserBits);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* Trace flags (passed to PR_InitGC or in environment GCLOG) */
|
||||
#define GC_TRACE 0x0001
|
||||
#define GC_ROOTS 0x0002
|
||||
#define GC_LIVE 0x0004
|
||||
#define GC_ALLOC 0x0008
|
||||
#define GC_MARK 0x0010
|
||||
#define GC_SWEEP 0x0020
|
||||
#define GC_DEBUG 0x0040
|
||||
#define GC_FINAL 0x0080
|
||||
|
||||
#if defined(DEBUG_kipp) || defined(DEBUG_warren)
|
||||
#define GC_CHECK 0x0100
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define GCTRACE(x, y) if (PR_GetGCInfo()->flags & x) GCTrace y
|
||||
PR_EXTERN(void) GCTrace(char *fmt, ...);
|
||||
#else
|
||||
#define GCTRACE(x, y)
|
||||
#endif
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* prgc_h___ */
|
||||
107
mozilla/nsprpub/lib/msgc/src/Makefile
Normal file
107
mozilla/nsprpub/lib/msgc/src/Makefile
Normal file
@@ -0,0 +1,107 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../../..
|
||||
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
# Disable optimization of the nspr on SunOS4.1.3
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
ifeq ($(OS_RELEASE),4.1.3_U1)
|
||||
OPTIMIZER =
|
||||
endif
|
||||
endif
|
||||
|
||||
INCLUDES = -I$(DIST)/include -I../include
|
||||
|
||||
CSRCS = prgcapi.c prmsgc.c
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifeq ($(OS_TARGET),WIN16)
|
||||
CSRCS += win16gc.c
|
||||
else
|
||||
ifeq ($(OS_TARGET),OS2)
|
||||
CSRCS += os2gc.c
|
||||
else
|
||||
CSRCS += win32gc.c
|
||||
endif
|
||||
endif
|
||||
else
|
||||
CSRCS += unixgc.c
|
||||
endif
|
||||
|
||||
NSPR_VERSION = $(MOD_VERSION)
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
ifeq (,$(filter-out WIN16 OS2,$(OS_TARGET)))
|
||||
EXTRA_LIBS = $(DIST)/lib/nspr$(NSPR_VERSION).lib
|
||||
else
|
||||
DLLBASE=/BASE:0x30000000
|
||||
#RES=$(OBJDIR)/ds.res
|
||||
#RESNAME=$(MOD_DEPTH)/pr/src/nspr.rc
|
||||
#OS_LIBS = user32.lib
|
||||
EXTRA_LIBS = $(DIST)/lib/libnspr$(NSPR_VERSION).lib
|
||||
endif
|
||||
else
|
||||
ifeq ($(OS_ARCH), AIX)
|
||||
ifeq ($(CLASSIC_NSPR),1)
|
||||
OS_LIBS += -lc
|
||||
else
|
||||
OS_LIBS += -lc_r
|
||||
endif
|
||||
endif
|
||||
ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
|
||||
EXTRA_LIBS = -L$(DIST)/lib -lnspr$(NSPR_VERSION)_shr
|
||||
else
|
||||
EXTRA_LIBS = -L$(DIST)/lib -lnspr$(NSPR_VERSION)
|
||||
endif
|
||||
endif
|
||||
|
||||
# On NCR and SCO_SV, we can't link with extra libraries when
|
||||
# we build a shared library. If we do so, the linker doesn't
|
||||
# complain, but we would run into weird problems at run-time.
|
||||
# Therefore on these platforms, we link just the .o files.
|
||||
ifeq ($(OS_ARCH),NCR)
|
||||
EXTRA_LIBS =
|
||||
endif
|
||||
ifeq ($(OS_ARCH),SCO_SV)
|
||||
EXTRA_LIBS =
|
||||
endif
|
||||
|
||||
LIBRARY_NAME = msgc
|
||||
LIBRARY_VERSION = $(MOD_VERSION)
|
||||
|
||||
RELEASE_LIBS = $(TARGETS)
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
#
|
||||
# The Client build wants the shared libraries in $(DIST)/bin,
|
||||
# so we also install them there.
|
||||
#
|
||||
|
||||
export:: $(TARGETS)
|
||||
$(INSTALL) -m 444 $(TARGETS) $(DIST)/lib
|
||||
$(INSTALL) -m 444 $(SHARED_LIBRARY) $(DIST)/bin
|
||||
ifeq ($(MOZ_BITS),16)
|
||||
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
|
||||
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
|
||||
endif
|
||||
|
||||
install:: export
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user