Compare commits

..

2 Commits

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


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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,32 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src res
include $(topsrcdir)/config/rules.mk

View File

@@ -1,27 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..
include <$(DEPTH)/config/config.mak>
DIRS = public src res
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,4 +0,0 @@
nsIPSMComponent.idl
nsIPSMUIHandler.idl
nsISecureBrowserUI.idl
nsISSLSocketProvider.idl

View File

@@ -1,45 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Hubbie Shaw
# Doug Turner <dougt@netscape.com>
# Terry Hayes <thayes@netscape.com>
#
MODULE = psmglue
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
XPIDLSRCS = \
nsIPSMComponent.idl \
nsIPSMUIHandler.idl \
nsISecureBrowserUI.idl \
nsIPSMSocketInfo.idl \
nsISSLSocketProvider.idl \
nsISecretDecoderRing.idl \
$(NULL)
PREF_JS_EXPORTS = $(srcdir)/psm-glue.js
include $(topsrcdir)/config/rules.mk

View File

@@ -1,53 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Hubbie Shaw
# Doug Turner <dougt@netscape.com>
# Terry Hayes <thayes@netscape.com>
#
MODULE = psmglue
DEPTH=..\..\..
IGNORE_MANIFEST=1
DLLNAME = psmglue
PDBFILE = $(DLLNAME).pdb
MAPFILE = $(DLLNAME).map
DLL = .\$(OBJDIR)\$(DLLNAME).dll
MAKE_OBJ_TYPE = DLL
include <$(DEPTH)/config/config.mak>
XPIDL_INCLUDES=-I$(DEPTH)\..\mozilla\dist\idl
XPIDLSRCS= \
.\nsIPSMComponent.idl \
.\nsIPSMUIHandler.idl \
.\nsISecureBrowserUI.idl \
.\nsISSLSocketProvider.idl \
.\nsIPSMSocketInfo.idl \
.\nsISecretDecoderRing.idl \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install::
$(MAKE_INSTALL) .\psm-glue.js $(DIST)\bin\defaults\pref

View File

@@ -1,87 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
* Mitch Stoltz <mstoltz@netscape.com>
*/
#include "nsISupports.idl"
interface nsIPrincipal;
%{C++
#include "cmtcmn.h"
%}
[ptr] native nsCMTControlStar(CMT_CONTROL);
[scriptable, uuid(9e482670-5412-11d3-bbc8-0000861d1237)]
interface nsIPSMComponent : nsISupports
{
[noscript] nsCMTControlStar getControlConnection( );
/**
* Display the Security Advisor. PickledStatus and hostName can be null.
* If they are, the "Selected Info" dialog will be empty.
*/
void displaySecurityAdvisor(in string pickledStatus, in string hostName);
/**
* This will send PSM all preferences that we know about.
*/
void passPrefs();
/* Sig Verification Error Codes */
const long VERIFY_OK = 0;
const long VERIFY_NOSIG = -2;
const long VERIFY_ERROR_UNKNOWN_CA = -8172;
/* Hash Algorithms (based on cmtcmn.h) */
const short MD2 = 1;
const short MD5 = 2;
const short SHA1 = 3;
const unsigned long MD2_LENGTH = 16;
const unsigned long MD5_LENGTH = 16;
const unsigned long SHA1_LENGTH = 20;
const unsigned long MAX_HASH_LENGTH = SHA1_LENGTH;
/* Secure Hashing functions */
void hashBegin(in unsigned long alg, out unsigned long id);
void hashUpdate(in unsigned long id, in string buf, in unsigned long buflen);
void hashEnd(in unsigned long id, out string hash, out unsigned long hashlen,
in unsigned long maxLen);
/* Signature Verification functions */
void verifyRSABegin(out unsigned long id);
void verifyRSAUpdate(in unsigned long id, in string buf,
in unsigned long buflen);
void verifyRSAEnd(in unsigned long id, in string plaintext,
in unsigned long plaintextLen,
in boolean keepCert, out nsIPrincipal principal, out long result);
nsIPrincipal CreatePrincipalFromCert(in unsigned long certID);
};
%{C++
#define PSM_COMPONENT_PROGID "component://netscape/psm"
#define PSM_COMPONENT_CLASSNAME "Mozilla PSM Component"
%}

View File

@@ -1,45 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Doug Turner <dougt@netscape.com>
*/
#include "nsISupports.idl"
%{C++
#include "cmtcmn.h"
#include "nsPSMShimLayer.h"
%}
[ptr] native psmtControlStar(CMT_CONTROL);
[ptr] native cmSocketStar(CMSocket);
[ptr] native nsFileDescStar(PRFileDesc);
[noscript, uuid(deeb8dfc-fb7a-11d3-ac84-00c04fa0d26b)]
interface nsIPSMSocketInfo : nsISupports {
readonly attribute string hostName;
readonly attribute psmtControlStar controlPtr;
readonly attribute cmSocketStar socketPtr;
readonly attribute nsFileDescStar fileDescPtr;
void getPickledStatus(out charStar pickledStatus);
};

View File

@@ -1,36 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Mozilla browser.
*
* The Initial Developer of the Original Code is Netscape
* Communications, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nsISupports.idl"
[scriptable, uuid(d92be9b0-601b-11d3-8c4a-000064657374)]
interface nsIPSMUIHandler : nsISupports
{
void DisplayURI(in long width, in long height, in string urlStr);
void PromptForFile(in wstring prompt, in string fileRegEx, in boolean shouldFileExist, out string outFile);
};
%{C++
#define PSM_UI_HANLDER_PROGID "component://netscape/psm/ui"
#define PSM_UI_HANLDER_CLASSNAME "Mozilla PSM UI Handler"
%}

View File

@@ -1,35 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nsISocketProvider.idl"
[noscript, uuid(856a93d0-5415-11d3-bbc8-0000861d1237)]
interface nsISSLSocketProvider : nsISocketProvider {
};
%{C++
#define NS_ISSLSOCKETPROVIDER_PROGID NS_NETWORK_SOCKET_PROGID_PREFIX "ssl"
#define NS_ISSLSOCKETPROVIDER_CLASSNAME "Mozilla SSL Socket Provider Component"
%}

View File

@@ -1,63 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* thayes@netscape.com
*
*/
#include "nsISupports.idl"
/* Buffer type - for storing 8-bit octet values */
[ptr] native buffer(unsigned char);
[scriptable, uuid(0EC80360-075C-11d4-9FD4-00C04F1B83D8)]
interface nsISecretDecoderRing: nsISupports {
/* Encrypt a buffer - callable only from C++ */
[noscript] long encrypt(in buffer data, in long dataLen, out buffer result);
/* Decrypt a buffer - callable only from C++ */
[noscript] long decrypt(in buffer data, in long dataLen, out buffer result);
/* Encrypt nul-terminated string to BASE64 output */
string encryptString(in string text);
/* Decrypt BASE64 input to nul-terminated string output */
/* There is no check for embedded nul values in the decrypted output */
string decryptString(in string crypt);
/* Prompt the user to change the password on the SDR key */
void changePassword();
/* Logout of the security device that protects the SDR key */
void logout();
};
/*
* Configuration interface for the Secret Decoder Ring
* - this interface allows setting the window that will be
* used as parent for dialog windows (such as password prompts)
*/
[scriptable, uuid(01D8C0F0-0CCC-11d4-9FDD-000064657374)]
interface nsISecretDecoderRingConfig: nsISupports {
void setWindow(in nsISupports w);
};

View File

@@ -1,44 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nsISupports.idl"
interface nsIDOMWindow;
interface nsIDOMElement;
[scriptable, uuid(081e31e0-a144-11d3-8c7c-00609792278c)]
interface nsSecureBrowserUI : nsISupports
{
void init(in nsIDOMWindow window, in nsIDOMElement button);
void displayPageInfoUI();
};
%{C++
#define NS_SECURE_BROWSER_UI_PROGID "component://netscape/secure_browser_ui"
#define NS_SECURE_BROWSER_UI_CLASSNAME "Mozilla Secure Browser UI Handler"
#define NS_SECURE_BROWSER_UI_CID \
{ 0x10fe7ea0, 0xa10a, 0x11d3, {0x8c, 0x7c, 0x00, 0x60, 0x97, 0x92, 0x27, 0x8c}}
%}

View File

@@ -1,11 +0,0 @@
pref("general.useragent.security", "U");
pref("security.enable_ssl2", true);
pref("security.enable_ssl3", true);
pref("security.default_personal_cert", "Select Automatically");
pref("security.ask_for_password", 0);
pref("security.password_lifetime", 30);
pref("security.warn_entering_secure", true);
pref("security.warn_leaving_secure", true);
pref("security.warn_viewing_mixed", true);
pref("security.warn_submit_insecure", true);

View File

@@ -1,32 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = content skin locale
include $(topsrcdir)/config/rules.mk

View File

@@ -1 +0,0 @@
PSMTaskMenu.xul

View File

@@ -1,2 +0,0 @@
NavSecurityOverlay.xul
NavSecurityUI.js

View File

@@ -1,43 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
NAVIGATOR_CONTENT_DIR = $(DIST)/bin/chrome/navigator/content/
NAVIGATOR_EXPORT_CONTENT = \
$(srcdir)/NavSecurityOverlay.xul \
$(srcdir)/NavSecurityUI.js \
$(NULL)
GLOBAL_CONTENT_DIR = $(DIST)/bin/chrome/global/content/
GLOBAL_EXPORT_CONTENT = \
$(srcdir)/PSMTaskMenu.xul \
$(NULL)
install::
$(INSTALL) $(NAVIGATOR_EXPORT_CONTENT) $(NAVIGATOR_CONTENT_DIR)
$(INSTALL) $(GLOBAL_EXPORT_CONTENT) $(GLOBAL_CONTENT_DIR)

View File

@@ -1,14 +0,0 @@
<?xml version="1.0"?>
<overlay id="NavSecurityOverlay"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<?xml-stylesheet href="chrome://navigator/skin/NavSecurityOverlay.css" type="text/css"?>
<html:script language="JavaScript" src="chrome://navigator/content/NavSecurityUI.js" />
<box id="state-box">
<titledbutton id="security-button" class="borderless" align="left" onclick="displayPageInfo()"/>
</box>
</overlay>

View File

@@ -1,45 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
window.addEventListener("load", SetSecurityButton, false);
var securityUI;
function SetSecurityButton()
{
dump("in SetSecurityButton\n");
var ui = Components.classes["component://netscape/secure_browser_ui"].createInstance();
securityUI = ui.QueryInterface(Components.interfaces.nsSecureBrowserUI);
var button = document.getElementById('security-button');
if (button && window.content)
securityUI.init(window.content, button);
}
function displayPageInfo()
{
if (securityUI)
securityUI.displayPageInfoUI();
}

View File

@@ -1,24 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE window SYSTEM "chrome://global/locale/PSMTaskMenu.dtd" >
<overlay id="psmTaskMenuID"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<html:script language="JavaScript">
function displaySecurityAdvisor()
{
var psm = Components.classes["component://netscape/psm"].getService();
psm = psm.QueryInterface(Components.interfaces.nsIPSMComponent);
psm.displaySecurityAdvisor( null, null );
}
</html:script>
<menupopup id="personalManagers">
<menuitem id="PSMMentItem" position="1" value="&PSMCmd.label;" oncommand="displaySecurityAdvisor()"/>
</menupopup>
</overlay>

View File

@@ -1,37 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) NavSecurityOverlay.xul $(DIST)\bin\chrome\navigator\content
$(MAKE_INSTALL) NavSecurityUI.js $(DIST)\bin\chrome\navigator\content
install:: $(DLL)
$(MAKE_INSTALL) PSMTaskMenu.xul $(DIST)\bin\chrome\global\content
clobber::
$(RM) $(DIST)\bin\chrome\navigator\content\NavSecurityOverlay.xul
$(RM) $(DIST)\bin\chrome\navigator\content\NavSecurityUI.js
$(RM) $(DIST)\bin\chrome\global\content\PSMTaskMenu.xul

View File

@@ -1,32 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = en-US
include $(topsrcdir)/config/rules.mk

View File

@@ -1 +0,0 @@
PSMTaskMenu.dtd

View File

@@ -1 +0,0 @@
security.properties

View File

@@ -1,44 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
EXPORT_RESOURCE_CONTENT = \
$(srcdir)/PSMTaskMenu.dtd \
$(NULL)
EXPORT_NAV_RESOURCE_CONTENT = \
$(srcdir)/security.properties \
$(NULL)
include $(topsrcdir)/config/rules.mk
install::
$(INSTALL) $(EXPORT_RESOURCE_CONTENT) $(DIST)/bin/chrome/global/locale
$(INSTALL) $(EXPORT_NAV_RESOURCE_CONTENT) $(DIST)/bin/chrome/navigator/locale

View File

@@ -1 +0,0 @@
<!ENTITY PSMCmd.label "Security Manager">

View File

@@ -1,36 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..\..\..
include <$(DEPTH)\config\rules.mak>
GLOBAL_DIST=$(DIST)\bin\chrome\global\locale
NAV_DIST=$(DIST)\bin\chrome\navigator\locale
install::
$(MAKE_INSTALL) PSMTaskMenu.dtd $(GLOBAL_DIST)
$(MAKE_INSTALL) security.properties $(NAV_DIST)
clobber::
$(RM) -f $(DIST)\bin\chrome\global\locale\PSMTaskMenu.dtd
$(RM) -f $(DIST)\bin\chrome\navigator\locale\security.properties

View File

@@ -1,28 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
Title=Security Warning
MixedContentMessage=You have requested a secure document that contains some insecure information.
LeaveSiteMessage=You have requested an insecure document. The document and any information you send back could be observed by a third party while in transit.
EnterSiteMessage=You have requested a secure document. The document and any information you send back are encrypted for privacy while in transit.
PostToInsecure=Although this document is secure, the information you have submitted is insecure and could be observed by a third party while in transit. If you are submitting passwords, credit card numbers, or other information you would like to keep private, it would be safer for you to cancel the submission.
DontShowAgain=Show Me This Alert Next Time.
FindText=Please find the Personal Security Manager application

View File

@@ -1,27 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..\..
DIRS=en-US
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,27 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
DIRS = skin content locale
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,4 +0,0 @@
lock.gif
unlock.gif
broken.gif
NavSecurityOverlay.css

View File

@@ -1,39 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
SKIN_DIR = $(DIST)/bin/chrome/navigator/skin/
EXPORT_SKINS = \
$(srcdir)/broken.gif \
$(srcdir)/lock.gif \
$(srcdir)/unlock.gif \
$(srcdir)/NavSecurityOverlay.css \
$(NULL)
install::
$(INSTALL) $(EXPORT_SKINS) $(SKIN_DIR)

View File

@@ -1,15 +0,0 @@
titledbutton#security-button {
list-style-image:url("chrome://navigator/skin/unlock.gif");
}
titledbutton#security-button[level="high"] {
list-style-image:url("chrome://navigator/skin/lock.gif");
}
titledbutton#security-button[level="low"] {
list-style-image:url("chrome://navigator/skin/lock.gif");
}
titledbutton#security-button[level="broken"] {
list-style-image:url("chrome://navigator/skin/broken.gif");
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 B

View File

@@ -1,41 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
include <$(DEPTH)\config\rules.mak>
install::
$(MAKE_INSTALL) broken.gif $(DIST)\bin\chrome\navigator\skin
$(MAKE_INSTALL) lock.gif $(DIST)\bin\chrome\navigator\skin
$(MAKE_INSTALL) unlock.gif $(DIST)\bin\chrome\navigator\skin
$(MAKE_INSTALL) NavSecurityOverlay.css $(DIST)\bin\chrome\navigator\skin
clobber::
$(RM) $(DIST)\bin\chrome\navigator\skin\broken.gif
$(RM) $(DIST)\bin\chrome\navigator\skin\lock.gif
$(RM) $(DIST)\bin\chrome\navigator\skin\unlock.gif
$(RM) $(DIST)\bin\chrome\navigator\skin\NavSecurityOverlay.css

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 B

View File

@@ -1,63 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Hubbie Shaw
# Doug Turner <dougt@netscape.com>
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = psmglue
IS_COMPONENT = 1
LIBRARY_NAME = psmglue
CPPSRCS = \
nsPSMComponent.cpp \
nsPSMUICallbacks.cpp \
nsSSLSocketProvider.cpp \
nsPSMModule.cpp \
nsSSLIOLayer.cpp \
nsSecureBrowserUIImpl.cpp \
nsSDR.cpp \
$(NULL)
CSRCS = \
nsPSMMutex.c \
nsPSMShimLayer.c \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(MOZ_COMPONENT_LIBS) \
-lcmt \
-lprotocol \
-lmozjs \
$(NULL)
include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir) \
$(NULL)

View File

@@ -1,68 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Hubbie Shaw
# Doug Turner <dougt@netscape.com>
#
MODULE = psmglue
DEPTH=..\..\..
IGNORE_MANIFEST=1
DLLNAME = psmglue
PDBFILE = $(DLLNAME).pdb
MAPFILE = $(DLLNAME).map
DLL = .\$(OBJDIR)\$(DLLNAME).dll
MAKE_OBJ_TYPE = DLL
include <$(DEPTH)/config/config.mak>
LINCS = $(LINCS) \
-I$(PUBLIC) \
-I$(PUBLIC)/security \
$(NULL)
LLIBS = \
$(LIBNSPR) \
$(DIST)\lib\neckobase_s.lib \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\js3250.lib \
$(DIST)\lib\cmt.lib \
$(DIST)\lib\protocol.lib \
$(DIST)\lib\mozreg.lib \
$(NULL)
OBJS = \
.\$(OBJDIR)\nsPSMMutex.obj \
.\$(OBJDIR)\nsPSMShimLayer.obj \
.\$(OBJDIR)\nsPSMComponent.obj \
.\$(OBJDIR)\nsPSMUICallbacks.obj \
.\$(OBJDIR)\nsPSMModule.obj \
.\$(OBJDIR)\nsSecureBrowserUIImpl.obj \
.\$(OBJDIR)\nsSSLIOLayer.obj \
.\$(OBJDIR)\nsSSLSocketProvider.obj \
.\$(OBJDIR)\nsSDR.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components

View File

@@ -1,822 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
* Mitch Stoltz <mstoltz@netscape.com>
*/
#include "nsProxiedService.h"
#include "nsPSMUICallbacks.h"
#include "VerReg.h"
#include "nspr.h"
#include "nsPSMComponent.h"
#include "nsCRT.h"
#include "nsIPref.h"
#include "nsIProfile.h"
#include "nsILocalFile.h"
#ifdef XP_MAC
#include "nsILocalFileMac.h"
#endif
#include "nsSpecialSystemDirectory.h"
#include "rsrcids.h"
#include "nsPSMMutex.h"
#include "nsPSMShimLayer.h"
#include "nsPSMUICallbacks.h"
#include "nsISecureBrowserUI.h"
#include "nsIDocumentLoaderObserver.h"
#include "nsIScriptSecurityManager.h"
#include "nsICertificatePrincipal.h"
#define PSM_VERSION_REG_KEY "/Netscape/Personal Security Manager"
#ifdef WIN32
#define PSM_FILE_NAME "psm.exe"
#elif XP_UNIX
#define PSM_FILE_NAME "start-psm"
#define PSM_FILE_LOCATION "/opt/netscape/security/start-psm"
#else
#define PSM_FILE_NAME "psm"
#endif
static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
static NS_DEFINE_CID(kProfileCID, NS_PROFILE_CID);
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
nsPSMComponent* nsPSMComponent::mInstance = nsnull;
nsPSMComponent::nsPSMComponent()
{
NS_INIT_REFCNT();
mControl = nsnull;
}
nsPSMComponent::~nsPSMComponent()
{
if (mControl)
{
CMT_CloseControlConnection(mControl);
mControl = nsnull;
}
}
NS_IMETHODIMP
nsPSMComponent::CreatePSMComponent(nsISupports* aOuter, REFNSIID aIID, void **aResult)
{
if (!aResult) {
return NS_ERROR_INVALID_POINTER;
}
if (aOuter) {
*aResult = nsnull;
return NS_ERROR_NO_AGGREGATION;
}
if (mInstance == nsnull)
{
mInstance = new nsPSMComponent();
}
if (mInstance == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = mInstance->QueryInterface(aIID, aResult);
if (NS_FAILED(rv))
{
*aResult = nsnull;
}
return rv;
}
/* nsISupports Implementation for the class */
NS_IMPL_THREADSAFE_ISUPPORTS1 (nsPSMComponent, nsIPSMComponent);
#define INIT_NUM_PREFS 100
/* preference types */
#define STRING_PREF 0
#define BOOL_PREF 1
#define INT_PREF 2
/* resizable list struct that contains pref items */
typedef struct CMSetPrefList {
int n; /* number of filled items */
int capacity; /* allocated memory */
CMTSetPrefElement* list; /* actual list */
} CMSetPrefList;
static void get_pack_bool_pref(nsIPref *prefManager, char* key, CMTSetPrefElement* list, int* n)
{
PRBool boolpref;
list[*n].key = nsCRT::strdup(key);
list[*n].type = BOOL_PREF;
if ((prefManager->GetBoolPref(key, &boolpref) != 0) || boolpref)
{
list[*n].value = nsCRT::strdup("true");
}
else
{
list[*n].value = nsCRT::strdup("false");
}
(*n)++; /* increment the counter after done packing */
return;
}
static void SaveAllPrefs(int number, CMTSetPrefElement* list)
{
nsCOMPtr<nsIPref> prefManager;
nsresult res = nsServiceManager::GetService(kPrefCID,
nsIPref::GetIID(),
getter_AddRefs(prefManager));
if (NS_FAILED(res) || !prefManager)
{
return;
}
int i;
int intval;
for (i = 0; i < number; i++)
{
if (list[i].key == nsnull)
{
/* misconfigured item: next */
continue;
}
switch (list[i].type)
{
case 0: /* string type */
prefManager->SetCharPref(list[i].key, list[i].value);
break;
case 1: /* boolean type */
if (strcmp(list[i].value, "true") == 0) {
prefManager->SetBoolPref(list[i].key, (PRBool)1);
}
else if (strcmp(list[i].value, "false") == 0) {
prefManager->SetBoolPref(list[i].key, (PRBool)0);
}
break;
case 2:
intval = atoi(list[i].value);
prefManager->SetIntPref(list[i].key, intval);
break;
default:
break;
}
}
return;
}
NS_IMETHODIMP
nsPSMComponent::PassPrefs()
{
// if we have not passed anything to psm yet, this function can just return.
if (!mControl)
return NS_OK;
int i;
nsresult rv = NS_ERROR_FAILURE;
char* strpref = NULL;
int intpref;
PRBool boolpref;
CMSetPrefList prefs = {0};
CMTSetPrefElement* list = NULL;
char* pickAuto = "Select Automatically";
char* alwaysAsk = "Ask Every Time";
nsCOMPtr<nsIPref> prefManager;
nsresult res = nsServiceManager::GetService(kPrefCID,
nsIPref::GetIID(),
getter_AddRefs(prefManager));
if (NS_OK != res)
{
return NS_ERROR_FAILURE;
}
/* allocate memory for list */
prefs.n = 0; /* counter */
prefs.capacity = INIT_NUM_PREFS;
prefs.list = (CMTSetPrefElement*) new char[(INIT_NUM_PREFS * sizeof(CMTSetPrefElement))];
if (prefs.list == NULL)
{
return rv;
}
/* shorthand */
list = prefs.list;
/* get preferences */
get_pack_bool_pref(prefManager, "security.enable_ssl2", (CMTSetPrefElement*)list, &(prefs.n));
get_pack_bool_pref(prefManager, "security.enable_ssl3", (CMTSetPrefElement*)list, &(prefs.n));
/* this pref is a boolean pref in nature but a string pref for
* historical reason
*/
list[prefs.n].key = nsCRT::strdup("security.default_personal_cert");
list[prefs.n].type = STRING_PREF;
if ((prefManager->CopyCharPref(list[prefs.n].key, &strpref) == 0) && (strcmp(strpref, pickAuto) == 0))
{
list[prefs.n].value = nsCRT::strdup(pickAuto);
}
else
{
/* although one could choose a specific cert for client auth in
* Nova, that mode is deprecated with PSM and mapped to ASK
*/
list[prefs.n].value = nsCRT::strdup(alwaysAsk);
}
prefs.n++;
if (strpref != NULL)
{
nsCRT::free(strpref);
}
list[prefs.n].key = nsCRT::strdup("security.default_mail_cert");
list[prefs.n].type = STRING_PREF;
if (prefManager->CopyCharPref(list[prefs.n].key, &list[prefs.n].value) != 0)
{
list[prefs.n].value = NULL;
}
prefs.n++;
list[prefs.n].key = nsCRT::strdup("security.ask_for_password");
list[prefs.n].type = INT_PREF;
if (prefManager->GetIntPref(list[prefs.n].key, &intpref) != 0)
{
intpref = 0; /* default */
}
list[prefs.n].value = PR_smprintf("%d", intpref);
prefs.n++;
list[prefs.n].key = nsCRT::strdup("security.password_lifetime");
list[prefs.n].type = INT_PREF;
if (prefManager->GetIntPref(list[prefs.n].key, &intpref) != 0)
{
intpref = 30; /* default */
}
list[prefs.n].value = PR_smprintf("%d", intpref);
prefs.n++;
/* OCSP preferences */
/* XXX since these are the new ones added by PSM, we will be more
* error-tolerant in fetching them
*/
if (prefManager->GetBoolPref("security.OCSP.enabled", &boolpref) == 0)
{
if (boolpref)
{
list[prefs.n].value = nsCRT::strdup("true");
}
else
{
list[prefs.n].value = nsCRT::strdup("false");
}
list[prefs.n].key = nsCRT::strdup("security.OCSP.enabled");
list[prefs.n].type = BOOL_PREF;
prefs.n++;
}
if (prefManager->GetBoolPref("security.OCSP.useDefaultResponder", &boolpref) == 0)
{
if (boolpref)
{
list[prefs.n].value = nsCRT::strdup("true");
}
else
{
list[prefs.n].value = nsCRT::strdup("false");
}
list[prefs.n].key = nsCRT::strdup("security.OCSP.useDefaultResponder");
list[prefs.n].type = BOOL_PREF;
prefs.n++;
}
if (prefManager->CopyCharPref("security.OCSP.URL", &strpref) == 0)
{
list[prefs.n].value = strpref;
list[prefs.n].key = nsCRT::strdup("security.OCSP.URL");
list[prefs.n].type = STRING_PREF;
prefs.n++;
}
if (prefManager->CopyCharPref("security.OCSP.signingCA", &strpref) == 0)
{
list[prefs.n].value = strpref;
list[prefs.n].key = nsCRT::strdup("security.OCSP.signingCA");
list[prefs.n].type = STRING_PREF;
prefs.n++;
}
/* now application-specific preferences */
/* get navigator preferences */
get_pack_bool_pref(prefManager, "security.warn_entering_secure", (CMTSetPrefElement*)list, &prefs.n);
get_pack_bool_pref(prefManager, "security.warn_leaving_secure", (CMTSetPrefElement*)list, &prefs.n);
get_pack_bool_pref(prefManager, "security.warn_viewing_mixed", (CMTSetPrefElement*)list, &prefs.n);
get_pack_bool_pref(prefManager, "security.warn_submit_insecure", (CMTSetPrefElement*)list, &prefs.n);
// Add any other prefs here such as ldap or mail/news.
CMT_SetSavePrefsCallback(mControl, (savePrefsCallback_fn)SaveAllPrefs);
if (CMT_PassAllPrefs(mControl, prefs.n, (CMTSetPrefElement*)prefs.list) != CMTSuccess)
{
goto loser;
}
rv = NS_OK; /* success */
loser:
/* clean out memory for prefs */
for (i = 0; i < prefs.n; i++)
{
if (prefs.list[i].key != NULL)
{
nsCRT::free(prefs.list[i].key);
}
if (prefs.list[i].value != NULL)
{
nsCRT::free(prefs.list[i].value);
}
}
if (prefs.list != NULL)
{
delete(prefs.list);
}
return rv;
}
NS_IMETHODIMP
nsPSMComponent::GetControlConnection( CMT_CONTROL * *_retval )
{
nsresult rv;
*_retval = nsnull;
if (mControl)
{
*_retval = mControl;
return NS_OK;
}
else /* initialize mutex, sock table, etc. */
{
if (nsPSMMutexInit() != PR_SUCCESS)
return NS_ERROR_FAILURE;
mControl = CMT_ControlConnect(&nsPSMMutexTbl, &nsPSMShimTbl);
if (mControl == nsnull)
{
//Try to find it.
int err;
char filepath[MAXREGPATHLEN];
err = VR_GetPath(PSM_VERSION_REG_KEY, sizeof(filepath), filepath);
if ( err == REGERR_OK )
{
nsFileSpec psmSpec(filepath);
psmSpec += PSM_FILE_NAME;
if (psmSpec.Exists())
{
mControl = CMT_EstablishControlConnection((char *)psmSpec.GetNativePathCString(), &nsPSMShimTbl, &nsPSMMutexTbl);
}
}
}
#ifndef XP_MAC
if (mControl == nsnull)
{
nsSpecialSystemDirectory sysDir(nsSpecialSystemDirectory::OS_CurrentProcessDirectory);
nsFileSpec spec = sysDir;
spec += "psm/";
spec += PSM_FILE_NAME;
if (spec.Exists())
{
mControl = CMT_EstablishControlConnection((char *)spec.GetNativePathCString(), &nsPSMShimTbl, &nsPSMMutexTbl);
}
}
#else
if (mControl == nsnull)
{
// Attempt to locate "Personal Security Manager" in "Essential Files".
nsCOMPtr<nsILocalFile> aPSMApp = do_CreateInstance(NS_LOCAL_FILE_PROGID, &rv);
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsILocalFileMac> psmAppMacFile = do_QueryInterface(aPSMApp, &rv);
if (NS_SUCCEEDED(rv))
{
rv = psmAppMacFile->InitFindingAppByCreatorCode('nPSM');
if (NS_SUCCEEDED(rv))
{
rv = psmAppMacFile->LaunchAppWithDoc(nsnull, PR_TRUE);
if (NS_SUCCEEDED(rv))
{
const PRUint32 kMaxWaitTicks = 180; // max 3 seconds
PRUint32 endTicks = ::TickCount() + kMaxWaitTicks;
do
{
EventRecord theEvent;
WaitNextEvent(0, &theEvent, 5, NULL);
mControl = CMT_ControlConnect(&nsPSMMutexTbl, &nsPSMShimTbl);
} while (!mControl && (::TickCount() < endTicks));
}
}
}
}
NS_ASSERTION(NS_SUCCEEDED(rv), "Launching Personal Security Manager failed");
}
#endif
#ifdef XP_UNIX
if (mControl == nsnull)
{
nsFileSpec psmSpec(PSM_FILE_LOCATION);
if (psmSpec.Exists())
{
mControl = CMT_EstablishControlConnection(PSM_FILE_LOCATION, &nsPSMShimTbl, &nsPSMMutexTbl);
}
}
#endif
if (mControl == nsnull)
{
char* filePath = nsnull;
NS_WITH_PROXIED_SERVICE(nsIPSMUIHandler, handler, nsPSMUIHandlerImpl::GetCID(), NS_UI_THREAD_EVENTQ, &rv);
if(NS_SUCCEEDED(rv))
{
NS_WITH_SERVICE(nsIStringBundleService, service, kCStringBundleServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsILocale* locale = nsnull;
nsCOMPtr<nsIStringBundle> stringBundle;
rv = service->CreateBundle(SECURITY_STRING_BUNDLE_URL, locale, getter_AddRefs(stringBundle));
if (NS_FAILED(rv)) return rv;
PRUnichar *ptrv = nsnull;
rv = stringBundle->GetStringFromName( NS_ConvertASCIItoUCS2("FindText").GetUnicode(), &ptrv);
if (NS_FAILED(rv)) return rv;
handler->PromptForFile(ptrv, PSM_FILE_NAME, PR_TRUE, &filePath);
nsAllocator::Free(ptrv);
}
if (! filePath)
return NS_ERROR_FAILURE;
mControl = CMT_EstablishControlConnection(filePath, &nsPSMShimTbl, &nsPSMMutexTbl);
}
if (!mControl || InitPSMUICallbacks(mControl) != PR_SUCCESS)
goto failure;
nsFileSpec profileSpec;
PRUnichar* profileName;
NS_WITH_SERVICE(nsIProfile, profile, kProfileCID, &rv);
if (NS_FAILED(rv)) goto failure;
rv = profile->GetCurrentProfileDir(&profileSpec);
if (NS_FAILED(rv)) goto failure;;
rv = profile->GetCurrentProfile(&profileName);
if (NS_FAILED(rv)) goto failure;
CMTStatus psmStatus;
nsCAutoString profilenameC;
profilenameC.AssignWithConversion(profileName);
psmStatus = CMT_Hello( mControl,
PROTOCOL_VERSION,
profilenameC,
(char*)profileSpec.GetNativePathCString());
if (psmStatus == CMTFailure)
{
PR_FREEIF(profileName);
goto failure;
}
if (NS_FAILED(PassPrefs()))
{
PR_FREEIF(profileName);
goto failure;
}
PR_FREEIF(profileName);
*_retval = mControl;
return NS_OK;
}
failure:
#ifdef DEBUG
printf("*** Failure setting up Cartman! \n");
#endif
if (mControl)
{
CMT_CloseControlConnection(mControl);
mControl = NULL;
}
// TODO we need to unregister our UI callback BEFORE destroying our mutex.
// nsPSMMutexDestroy();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPSMComponent::DisplaySecurityAdvisor(const char *pickledStatus, const char *hostName)
{
CMT_CONTROL *controlConnection;
GetControlConnection( &controlConnection );
if (DisplayPSMUIDialog(controlConnection, pickledStatus, hostName) == PR_SUCCESS)
return NS_OK;
return NS_ERROR_FAILURE;
}
//-----------------------------------------
// Secure Hash Functions
//-----------------------------------------
NS_IMETHODIMP
nsPSMComponent::HashBegin(PRUint32 alg, PRUint32* id)
{
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
if(CMT_HashCreate(controlConnection, alg, (CMUint32*)id) != CMTSuccess)
return NS_ERROR_FAILURE;
if(CMT_HASH_Begin(controlConnection, *id) != CMTSuccess)
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
nsPSMComponent::HashUpdate(PRUint32 id, const char* buf, PRUint32 buflen)
{
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
if (CMT_HASH_Update(controlConnection, id,
(const unsigned char*)buf, buflen) != CMTSuccess)
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
nsPSMComponent::HashEnd(PRUint32 id, char** hash, PRUint32* hashlen,
PRUint32 maxLen)
{
if (!hash)
return NS_ERROR_ILLEGAL_VALUE;
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
if(CMT_HASH_End(controlConnection, id, (unsigned char*)*hash,
(CMUint32*)hashlen, maxLen) != CMTSuccess)
return NS_ERROR_FAILURE;
CMT_HASH_Destroy(controlConnection, id);
return NS_OK;
}
//-----------------------------------------
// Signature Verification Functions
//-----------------------------------------
PR_STATIC_CALLBACK(void)
UselessPK7DataSink(void* arg, const char* buf, CMUint32 len)
{
}
NS_IMETHODIMP
nsPSMComponent::VerifyRSABegin(PRUint32* id)
{
if (!id)
return NS_ERROR_ILLEGAL_VALUE;
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
CMInt32* blah = nsnull;
CMTStatus result = CMT_PKCS7DecoderStart(controlConnection, nsnull,
(CMUint32*)id, blah,
UselessPK7DataSink, nsnull);
if (result == CMTSuccess)
return NS_OK;
else
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPSMComponent::VerifyRSAUpdate(PRUint32 id, const char* buf, PRUint32 buflen)
{
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
CMTStatus result = CMT_PKCS7DecoderUpdate(controlConnection, id, buf, buflen);
if (result == CMTSuccess)
return NS_OK;
else
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPSMComponent::VerifyRSAEnd(PRUint32 id, const char* plaintext,
PRUint32 plaintextLen,
PRBool aKeepCert,
nsIPrincipal** aPrincipal,
PRInt32* aVerifyError)
{
*aVerifyError = -1;
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
CMUint32 contentInfo;
CMTStatus result = CMT_PKCS7DecoderFinish(controlConnection,
id, &contentInfo);
if (result != CMTSuccess)
return NS_ERROR_FAILURE;
//-- Make sure a signature is present
CMInt32 isSigned;
result = CMT_GetNumericAttribute(controlConnection, contentInfo,
SSM_FID_P7CINFO_IS_SIGNED, &isSigned);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
if (!isSigned)
{
*aPrincipal = nsnull;
*aVerifyError = nsIPSMComponent::VERIFY_NOSIG;
return NS_OK;
}
// SHA1 hash the plaintext to compare it to the signature
CMUint32 hashId;
CMT_HashCreate(controlConnection, nsIPSMComponent::SHA1, &hashId);
CMT_HASH_Begin(controlConnection, hashId);
result = CMT_HASH_Update(controlConnection, hashId,
(const unsigned char*)plaintext, plaintextLen);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
unsigned char* hash = (unsigned char*)PR_MALLOC(nsIPSMComponent::SHA1_LENGTH);
if (!hash) return NS_ERROR_OUT_OF_MEMORY;
CMUint32 hashLen;
result = CMT_HASH_End(controlConnection, hashId, hash,
&hashLen, nsIPSMComponent::SHA1_LENGTH);
NS_ASSERTION(hashLen == nsIPSMComponent::SHA1_LENGTH,
"PSMComponent: Hash too short.");
CMT_HASH_Destroy(controlConnection, hashId);
if (result != CMTSuccess)
{
PR_FREEIF(hash);
return NS_ERROR_FAILURE;
}
//-- Verify signature
CMTItemStr hashItem;
hashItem.data = hash;
hashItem.len = hashLen;
result = CMT_PKCS7VerifyDetachedSignature(controlConnection, contentInfo,
6 /* =Object Signing Cert */,
3 /* =SHA1 algorithm (MD5=2)*/,
(CMUint32)aKeepCert,
&hashItem, (CMInt32*)aVerifyError);
PR_FREEIF(hash);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
//-- Did it verify?
if (*aVerifyError != 0)
*aPrincipal = nsnull;
else
{
//-- Generate a principal from the cert
CMUint32 certID;
result = CMT_GetRIDAttribute(controlConnection, contentInfo,
SSM_FID_P7CINFO_SIGNER_CERT, &certID);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
if (NS_FAILED(CreatePrincipalFromCert(certID, aPrincipal)))
return NS_ERROR_FAILURE;
}
CMT_PKCS7DestroyContentInfo(controlConnection, contentInfo);
return NS_OK;
}
NS_IMETHODIMP
nsPSMComponent::CreatePrincipalFromCert(PRUint32 aCertID, nsIPrincipal** aPrincipal)
{
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
//-- Read cert ID
CMTStatus result;
CMTItem fingerprint;
result = CMT_GetStringAttribute(controlConnection, aCertID,
SSM_FID_CERT_FINGERPRINT, &fingerprint);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
//-- Get a principal
nsresult rv;
NS_WITH_SERVICE(nsIScriptSecurityManager, secMan,
NS_SCRIPTSECURITYMANAGER_PROGID, &rv)
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
rv = secMan->GetCertificatePrincipal((char*)fingerprint.data,
aPrincipal);
if (NS_FAILED(rv)) return rv;
//-- Get common name and store it in the principal.
// Using common name + organizational unit as the user-visible certificate name
nsCOMPtr<nsICertificatePrincipal> certificate = do_QueryInterface(*aPrincipal, &rv);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
CMTItem common;
result = CMT_GetStringAttribute(controlConnection, aCertID,
SSM_FID_CERT_COMMON_NAME, &common);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
CMTItem subject;
result = CMT_GetStringAttribute(controlConnection, aCertID,
SSM_FID_CERT_SUBJECT_NAME, &subject);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
nsCAutoString commonName;
commonName = (char*)common.data;
static const char orgUnitTag[] = " OU=";
char* orgUnitPos = PL_strstr((char*)subject.data, orgUnitTag);
if (orgUnitPos)
{
orgUnitPos += sizeof(orgUnitTag)-1;
char* orgUnitEnd = PL_strchr(orgUnitPos, ',');
PRInt32 orgUnitLen;
if(orgUnitEnd)
orgUnitLen = orgUnitEnd - orgUnitPos;
else
orgUnitLen = PL_strlen(orgUnitPos);
commonName.Append(' ');
commonName.Append(orgUnitPos, orgUnitLen);
}
char* commonChar = commonName.ToNewCString();
if (!commonChar) return NS_ERROR_OUT_OF_MEMORY;
rv = certificate->SetCommonName(commonChar);
Recycle(commonChar);
return rv;
}

View File

@@ -1,54 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nscore.h"
#include "nsIPSMComponent.h"
#include "nsIStringBundle.h"
#define SECURITY_STRING_BUNDLE_URL "chrome://navigator/locale/security.properties"
#define NS_PSMCOMPONENT_CID {0xddcae170, 0x5412, 0x11d3, {0xbb, 0xc8, 0x00, 0x00, 0x86, 0x1d, 0x12, 0x37}}
// Implementation of the PSM component interface.
class nsPSMComponent : public nsIPSMComponent
{
public:
NS_DEFINE_STATIC_CID_ACCESSOR( NS_PSMCOMPONENT_CID );
nsPSMComponent();
virtual ~nsPSMComponent();
NS_DECL_ISUPPORTS
NS_DECL_NSIPSMCOMPONENT
static NS_METHOD CreatePSMComponent(nsISupports* aOuter, REFNSIID aIID, void **aResult);
private:
PCMT_CONTROL mControl;
nsCOMPtr<nsISupports> mSecureBrowserIU;
static nsPSMComponent* mInstance;
};

View File

@@ -1,86 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nsIModule.h"
#include "nsIGenericFactory.h"
#include "nsPSMUICallbacks.h"
#include "nsPSMComponent.h"
#include "nsISecureBrowserUI.h"
#include "nsSecureBrowserUIImpl.h"
#include "nsSSLSocketProvider.h"
#include "nsSDR.h"
// Define SDR object constructor
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSecretDecoderRing, init)
static nsModuleComponentInfo components[] =
{
{
PSM_COMPONENT_CLASSNAME,
NS_PSMCOMPONENT_CID,
PSM_COMPONENT_PROGID,
nsPSMComponent::CreatePSMComponent
},
{
PSM_UI_HANLDER_CLASSNAME,
NS_PSMUIHANDLER_CID,
PSM_UI_HANLDER_PROGID,
nsPSMUIHandlerImpl::CreatePSMUIHandler
},
{
NS_SECURE_BROWSER_UI_CLASSNAME,
NS_SECURE_BROWSER_UI_CID,
NS_SECURE_BROWSER_UI_PROGID,
nsSecureBrowserUIImpl::Create
},
{
NS_SECURE_BROWSER_DOCOBSERVER_CLASSNAME,
NS_SECURE_BROWSER_DOCOBSERVER_CID,
NS_SECURE_BROWSER_DOCOBSERVER_PROGID,
nsSecureBrowserUIImpl::Create
},
{
NS_ISSLSOCKETPROVIDER_CLASSNAME,
NS_SSLSOCKETPROVIDER_CID,
NS_ISSLSOCKETPROVIDER_PROGID,
nsSSLSocketProvider::Create
},
{
NS_SDR_CLASSNAME,
NS_SDR_CID,
NS_SDR_PROGID,
nsSecretDecoderRingConstructor
}
};
NS_IMPL_NSGETMODULE("PSMComponent", components);

View File

@@ -1,72 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "prmon.h"
#include "prtypes.h"
#include "nsPSMMutex.h"
static PRMonitor *_nsPSMMutexVar;
PRStatus
nsPSMMutexInit()
{
if (!_nsPSMMutexVar)
_nsPSMMutexVar = PR_NewMonitor();
return _nsPSMMutexVar ? PR_SUCCESS : PR_FAILURE;
}
PRStatus
nsPSMMutexDestroy()
{
if (!_nsPSMMutexVar)
return PR_FAILURE;
PR_Wait(_nsPSMMutexVar, PR_INTERVAL_NO_TIMEOUT);
PR_DestroyMonitor(_nsPSMMutexVar);
return PR_SUCCESS;
}
static void
nsPSMMutexLock(CMTMutexPointer *p)
{
PR_EnterMonitor(*(PRMonitor **)p);
return;
}
static void
nsPSMMutexUnlock(CMTMutexPointer *p)
{
PR_ExitMonitor(*(PRMonitor **)p);
return;
}
CMT_MUTEX nsPSMMutexTbl =
{
&_nsPSMMutexVar,
(CMTMutexFunction)nsPSMMutexLock,
(CMTMutexFunction)nsPSMMutexUnlock
};

View File

@@ -1,39 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#ifndef _NSPSMMUTEX_H
#define _NSPSMMUTEX_H
#include "cmtcmn.h"
PR_BEGIN_EXTERN_C
PR_EXTERN(CMT_MUTEX) nsPSMMutexTbl;
PR_EXTERN(PRStatus) nsPSMMutexInit(void);
PR_EXTERN(PRStatus) nsPSMMutexDestroy(void);
PR_END_EXTERN_C
#endif

View File

@@ -1,284 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nspr.h"
#include "nsPSMShimLayer.h"
#ifdef XP_UNIX
#include <sys/stat.h>
#include <unistd.h>
#endif
#define NSPSMSHIMMAXFD 50
CMT_SocketFuncs nsPSMShimTbl =
{
nsPSMShimGetSocket,
nsPSMShimConnect,
nsPSMShimVerifyUnixSocket,
nsPSMShimSend,
nsPSMShimSelect,
nsPSMShimReceive,
nsPSMShimShutdown,
nsPSMShimClose
};
CMTSocket
nsPSMShimGetSocket(int unixSock)
{
PRStatus rv;
PRFileDesc *fd;
CMSocket *sock;
if (unixSock)
{
#ifndef XP_UNIX
return NULL;
#else
fd = PR_OpenTCPSocket(AF_UNIX);
PR_ASSERT(fd);
#endif
}
else
{
PRSocketOptionData sockopt;
fd = PR_NewTCPSocket();
PR_ASSERT(fd);
/* disable Nagle algorithm delay for control sockets */
sockopt.option = PR_SockOpt_NoDelay;
sockopt.value.no_delay = PR_TRUE;
rv = PR_SetSocketOption(fd, &sockopt);
PR_ASSERT(PR_SUCCESS == rv);
}
sock = (CMSocket *)PR_Malloc(sizeof(CMSocket));
if (sock == NULL)
return sock;
sock->fd = fd;
sock->isUnix = unixSock;
memset(&sock->netAddr, 0, sizeof(PRNetAddr));
return (CMTSocket)sock;
}
CMTStatus
nsPSMShimConnect(CMTSocket sock, short port, char *path)
{
PRStatus err;
PRErrorCode errcode;
CMTStatus rv = CMTSuccess;
CMSocket *cmSock = (CMSocket *)sock;
if (!sock) return CMTFailure;
if (cmSock->isUnix)
{
#ifndef XP_UNIX
return CMTFailure;
#else
int pathLen;
if (!path)
{
return CMTFailure;
}
/* check buffer overrun */
pathLen = strlen(path)+1;
pathLen = pathLen < sizeof(cmSock->netAddr.local.path)
? pathLen : sizeof(cmSock->netAddr.local.path);
memcpy(&cmSock->netAddr.local.path, path, pathLen);
cmSock->netAddr.local.family = PR_AF_LOCAL;
#endif
}
else /* cmSock->isUnix */
{
cmSock->netAddr.inet.family = PR_AF_INET;
cmSock->netAddr.inet.port = PR_htons(port);
cmSock->netAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
}
err = PR_Connect( cmSock->fd, &cmSock->netAddr, PR_INTERVAL_MAX );
if (err == PR_FAILURE)
{
errcode = PR_GetError();
/* TODO: verify PR_INVALID_ARGUMENT_ERROR continue with connect */
switch (errcode)
{
case PR_IS_CONNECTED_ERROR:
rv = CMTSuccess;
break;
case PR_IN_PROGRESS_ERROR:
case PR_IO_TIMEOUT_ERROR:
#ifdef WIN32
case PR_WOULD_BLOCK_ERROR:
case PR_INVALID_ARGUMENT_ERROR:
#endif
default:
rv = CMTFailure;
break;
}
}
return rv;
}
CMTStatus
nsPSMShimVerifyUnixSocket(CMTSocket sock)
{
#ifndef XP_UNIX
return CMTFailure;
#else
int rv;
CMSocket *cmSock;
struct stat statbuf;
cmSock = (CMSocket *)sock;
if (!cmSock || !cmSock->isUnix)
return CMTFailure;
rv = stat(cmSock->netAddr.local.path, &statbuf);
if (rv < 0 || statbuf.st_uid != geteuid() )
{
PR_Close(cmSock->fd);
cmSock->fd = NULL;
PR_Free(cmSock);
return CMTFailure;
}
return CMTSuccess;
#endif
}
size_t
nsPSMShimSend(CMTSocket sock, void *buffer, size_t length)
{
PRInt32 total;
CMSocket *cmSock = (CMSocket *)sock;
if (!sock) return CMTFailure;
total = PR_Send(cmSock->fd, buffer, length, 0, PR_INTERVAL_NO_TIMEOUT);
/* TODO: for now, return 0 if there's an error */
return (total < 0) ? 0 : total;
}
CMTSocket
nsPSMShimSelect(CMTSocket *socks, int numsocks, int poll)
{
CMSocket **sockArr = (CMSocket **)socks;
PRPollDesc readPDs[NSPSMSHIMMAXFD];
PRIntervalTime timeout;
PRInt32 cnt;
int i;
if (!socks) return NULL;
memset(readPDs, 0, sizeof(readPDs));
PR_ASSERT(NSPSMSHIMMAXFD >= numsocks);
for (i=0; i<numsocks; i++)
{
readPDs[i].fd = sockArr[i]->fd;
readPDs[i].in_flags = PR_POLL_READ;
}
timeout = poll ? PR_INTERVAL_NO_WAIT : PR_INTERVAL_NO_TIMEOUT;
cnt = PR_Poll(readPDs, numsocks, timeout);
/* Figure out which socket was selected */
if (cnt > 0)
{
for (i=0; i<numsocks; i++)
{
if (readPDs[i].out_flags & PR_POLL_READ)
{
return (CMTSocket)sockArr[i];
}
}
}
return NULL;
}
size_t
nsPSMShimReceive(CMTSocket sock, void *buffer, size_t bufSize)
{
PRInt32 total;
CMSocket *cmSock = (CMSocket *)sock;
if (!sock) return CMTFailure;
total = PR_Recv(cmSock->fd, buffer, bufSize, 0, PR_INTERVAL_NO_TIMEOUT);
/* TODO: for now, return 0 if there's an error */
return (total < 0) ? 0 : total;
}
CMTStatus
nsPSMShimShutdown(CMTSocket sock)
{
CMSocket *cmSock = (CMSocket*)sock;
PRStatus rv;
if (!sock) return CMTFailure;
rv = PR_Shutdown(cmSock->fd, PR_SHUTDOWN_SEND);
return (PR_SUCCESS == rv) ? CMTSuccess : CMTFailure;
}
CMTStatus
nsPSMShimClose(CMTSocket sock)
{
CMSocket *cmSock = (CMSocket*)sock;
PRStatus rv = PR_SUCCESS;
PR_ASSERT(cmSock);
if (!sock) return CMTFailure;
rv = PR_Close(cmSock->fd);
cmSock->fd = NULL;
PR_Free(cmSock);
return (PR_SUCCESS == rv) ? CMTSuccess : CMTFailure;
}

View File

@@ -1,67 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#ifndef _NSPSMSHIMLAYER_H_
#define _NSPSMSHIMLAYER_H_
#include "cmtcmn.h"
#include "prio.h"
PR_BEGIN_EXTERN_C
typedef struct CMSocket {
PRFileDesc *fd;
PRBool isUnix;
PRNetAddr netAddr;
} CMSocket;
PR_EXTERN(CMT_SocketFuncs) nsPSMShimTbl;
PR_EXTERN(CMTSocket)
nsPSMShimGetSocket(int unixSock);
PR_EXTERN(CMTStatus)
nsPSMShimConnect(CMTSocket sock, short port, char *path);
PR_EXTERN(CMTStatus)
nsPSMShimVerifyUnixSocket(CMTSocket sock);
PR_EXTERN(size_t)
nsPSMShimSend(CMTSocket sock, void *buffer, size_t length);
PR_EXTERN(CMTSocket)
nsPSMShimSelect(CMTSocket *socks, int numsocks, int poll);
PR_EXTERN(size_t)
nsPSMShimReceive(CMTSocket sock, void *buffer, size_t bufSize);
PR_EXTERN(CMTStatus)
nsPSMShimShutdown(CMTSocket sock);
PR_EXTERN(CMTStatus)
nsPSMShimClose(CMTSocket sock);
PR_END_EXTERN_C
#endif /* _NSPSMSHIMLAYER_H_ */

View File

@@ -1,333 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nsProxiedService.h"
#include "nsIEventQueueService.h"
#include "nsPSMUICallbacks.h"
#include "nsINetSupportDialogService.h"
#include "nsIFilePicker.h"
#include "nsAppShellCIDs.h"
#include "prprf.h"
#include "prmem.h"
#include "nsSSLIOLayer.h" // for SSMSTRING_PADDED_LENGTH
#include "ssmdefs.h"
#include "rsrcids.h"
// Interfaces Needed
#include "nsIAppShellService.h"
#include "nsIDocShell.h"
#include "nsIDOMWindow.h"
#include "nsIInterfaceRequestor.h"
#include "nsIPrompt.h"
#include "nsIScriptGlobalObject.h"
#include "nsIURL.h"
#include "nsIXULWindow.h"
static NS_DEFINE_IID(kAppShellServiceCID, NS_APPSHELL_SERVICE_CID);
static NS_DEFINE_CID(kNetSupportDialogCID, NS_NETSUPPORTDIALOG_CID);
// Happy callbacks
static char * PromptUserCallback(void *arg, char *prompt, int isPasswd);
static char * FilePathPromptCallback(void *arg, char *prompt, char *fileRegEx, CMUint32 shouldFileExist);
static void ApplicationFreeCallback(char *userInput);
static void * CartmanUIHandler(uint32 resourceID, void* clientContext, uint32 width, uint32 height, PRBool isModel,
char* urlStr, void *data);
extern "C" void CARTMAN_UIEventLoop(void *data);
/* nsISupports Implementation for the class */
NS_IMPL_ISUPPORTS1(nsPSMUIHandlerImpl, nsIPSMUIHandler)
NS_METHOD
nsPSMUIHandlerImpl::DisplayURI(PRInt32 width, PRInt32 height, const char *urlStr)
{
nsresult rv;
nsCOMPtr<nsIDOMWindow> hiddenWindow;
JSContext *jsContext;
NS_WITH_SERVICE(nsIAppShellService, appShell, kAppShellServiceCID, &rv);
if (NS_SUCCEEDED(rv))
{
rv = appShell->GetHiddenWindowAndJSContext( getter_AddRefs( hiddenWindow ),
&jsContext );
if ( NS_SUCCEEDED( rv ) )
{
// Set up arguments for "window.open"
void *stackPtr;
char buffer[256];
PR_snprintf(buffer,
sizeof(buffer),
"menubar=no,height=%d,width=%d",
height,
width );
jsval *argv = JS_PushArguments(jsContext, &stackPtr, "sss", urlStr, "_blank", buffer);
if (argv)
{
// open the window
nsIDOMWindow *newWindow;
hiddenWindow->Open(jsContext, argv, 3, &newWindow);
newWindow->ResizeTo(width, height);
JS_PopArguments(jsContext, stackPtr);
}
}
}
return rv;
}
NS_IMETHODIMP
nsPSMUIHandlerImpl::PromptForFile(const PRUnichar *prompt, const char *fileRegEx, PRBool shouldFileExist, char **outFile)
{
NS_ENSURE_ARG_POINTER(outFile);
nsCOMPtr<nsIFilePicker> fp = do_CreateInstance("component://mozilla/filepicker");
if (!fp)
return NS_ERROR_NULL_POINTER;
fp->Init(nsnull, prompt, nsIFilePicker::modeOpen);
fp->SetFilters(nsIFilePicker::filterAll);
fp->AppendFilter(NS_ConvertASCIItoUCS2(fileRegEx).GetUnicode(), NS_ConvertASCIItoUCS2(fileRegEx).GetUnicode());
PRInt16 mode;
nsresult rv = fp->Show(&mode);
if (NS_FAILED(rv) || (mode == nsIFilePicker::returnCancel))
return rv;
nsCOMPtr<nsILocalFile> file;
rv = fp->GetFile(getter_AddRefs(file));
if (file)
file->GetPath(outFile);
return rv;
}
NS_METHOD
nsPSMUIHandlerImpl::CreatePSMUIHandler(nsISupports* aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv = NS_OK;
if ( aResult )
{
/* Allocate new find component object. */
nsPSMUIHandlerImpl *component = new nsPSMUIHandlerImpl();
if ( component )
{
/* Allocated OK, do query interface to get proper */
/* pointer and increment refcount. */
rv = component->QueryInterface( aIID, aResult );
if ( NS_FAILED( rv ) )
{
/* refcount still at zero, delete it here. */
delete component;
}
}
else
{
rv = NS_ERROR_OUT_OF_MEMORY;
}
}
else
{
rv = NS_ERROR_NULL_POINTER;
}
return rv;
}
extern "C" void CARTMAN_UIEventLoop(void *data)
{
CMT_EventLoop((PCMT_CONTROL)data);
}
PRStatus InitPSMUICallbacks(PCMT_CONTROL control)
{
if (!control)
return PR_FAILURE;
CMT_SetPromptCallback(control, (promptCallback_fn)PromptUserCallback, nsnull);
CMT_SetAppFreeCallback(control, (applicationFreeCallback_fn) ApplicationFreeCallback);
CMT_SetFilePathPromptCallback(control, (filePathPromptCallback_fn) FilePathPromptCallback, nsnull);
if (CMT_SetUIHandlerCallback(control, (uiHandlerCallback_fn) CartmanUIHandler, NULL) != CMTSuccess)
return PR_FAILURE;
PR_CreateThread(PR_USER_THREAD,
CARTMAN_UIEventLoop,
control,
PR_PRIORITY_NORMAL,
PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD,
0);
return PR_SUCCESS;
}
PRStatus DisplayPSMUIDialog(PCMT_CONTROL control, const char *pickledStatus, const char *hostName)
{
CMUint32 advRID = 0;
CMInt32 width = 0;
CMInt32 height = 0;
CMTItem urlItem = {0, NULL, 0};
CMTStatus rv = CMTSuccess;
CMTItem advisorContext = {0, NULL, 0};
void * pwin;
CMTSecurityAdvisorData data;
memset(&data, '\0', sizeof(CMTSecurityAdvisorData));
if (hostName)
{
// if there is a hostName, than this request is about
// a webpage.
data.hostname = (char*) hostName;
data.infoContext = SSM_BROWSER;
if (pickledStatus)
{
CMTItem pickledResource = {0, NULL, 0};
CMUint32 socketStatus = 0;
pickledResource.len = *(int*)(pickledStatus);
pickledResource.data = (unsigned char*) PR_Malloc(SSMSTRING_PADDED_LENGTH(pickledResource.len));
if (! pickledResource.data) return PR_FAILURE;
memcpy(pickledResource.data, pickledStatus+sizeof(int), pickledResource.len);
/* Unpickle the SSL Socket Status */
if (CMT_UnpickleResource( control,
SSM_RESTYPE_SSL_SOCKET_STATUS,
pickledResource,
&socketStatus) == CMTSuccess)
{
data.infoContext = SSM_BROWSER;
data.resID = socketStatus;
}
PR_FREEIF(pickledResource.data);
}
}
/* Create a Security Advisor context object. */
rv = CMT_SecurityAdvisor(control, &data, &advRID);
if (rv != CMTSuccess)
return PR_FAILURE;
/* Get the URL, width, height, etc. from the advisor context. */
rv = CMT_GetStringAttribute(control,
advRID,
SSM_FID_SECADVISOR_URL,
&urlItem);
if ((rv != CMTSuccess) || (!urlItem.data))
return PR_FAILURE;
rv = CMT_GetNumericAttribute(control,
advRID,
SSM_FID_SECADVISOR_WIDTH,
&width);
if (rv != CMTSuccess)
return PR_FAILURE;
rv = CMT_GetNumericAttribute(control,
advRID,
SSM_FID_SECADVISOR_HEIGHT,
&height);
if (rv != CMTSuccess)
return PR_FAILURE;
/* Fire the URL up in a window of its own. */
pwin = CartmanUIHandler(advRID, nsnull, width, height, PR_FALSE, (char*)urlItem.data, NULL);
//allocated by cmt, we can free with free:
free(urlItem.data);
return PR_SUCCESS;
}
void* CartmanUIHandler(uint32 resourceID, void* clientContext, uint32 width, uint32 height, PRBool isModal, char* urlStr, void *data)
{
nsresult rv = NS_OK;
NS_WITH_PROXIED_SERVICE(nsIPSMUIHandler, handler, nsPSMUIHandlerImpl::GetCID(), NS_UI_THREAD_EVENTQ, &rv);
if(NS_SUCCEEDED(rv))
handler->DisplayURI(width, height, urlStr);
return nsnull;
}
char * PromptUserCallback(void *arg, char *prompt, int isPasswd)
{
nsresult rv = NS_OK;
PRUnichar *password;
PRInt32 value;
NS_WITH_PROXIED_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, NS_UI_THREAD_EVENTQ, &rv);
if (NS_SUCCEEDED(rv)) {
rv = dialog->PromptPassword(NS_ConvertASCIItoUCS2(prompt).GetUnicode(), NS_ConvertASCIItoUCS2(" ").GetUnicode(), &password, &value);
if (NS_SUCCEEDED(rv)) {
nsString a(password);
char* str = a.ToNewCString();
Recycle(password);
return str;
}
}
return nsnull;
}
void ApplicationFreeCallback(char *userInput)
{
nsAllocator::Free(userInput);
}
char * FilePathPromptCallback(void *arg, char *prompt, char *fileRegEx, CMUint32 shouldFileExist)
{
nsresult rv = NS_OK;
char* filePath = nsnull;
NS_WITH_PROXIED_SERVICE(nsIPSMUIHandler, handler, nsPSMUIHandlerImpl::GetCID(), NS_UI_THREAD_EVENTQ, &rv);
if(NS_SUCCEEDED(rv))
handler->PromptForFile(NS_ConvertASCIItoUCS2(prompt).GetUnicode(), fileRegEx, (PRBool)shouldFileExist, &filePath);
return filePath;
}

View File

@@ -1,55 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#ifndef _NSPSMUICALLBACKS_H
#define _NSPSMUICALLBACKS_H
#include "prtypes.h"
#include "cmtcmn.h"
#include "nsIPSMUIHandler.h"
PRStatus InitPSMUICallbacks(PCMT_CONTROL gControl);
PRStatus DisplayPSMUIDialog(PCMT_CONTROL control, const char* pickledStatus, const char *hostName);
#define NS_PSMUIHANDLER_CID {0x15944e30, 0x601e, 0x11d3, {0x8c, 0x4a, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}}
class nsPSMUIHandlerImpl : public nsIPSMUIHandler
{
public:
NS_DEFINE_STATIC_CID_ACCESSOR( NS_PSMUIHANDLER_CID );
/* ctor/dtor */
nsPSMUIHandlerImpl() { NS_INIT_REFCNT(); }
virtual ~nsPSMUIHandlerImpl() { }
NS_DECL_ISUPPORTS
NS_DECL_NSIPSMUIHANDLER
static NS_METHOD CreatePSMUIHandler(nsISupports* aOuter, REFNSIID aIID, void **aResult);
};
#endif

View File

@@ -1,310 +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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* thayes@netscape.com
*/
#include "stdlib.h"
#include "plstr.h"
#include "nsIAllocator.h"
#include "nsIServiceManager.h"
#include "plbase64.h"
#include "nsISecretDecoderRing.h"
#include "cmtcmn.h"
#include "nsIPSMComponent.h"
#include "nsSDR.h"
NS_IMPL_ISUPPORTS1(nsSecretDecoderRing, nsISecretDecoderRing)
nsSecretDecoderRing::nsSecretDecoderRing()
{
NS_INIT_ISUPPORTS();
mPSM = NULL;
}
nsSecretDecoderRing::~nsSecretDecoderRing()
{
if (mPSM) mPSM->Release();
}
/* Init the new instance */
nsresult nsSecretDecoderRing::
init()
{
nsresult rv;
nsISupports *psm;
rv = nsServiceManager::GetService(kPSMComponentProgID, NS_GET_IID(nsIPSMComponent),
&psm);
if (rv != NS_OK) goto loser; /* Should promote error */
mPSM = (nsIPSMComponent *)psm;
loser:
return rv;
}
/* [noscript] long encrypt (in buffer data, in long dataLen, out buffer result); */
NS_IMETHODIMP nsSecretDecoderRing::
Encrypt(unsigned char * data, PRInt32 dataLen, unsigned char * *result, PRInt32 *_retval)
{
nsresult rv = NS_OK;
unsigned char *r = 0;
CMT_CONTROL *control;
CMTStatus status;
CMUint32 cLen;
if (data == nsnull || result == nsnull || _retval == nsnull) {
rv = NS_ERROR_INVALID_POINTER;
goto loser;
}
/* Check object initialization */
NS_ASSERTION(mPSM != nsnull, "SDR object not initialized");
if (mPSM == nsnull) { rv = NS_ERROR_NOT_INITIALIZED; goto loser; }
/* Get the control connect to use for the request */
rv = mPSM->GetControlConnection(&control);
if (rv != NS_OK) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
status = CMT_SDREncrypt(control, (const unsigned char *)0, 0,
data, dataLen, result, &cLen);
if (status != CMTSuccess) { rv = NS_ERROR_FAILURE; goto loser; } /* XXX */
/* Copy returned data to nsAllocator buffer ? */
*_retval = cLen;
loser:
return rv;
}
/* [noscript] long decrypt (in buffer data, in long dataLen, out buffer result); */
NS_IMETHODIMP nsSecretDecoderRing::
Decrypt(unsigned char * data, PRInt32 dataLen, unsigned char * *result, PRInt32 *_retval)
{
nsresult rv = NS_OK;
CMTStatus status;
CMT_CONTROL *control;
CMUint32 len;
if (data == nsnull || result == nsnull || _retval == nsnull) {
rv = NS_ERROR_INVALID_POINTER;
goto loser;
}
/* Check object initialization */
NS_ASSERTION(mPSM != nsnull, "SDR object not initialized");
if (mPSM == nsnull) { rv = NS_ERROR_NOT_INITIALIZED; goto loser; }
/* Get the control connection */
rv = mPSM->GetControlConnection(&control);
if (rv != NS_OK) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
/* Call PSM to decrypt the value */
status = CMT_SDRDecrypt(control, data, dataLen, result, &len);
if (status != CMTSuccess) { rv = NS_ERROR_FAILURE; goto loser; } /* Promote? */
/* Copy returned data to nsAllocator buffer ? */
*_retval = len;
loser:
return rv;
}
/* string encryptString (in string text); */
NS_IMETHODIMP nsSecretDecoderRing::
EncryptString(const char *text, char **_retval)
{
nsresult rv = NS_OK;
unsigned char *encrypted = 0;
PRInt32 eLen;
if (text == nsnull || _retval == nsnull) {
rv = NS_ERROR_INVALID_POINTER;
goto loser;
}
rv = Encrypt((unsigned char *)text, PL_strlen(text), &encrypted, &eLen);
if (rv != NS_OK) { goto loser; }
rv = encode(encrypted, eLen, _retval);
loser:
if (encrypted) nsAllocator::Free(encrypted);
return rv;
}
/* string decryptString (in string crypt); */
NS_IMETHODIMP nsSecretDecoderRing::
DecryptString(const char *crypt, char **_retval)
{
nsresult rv = NS_OK;
char *r = 0;
unsigned char *decoded = 0;
PRInt32 decodedLen;
unsigned char *decrypted = 0;
PRInt32 decryptedLen;
if (crypt == nsnull || _retval == nsnull) {
rv = NS_ERROR_INVALID_POINTER;
goto loser;
}
rv = decode(crypt, &decoded, &decodedLen);
if (rv != NS_OK) goto loser;
rv = Decrypt(decoded, decodedLen, &decrypted, &decryptedLen);
if (rv != NS_OK) goto loser;
// Convert to NUL-terminated string
r = (char *)nsAllocator::Alloc(decryptedLen+1);
if (!r) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; }
memcpy(r, decrypted, decryptedLen);
r[decryptedLen] = 0;
*_retval = r;
r = 0;
loser:
if (r) nsAllocator::Free(r);
if (decrypted) nsAllocator::Free(decrypted);
if (decoded) nsAllocator::Free(decoded);
return rv;
}
/* void changePassword(); */
NS_IMETHODIMP nsSecretDecoderRing::
ChangePassword()
{
return NS_OK;
}
/* void logout(); */
NS_IMETHODIMP nsSecretDecoderRing::
Logout()
{
nsresult rv = NS_OK;
CMTStatus status;
CMT_CONTROL *control;
/* Check object initialization */
NS_ASSERTION(mPSM != nsnull, "SDR object not initialized");
if (mPSM == nsnull) { rv = NS_ERROR_NOT_INITIALIZED; goto loser; }
/* Get the control connection */
rv = mPSM->GetControlConnection(&control);
if (rv != NS_OK) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
/* Call PSM to decrypt the value */
status = CMT_LogoutAllTokens(control);
if (status != CMTSuccess) { rv = NS_ERROR_FAILURE; goto loser; } /* Promote? */
loser:
return rv;
}
// Support routines
nsresult nsSecretDecoderRing::
encode(const unsigned char *data, PRInt32 dataLen, char **_retval)
{
nsresult rv = NS_OK;
*_retval = PL_Base64Encode((const char *)data, dataLen, NULL);
if (!*_retval) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; }
loser:
return rv;
#if 0
nsresult rv = NS_OK;
char *r = 0;
// Allocate space for encoded string (with NUL)
r = (char *)nsAllocator::Alloc(dataLen+1);
if (!r) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; }
memcpy(r, data, dataLen);
r[dataLen] = 0;
*_retval = r;
r = 0;
loser:
if (r) nsAllocator::Free(r);
return rv;
#endif
}
nsresult nsSecretDecoderRing::
decode(const char *data, unsigned char **result, PRInt32 * _retval)
{
nsresult rv = NS_OK;
PRUint32 len = PL_strlen(data);
int adjust = 0;
/* Compute length adjustment */
if (data[len-1] == '=') {
adjust++;
if (data[len-2] == '=') adjust++;
}
*result = (unsigned char *)PL_Base64Decode(data, len, NULL);
if (!*result) { rv = NS_ERROR_ILLEGAL_VALUE; goto loser; }
*_retval = (len*3)/4 - adjust;
loser:
return rv;
#if 0
nsresult rv = NS_OK;
unsigned char *r = 0;
PRInt32 rLen;
// Allocate space for decoded string (missing NUL)
rLen = PL_strlen(data);
r = (unsigned char *)nsAllocator::Alloc(rLen);
if (!r) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; }
memcpy(r, data, rLen);
*result = r;
r = 0;
*_retval = rLen;
loser:
if (r) nsAllocator::Free(r);
return rv;
#endif
}
const char * nsSecretDecoderRing::kPSMComponentProgID = PSM_COMPONENT_PROGID;

View File

@@ -1,58 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Terry Hayes <thayes@netscape.com>
*/
#ifndef _NSSDR_H_
#define _NSSDR_H_
#include "nsISecretDecoderRing.h"
// ===============================================
// nsSecretDecoderRing - implementation of nsISecretDecoderRing
// ===============================================
#define NS_SDR_CLASSNAME "Secret Decoder Ring"
#define NS_SDR_CID \
{ 0xd9a0341, 0xce7, 0x11d4, { 0x9f, 0xdd, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
#define NS_SDR_PROGID "netscape.security.sdr"
class nsSecretDecoderRing : public nsISecretDecoderRing
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISECRETDECODERRING
nsSecretDecoderRing();
virtual ~nsSecretDecoderRing();
nsresult init();
private:
nsIPSMComponent *mPSM;
static const char *kPSMComponentProgID;
nsresult encode(const unsigned char *data, PRInt32 dataLen, char **_retval);
nsresult decode(const char *data, unsigned char **result, PRInt32 * _retval);
};
#endif /* _NSSDR_H_ */

View File

@@ -1,432 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nspr.h"
#include "nsString.h"
#include "cmtcmn.h"
#include "nsIPSMComponent.h"
#include "nsIPSMSocketInfo.h"
#include "nsIServiceManager.h"
#include "nsPSMShimLayer.h"
#include "nsSSLIOLayer.h"
static PRDescIdentity nsSSLIOLayerIdentity;
static PRIOMethods nsSSLIOLayerMethods;
static nsIPSMComponent* gPSMService = nsnull;
class nsPSMSocketInfo : public nsIPSMSocketInfo
{
public:
nsPSMSocketInfo();
~nsPSMSocketInfo();
NS_DECL_ISUPPORTS
NS_DECL_NSIPSMSOCKETINFO
// internal functions to psm-glue.
nsresult SetSocketPtr(CMSocket *socketPtr);
nsresult SetControlPtr(CMT_CONTROL *aControlPtr);
nsresult SetFileDescPtr(PRFileDesc *aControlPtr);
nsresult SetHostName(char *aHostName);
protected:
CMT_CONTROL* mControl;
CMSocket* mSocket;
PRFileDesc* mFd;
nsString mHostName;
};
static PRStatus PR_CALLBACK
nsSSLIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
{
nsresult result;
PRStatus rv = PR_SUCCESS;
CMTStatus status = CMTFailure;
char* hostName;
/* Set the error in case of failure. */
PR_SetError(PR_UNKNOWN_ERROR, status);
if (!fd || !addr || !fd->secret)
return PR_FAILURE;
if (gPSMService == nsnull)
{
result = nsServiceManager::GetService( PSM_COMPONENT_PROGID,
NS_GET_IID(nsIPSMComponent),
(nsISupports**)&gPSMService); //FIX leak one per app run
if (NS_FAILED(result))
return PR_FAILURE;
}
// Make the socket non-blocking...
PRSocketOptionData opt;
opt.option = PR_SockOpt_Nonblocking;
opt.value.non_blocking = PR_FALSE;
rv = PR_SetSocketOption(fd->lower, &opt);
if (PR_SUCCESS != rv)
return PR_FAILURE;
char ipBuffer[PR_NETDB_BUF_SIZE];
rv = PR_NetAddrToString(addr, (char*)&ipBuffer, PR_NETDB_BUF_SIZE);
if (rv != PR_SUCCESS)
return PR_FAILURE;
if (addr->raw.family == PR_AF_INET6 && PR_IsNetAddrType(addr, PR_IpAddrV4Mapped))
{
/* Chop off the leading "::ffff:" */
strcpy(ipBuffer, ipBuffer + 7);
}
CMSocket* cmsock = (CMSocket *)PR_Malloc(sizeof(CMSocket));
if (!cmsock)
return PR_FAILURE;
memset(cmsock, 0, sizeof(CMSocket));
CMT_CONTROL *control;
result = gPSMService->GetControlConnection(&control);
if (result != PR_SUCCESS)
{
PR_FREEIF(cmsock)
return PR_FAILURE;
}
cmsock->fd = fd->lower;
cmsock->isUnix = PR_FALSE;
nsPSMSocketInfo *infoObject = (nsPSMSocketInfo *)fd->secret;
infoObject->GetHostName(&hostName);
infoObject->SetControlPtr(control);
infoObject->SetSocketPtr(cmsock);
status = CMT_OpenSSLConnection(control,
cmsock,
SSM_REQUEST_SSL_DATA_SSL,
PR_ntohs(addr->inet.port),
ipBuffer,
(hostName ? hostName : ipBuffer),
CM_FALSE,
nsnull);
if (CMTSuccess == status)
{
// since our stuff can block, what we want to do is return PR_FAILURE,
// but set the nspr ERROR to BLOCK. This will put us into a select
// q.
PR_SetError(PR_WOULD_BLOCK_ERROR, status);
return PR_FAILURE;
}
return PR_FAILURE;
}
/* CMT_DestroyDataConnection(ctrl, sock); */
/* need to strip our layer, pass result to DestroyDataConnection */
/* which will clean up the CMT accounting of sock, then call our */
/* shim layer to translate back to NSPR */
static PRStatus PR_CALLBACK
nsSSLIOLayerClose(PRFileDesc *fd)
{
nsPSMSocketInfo *infoObject = (nsPSMSocketInfo *)fd->secret;
PRDescIdentity id = PR_GetLayersIdentity(fd);
if (infoObject && id == nsSSLIOLayerIdentity)
{
CMInt32 errorCode = PR_FAILURE;
CMT_CONTROL* control;
CMSocket* socket;
infoObject->GetControlPtr(&control);
infoObject->GetSocketPtr(&socket);
if (((PRStatus) CMT_GetSSLDataErrorCode(control, socket, &errorCode)) == PR_SUCCESS)
{
CMT_DestroyDataConnection(control, socket);
NS_RELEASE(infoObject);
fd->identity = PR_INVALID_IO_LAYER;
}
return (PRStatus)errorCode;
}
return PR_FAILURE;
}
static PRInt32 PR_CALLBACK
nsSSLIOLayerRead( PRFileDesc *fd, void *buf, PRInt32 amount)
{
if (!fd)
return PR_FAILURE;
PRInt32 result = PR_Recv(fd, buf, amount, 0, PR_INTERVAL_MIN);
if (result > 0)
return result;
if (result == -1)
{
PRErrorCode code = PR_GetError();
if (code == PR_IO_TIMEOUT_ERROR )
PR_SetError(PR_WOULD_BLOCK_ERROR, PR_WOULD_BLOCK_ERROR);
return PR_FAILURE;
}
if (result == 0)
{
nsPSMSocketInfo *infoObject = (nsPSMSocketInfo *)fd->secret;
PRDescIdentity id = PR_GetLayersIdentity(fd);
if (infoObject && id == nsSSLIOLayerIdentity)
{
CMInt32 errorCode = PR_FAILURE;
CMT_CONTROL* control;
CMSocket* socket;
infoObject->GetControlPtr(&control);
infoObject->GetSocketPtr(&socket);
CMT_GetSSLDataErrorCode(control, socket, &errorCode);
if (errorCode == PR_IO_TIMEOUT_ERROR)
{
PR_SetError(PR_WOULD_BLOCK_ERROR, PR_WOULD_BLOCK_ERROR);
return PR_FAILURE;
}
PR_SetError(0, 0);
return errorCode;
}
}
return result;
}
static PRInt32 PR_CALLBACK
nsSSLIOLayerWrite( PRFileDesc *fd, const void *buf, PRInt32 amount)
{
if (!fd)
return PR_FAILURE;
PRInt32 result = PR_Send(fd, buf, amount, 0, PR_INTERVAL_MIN);
if (result > 0)
return result;
if (result == -1)
{
PRErrorCode code = PR_GetError();
if (code == PR_IO_TIMEOUT_ERROR )
PR_SetError(PR_WOULD_BLOCK_ERROR, PR_WOULD_BLOCK_ERROR);
return PR_FAILURE;
}
if (result == 0)
{
nsPSMSocketInfo *infoObject = (nsPSMSocketInfo *)fd->secret;
PRDescIdentity id = PR_GetLayersIdentity(fd);
if (infoObject && id == nsSSLIOLayerIdentity)
{
CMInt32 errorCode = PR_FAILURE;
CMT_CONTROL* control;
CMSocket* socket;
infoObject->GetControlPtr(&control);
infoObject->GetSocketPtr(&socket);
CMT_GetSSLDataErrorCode(control, socket, &errorCode);
PR_SetError(0, 0);
return errorCode;
}
}
return result;
}
nsPSMSocketInfo::nsPSMSocketInfo()
{
NS_INIT_REFCNT();
mControl = nsnull;
mSocket = nsnull;
}
nsPSMSocketInfo::~nsPSMSocketInfo()
{
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsPSMSocketInfo, nsIPSMSocketInfo);
NS_IMETHODIMP
nsPSMSocketInfo::GetControlPtr(CMT_CONTROL * *aControlPtr)
{
*aControlPtr = mControl;
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetControlPtr(CMT_CONTROL *aControlPtr)
{
mControl = aControlPtr;
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetSocketPtr(CMSocket * *socketPtr)
{
*socketPtr = mSocket;
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetSocketPtr(CMSocket *socketPtr)
{
mSocket = socketPtr;
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetFileDescPtr(PRFileDesc * *aFilePtr)
{
*aFilePtr = mFd;
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetFileDescPtr(PRFileDesc *aFilePtr)
{
mFd = aFilePtr;
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetHostName(char * *aHostName)
{
*aHostName = mHostName.ToNewCString();
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetHostName(char *aHostName)
{
mHostName.AssignWithConversion(aHostName);
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetPickledStatus(char * *pickledStatusString)
{
*pickledStatusString = nsnull;
if (mSocket && mControl)
{
long level;
CMTItem pickledStatus = {0, nsnull, 0};
unsigned char* ret = nsnull;
if (CMT_GetSSLSocketStatus(mControl, mSocket, &pickledStatus, &level) == PR_FAILURE)
return nsnull;
ret = (unsigned char*) PR_Malloc( (SSMSTRING_PADDED_LENGTH(pickledStatus.len) + sizeof(int)) );
if (!ret)
return NS_ERROR_OUT_OF_MEMORY;
*(int*)ret = pickledStatus.len;
memcpy(ret+sizeof(int), pickledStatus.data, *(int*)ret);
PR_FREEIF(pickledStatus.data);
*pickledStatusString = (char*) ret;
}
return NS_OK;
}
nsresult
nsSSLIOLayerNewSocket(const char* hostName, PRFileDesc **fd, nsISupports** info)
{
static PRBool firstTime = PR_TRUE;
if (firstTime)
{
nsSSLIOLayerIdentity = PR_GetUniqueIdentity("Cartman layer");
nsSSLIOLayerMethods = *PR_GetDefaultIOMethods();
nsSSLIOLayerMethods.connect = nsSSLIOLayerConnect;
nsSSLIOLayerMethods.close = nsSSLIOLayerClose;
nsSSLIOLayerMethods.read = nsSSLIOLayerRead;
nsSSLIOLayerMethods.write = nsSSLIOLayerWrite;
firstTime = PR_FALSE;
}
PRFileDesc * sock;
PRFileDesc * layer;
PRStatus rv;
/* Get a normal NSPR socket */
sock = PR_NewTCPSocket();
if (! sock) return NS_ERROR_OUT_OF_MEMORY;
layer = PR_CreateIOLayerStub(nsSSLIOLayerIdentity, &nsSSLIOLayerMethods);
if (! layer)
{
PR_Close(sock);
return NS_ERROR_FAILURE;
}
nsPSMSocketInfo *infoObject = new nsPSMSocketInfo();
if (!infoObject)
{
PR_Close(sock);
// clean up IOLayerStub.
return NS_ERROR_FAILURE;
}
NS_ADDREF(infoObject);
infoObject->SetHostName((char*)hostName);
layer->secret = (PRFilePrivate*) infoObject;
rv = PR_PushIOLayer(sock, PR_GetLayersIdentity(sock), layer);
if (rv == PR_SUCCESS)
{
*fd = sock;
*info = infoObject;
NS_ADDREF(*info);
return NS_OK;
}
PR_Close(sock);
return NS_ERROR_FAILURE;
}

View File

@@ -1,37 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef _NSSSLIOLAYER_H
#define _NSSSLIOLAYER_H
#include "prtypes.h"
#include "prio.h"
#include "nsIPSMSocketInfo.h"
// define taken from 4.x cartman glue code.
#define SSMSTRING_PADDED_LENGTH(x) ((((x)+3)/4)*4)
nsresult nsSSLIOLayerNewSocket(const char* hostName, PRFileDesc **fd, nsISupports **securityInfo);
#endif /* _NSSSLIOLAYER_H */

View File

@@ -1,83 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsSSLSocketProvider.h"
#include "nsSSLIOLayer.h"
////////////////////////////////////////////////////////////////////////////////
nsSSLSocketProvider::nsSSLSocketProvider()
{
NS_INIT_REFCNT();
}
nsresult
nsSSLSocketProvider::Init()
{
nsresult rv = NS_OK;
return rv;
}
nsSSLSocketProvider::~nsSSLSocketProvider()
{
}
NS_IMPL_THREADSAFE_ISUPPORTS2(nsSSLSocketProvider, nsISocketProvider, nsISSLSocketProvider);
NS_METHOD
nsSSLSocketProvider::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv;
nsSSLSocketProvider * inst;
if (NULL == aResult) {
rv = NS_ERROR_NULL_POINTER;
return rv;
}
*aResult = NULL;
if (NULL != aOuter) {
rv = NS_ERROR_NO_AGGREGATION;
return rv;
}
NS_NEWXPCOM(inst, nsSSLSocketProvider);
if (NULL == inst) {
rv = NS_ERROR_OUT_OF_MEMORY;
return rv;
}
NS_ADDREF(inst);
rv = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return rv;
}
NS_IMETHODIMP
nsSSLSocketProvider::NewSocket(const char *hostName, PRFileDesc **_result, nsISupports **securityInfo)
{
nsresult rv = nsSSLIOLayerNewSocket(hostName, _result, securityInfo);
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
}

View File

@@ -1,54 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef _NSSSLSOCKETPROVIDER_H_
#define _NSSSLSOCKETPROVIDER_H_
#include "nsISSLSocketProvider.h"
/* 274418d0-5437-11d3-bbc8-0000861d1237 */
#define NS_SSLSOCKETPROVIDER_CID { 0x274418d0, 0x5437, 0x11d3, {0xbb, 0xc8, 0x00, 0x00, 0x86, 0x1d, 0x12, 0x37}}
class nsSSLSocketProvider : public nsISSLSocketProvider
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISOCKETPROVIDER
NS_DECL_NSISSLSOCKETPROVIDER
// nsSSLSocketProvider methods:
nsSSLSocketProvider();
virtual ~nsSSLSocketProvider();
static NS_METHOD
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
nsresult Init();
protected:
};
#endif /* _NSSSLSOCKETPROVIDER_H_ */

View File

@@ -1,619 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nspr.h"
#include "prlog.h"
#include "nsISecureBrowserUI.h"
#include "nsSecureBrowserUIImpl.h"
#include "nsIPSMComponent.h"
#include "nsPSMComponent.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsIScriptGlobalObject.h"
#include "nsIObserverService.h"
#include "nsIDocumentLoader.h"
#include "nsCURILoader.h"
#include "nsIDocShell.h"
#include "nsIDocumentViewer.h"
#include "nsCURILoader.h"
#include "nsIDocument.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMXULDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMWindow.h"
#include "nsIWebProgress.h"
#include "nsIChannel.h"
#include "nsIPSMSocketInfo.h"
#include "nsIURI.h"
#include "prmem.h"
#include "nsINetSupportDialogService.h"
#include "nsIPrompt.h"
#include "nsICommonDialogs.h"
#include "nsIPref.h"
#include "nsIFormSubmitObserver.h"
static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
static NS_DEFINE_CID(kCommonDialogsCID, NS_CommonDialog_CID );
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
#define ENTER_SITE_PREF "security.warn_entering_secure"
#define LEAVE_SITE_PREF "security.warn_leaving_secure"
#define MIXEDCONTENT_PREF "security.warn_viewing_mixed"
#define INSECURE_SUBMIT_PREF "security.warn_submit_insecure"
#if defined(PR_LOGGING)
//
// Log module for nsSecureBroswerUI logging...
//
// To enable logging (see prlog.h for full details):
//
// set NSPR_LOG_MODULES=nsSecureBroswerUI:5
// set NSPR_LOG_FILE=nspr.log
//
// this enables PR_LOG_DEBUG level information and places all output in
// the file nspr.log
//
PRLogModuleInfo* gSecureDocLog = nsnull;
#endif /* PR_LOGGING */
NS_IMETHODIMP
nsSecureBrowserUIImpl::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv;
nsSecureBrowserUIImpl * inst;
if (NULL == aResult) {
rv = NS_ERROR_NULL_POINTER;
return rv;
}
*aResult = NULL;
if (NULL != aOuter) {
rv = NS_ERROR_NO_AGGREGATION;
return rv;
}
NS_NEWXPCOM(inst, nsSecureBrowserUIImpl);
if (NULL == inst) {
rv = NS_ERROR_OUT_OF_MEMORY;
return rv;
}
NS_ADDREF(inst);
rv = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return rv;
}
nsSecureBrowserUIImpl::nsSecureBrowserUIImpl()
{
NS_INIT_REFCNT();
#if defined(PR_LOGGING)
if (nsnull == gSecureDocLog) {
gSecureDocLog = PR_NewLogModule("nsSecureBroswerUI");
}
#endif /* PR_LOGGING */
mIsSecureDocument = mMixContentAlertShown = mIsDocumentBroken = PR_FALSE;
mLastPSMStatus = nsnull;
mCurrentURI = nsnull;
mSecurityButton = nsnull;
}
nsSecureBrowserUIImpl::~nsSecureBrowserUIImpl()
{
PR_FREEIF(mLastPSMStatus);
}
NS_IMPL_ISUPPORTS4(nsSecureBrowserUIImpl,
nsSecureBrowserUI,
nsIWebProgressListener,
nsIFormSubmitObserver,
nsIObserver);
NS_IMETHODIMP
nsSecureBrowserUIImpl::Init(nsIDOMWindow *window, nsIDOMElement *button)
{
mSecurityButton = button;
mWindow = window;
nsresult rv = nsServiceManager::GetService( kPrefCID,
NS_GET_IID(nsIPref),
getter_AddRefs(mPref));
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIStringBundleService, service, kCStringBundleServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsILocale* locale = nsnull;
rv = service->CreateBundle(SECURITY_STRING_BUNDLE_URL, locale, getter_AddRefs(mStringBundle));
if (NS_FAILED(rv)) return rv;
// hook up to the form post notifications:
nsIObserverService *svc = 0;
rv = nsServiceManager::GetService(NS_OBSERVERSERVICE_PROGID,
NS_GET_IID(nsIObserverService),
(nsISupports**)&svc );
if ( NS_SUCCEEDED( rv ) && svc )
{
nsString topic; topic.AssignWithConversion(NS_FORMSUBMIT_SUBJECT);
rv = svc->AddObserver( this, topic.GetUnicode());
nsServiceManager::ReleaseService( NS_OBSERVERSERVICE_PROGID, svc );
}
// hook up to the webprogress notifications.
nsCOMPtr<nsIDocShell> docShell;
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
if (!sgo) return NS_ERROR_NULL_POINTER;
sgo->GetDocShell(getter_AddRefs(docShell));
if (!docShell) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIWebProgress> wp = do_QueryInterface(docShell);
if (!wp) return NS_ERROR_NULL_POINTER;
wp->AddProgressListener(NS_STATIC_CAST(nsIWebProgressListener*,this));
// Set up stuff the first time the window loads:
docShell->GetCurrentURI(getter_AddRefs(mCurrentURI));
return IsURLHTTPS(mCurrentURI, &mIsSecureDocument);
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::DisplayPageInfoUI()
{
nsresult res;
NS_WITH_SERVICE(nsIPSMComponent, psm, PSM_COMPONENT_PROGID, &res);
if (NS_FAILED(res))
return res;
nsXPIDLCString temp;
mCurrentURI->GetHost(getter_Copies(temp));
return psm->DisplaySecurityAdvisor(mLastPSMStatus, temp);
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::Observe(nsISupports*, const PRUnichar*, const PRUnichar*)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::Notify(nsIContent* formNode, nsIDOMWindow* window, nsIURI* actionURL)
{
// Return NS_OK unless we want to prevent this form from submitting.
if (!window || (mWindow.get() != window) || !actionURL) {
return NS_OK;
}
PRBool okayToPost;
nsresult res = CheckPost(actionURL, &okayToPost);
// Return NS_OK unless we want to prevent this form from submitting.
if (NS_SUCCEEDED(res) && okayToPost)
return NS_OK;
return NS_ERROR_FAILURE;
}
// nsIWebProgressListener
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnProgressChange(nsIChannel* aChannel,
PRInt32 aCurSelfProgress,
PRInt32 aMaxSelfProgress,
PRInt32 aCurTotalProgress,
PRInt32 aMaxTotalProgress)
{
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnChildProgressChange(nsIChannel* aChannel,
PRInt32 aCurSelfProgress,
PRInt32 aMaxSelfProgress)
{
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnStatusChange(nsIChannel* aChannel,
PRInt32 aProgressStatusFlags)
{
nsresult res;
if (aChannel == nsnull || !mSecurityButton || !mPref)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIURI> loadingURI;
aChannel->GetURI(getter_AddRefs(loadingURI));
#if defined(DEBUG)
nsXPIDLCString temp;
loadingURI->GetSpec(getter_Copies(temp));
PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI:%p: OnStatusChange: %x :%s\n", this, aProgressStatusFlags,(const char*)temp));
#endif
if (aProgressStatusFlags & nsIWebProgress::flag_net_start)
{
// starting to load a webpage
PR_FREEIF(mLastPSMStatus); mLastPSMStatus = nsnull;
mIsSecureDocument = mMixContentAlertShown = mIsDocumentBroken = PR_FALSE;
res = CheckProtocolContextSwitch( loadingURI, mCurrentURI);
}
else if ((aProgressStatusFlags & nsIWebProgress::flag_net_stop) && mIsSecureDocument)
{
if (!mIsDocumentBroken) // and status is okay FIX
{
// qi for the psm information about this channel load.
nsCOMPtr<nsISupports> info;
aChannel->GetSecurityInfo(getter_AddRefs(info));
nsCOMPtr<nsIPSMSocketInfo> psmInfo = do_QueryInterface(info);
if ( psmInfo )
{
// Everything looks okay. Lets stash the picked status.
PR_FREEIF(mLastPSMStatus);
res = psmInfo->GetPickledStatus(&mLastPSMStatus);
if (NS_SUCCEEDED(res))
{
PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI:%p: Icon set to lock\n", this));
res = mSecurityButton->SetAttribute( NS_ConvertASCIItoUCS2("level"), NS_ConvertASCIItoUCS2("high") );
}
}
}
else
{
PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI:%p: Icon set to broken\n", this));
mIsDocumentBroken = PR_TRUE;
res = mSecurityButton->SetAttribute( NS_ConvertASCIItoUCS2("level"), NS_ConvertASCIItoUCS2("broken") );
}
}
else // if (aProgressStatusFlags == nsIWebProgress::flag_net_redirecting)
{
res = NS_ERROR_NOT_IMPLEMENTED;
// xxx need to fix.
}
return res;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnChildStatusChange(nsIChannel* aChannel, PRInt32 aProgressStatusFlags)
{
nsresult rv;
if (aChannel == nsnull || !mSecurityButton || !mPref)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIURI> uri;
rv = aChannel->GetURI(getter_AddRefs(uri));
if (NS_FAILED(rv)) return rv;
#if defined(DEBUG)
nsXPIDLCString temp;
uri->GetSpec(getter_Copies(temp));
PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI:%p: OnChildStatusChange: %x :%s\n", this, aProgressStatusFlags,(const char*)temp));
#endif
// don't need to do anything more if the page is broken or not secure...
if (!mIsSecureDocument || mIsDocumentBroken)
return NS_OK;
if (aProgressStatusFlags & nsIWebProgress::flag_net_start)
{ // check to see if we are going to mix content.
return CheckMixedContext(uri);
}
if (aProgressStatusFlags & nsIWebProgress::flag_net_stop)
{
if (1) // FIX status from the flag...
{
nsCOMPtr<nsISupports> info;
aChannel->GetSecurityInfo(getter_AddRefs(info));
nsCOMPtr<nsIPSMSocketInfo> psmInfo = do_QueryInterface(info, &rv);
// qi for the psm information about this channel load.
if ( psmInfo )
{
return NS_OK;
}
}
PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI:%p: OnChildStatusChange - Icon set to broken\n", this));
mSecurityButton->SetAttribute( NS_ConvertASCIItoUCS2("level"), NS_ConvertASCIItoUCS2("broken") );
mIsDocumentBroken = PR_TRUE;
}
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnLocationChange(nsIURI* aLocation)
{
mCurrentURI = aLocation;
return NS_OK;
}
nsresult
nsSecureBrowserUIImpl::IsURLHTTPS(nsIURI* aURL, PRBool* value)
{
*value = PR_FALSE;
if (!aURL)
return NS_OK;
char* scheme;
aURL->GetScheme(&scheme);
if (scheme == nsnull)
return NS_ERROR_NULL_POINTER;
if ( PL_strncasecmp(scheme, "https", 5) == 0 )
*value = PR_TRUE;
nsAllocator::Free(scheme);
return NS_OK;
}
void nsSecureBrowserUIImpl::GetBundleString(const nsString& name, nsString &outString)
{
if (mStringBundle && name.Length() > 0)
{
PRUnichar *ptrv = nsnull;
if (NS_SUCCEEDED(mStringBundle->GetStringFromName(name.GetUnicode(), &ptrv)))
outString = ptrv;
else
outString.SetLength(0);;
nsAllocator::Free(ptrv);
}
else
{
outString.SetLength(0);;
}
}
nsresult
nsSecureBrowserUIImpl::CheckProtocolContextSwitch( nsIURI* newURI, nsIURI* oldURI)
{
nsresult res;
PRBool isNewSchemeSecure, isOldSchemeSecure, boolpref;
res = IsURLHTTPS(oldURI, &isOldSchemeSecure);
if (NS_FAILED(res))
return res;
res = IsURLHTTPS(newURI, &isNewSchemeSecure);
if (NS_FAILED(res))
return res;
// Check to see if we are going from a secure page to and insecure page
if ( !isNewSchemeSecure && isOldSchemeSecure)
{
mSecurityButton->RemoveAttribute( NS_ConvertASCIItoUCS2("level") );
if ((mPref->GetBoolPref(LEAVE_SITE_PREF, &boolpref) != 0))
boolpref = PR_TRUE;
if (boolpref)
{
NS_WITH_SERVICE(nsICommonDialogs, dialog, kCommonDialogsCID, &res);
if (NS_FAILED(res))
return res;
nsAutoString windowTitle, message, dontShowAgain;
GetBundleString(NS_ConvertASCIItoUCS2("Title"), windowTitle);
GetBundleString(NS_ConvertASCIItoUCS2("LeaveSiteMessage"), message);
GetBundleString(NS_ConvertASCIItoUCS2("DontShowAgain"), dontShowAgain);
PRBool outCheckValue = PR_TRUE;
dialog->AlertCheck(mWindow,
windowTitle.GetUnicode(),
message.GetUnicode(),
dontShowAgain.GetUnicode(),
&outCheckValue);
if (!outCheckValue)
{
mPref->SetBoolPref(LEAVE_SITE_PREF, PR_FALSE);
NS_WITH_SERVICE(nsIPSMComponent, psm, PSM_COMPONENT_PROGID, &res);
if (NS_FAILED(res))
return res;
psm->PassPrefs();
}
}
}
// check to see if we are going from an insecure page to a secure one.
else if (isNewSchemeSecure && !isOldSchemeSecure)
{
if ((mPref->GetBoolPref(ENTER_SITE_PREF, &boolpref) != 0))
boolpref = PR_TRUE;
if (boolpref)
{
NS_WITH_SERVICE(nsICommonDialogs, dialog, kCommonDialogsCID, &res);
if (NS_FAILED(res))
return res;
nsAutoString windowTitle, message, dontShowAgain;
GetBundleString(NS_ConvertASCIItoUCS2("Title"), windowTitle);
GetBundleString(NS_ConvertASCIItoUCS2("EnterSiteMessage"), message);
GetBundleString(NS_ConvertASCIItoUCS2("DontShowAgain"), dontShowAgain);
PRBool outCheckValue = PR_TRUE;
dialog->AlertCheck(mWindow,
windowTitle.GetUnicode(),
message.GetUnicode(),
dontShowAgain.GetUnicode(),
&outCheckValue);
if (!outCheckValue)
{
mPref->SetBoolPref(ENTER_SITE_PREF, PR_FALSE);
NS_WITH_SERVICE(nsIPSMComponent, psm, PSM_COMPONENT_PROGID, &res);
if (NS_FAILED(res))
return res;
psm->PassPrefs();
}
}
}
mIsSecureDocument = isNewSchemeSecure;
return NS_OK;
}
nsresult
nsSecureBrowserUIImpl::CheckMixedContext(nsIURI* nextURI)
{
PRBool secure;
nsresult rv = IsURLHTTPS(nextURI, &secure);
if (NS_FAILED(rv))
return rv;
if (!secure && mIsSecureDocument)
{
mIsDocumentBroken = PR_TRUE;
mSecurityButton->SetAttribute( NS_ConvertASCIItoUCS2("level"), NS_ConvertASCIItoUCS2("broken") );
if (!mPref) return NS_ERROR_NULL_POINTER;
PRBool boolpref;
if ((mPref->GetBoolPref(MIXEDCONTENT_PREF, &boolpref) != 0))
boolpref = PR_TRUE;
if (boolpref && !mMixContentAlertShown)
{
NS_WITH_SERVICE(nsICommonDialogs, dialog, kCommonDialogsCID, &rv);
if (NS_FAILED(rv))
return rv;
nsAutoString windowTitle, message, dontShowAgain;
GetBundleString(NS_ConvertASCIItoUCS2("Title"), windowTitle);
GetBundleString(NS_ConvertASCIItoUCS2("MixedContentMessage"), message);
GetBundleString(NS_ConvertASCIItoUCS2("DontShowAgain"), dontShowAgain);
PRBool outCheckValue = PR_TRUE;
dialog->AlertCheck(mWindow,
windowTitle.GetUnicode(),
message.GetUnicode(),
dontShowAgain.GetUnicode(),
&outCheckValue);
if (!outCheckValue)
{
mPref->SetBoolPref(MIXEDCONTENT_PREF, PR_FALSE);
NS_WITH_SERVICE(nsIPSMComponent, psm, PSM_COMPONENT_PROGID, &rv);
if (NS_FAILED(rv))
return rv;
psm->PassPrefs();
}
mMixContentAlertShown = PR_TRUE;
}
}
return NS_OK;
}
nsresult
nsSecureBrowserUIImpl::CheckPost(nsIURI *actionURL, PRBool *okayToPost)
{
PRBool secure;
nsresult rv = IsURLHTTPS(actionURL, &secure);
if (NS_FAILED(rv))
return rv;
if (!secure && mIsSecureDocument)
{
PRBool boolpref;
// posting to a non https URL.
if ((mPref->GetBoolPref(INSECURE_SUBMIT_PREF, &boolpref) != 0))
boolpref = PR_TRUE;
if (boolpref)
{
NS_WITH_SERVICE(nsICommonDialogs, dialog, kCommonDialogsCID, &rv);
if (NS_FAILED(rv))
return rv;
nsAutoString windowTitle, message, dontShowAgain;
GetBundleString(NS_ConvertASCIItoUCS2("Title"), windowTitle);
GetBundleString(NS_ConvertASCIItoUCS2("PostToInsecure"), message);
GetBundleString(NS_ConvertASCIItoUCS2("DontShowAgain"), dontShowAgain);
PRBool outCheckValue = PR_TRUE;
dialog->ConfirmCheck(mWindow,
windowTitle.GetUnicode(),
message.GetUnicode(),
dontShowAgain.GetUnicode(),
&outCheckValue,
okayToPost);
if (!outCheckValue)
{
mPref->SetBoolPref(INSECURE_SUBMIT_PREF, PR_FALSE);
NS_WITH_SERVICE(nsIPSMComponent, psm, PSM_COMPONENT_PROGID, &rv);
if (NS_FAILED(rv))
return rv;
psm->PassPrefs();
}
}
}
return NS_OK;
}

View File

@@ -1,99 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#ifndef nsSecureBrowserUIImpl_h_
#define nsSecureBrowserUIImpl_h_
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsString.h"
#include "nsIObserver.h"
#include "nsIDocumentLoaderObserver.h"
#include "nsIDOMElement.h"
#include "nsIDOMWindow.h"
#include "nsIStringBundle.h"
#include "nsISecureBrowserUI.h"
#include "nsIDocShell.h"
#include "nsIPref.h"
#include "nsIWebProgressListener.h"
#include "nsIFormSubmitObserver.h"
#include "nsIURI.h"
#define NS_SECURE_BROWSER_DOCOBSERVER_CLASSNAME "Mozilla Secure Browser Doc Observer"
#define NS_SECURE_BROWSER_DOCOBSERVER_CID \
{0x97c06c30, 0xa145, 0x11d3, \
{0x8c, 0x7c, 0x00, 0x60, 0x97, 0x92, 0x27, 0x8c}}
#define NS_SECURE_BROWSER_DOCOBSERVER_PROGID "component://netscape/secure_browser_docobserver"
class nsSecureBrowserUIImpl : public nsSecureBrowserUI,
public nsIWebProgressListener,
public nsIFormSubmitObserver,
public nsIObserver
{
public:
nsSecureBrowserUIImpl();
virtual ~nsSecureBrowserUIImpl();
static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSSECUREBROWSERUI
// nsIObserver
NS_DECL_NSIOBSERVER
NS_IMETHOD Notify(nsIContent* formNode, nsIDOMWindow* window, nsIURI *actionURL);
protected:
nsCOMPtr<nsIDOMWindow> mWindow;
nsCOMPtr<nsIDOMElement> mSecurityButton;
nsCOMPtr<nsIDocumentLoaderObserver> mOldWebShellObserver;
nsCOMPtr<nsIPref> mPref;
nsCOMPtr<nsIStringBundle> mStringBundle;
nsCOMPtr<nsIURI> mCurrentURI;
PRBool mIsSecureDocument; // is https loaded
PRBool mIsDocumentBroken; //
PRBool mMixContentAlertShown;
char* mLastPSMStatus;
void GetBundleString(const nsString& name, nsString &outString);
nsresult CheckProtocolContextSwitch( nsIURI* newURI, nsIURI* oldURI);
nsresult CheckMixedContext(nsIURI* nextURI);
nsresult CheckPost(nsIURI *actionURL, PRBool *okayToPost);
nsresult IsURLHTTPS(nsIURI* aURL, PRBool *value);
};
#endif /* nsSecureBrowserUIImpl_h_ */

View File

@@ -1,31 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = psm
include $(topsrcdir)/config/rules.mk

View File

@@ -1,27 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..
include <$(DEPTH)/config/config.mak>
DIRS = psm
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,31 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = lib
include $(topsrcdir)/config/rules.mk

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,502 +0,0 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.7 [en] (WinNT; U) [Netscape]">
<title>Javascript API for Client Certificate Management</title>
</head>
<body>
&nbsp;
<table WIDTH="100%" >
<tr>
<td>
<h1>
<font face="Arial,Helvetica">Personal Security Manager 1.0</font></h1>
<h2>
<font face="Arial,Helvetica">JavaScript API for Client Certificate Management</font></h2>
</td>
</tr>
</table>
Version 0.3 - 10/27/1999
<br>Comments to: <a href="mailto:psmfeedback@netscape.com?subject=JavaScript%20API%20Feedback">psmfeedback@netscape.com</a>
<p>This document describes a new JavaScript API for performing user certificate
management operations within a client. The JavaScript runs in the context
of a web page operated by a Certificate Authority (CA) or Registration
Authority (RA). The API allows the CA or RA to instruct the client to perform
PKI operations such as key generation, certificate request generation,
key escrow, import of user certificates, key recovery, and revocation requests.
<p>These properties and methods reflect behavior currently implemented
in Personal Security Manager 1.0.
<p>The messages imported by or generated by these JavaScript methods are
defined in the CRMF, CMMF, and CMC internet drafts.
<h2>
<font face="Arial,Helvetica">Overview of New Cert Issuing Process</font></h2>
<ol>
<li>
User fills out enrollment form</li>
<li>
User action initiates script</li>
<li>
Script calls key generation method</li>
<li>
Signing and Encryption keys are generated</li>
<li>
Encryption Private Key is wrapped with public key of Key Recovery Authority
(KRA) (passed in in the form of a certificate as part of the script, and
checked against a pre-installed certificate copy in the local certificate
database)</li>
<li>
The public keys, wrapped encryption private key, and text string from the
script (possibly containing naming or enrollment info) are signed by the
user</li>
<li>
Signed blob is returned to the script</li>
<li>
Script submits signed blob and any other necessary info to the CA/RA</li>
<li>
CA/RA verifies signature on signed blob</li>
<li>
CA/RA validates identity of user</li>
<li>
CA/RA sends wrapped encryption private key to KRA</li>
<li>
KRA sends escrow verification back to CA</li>
<li>
CA creates and signs certificates</li>
<li>
CA sends certificates back to Communicator</li>
</ol>
<h2>
<font face="Arial,Helvetica">JavaScript API</font></h2>
<h3>
<font face="Arial,Helvetica">Properties</font></h3>
<tt>crypto.algorithms.dh.keySizes</tt>
<br><tt>crypto.algorithms.dsa.keySizes</tt>
<br><tt>crypto.algorithms.rsa.signing.keySizes</tt>
<br><tt>crypto.algorithms.rsa.keyEx.keySizes</tt>
<p><tt>keySizes</tt> is an an array that describes the available key sizes
for the particular algorithms and operations.
<p>The table below describes the key sizes that will be supported in the
US and Export versions of Communicator.
<br>&nbsp;
<table BORDER WIDTH="100%" >
<tr>
<td ALIGN=CENTER><b>Algorithm</b></td>
<td ALIGN=CENTER><b>US Version Key Sizes</b></td>
<td ALIGN=CENTER><b>Export Version Key Sizes</b></td>
</tr>
<tr>
<td>DSA Signing Only</td>
<td>1024, 2048</td>
<td>1024, 2048</td>
</tr>
<tr>
<td>RSA Signing Only</td>
<td>1024, 2048</td>
<td>1024, 2048</td>
</tr>
<tr>
<td>RSA Encryption Only</td>
<td>1024, 2048</td>
<td>512,1024</td>
</tr>
<tr>
<td>RSA Dual Use Signing And Encryption</td>
<td>1024, 2048</td>
<td>512,1024</td>
</tr>
<tr>
<td>DH Key Exchange</td>
<td>1024, 2048</td>
<td>512,1024</td>
</tr>
</table>
<h3>
<font face="Arial,Helvetica">Methods</font></h3>
<h4>
<font face="Arial,Helvetica">generateCRMFRequest()</font></h4>
<tt>crmfObject = crypto.generateCRMFRequest(<i>"requestedDN", "regToken",
"authenticator","escrowAuthorityCert", "KeyGen Done Code",keySize1, "keyParams1",
"keyGenAlg1",..., keySizeN, "keyParamsN", "keyGenAlgN");</i></tt>
<p>This method will generate a sequence of CRMF requests that has N requests.&nbsp;
One request for each key pair that is generated.&nbsp; The first three
parameters will be applied to every request.&nbsp; the "escrowAuthorityCert"
parameter will only be used for requests that pertain to a key that is
being escrowed.&nbsp; After the "escrowAuthorityCert" parameter, the method
takes some JavaScript code that&nbsp; is invoked when the CRMF request
is ready. Finally, there are 1 or more sets of key generation arguments.&nbsp;
Each key generation will be associated with its own request.&nbsp; All
the requests will have the same DN.
<br>&nbsp;
<table BORDER WIDTH="100%" >
<tr>
<td ALIGN=CENTER VALIGN=TOP><b>Argument</b></td>
<td ALIGN=CENTER><b>Description</b></td>
</tr>
<tr>
<td><i><tt>"requestedDN"</tt></i></td>
<td>An RFC1485 formatted DN to include in the certificate request.</td>
</tr>
<tr>
<td><i><tt>"regToken"</tt></i></td>
<td>A value used to authenticate the user to the RA/CA.</td>
</tr>
<tr>
<td><i><tt>"authenticator"</tt></i></td>
<td>A value that the user can authenticate with in the future when their
private key is not available. Can be used for key recovery or revocation
requests.</td>
</tr>
<tr>
<td><i><tt>"escrowAuthorityCert"</tt></i></td>
<td>If this value is NULL, then no key escrow will be performed. This value
specifies which KRA certificate should be used to wrap the private key
being escrowed. The user will be prompted for confirmation whenever a key
will be escrowed.&nbsp; Only key exchange keys will be escrowed. If a dual
use key is being generated, it will not be escrowed.&nbsp; The value of
this argument is a base-64 encoded certificate.</td>
</tr>
<tr>
<td><i><tt>"CRMF Generation Done Code"</tt></i></td>
<td>This parameter is JavaScript to execute when the CRMF generation is
complete.&nbsp;</td>
</tr>
<tr>
<td VALIGN=TOP><i><tt>keySizeN</tt></i></td>
<td>The size in bits of the Nth key to generate</td>
</tr>
<tr>
<td VALIGN=TOP><i><tt>"keyParamsN"</tt></i></td>
<td>This string is an optional algorithm dependent parameter value. For
Diffie-Hellman it is used to specify p and g parameters.&nbsp; For DSA,
it will be used to specify pqg. If the key generation requires parameters
and the value passed in is NULL, then the client will generate the parameters
on its own. Currently, this value is ignored.</td>
</tr>
<tr>
<td VALIGN=TOP><i><tt>"keyGenAlgN"</tt></i></td>
<td>Which algorithm the generated key will support. Acceptable values are
(the mentioned values for keyUsage pertain to the keyUsage value of the
Certificate Extension that will ultimately be in the issued certificate):&nbsp;
<ul>
<li>
"rsa-ex" - generate an RSA key for key exchange only (This will have keyEncipherment
set for keyUsage.)</li>
<li>
"rsa-dual-use" - generate a single RSA key for both signing and encryption.&nbsp;
(This will have digitalSignature, keyEncipherment, and nonRepudiation set
for keyUsage.)</li>
<li>
"rsa-sign" - generate an RSA key for signing only. (This will have digitalSignature
set for keyUsage.)</li>
<li>
"rsa-nonrepudiation" - generate a single RSA key for nonRepudiation only.
(This will have non-repudiation set for keyUsage.)</li>
<li>
"rsa-sign-nonrepudiation" - generate a single RSA key use for both signing
and nonRepudiation. (This will have both digitalSignature and nonRepudiation
set for keyUsage.)</li>
<li>
"dsa-sign" - generate a single DSA key for signing only. (This will have
digitalSignature set for keyUsage.)</li>
<li>
"dsa-nonrepudiation" - generate a single DSA key for nonRepudiation. (This
will have nonRepudiation set for keyUsage.)</li>
<li>
"dsa-sign-nonrepudiation" - generate a single DSA key for signing and non-repudiation.
(This will have digitalSignature and nonRepudiation set for keyUsage.)</li>
</ul>
</td>
</tr>
</table>
<p>The <b>generateCRMFRequest()</b> method will cause the user to be presented
with a key generation dialog. The dialog describes the key generation process
and gives the user the opportunity to cancel the operation.
<p>The method <b>generateCRMFRequest() </b>will return an instance of a
CRMF object. The JavaScript passed in as the <i><tt>"CRMF Generation Done
Code"</tt></i> parameter should look at the attribute <i>request </i>of
the returned object to get the result of the CRMF generation.
<p>The string found by accessing <i><tt>crmfObject.request</tt></i> is
the base-64 encoded CRMF message to be sent to the CA/RA, or an error string.
The possible error strings are:
<br>&nbsp;
<table BORDER WIDTH="100%" >
<tr>
<td ALIGN=CENTER><b>Error String</b></td>
<td ALIGN=CENTER><b>Description</b></td>
</tr>
<tr>
<td>"error:invalidParameter:XXX"</td>
<td>The parameter XXX was an invalid value.</td>
</tr>
<tr>
<td>"error:userCancel"</td>
<td>the user has canceled the key generation operation</td>
</tr>
<tr>
<td>"error:internalError"</td>
<td>the software encountered some internal error, such as out of memory</td>
</tr>
</table>
<h4>
<font face="Arial,Helvetica">importUserCertificates()</font></h4>
<tt><i>resultString</i> = crypto.importUserCertificates(<i>"nicknameString"</i>,
<i>"certString"</i>,
<i>allowBackup</i>)</tt>
<br>&nbsp;
<br>&nbsp;
<table BORDER WIDTH="100%" >
<tr>
<td ALIGN=CENTER><b>Argument</b></td>
<td ALIGN=CENTER><b>Description</b></td>
</tr>
<tr>
<td VALIGN=TOP><i><tt>"nicknameString"</tt></i></td>
<td>This is the nickname that will be used to describe the certificate
in the client's certificate management UI.&nbsp; It should serve to uniquely
identify the certificate to the user. For example, "John Smith's VeriSign
Class 3 Digital ID" or "John Smith's Ford ID Certificate". However, if
this certificate has the same DN as one or more certificates that already
exist in the user's certificate store, the nickname associated with the
certificate(s) of the same DN in the certificate store is used, and the
<tt>"nicknameString"</tt> parameter is ignored. If the string is null and
no certificate with the same DN exists in the user's certificate store,
Personal Security Manager uses the following pattern to derive the nickname:
<tt>&lt;Common Name>'s &lt;Issuer Name> ID</tt>.</td>
</tr>
<tr>
<td VALIGN=TOP><i><tt>"certRepString"</tt></i></td>
<td>This string is the CMMF Certification Response from the CA that contains
the user's certificate(s). The response is base-64 encoded.</td>
</tr>
<tr>
<td><i><tt>allowBackup</tt></i></td>
<td>This is a Boolean argument. It allows the CA or RA to indicate to the
client whether to force the user to back up a newly issued certificate
(PKCS #12).</td>
</tr>
</table>
<p>The <b>importUserCertificates()</b> method is used to import newly issued
certificates for the user. The private key for the certificates must already
reside in the user's personal private key database.
<p>The request ID in the response being imported must match the request
ID in the associated Certification Request or Recovery Request.
<p>If the import operation succeeds, an empty string will be returned.&nbsp;
If it fails, one of the following error strings will be returned:
<br>&nbsp;
<br>&nbsp;
<table BORDER WIDTH="100%" >
<tr>
<td ALIGN=CENTER><b>Error String</b></td>
<td ALIGN=CENTER><b>Description</b></td>
</tr>
<tr>
<td>"error:userCancel"</td>
<td>The user canceled the import operation</td>
</tr>
<tr>
<td>"error:invalidCertificate"</td>
<td>One of the certificate packages was incorrectly formatted</td>
</tr>
<tr>
<td>"error:internalError"</td>
<td>The software encountered some internal error, such as out of memory</td>
</tr>
<tr>
<td>"error:invalidRequestID"</td>
<td>The request ID in the response message does not match any outstanding
request</td>
</tr>
</table>
<h4>
<font face="Arial,Helvetica">popChallengeResponse()</font></h4>
<tt><i>resultString</i> = crypto.popChallengeResponse(<i>"challengeString"</i>);</tt>
<br>&nbsp;
<table BORDER WIDTH="100%" >
<tr>
<td ALIGN=CENTER VALIGN=TOP><b>Argument</b></td>
<td ALIGN=CENTER><b>Description</b></td>
</tr>
<tr>
<td VALIGN=TOP><i><tt>"challengeString"</tt></i></td>
<td>A base-64 encoded CMMF POPODecKeyChallContent message. The current
implementation does not conform to that defined in the CMMF draft, and
we intend to change this implementation to that defined in the CMC RFC..
See below for the current implementation.</td>
</tr>
</table>
<p>The resultString will either be a base-64 encoded POPODecKeyRespContent
message, or one of the following error strings:
<br>&nbsp;
<br>&nbsp;
<table BORDER WIDTH="100%" >
<tr>
<td ALIGN=CENTER><b>Error String</b></td>
<td ALIGN=CENTER><b>Description</b></td>
</tr>
<tr>
<td>"error:invalidParameter:XXX"</td>
<td>The parameter XXX was an invalid value.</td>
</tr>
<tr>
<td>"error:internalError"</td>
<td>the software encountered some internal error, such as out of memory</td>
</tr>
</table>
<p><b>Challenge-Response Proof Of Possession</b>
<p><tt>Expected Input:</tt>
<p><tt>POPODecKeyChallContent ::= SEQUENCE OF Challenge</tt>
<br><tt>&nbsp;&nbsp;&nbsp; -- One Challenge per encryption key certification
request (in the</tt>
<br><tt>&nbsp;&nbsp;&nbsp; -- same order as these requests appear in FullCertTemplates).</tt>
<p><tt>Challenge ::= SEQUENCE {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; owf&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
AlgorithmIdentifier&nbsp; OPTIONAL,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- MUST be present in the first
Challenge; MAY be omitted in any</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- subsequent Challenge in POPODecKeyChallContent
(if omitted,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- then the owf used in the immediately
preceding Challenge is</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- to be used).</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; witness&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
OCTET STRING,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- the result of applying the one-way
function (owf) to a</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- randomly-generated INTEGER, A.&nbsp;
[Note that a different</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- INTEGER MUST be used for each
Challenge.]</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sender&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
GeneralName,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- the name of the sender.</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; key&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
OCTET STRING,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- the public key used to encrypt
the challenge.&nbsp; This will allow</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- the client to find the appropriate
key to do the decryption.</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; challenge&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
OCTET STRING</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- the encryption (under the public
key for which the cert.</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- request is being made) of Rand,
where Rand is specified as</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&nbsp;&nbsp; Rand ::= SEQUENCE
{</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INTEGER,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- the randomly-generated INTEGER A (above)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
senderHash&nbsp; OCTET STRING</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- the result of applying the one-way function (owf) to</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- the sender's general name</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&nbsp;&nbsp; }</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- the size of "int" must be small
enough such that "Rand" can be</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- contained within a single PKCS
#1 encryption block.</tt>
<br><tt>&nbsp; }</tt>
<p>&copy; Copyright 1999 Netscape Communications Corporation
</body>
</html>

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