Compare commits
2 Commits
SPIDERMONK
...
regalloc_c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c43d4984f | ||
|
|
cfe021ff88 |
134
mozilla/ef/Compiler/RegisterAllocator/BitSet.cpp
Normal file
134
mozilla/ef/Compiler/RegisterAllocator/BitSet.cpp
Normal 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
|
||||
195
mozilla/ef/Compiler/RegisterAllocator/BitSet.h
Normal file
195
mozilla/ef/Compiler/RegisterAllocator/BitSet.h
Normal 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
|
||||
159
mozilla/ef/Compiler/RegisterAllocator/Coalescing.h
Normal file
159
mozilla/ef/Compiler/RegisterAllocator/Coalescing.h
Normal 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_
|
||||
283
mozilla/ef/Compiler/RegisterAllocator/Coloring.cpp
Normal file
283
mozilla/ef/Compiler/RegisterAllocator/Coloring.cpp
Normal 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
|
||||
284
mozilla/ef/Compiler/RegisterAllocator/Coloring.h
Normal file
284
mozilla/ef/Compiler/RegisterAllocator/Coloring.h
Normal 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));
|
||||
}
|
||||
212
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.cpp
Normal file
212
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.cpp
Normal 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
|
||||
|
||||
|
||||
|
||||
80
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.h
Normal file
80
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.h
Normal 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_
|
||||
20
mozilla/ef/Compiler/RegisterAllocator/HashSet.cpp
Normal file
20
mozilla/ef/Compiler/RegisterAllocator/HashSet.cpp
Normal 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"
|
||||
97
mozilla/ef/Compiler/RegisterAllocator/HashSet.h
Normal file
97
mozilla/ef/Compiler/RegisterAllocator/HashSet.h
Normal 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_
|
||||
213
mozilla/ef/Compiler/RegisterAllocator/IndexedPool.h
Normal file
213
mozilla/ef/Compiler/RegisterAllocator/IndexedPool.h
Normal 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_
|
||||
258
mozilla/ef/Compiler/RegisterAllocator/InterferenceGraph.h
Normal file
258
mozilla/ef/Compiler/RegisterAllocator/InterferenceGraph.h
Normal 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_
|
||||
87
mozilla/ef/Compiler/RegisterAllocator/LiveRange.h
Normal file
87
mozilla/ef/Compiler/RegisterAllocator/LiveRange.h
Normal 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_
|
||||
163
mozilla/ef/Compiler/RegisterAllocator/LiveRangeGraph.h
Normal file
163
mozilla/ef/Compiler/RegisterAllocator/LiveRangeGraph.h
Normal 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_
|
||||
21
mozilla/ef/Compiler/RegisterAllocator/Liveness.cpp
Normal file
21
mozilla/ef/Compiler/RegisterAllocator/Liveness.cpp
Normal 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"
|
||||
|
||||
301
mozilla/ef/Compiler/RegisterAllocator/Liveness.h
Normal file
301
mozilla/ef/Compiler/RegisterAllocator/Liveness.h
Normal 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_
|
||||
40
mozilla/ef/Compiler/RegisterAllocator/Makefile
Normal file
40
mozilla/ef/Compiler/RegisterAllocator/Makefile
Normal 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)
|
||||
392
mozilla/ef/Compiler/RegisterAllocator/PhiNodeRemover.h
Normal file
392
mozilla/ef/Compiler/RegisterAllocator/PhiNodeRemover.h
Normal 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_
|
||||
155
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.cpp
Normal file
155
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.cpp
Normal 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;
|
||||
}
|
||||
88
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.h
Normal file
88
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.h
Normal 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_
|
||||
|
||||
355
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.cpp
Normal file
355
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.cpp
Normal 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
|
||||
117
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.h
Normal file
117
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.h
Normal 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_
|
||||
38
mozilla/ef/Compiler/RegisterAllocator/RegisterAssigner.h
Normal file
38
mozilla/ef/Compiler/RegisterAllocator/RegisterAssigner.h
Normal 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_ */
|
||||
25
mozilla/ef/Compiler/RegisterAllocator/RegisterClass.h
Normal file
25
mozilla/ef/Compiler/RegisterAllocator/RegisterClass.h
Normal 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_
|
||||
37
mozilla/ef/Compiler/RegisterAllocator/RegisterPressure.h
Normal file
37
mozilla/ef/Compiler/RegisterAllocator/RegisterPressure.h
Normal 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_
|
||||
104
mozilla/ef/Compiler/RegisterAllocator/RegisterTypes.h
Normal file
104
mozilla/ef/Compiler/RegisterAllocator/RegisterTypes.h
Normal 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_
|
||||
32
mozilla/ef/Compiler/RegisterAllocator/SSATools.cpp
Normal file
32
mozilla/ef/Compiler/RegisterAllocator/SSATools.cpp
Normal 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);
|
||||
}
|
||||
29
mozilla/ef/Compiler/RegisterAllocator/SSATools.h
Normal file
29
mozilla/ef/Compiler/RegisterAllocator/SSATools.h
Normal 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_
|
||||
37
mozilla/ef/Compiler/RegisterAllocator/SparseSet.cpp
Normal file
37
mozilla/ef/Compiler/RegisterAllocator/SparseSet.cpp
Normal 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
|
||||
168
mozilla/ef/Compiler/RegisterAllocator/SparseSet.h
Normal file
168
mozilla/ef/Compiler/RegisterAllocator/SparseSet.h
Normal 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_
|
||||
270
mozilla/ef/Compiler/RegisterAllocator/Spilling.cpp
Normal file
270
mozilla/ef/Compiler/RegisterAllocator/Spilling.cpp
Normal 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
|
||||
269
mozilla/ef/Compiler/RegisterAllocator/Spilling.h
Normal file
269
mozilla/ef/Compiler/RegisterAllocator/Spilling.h
Normal 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_
|
||||
239
mozilla/ef/Compiler/RegisterAllocator/Splits.h
Normal file
239
mozilla/ef/Compiler/RegisterAllocator/Splits.h
Normal 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_
|
||||
186
mozilla/ef/Compiler/RegisterAllocator/Timer.cpp
Normal file
186
mozilla/ef/Compiler/RegisterAllocator/Timer.cpp
Normal 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();
|
||||
}
|
||||
|
||||
80
mozilla/ef/Compiler/RegisterAllocator/Timer.h
Normal file
80
mozilla/ef/Compiler/RegisterAllocator/Timer.h
Normal 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_ */
|
||||
40
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.cpp
Normal file
40
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.cpp
Normal 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;
|
||||
}
|
||||
|
||||
116
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.h
Normal file
116
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.h
Normal 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 ®A == ®B;}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegisterManager -
|
||||
|
||||
struct PreColoredRegister
|
||||
{
|
||||
RegisterID id;
|
||||
RegisterName color;
|
||||
};
|
||||
|
||||
class VirtualRegisterManager
|
||||
{
|
||||
private:
|
||||
|
||||
IndexedPool<VirtualRegister> registerPool;
|
||||
PreColoredRegister machineRegister[6];
|
||||
|
||||
public:
|
||||
VirtualRegisterManager()
|
||||
{
|
||||
for (Uint32 i = 0; i < 6; i++)
|
||||
machineRegister[i].id = invalidID;
|
||||
}
|
||||
|
||||
// Return the VirtualRegister at the given index.
|
||||
VirtualRegister& getVirtualRegister(RegisterName name) const {return registerPool.get(name);}
|
||||
|
||||
// Return a new VirtualRegister.
|
||||
RegisterID newVirtualRegister(RegisterClassKind classKind)
|
||||
{
|
||||
VirtualRegister& vReg = *new(registerPool) VirtualRegister(classKind);
|
||||
RegisterID rid;
|
||||
|
||||
setName(rid, RegisterName(vReg.getIndex()));
|
||||
setClass(rid, classKind);
|
||||
return rid;
|
||||
}
|
||||
|
||||
RegisterID newMachineRegister(RegisterName name, RegisterClassKind classKind)
|
||||
{
|
||||
RegisterID rid = machineRegister[name].id;
|
||||
|
||||
if (rid == invalidID) {
|
||||
rid = newVirtualRegister(classKind);
|
||||
DEBUG_ONLY(setMachineRegister(rid));
|
||||
machineRegister[name].id = rid;
|
||||
machineRegister[name].color = name;
|
||||
}
|
||||
|
||||
return rid;
|
||||
}
|
||||
|
||||
PreColoredRegister* getMachineRegistersBegin() const {return (PreColoredRegister*) machineRegister;} // FIX
|
||||
PreColoredRegister* getMachineRegistersEnd() const {return (PreColoredRegister*) &machineRegister[6];} // FIX
|
||||
|
||||
// Return the VirtualRegister universe size.
|
||||
Uint32 getSize() {return registerPool.getSize();}
|
||||
|
||||
void setSize(Uint32 size) {registerPool.setSize(size);}
|
||||
};
|
||||
|
||||
#endif // _VIRTUAL_REGISTER_H_
|
||||
@@ -1,66 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ..
|
||||
topsrcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
#
|
||||
# Normally DIRS should contain all sub-dirs, but this
|
||||
# directory was built to organize code rather than to
|
||||
# reflect build order.
|
||||
#
|
||||
# Thus on the first pass we build the core classes and the
|
||||
# top-level Makefile will control the order of subsequent
|
||||
# directories by going directly into the specific directories
|
||||
#
|
||||
# The proper way to do this would be to introduce different
|
||||
# stages into the java code build cycle, but that has the
|
||||
# potential to introduce too many changes
|
||||
#
|
||||
# This is necessary to break circular dependencies the logical
|
||||
# tree directory structure would otherwise introduce.
|
||||
#
|
||||
# See top-level makefile for details
|
||||
#
|
||||
|
||||
DIRS = src/fdlibm src
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
@@ -1,110 +0,0 @@
|
||||
#!gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = jsdebug
|
||||
LIBRARY_NAME = jsd
|
||||
FORCE_SHARED_LIB= 1
|
||||
ifeq ($(OS_ARCH)$(MOZ_ENABLE_LIBXUL),WINNT)
|
||||
LIBRARY_NAME = jsd$(MOZ_BITS)$(VERSION_NUMBER)
|
||||
endif
|
||||
|
||||
# REQUIRES = java js
|
||||
REQUIRES = js
|
||||
|
||||
ifndef JSD_STANDALONE
|
||||
REQUIRES += \
|
||||
string \
|
||||
xpcom \
|
||||
xpconnect \
|
||||
widget \
|
||||
dom \
|
||||
$(NULL)
|
||||
|
||||
PACKAGE_FILE = jsd.pkg
|
||||
endif
|
||||
|
||||
EXTRA_DSO_LDOPTS += \
|
||||
$(MOZ_COMPONENT_LIBS) \
|
||||
$(MOZ_JS_LIBS) \
|
||||
$(NULL)
|
||||
EXPORTS = jsdebug.h
|
||||
|
||||
ifdef JS_THREADSAFE
|
||||
DEFINES += -DJS_THREADSAFE
|
||||
endif
|
||||
|
||||
CSRCS = \
|
||||
jsdebug.c \
|
||||
jsd_atom.c \
|
||||
jsd_high.c \
|
||||
jsd_hook.c \
|
||||
jsd_lock.c \
|
||||
jsd_obj.c \
|
||||
jsd_scpt.c \
|
||||
jsd_stak.c \
|
||||
jsd_step.c \
|
||||
jsd_text.c \
|
||||
jsd_val.c \
|
||||
$(NULL)
|
||||
|
||||
ifdef JSD_STANDALONE
|
||||
DIRS += jsdb
|
||||
else
|
||||
DIRS += idl
|
||||
CPPSRCS = jsd_xpc.cpp
|
||||
IS_COMPONENT = 1
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
ifdef MOZ_ENABLE_LIBXUL
|
||||
FORCE_SHARED_LIB=
|
||||
MODULE_NAME = JavaScript_Debugger
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES += -DEXPORT_JSD_API
|
||||
@@ -1,6 +0,0 @@
|
||||
js/jsd contains code for debugging support for the C-based JavaScript engine
|
||||
in js/src. jsd_xpc.cpp provides an XPCOM binding for the library.
|
||||
|
||||
js/jsd/jsdb is a console debugger using only native code (see README in that
|
||||
directory.) This debugger is no longer being actively developed, though it
|
||||
should work.
|
||||
@@ -1,52 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = jsdebug
|
||||
XPIDL_MODULE = jsdservice
|
||||
|
||||
XPIDLSRCS = \
|
||||
jsdIDebuggerService.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
File diff suppressed because it is too large
Load Diff
1135
mozilla/js/jsd/jsd.h
1135
mozilla/js/jsd/jsd.h
File diff suppressed because it is too large
Load Diff
@@ -1,70 +0,0 @@
|
||||
|
||||
PROJ = jsd
|
||||
JSD = .
|
||||
JS = $(JSD)\..\src
|
||||
JSPROJ = js32
|
||||
|
||||
!IF "$(BUILD_OPT)" != ""
|
||||
OBJ = Release
|
||||
CC_FLAGS = /DNDEBUG
|
||||
!ELSE
|
||||
OBJ = Debug
|
||||
CC_FLAGS = /DDEBUG
|
||||
LINK_FLAGS = /DEBUG
|
||||
!ENDIF
|
||||
|
||||
QUIET=@
|
||||
|
||||
CFLAGS = /nologo /MDd /W3 /Gm /GX /Zi /Od\
|
||||
/I $(JS)\
|
||||
/I $(JSD)\
|
||||
/DDEBUG /DWIN32 /D_CONSOLE /DXP_WIN /D_WINDOWS /D_WIN32\
|
||||
/DJSDEBUGGER\
|
||||
!IF "$(JSD_THREADSAFE)" != ""
|
||||
/DJSD_THREADSAFE\
|
||||
!ENDIF
|
||||
/DEXPORT_JSD_API\
|
||||
$(CC_FLAGS)\
|
||||
/c /Fp$(OBJ)\$(PROJ).pch /Fd$(OBJ)\$(PROJ).pdb /YX -Fo$@ $<
|
||||
|
||||
LFLAGS = /nologo /subsystem:console /DLL /incremental:no /machine:I386 \
|
||||
$(LINK_FLAGS) /pdb:$(OBJ)\$(PROJ).pdb -out:$(OBJ)\$(PROJ).dll
|
||||
|
||||
LLIBS = kernel32.lib advapi32.lib $(JS)\$(OBJ)\$(JSPROJ).lib
|
||||
# unused... user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib
|
||||
|
||||
CPP=cl.exe
|
||||
LINK32=link.exe
|
||||
|
||||
all: $(OBJ) $(OBJ)\$(PROJ).dll
|
||||
|
||||
|
||||
$(OBJ)\$(PROJ).dll: \
|
||||
$(OBJ)\jsdebug.obj \
|
||||
$(OBJ)\jsd_atom.obj \
|
||||
$(OBJ)\jsd_high.obj \
|
||||
$(OBJ)\jsd_hook.obj \
|
||||
$(OBJ)\jsd_obj.obj \
|
||||
$(OBJ)\jsd_scpt.obj \
|
||||
$(OBJ)\jsd_stak.obj \
|
||||
$(OBJ)\jsd_step.obj \
|
||||
$(OBJ)\jsd_text.obj \
|
||||
$(OBJ)\jsd_lock.obj \
|
||||
$(OBJ)\jsd_val.obj
|
||||
$(QUIET)$(LINK32) $(LFLAGS) $** $(LLIBS)
|
||||
|
||||
{$(JSD)}.c{$(OBJ)}.obj :
|
||||
$(QUIET)$(CPP) $(CFLAGS)
|
||||
|
||||
$(OBJ) :
|
||||
$(QUIET)mkdir $(OBJ)
|
||||
|
||||
clean:
|
||||
@echo deleting old output
|
||||
$(QUIET)del $(OBJ)\*.pch >NUL
|
||||
$(QUIET)del $(OBJ)\*.obj >NUL
|
||||
$(QUIET)del $(OBJ)\*.exp >NUL
|
||||
$(QUIET)del $(OBJ)\*.lib >NUL
|
||||
$(QUIET)del $(OBJ)\*.idb >NUL
|
||||
$(QUIET)del $(OBJ)\*.pdb >NUL
|
||||
$(QUIET)del $(OBJ)\*.dll >NUL
|
||||
@@ -1,8 +0,0 @@
|
||||
# xxxbsmedberg: this should arguably be part of the GRE
|
||||
[xpfe-browser]
|
||||
#if SHARED_LIBRARY
|
||||
dist/bin/components/@SHARED_LIBRARY@
|
||||
#else
|
||||
!staticcomp @LIBRARY@ @MODULE_NAME@
|
||||
#endif
|
||||
!xpt dist/bin/components/jsdservice.xpt
|
||||
@@ -1,110 +0,0 @@
|
||||
; -*- Mode: Fundamental; tab-width: 4; indent-tabs-mode: nil -*-
|
||||
;
|
||||
; ***** BEGIN LICENSE BLOCK *****
|
||||
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;
|
||||
; 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 the Initial Developer are Copyright (C) 1998
|
||||
; the Initial Developer. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s):
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the terms of
|
||||
; either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
; in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
; of those above. If you wish to allow use of your version of this file only
|
||||
; under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
; use your version of this file under the terms of the MPL, indicate your
|
||||
; decision by deleting the provisions above and replace them with the notice
|
||||
; and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
; the provisions above, a recipient may use your version of this file under
|
||||
; the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;
|
||||
; ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
LIBRARY JSD1640.DLL
|
||||
EXETYPE WINDOWS
|
||||
PROTMODE
|
||||
|
||||
DESCRIPTION 'Netscape 16-bit JavaScript Debugger Library'
|
||||
|
||||
CODE LOADONCALL MOVEABLE DISCARDABLE
|
||||
DATA PRELOAD MOVEABLE SINGLE
|
||||
|
||||
HEAPSIZE 8192
|
||||
|
||||
EXPORTS
|
||||
WEP @1 RESIDENTNAME NONAME
|
||||
_JSD_AppendSourceText
|
||||
_JSD_ClearAllExecutionHooks
|
||||
_JSD_ClearAllExecutionHooksForScript
|
||||
_JSD_ClearDebugBreakHook
|
||||
_JSD_ClearExecutionHook
|
||||
_JSD_ClearInterruptHook
|
||||
_JSD_ClearSourceText
|
||||
_JSD_DebuggerOff
|
||||
_JSD_DebuggerOn
|
||||
_JSD_EvaluateScriptInStackFrame
|
||||
_JSD_FindSourceForURL
|
||||
_JSD_GetCallingStackFrame
|
||||
_JSD_GetClosestLine
|
||||
_JSD_GetClosestPC
|
||||
_JSD_GetCountOfStackFrames
|
||||
_JSD_GetDefaultJSContext
|
||||
_JSD_GetMajorVersion
|
||||
_JSD_GetMinorVersion
|
||||
_JSD_GetPCForStackFrame
|
||||
_JSD_GetScriptBaseLineNumber
|
||||
_JSD_GetScriptFilename
|
||||
_JSD_GetScriptForStackFrame
|
||||
_JSD_GetScriptFunctionName
|
||||
_JSD_GetScriptHook
|
||||
_JSD_GetScriptLineExtent
|
||||
_JSD_GetSourceAlterCount
|
||||
_JSD_GetSourceStatus
|
||||
_JSD_GetSourceText
|
||||
_JSD_GetSourceURL
|
||||
_JSD_GetStackFrame
|
||||
_JSD_IncrementSourceAlterCount
|
||||
_JSD_IsSourceDirty
|
||||
_JSD_IterateScripts
|
||||
_JSD_IterateSources
|
||||
_JSD_LockScriptSubsystem
|
||||
_JSD_LockSourceTextSubsystem
|
||||
_JSD_NewSourceText
|
||||
_JSD_SetDebugBreakHook
|
||||
_JSD_SetErrorReporter
|
||||
_JSD_SetExecutionHook
|
||||
_JSD_SetInterruptHook
|
||||
_JSD_SetScriptHook
|
||||
_JSD_SetSourceDirty
|
||||
_JSD_SetUserCallbacks
|
||||
_JSD_UnlockScriptSubsystem
|
||||
_JSD_UnlockSourceTextSubsystem
|
||||
_Java_netscape_jsdebug_DebugController__0005fsetController_stub
|
||||
_Java_netscape_jsdebug_DebugController_executeScriptInStackFrame_stub
|
||||
_Java_netscape_jsdebug_DebugController_sendInterrupt_stub
|
||||
_Java_netscape_jsdebug_DebugController_setInstructionHook0_stub
|
||||
_Java_netscape_jsdebug_JSPC_getSourceLocation_stub
|
||||
_Java_netscape_jsdebug_JSSourceTextProvider_loadSourceTextItem_stub
|
||||
_Java_netscape_jsdebug_JSSourceTextProvider_refreshSourceTextVector_stub
|
||||
_Java_netscape_jsdebug_JSStackFrameInfo_getCaller0_stub
|
||||
_Java_netscape_jsdebug_JSStackFrameInfo_getPC_stub
|
||||
_Java_netscape_jsdebug_JSThreadState_countStackFrames_stub
|
||||
_Java_netscape_jsdebug_JSThreadState_getCurrentFrame_stub
|
||||
_Java_netscape_jsdebug_Script_getClosestPC_stub
|
||||
@@ -1,99 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Version stamp for this .DLL
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ver.h>
|
||||
|
||||
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
|
||||
FILEVERSION 4 // major, minor, release (alpha 1), build #
|
||||
|
||||
PRODUCTVERSION 4
|
||||
|
||||
FILEFLAGSMASK 0
|
||||
|
||||
FILEFLAGS 0 // final version
|
||||
|
||||
FILEOS VOS_DOS_WINDOWS16
|
||||
|
||||
FILETYPE VFT_DLL
|
||||
|
||||
FILESUBTYPE 0 // not used
|
||||
|
||||
BEGIN
|
||||
|
||||
BLOCK "StringFileInfo"
|
||||
|
||||
BEGIN
|
||||
|
||||
BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual
|
||||
|
||||
BEGIN
|
||||
|
||||
VALUE "CompanyName", "Netscape Communications Corporation\0"
|
||||
|
||||
VALUE "FileDescription", "Netscape 16-bit JavaScript Debugger Module\0"
|
||||
|
||||
VALUE "FileVersion", "4.0\0"
|
||||
|
||||
VALUE "InternalName", "JSD1640\0"
|
||||
|
||||
VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
|
||||
|
||||
VALUE "LegalTrademarks", "Netscape, Mozilla\0"
|
||||
|
||||
VALUE "OriginalFilename","JSD1640.DLL\0"
|
||||
|
||||
VALUE "ProductName", "NETSCAPE\0"
|
||||
|
||||
VALUE "ProductVersion", "4.0\0"
|
||||
|
||||
END
|
||||
|
||||
END
|
||||
|
||||
END
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winver.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,0,0,0
|
||||
PRODUCTVERSION 4,0,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x10004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Netscape Communications Corporation\0"
|
||||
VALUE "FileDescription", "Netscape 32-bit JavaScript Debugger Module\0"
|
||||
VALUE "FileVersion", "4.0\0"
|
||||
VALUE "InternalName", "JSD3240\0"
|
||||
VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
|
||||
VALUE "LegalTrademarks", "Netscape, Mozilla\0"
|
||||
VALUE "OriginalFilename", "jsd3240.dll\0"
|
||||
VALUE "ProductName", "NETSCAPE\0"
|
||||
VALUE "ProductVersion", "4.0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1252
|
||||
END
|
||||
END
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""winver.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,178 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - Atom support
|
||||
*/
|
||||
|
||||
#include "jsd.h"
|
||||
|
||||
/* #define TEST_ATOMS 1 */
|
||||
|
||||
#ifdef TEST_ATOMS
|
||||
static void
|
||||
_testAtoms(JSDContext*jsdc)
|
||||
{
|
||||
JSDAtom* atom0 = jsd_AddAtom(jsdc, "foo");
|
||||
JSDAtom* atom1 = jsd_AddAtom(jsdc, "foo");
|
||||
JSDAtom* atom2 = jsd_AddAtom(jsdc, "bar");
|
||||
JSDAtom* atom3 = jsd_CloneAtom(jsdc, atom1);
|
||||
JSDAtom* atom4 = jsd_CloneAtom(jsdc, atom2);
|
||||
|
||||
const char* c0 = JSD_ATOM_TO_STRING(atom0);
|
||||
const char* c1 = JSD_ATOM_TO_STRING(atom1);
|
||||
const char* c2 = JSD_ATOM_TO_STRING(atom2);
|
||||
const char* c3 = JSD_ATOM_TO_STRING(atom3);
|
||||
const char* c4 = JSD_ATOM_TO_STRING(atom4);
|
||||
|
||||
jsd_DropAtom(jsdc, atom0);
|
||||
jsd_DropAtom(jsdc, atom1);
|
||||
jsd_DropAtom(jsdc, atom2);
|
||||
jsd_DropAtom(jsdc, atom3);
|
||||
jsd_DropAtom(jsdc, atom4);
|
||||
}
|
||||
#endif
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(intN)
|
||||
_atom_smasher(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
JS_ASSERT(he);
|
||||
JS_ASSERT(he->value);
|
||||
JS_ASSERT(((JSDAtom*)(he->value))->str);
|
||||
|
||||
free(((JSDAtom*)(he->value))->str);
|
||||
free(he->value);
|
||||
he->value = NULL;
|
||||
he->key = NULL;
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(intN)
|
||||
_compareAtomKeys(const void *v1, const void *v2)
|
||||
{
|
||||
return 0 == strcmp((const char*)v1, (const char*)v2);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(intN)
|
||||
_compareAtoms(const void *v1, const void *v2)
|
||||
{
|
||||
return 0 == strcmp(((JSDAtom*)v1)->str, ((JSDAtom*)v2)->str);
|
||||
}
|
||||
|
||||
|
||||
JSBool
|
||||
jsd_CreateAtomTable(JSDContext* jsdc)
|
||||
{
|
||||
jsdc->atoms = JS_NewHashTable(256, JS_HashString,
|
||||
_compareAtomKeys, _compareAtoms,
|
||||
NULL, NULL);
|
||||
#ifdef TEST_ATOMS
|
||||
_testAtoms(jsdc);
|
||||
#endif
|
||||
return (JSBool) jsdc->atoms;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_DestroyAtomTable(JSDContext* jsdc)
|
||||
{
|
||||
if( jsdc->atoms )
|
||||
{
|
||||
JS_HashTableEnumerateEntries(jsdc->atoms, _atom_smasher, NULL);
|
||||
JS_HashTableDestroy(jsdc->atoms);
|
||||
jsdc->atoms = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSDAtom*
|
||||
jsd_AddAtom(JSDContext* jsdc, const char* str)
|
||||
{
|
||||
JSDAtom* atom;
|
||||
|
||||
if(!str)
|
||||
{
|
||||
JS_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSD_LOCK_ATOMS(jsdc);
|
||||
|
||||
atom = (JSDAtom*) JS_HashTableLookup(jsdc->atoms, str);
|
||||
|
||||
if( atom )
|
||||
atom->refcount++;
|
||||
else
|
||||
{
|
||||
atom = (JSDAtom*) malloc(sizeof(JSDAtom));
|
||||
if( atom )
|
||||
{
|
||||
atom->str = strdup(str);
|
||||
atom->refcount = 1;
|
||||
if(!JS_HashTableAdd(jsdc->atoms, atom->str, atom))
|
||||
{
|
||||
free(atom->str);
|
||||
free(atom);
|
||||
atom = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSD_UNLOCK_ATOMS(jsdc);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JSDAtom*
|
||||
jsd_CloneAtom(JSDContext* jsdc, JSDAtom* atom)
|
||||
{
|
||||
JSD_LOCK_ATOMS(jsdc);
|
||||
atom->refcount++;
|
||||
JSD_UNLOCK_ATOMS(jsdc);
|
||||
return atom;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_DropAtom(JSDContext* jsdc, JSDAtom* atom)
|
||||
{
|
||||
JSD_LOCK_ATOMS(jsdc);
|
||||
if(! --atom->refcount)
|
||||
{
|
||||
JS_HashTableRemove(jsdc->atoms, atom->str);
|
||||
free(atom->str);
|
||||
free(atom);
|
||||
}
|
||||
JSD_UNLOCK_ATOMS(jsdc);
|
||||
}
|
||||
|
||||
@@ -1,404 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - 'High Level' functions
|
||||
*/
|
||||
|
||||
#include "jsd.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* XXX not 'static' because of old Mac CodeWarrior bug */
|
||||
JSCList _jsd_context_list = JS_INIT_STATIC_CLIST(&_jsd_context_list);
|
||||
|
||||
/* these are used to connect JSD_SetUserCallbacks() with JSD_DebuggerOn() */
|
||||
static JSD_UserCallbacks _callbacks;
|
||||
static void* _user = NULL;
|
||||
static JSRuntime* _jsrt = NULL;
|
||||
|
||||
#ifdef JSD_HAS_DANGEROUS_THREAD
|
||||
static void* _dangerousThread = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef JSD_THREADSAFE
|
||||
void* _jsd_global_lock = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
void JSD_ASSERT_VALID_CONTEXT(JSDContext* jsdc)
|
||||
{
|
||||
JS_ASSERT(jsdc->inited);
|
||||
JS_ASSERT(jsdc->jsrt);
|
||||
JS_ASSERT(jsdc->dumbContext);
|
||||
JS_ASSERT(jsdc->glob);
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSClass global_class = {
|
||||
"JSDGlobal", 0,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
static JSBool
|
||||
_validateUserCallbacks(JSD_UserCallbacks* callbacks)
|
||||
{
|
||||
return !callbacks ||
|
||||
(callbacks->size && callbacks->size <= sizeof(JSD_UserCallbacks));
|
||||
}
|
||||
|
||||
static JSDContext*
|
||||
_newJSDContext(JSRuntime* jsrt,
|
||||
JSD_UserCallbacks* callbacks,
|
||||
void* user)
|
||||
{
|
||||
JSDContext* jsdc = NULL;
|
||||
|
||||
if( ! jsrt )
|
||||
return NULL;
|
||||
|
||||
if( ! _validateUserCallbacks(callbacks) )
|
||||
return NULL;
|
||||
|
||||
jsdc = (JSDContext*) calloc(1, sizeof(JSDContext));
|
||||
if( ! jsdc )
|
||||
goto label_newJSDContext_failure;
|
||||
|
||||
if( ! JSD_INIT_LOCKS(jsdc) )
|
||||
goto label_newJSDContext_failure;
|
||||
|
||||
JS_INIT_CLIST(&jsdc->links);
|
||||
|
||||
jsdc->jsrt = jsrt;
|
||||
|
||||
if( callbacks )
|
||||
memcpy(&jsdc->userCallbacks, callbacks, callbacks->size);
|
||||
|
||||
jsdc->user = user;
|
||||
|
||||
#ifdef JSD_HAS_DANGEROUS_THREAD
|
||||
jsdc->dangerousThread = _dangerousThread;
|
||||
#endif
|
||||
|
||||
JS_INIT_CLIST(&jsdc->threadsStates);
|
||||
JS_INIT_CLIST(&jsdc->sources);
|
||||
JS_INIT_CLIST(&jsdc->removedSources);
|
||||
|
||||
jsdc->sourceAlterCount = 1;
|
||||
|
||||
if( ! jsd_CreateAtomTable(jsdc) )
|
||||
goto label_newJSDContext_failure;
|
||||
|
||||
if( ! jsd_InitObjectManager(jsdc) )
|
||||
goto label_newJSDContext_failure;
|
||||
|
||||
if( ! jsd_InitScriptManager(jsdc) )
|
||||
goto label_newJSDContext_failure;
|
||||
|
||||
jsdc->dumbContext = JS_NewContext(jsdc->jsrt, 256);
|
||||
if( ! jsdc->dumbContext )
|
||||
goto label_newJSDContext_failure;
|
||||
|
||||
jsdc->glob = JS_NewObject(jsdc->dumbContext, &global_class, NULL, NULL);
|
||||
if( ! jsdc->glob )
|
||||
goto label_newJSDContext_failure;
|
||||
|
||||
if( ! JS_InitStandardClasses(jsdc->dumbContext, jsdc->glob) )
|
||||
goto label_newJSDContext_failure;
|
||||
|
||||
jsdc->data = NULL;
|
||||
jsdc->inited = JS_TRUE;
|
||||
|
||||
JSD_LOCK();
|
||||
JS_INSERT_LINK(&jsdc->links, &_jsd_context_list);
|
||||
JSD_UNLOCK();
|
||||
|
||||
return jsdc;
|
||||
|
||||
label_newJSDContext_failure:
|
||||
jsd_DestroyObjectManager(jsdc);
|
||||
jsd_DestroyAtomTable(jsdc);
|
||||
if( jsdc )
|
||||
free(jsdc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_destroyJSDContext(JSDContext* jsdc)
|
||||
{
|
||||
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
||||
|
||||
JSD_LOCK();
|
||||
JS_REMOVE_LINK(&jsdc->links);
|
||||
JSD_UNLOCK();
|
||||
|
||||
jsd_DestroyObjectManager(jsdc);
|
||||
jsd_DestroyAtomTable(jsdc);
|
||||
|
||||
jsdc->inited = JS_FALSE;
|
||||
|
||||
/*
|
||||
* We should free jsdc here, but we let it leak in case there are any
|
||||
* asynchronous hooks calling into the system using it as a handle
|
||||
*
|
||||
* XXX we also leak the locks
|
||||
*/
|
||||
JS_DestroyContext(jsdc->dumbContext);
|
||||
jsdc->dumbContext = NULL;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
JSDContext*
|
||||
jsd_DebuggerOnForUser(JSRuntime* jsrt,
|
||||
JSD_UserCallbacks* callbacks,
|
||||
void* user)
|
||||
{
|
||||
JSDContext* jsdc;
|
||||
JSContext* iter = NULL;
|
||||
|
||||
jsdc = _newJSDContext(jsrt, callbacks, user);
|
||||
if( ! jsdc )
|
||||
return NULL;
|
||||
|
||||
/* set hooks here */
|
||||
JS_SetNewScriptHookProc(jsdc->jsrt, jsd_NewScriptHookProc, jsdc);
|
||||
JS_SetDestroyScriptHookProc(jsdc->jsrt, jsd_DestroyScriptHookProc, jsdc);
|
||||
JS_SetDebuggerHandler(jsdc->jsrt, jsd_DebuggerHandler, jsdc);
|
||||
JS_SetExecuteHook(jsdc->jsrt, jsd_TopLevelCallHook, jsdc);
|
||||
JS_SetCallHook(jsdc->jsrt, jsd_FunctionCallHook, jsdc);
|
||||
JS_SetObjectHook(jsdc->jsrt, jsd_ObjectHook, jsdc);
|
||||
JS_SetThrowHook(jsdc->jsrt, jsd_ThrowHandler, jsdc);
|
||||
JS_SetDebugErrorHook(jsdc->jsrt, jsd_DebugErrorHook, jsdc);
|
||||
#ifdef LIVEWIRE
|
||||
LWDBG_SetNewScriptHookProc(jsd_NewScriptHookProc, jsdc);
|
||||
#endif
|
||||
if( jsdc->userCallbacks.setContext )
|
||||
jsdc->userCallbacks.setContext(jsdc, jsdc->user);
|
||||
return jsdc;
|
||||
}
|
||||
|
||||
JSDContext*
|
||||
jsd_DebuggerOn(void)
|
||||
{
|
||||
JS_ASSERT(_jsrt);
|
||||
JS_ASSERT(_validateUserCallbacks(&_callbacks));
|
||||
return jsd_DebuggerOnForUser(_jsrt, &_callbacks, _user);
|
||||
}
|
||||
|
||||
void
|
||||
jsd_DebuggerOff(JSDContext* jsdc)
|
||||
{
|
||||
/* clear hooks here */
|
||||
JS_SetNewScriptHookProc(jsdc->jsrt, NULL, NULL);
|
||||
JS_SetDestroyScriptHookProc(jsdc->jsrt, NULL, NULL);
|
||||
JS_SetDebuggerHandler(jsdc->jsrt, NULL, NULL);
|
||||
JS_SetExecuteHook(jsdc->jsrt, NULL, NULL);
|
||||
JS_SetCallHook(jsdc->jsrt, NULL, NULL);
|
||||
JS_SetObjectHook(jsdc->jsrt, NULL, NULL);
|
||||
JS_SetThrowHook(jsdc->jsrt, NULL, NULL);
|
||||
JS_SetDebugErrorHook(jsdc->jsrt, NULL, NULL);
|
||||
#ifdef LIVEWIRE
|
||||
LWDBG_SetNewScriptHookProc(NULL,NULL);
|
||||
#endif
|
||||
|
||||
/* clean up */
|
||||
JSD_LockScriptSubsystem(jsdc);
|
||||
jsd_DestroyScriptManager(jsdc);
|
||||
JSD_UnlockScriptSubsystem(jsdc);
|
||||
jsd_DestroyAllSources(jsdc);
|
||||
|
||||
_destroyJSDContext(jsdc);
|
||||
|
||||
if( jsdc->userCallbacks.setContext )
|
||||
jsdc->userCallbacks.setContext(NULL, jsdc->user);
|
||||
}
|
||||
|
||||
void
|
||||
jsd_SetUserCallbacks(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user)
|
||||
{
|
||||
_jsrt = jsrt;
|
||||
_user = user;
|
||||
|
||||
#ifdef JSD_HAS_DANGEROUS_THREAD
|
||||
_dangerousThread = JSD_CURRENT_THREAD();
|
||||
#endif
|
||||
|
||||
if( callbacks )
|
||||
memcpy(&_callbacks, callbacks, sizeof(JSD_UserCallbacks));
|
||||
else
|
||||
memset(&_callbacks, 0 , sizeof(JSD_UserCallbacks));
|
||||
}
|
||||
|
||||
void*
|
||||
jsd_SetContextPrivate(JSDContext* jsdc, void *data)
|
||||
{
|
||||
void *rval = jsdc->data;
|
||||
jsdc->data = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
void*
|
||||
jsd_GetContextPrivate(JSDContext* jsdc)
|
||||
{
|
||||
return jsdc->data;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_ClearAllProfileData(JSDContext* jsdc)
|
||||
{
|
||||
JSDScript *current;
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
current = (JSDScript *)jsdc->scripts.next;
|
||||
while (current != (JSDScript *)&jsdc->scripts)
|
||||
{
|
||||
jsd_ClearScriptProfileData(jsdc, current);
|
||||
current = (JSDScript *)current->links.next;
|
||||
}
|
||||
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
}
|
||||
|
||||
JSDContext*
|
||||
jsd_JSDContextForJSContext(JSContext* context)
|
||||
{
|
||||
JSDContext* iter;
|
||||
JSDContext* jsdc = NULL;
|
||||
JSRuntime* runtime = JS_GetRuntime(context);
|
||||
|
||||
JSD_LOCK();
|
||||
for( iter = (JSDContext*)_jsd_context_list.next;
|
||||
iter != (JSDContext*)&_jsd_context_list;
|
||||
iter = (JSDContext*)iter->links.next )
|
||||
{
|
||||
if( runtime == iter->jsrt )
|
||||
{
|
||||
jsdc = iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
JSD_UNLOCK();
|
||||
return jsdc;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
jsd_DebugErrorHook(JSContext *cx, const char *message,
|
||||
JSErrorReport *report, void *closure)
|
||||
{
|
||||
JSDContext* jsdc = (JSDContext*) closure;
|
||||
JSD_ErrorReporter errorReporter;
|
||||
void* errorReporterData;
|
||||
|
||||
if( ! jsdc )
|
||||
{
|
||||
JS_ASSERT(0);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||
return JS_TRUE;
|
||||
|
||||
/* local in case hook gets cleared on another thread */
|
||||
JSD_LOCK();
|
||||
errorReporter = jsdc->errorReporter;
|
||||
errorReporterData = jsdc->errorReporterData;
|
||||
JSD_UNLOCK();
|
||||
|
||||
if(!errorReporter)
|
||||
return JS_TRUE;
|
||||
|
||||
switch(errorReporter(jsdc, cx, message, report, errorReporterData))
|
||||
{
|
||||
case JSD_ERROR_REPORTER_PASS_ALONG:
|
||||
return JS_TRUE;
|
||||
case JSD_ERROR_REPORTER_RETURN:
|
||||
return JS_FALSE;
|
||||
case JSD_ERROR_REPORTER_DEBUG:
|
||||
{
|
||||
jsval rval;
|
||||
JSD_ExecutionHookProc hook;
|
||||
void* hookData;
|
||||
|
||||
/* local in case hook gets cleared on another thread */
|
||||
JSD_LOCK();
|
||||
hook = jsdc->debugBreakHook;
|
||||
hookData = jsdc->debugBreakHookData;
|
||||
JSD_UNLOCK();
|
||||
|
||||
jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUG_REQUESTED,
|
||||
hook, hookData, &rval);
|
||||
/* XXX Should make this dependent on ExecutionHook retval */
|
||||
return JS_TRUE;
|
||||
}
|
||||
case JSD_ERROR_REPORTER_CLEAR_RETURN:
|
||||
if(report && JSREPORT_IS_EXCEPTION(report->flags))
|
||||
JS_ClearPendingException(cx);
|
||||
return JS_FALSE;
|
||||
default:
|
||||
JS_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_SetErrorReporter(JSDContext* jsdc,
|
||||
JSD_ErrorReporter reporter,
|
||||
void* callerdata)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->errorReporter = reporter;
|
||||
jsdc->errorReporterData = callerdata;
|
||||
JSD_UNLOCK();
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_GetErrorReporter(JSDContext* jsdc,
|
||||
JSD_ErrorReporter* reporter,
|
||||
void** callerdata)
|
||||
{
|
||||
JSD_LOCK();
|
||||
if( reporter )
|
||||
*reporter = jsdc->errorReporter;
|
||||
if( callerdata )
|
||||
*callerdata = jsdc->errorReporterData;
|
||||
JSD_UNLOCK();
|
||||
return JS_TRUE;
|
||||
}
|
||||
@@ -1,363 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - Hook support
|
||||
*/
|
||||
|
||||
#include "jsd.h"
|
||||
|
||||
JSTrapStatus JS_DLL_CALLBACK
|
||||
jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
void *closure)
|
||||
{
|
||||
JSDScript* jsdscript;
|
||||
JSDContext* jsdc = (JSDContext*) closure;
|
||||
JSD_ExecutionHookProc hook;
|
||||
void* hookData;
|
||||
|
||||
if( ! jsdc || ! jsdc->inited )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
/* local in case jsdc->interruptHook gets cleared on another thread */
|
||||
JSD_LOCK();
|
||||
hook = jsdc->interruptHook;
|
||||
hookData = jsdc->interruptHookData;
|
||||
JSD_UNLOCK();
|
||||
|
||||
if (!hook)
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if( ! jsdscript )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
#ifdef LIVEWIRE
|
||||
if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (jsuword)pc) )
|
||||
return JSTRAP_CONTINUE;
|
||||
#endif
|
||||
|
||||
return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_INTERRUPTED,
|
||||
hook, hookData, rval);
|
||||
}
|
||||
|
||||
JSTrapStatus JS_DLL_CALLBACK
|
||||
jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
jsval *rval, void *closure)
|
||||
{
|
||||
JSDScript* jsdscript;
|
||||
JSDContext* jsdc = (JSDContext*) closure;
|
||||
JSD_ExecutionHookProc hook;
|
||||
void* hookData;
|
||||
|
||||
if( ! jsdc || ! jsdc->inited )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
/* local in case jsdc->debuggerHook gets cleared on another thread */
|
||||
JSD_LOCK();
|
||||
hook = jsdc->debuggerHook;
|
||||
hookData = jsdc->debuggerHookData;
|
||||
JSD_UNLOCK();
|
||||
if(!hook)
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if( ! jsdscript )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUGGER_KEYWORD,
|
||||
hook, hookData, rval);
|
||||
}
|
||||
|
||||
|
||||
JSTrapStatus JS_DLL_CALLBACK
|
||||
jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
jsval *rval, void *closure)
|
||||
{
|
||||
JSDScript* jsdscript;
|
||||
JSDContext* jsdc = (JSDContext*) closure;
|
||||
JSD_ExecutionHookProc hook;
|
||||
void* hookData;
|
||||
|
||||
if( ! jsdc || ! jsdc->inited )
|
||||
return JSD_HOOK_RETURN_CONTINUE_THROW;
|
||||
|
||||
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||
return JSD_HOOK_RETURN_CONTINUE_THROW;
|
||||
|
||||
/* local in case jsdc->throwHook gets cleared on another thread */
|
||||
JSD_LOCK();
|
||||
hook = jsdc->throwHook;
|
||||
hookData = jsdc->throwHookData;
|
||||
JSD_UNLOCK();
|
||||
if (!hook)
|
||||
return JSD_HOOK_RETURN_CONTINUE_THROW;
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if( ! jsdscript )
|
||||
return JSD_HOOK_RETURN_CONTINUE_THROW;
|
||||
|
||||
JS_GetPendingException(cx, rval);
|
||||
|
||||
return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_THROW,
|
||||
hook, hookData, rval);
|
||||
}
|
||||
|
||||
JSTrapStatus
|
||||
jsd_CallExecutionHook(JSDContext* jsdc,
|
||||
JSContext *cx,
|
||||
uintN type,
|
||||
JSD_ExecutionHookProc hook,
|
||||
void* hookData,
|
||||
jsval* rval)
|
||||
{
|
||||
uintN hookanswer = JSD_HOOK_THROW == type ?
|
||||
JSD_HOOK_RETURN_CONTINUE_THROW :
|
||||
JSD_HOOK_RETURN_CONTINUE;
|
||||
JSDThreadState* jsdthreadstate;
|
||||
|
||||
if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc,cx)))
|
||||
{
|
||||
if ((type != JSD_HOOK_THROW && type != JSD_HOOK_INTERRUPTED) ||
|
||||
jsdc->flags & JSD_MASK_TOP_FRAME_ONLY ||
|
||||
!(jsdthreadstate->flags & TS_HAS_DISABLED_FRAME))
|
||||
{
|
||||
/*
|
||||
* if it's not a throw and it's not an interrupt,
|
||||
* or we're only masking the top frame,
|
||||
* or there are no disabled frames in this stack,
|
||||
* then call out.
|
||||
*/
|
||||
hookanswer = hook(jsdc, jsdthreadstate, type, hookData, rval);
|
||||
jsd_DestroyThreadState(jsdc, jsdthreadstate);
|
||||
}
|
||||
}
|
||||
|
||||
switch(hookanswer)
|
||||
{
|
||||
case JSD_HOOK_RETURN_ABORT:
|
||||
case JSD_HOOK_RETURN_HOOK_ERROR:
|
||||
return JSTRAP_ERROR;
|
||||
case JSD_HOOK_RETURN_RET_WITH_VAL:
|
||||
return JSTRAP_RETURN;
|
||||
case JSD_HOOK_RETURN_THROW_WITH_VAL:
|
||||
return JSTRAP_THROW;
|
||||
case JSD_HOOK_RETURN_CONTINUE:
|
||||
break;
|
||||
case JSD_HOOK_RETURN_CONTINUE_THROW:
|
||||
/* only makes sense for jsd_ThrowHandler (which init'd rval) */
|
||||
JS_ASSERT(JSD_HOOK_THROW == type);
|
||||
return JSTRAP_THROW;
|
||||
default:
|
||||
JS_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return JSTRAP_CONTINUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_CallCallHook (JSDContext* jsdc,
|
||||
JSContext *cx,
|
||||
uintN type,
|
||||
JSD_CallHookProc hook,
|
||||
void* hookData)
|
||||
{
|
||||
JSBool hookanswer;
|
||||
JSDThreadState* jsdthreadstate;
|
||||
|
||||
hookanswer = JS_FALSE;
|
||||
if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc, cx)))
|
||||
{
|
||||
hookanswer = hook(jsdc, jsdthreadstate, type, hookData);
|
||||
jsd_DestroyThreadState(jsdc, jsdthreadstate);
|
||||
}
|
||||
|
||||
return hookanswer;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_SetInterruptHook(JSDContext* jsdc,
|
||||
JSD_ExecutionHookProc hook,
|
||||
void* callerdata)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->interruptHookData = callerdata;
|
||||
jsdc->interruptHook = hook;
|
||||
JS_SetInterrupt(jsdc->jsrt, jsd_InterruptHandler, (void*) jsdc);
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_ClearInterruptHook(JSDContext* jsdc)
|
||||
{
|
||||
JSD_LOCK();
|
||||
JS_ClearInterrupt(jsdc->jsrt, NULL, NULL );
|
||||
jsdc->interruptHook = NULL;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_SetDebugBreakHook(JSDContext* jsdc,
|
||||
JSD_ExecutionHookProc hook,
|
||||
void* callerdata)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->debugBreakHookData = callerdata;
|
||||
jsdc->debugBreakHook = hook;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_ClearDebugBreakHook(JSDContext* jsdc)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->debugBreakHook = NULL;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_SetDebuggerHook(JSDContext* jsdc,
|
||||
JSD_ExecutionHookProc hook,
|
||||
void* callerdata)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->debuggerHookData = callerdata;
|
||||
jsdc->debuggerHook = hook;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_ClearDebuggerHook(JSDContext* jsdc)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->debuggerHook = NULL;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_SetThrowHook(JSDContext* jsdc,
|
||||
JSD_ExecutionHookProc hook,
|
||||
void* callerdata)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->throwHookData = callerdata;
|
||||
jsdc->throwHook = hook;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_ClearThrowHook(JSDContext* jsdc)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->throwHook = NULL;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_SetFunctionHook(JSDContext* jsdc,
|
||||
JSD_CallHookProc hook,
|
||||
void* callerdata)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->functionHookData = callerdata;
|
||||
jsdc->functionHook = hook;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_ClearFunctionHook(JSDContext* jsdc)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->functionHook = NULL;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_SetTopLevelHook(JSDContext* jsdc,
|
||||
JSD_CallHookProc hook,
|
||||
void* callerdata)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->toplevelHookData = callerdata;
|
||||
jsdc->toplevelHook = hook;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_ClearTopLevelHook(JSDContext* jsdc)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->toplevelHook = NULL;
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@@ -1,810 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* this is all going away... replaced by code in js/jsd/java */
|
||||
|
||||
#if 0
|
||||
|
||||
#include "native.h"
|
||||
#include "jsdebug.h"
|
||||
|
||||
#include "_gen/netscape_jsdebug_DebugController.h"
|
||||
#include "_gen/netscape_jsdebug_Script.h"
|
||||
#include "_gen/netscape_jsdebug_JSThreadState.h"
|
||||
#include "_gen/netscape_jsdebug_JSStackFrameInfo.h"
|
||||
#include "_gen/netscape_jsdebug_JSPC.h"
|
||||
#include "_gen/netscape_jsdebug_JSSourceTextProvider.h"
|
||||
#include "_gen/netscape_jsdebug_JSErrorReporter.h"
|
||||
|
||||
static JSDContext* context = 0;
|
||||
static struct Hnetscape_jsdebug_DebugController* controller = 0;
|
||||
|
||||
/***************************************************************************/
|
||||
/* helpers */
|
||||
|
||||
static JHandle*
|
||||
_constructInteger(ExecEnv *ee, long i)
|
||||
{
|
||||
return (JHandle*)
|
||||
execute_java_constructor(ee, "java/lang/Integer", 0, "(I)", i);
|
||||
}
|
||||
|
||||
static JHandle*
|
||||
_putHash(ExecEnv *ee, JHandle* tbl, JHandle* key, JHandle* ob)
|
||||
{
|
||||
return (JHandle*)
|
||||
execute_java_dynamic_method(
|
||||
ee, tbl, "put",
|
||||
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
|
||||
key, ob );
|
||||
}
|
||||
|
||||
static JHandle*
|
||||
_getHash(ExecEnv *ee, JHandle* tbl, JHandle* key)
|
||||
{
|
||||
return (JHandle*)
|
||||
execute_java_dynamic_method(
|
||||
ee, tbl, "get",
|
||||
"(Ljava/lang/Object;)Ljava/lang/Object;",
|
||||
key );
|
||||
}
|
||||
|
||||
static JHandle*
|
||||
_removeHash(ExecEnv *ee, JHandle* tbl, JHandle* key)
|
||||
{
|
||||
return (JHandle*)
|
||||
execute_java_dynamic_method(
|
||||
ee, tbl, "remove",
|
||||
"(Ljava/lang/Object;)Ljava/lang/Object;",
|
||||
key );
|
||||
}
|
||||
|
||||
struct Hnetscape_jsdebug_JSStackFrameInfo*
|
||||
_constructJSStackFrameInfo( ExecEnv* ee, JSDStackFrameInfo* jsdframe,
|
||||
struct Hnetscape_jsdebug_JSThreadState* threadState )
|
||||
{
|
||||
struct Hnetscape_jsdebug_JSStackFrameInfo* frame;
|
||||
|
||||
frame = (struct Hnetscape_jsdebug_JSStackFrameInfo*)
|
||||
execute_java_constructor( ee, "netscape/jsdebug/JSStackFrameInfo", 0,
|
||||
"(Lnetscape/jsdebug/JSThreadState;)",
|
||||
threadState );
|
||||
if( ! frame )
|
||||
return NULL;
|
||||
|
||||
/* XXX fill in additional fields */
|
||||
unhand(frame)->_nativePtr = (long) jsdframe;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
struct Hnetscape_jsdebug_JSPC*
|
||||
_constructJSPC( ExecEnv* ee, struct Hnetscape_jsdebug_Script* script, long pc )
|
||||
{
|
||||
struct Hnetscape_jsdebug_JSPC * pcOb;
|
||||
|
||||
pcOb = (struct Hnetscape_jsdebug_JSPC *)
|
||||
execute_java_constructor( ee, "netscape/jsdebug/JSPC", 0,
|
||||
"(Lnetscape/jsdebug/Script;I)",
|
||||
script, pc );
|
||||
if( ! pcOb )
|
||||
return NULL;
|
||||
|
||||
/* XXX fill in additional fields */
|
||||
|
||||
return pcOb;
|
||||
}
|
||||
|
||||
static Hnetscape_jsdebug_Script*
|
||||
_scriptObFromJSDScriptPtr( ExecEnv* ee, JSDScript* jsdscript )
|
||||
{
|
||||
JHandle* tbl = (JHandle*) unhand(controller)->scriptTable;
|
||||
JHandle* key = _constructInteger(ee,(long)jsdscript);
|
||||
return (Hnetscape_jsdebug_Script*) _getHash( ee, tbl, key );
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void PR_CALLBACK
|
||||
_scriptHook( JSDContext* jsdc,
|
||||
JSDScript* jsdscript,
|
||||
JSBool creating,
|
||||
void* callerdata )
|
||||
{
|
||||
Hnetscape_jsdebug_Script* script;
|
||||
ExecEnv* ee = EE();
|
||||
|
||||
if( ! context || ! controller || ! ee )
|
||||
return;
|
||||
|
||||
if( creating )
|
||||
{
|
||||
char* url = (char*)JSD_GetScriptFilename (jsdc, jsdscript);
|
||||
char* function = (char*)JSD_GetScriptFunctionName (jsdc, jsdscript);
|
||||
int base = JSD_GetScriptBaseLineNumber (jsdc, jsdscript);
|
||||
int extent = JSD_GetScriptLineExtent (jsdc, jsdscript);
|
||||
|
||||
if( ! url )
|
||||
{
|
||||
return;
|
||||
/* url = ""; */
|
||||
}
|
||||
|
||||
/* create Java Object for Script */
|
||||
script = (Hnetscape_jsdebug_Script*)
|
||||
execute_java_constructor(ee, "netscape/jsdebug/Script", 0, "()");
|
||||
|
||||
if( ! script )
|
||||
return;
|
||||
|
||||
/* set the members */
|
||||
unhand(script)->_url = makeJavaString(url,strlen(url));
|
||||
unhand(script)->_function = function ? makeJavaString(function,strlen(function)) : 0;
|
||||
unhand(script)->_baseLineNumber = base;
|
||||
unhand(script)->_lineExtent = extent;
|
||||
unhand(script)->_nativePtr = (long)jsdscript;
|
||||
|
||||
/* add it to the hash table */
|
||||
_putHash( ee, (JHandle*) unhand(controller)->scriptTable,
|
||||
_constructInteger(ee, (long)jsdscript), (JHandle*)script );
|
||||
|
||||
/* call the hook */
|
||||
if( unhand(controller)->scriptHook )
|
||||
{
|
||||
execute_java_dynamic_method( ee,(JHandle*)unhand(controller)->scriptHook,
|
||||
"justLoadedScript",
|
||||
"(Lnetscape/jsdebug/Script;)V",
|
||||
script );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JHandle* tbl = (JHandle*) unhand(controller)->scriptTable;
|
||||
JHandle* key = _constructInteger(ee,(long)jsdscript);
|
||||
|
||||
/* find Java Object for Script */
|
||||
script = (Hnetscape_jsdebug_Script*) _getHash( ee, tbl, key );
|
||||
|
||||
if( ! script )
|
||||
return;
|
||||
|
||||
/* remove it from the hash table */
|
||||
_removeHash( ee, tbl, key );
|
||||
|
||||
/* call the hook */
|
||||
if( unhand(controller)->scriptHook )
|
||||
{
|
||||
execute_java_dynamic_method( ee,(JHandle*)unhand(controller)->scriptHook,
|
||||
"aboutToUnloadScript",
|
||||
"(Lnetscape/jsdebug/Script;)V",
|
||||
script );
|
||||
}
|
||||
/* set the Script as invalid */
|
||||
execute_java_dynamic_method( ee,(JHandle*)script,
|
||||
"_setInvalid",
|
||||
"()V" );
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
PRUintn PR_CALLBACK
|
||||
_executionHook( JSDContext* jsdc,
|
||||
JSDThreadState* jsdstate,
|
||||
PRUintn type,
|
||||
void* callerdata )
|
||||
{
|
||||
Hnetscape_jsdebug_JSThreadState* threadState;
|
||||
Hnetscape_jsdebug_Script* script;
|
||||
JHandle* pcOb;
|
||||
JSDStackFrameInfo* jsdframe;
|
||||
JSDScript* jsdscript;
|
||||
int pc;
|
||||
JHandle* tblScript;
|
||||
JHandle* keyScript;
|
||||
ExecEnv* ee = EE();
|
||||
|
||||
if( ! context || ! controller || ! ee )
|
||||
return JSD_HOOK_RETURN_HOOK_ERROR;
|
||||
|
||||
/* get the JSDStackFrameInfo */
|
||||
jsdframe = JSD_GetStackFrame(jsdc, jsdstate);
|
||||
if( ! jsdframe )
|
||||
return JSD_HOOK_RETURN_HOOK_ERROR;
|
||||
|
||||
/* get the JSDScript */
|
||||
jsdscript = JSD_GetScriptForStackFrame(jsdc, jsdstate, jsdframe);
|
||||
if( ! jsdscript )
|
||||
return JSD_HOOK_RETURN_HOOK_ERROR;
|
||||
|
||||
/* find Java Object for Script */
|
||||
tblScript = (JHandle*) unhand(controller)->scriptTable;
|
||||
keyScript = _constructInteger(ee, (long)jsdscript);
|
||||
script = (Hnetscape_jsdebug_Script*) _getHash( ee, tblScript, keyScript );
|
||||
if( ! script )
|
||||
return JSD_HOOK_RETURN_HOOK_ERROR;
|
||||
|
||||
/* generate a JSPC */
|
||||
pc = JSD_GetPCForStackFrame(jsdc, jsdstate, jsdframe);
|
||||
|
||||
pcOb = (JHandle*)
|
||||
_constructJSPC(ee, script, pc);
|
||||
if( ! pcOb )
|
||||
return JSD_HOOK_RETURN_HOOK_ERROR;
|
||||
|
||||
/* build a JSThreadState */
|
||||
threadState = (struct Hnetscape_jsdebug_JSThreadState*)
|
||||
execute_java_constructor( ee, "netscape/jsdebug/JSThreadState",0,"()");
|
||||
if( ! threadState )
|
||||
return JSD_HOOK_RETURN_HOOK_ERROR;
|
||||
|
||||
/* populate the ThreadState */
|
||||
/* XXX FILL IN THE REST... */
|
||||
unhand(threadState)->valid = 1; /* correct value for true? */
|
||||
unhand(threadState)->currentFramePtr = (long) jsdframe;
|
||||
unhand(threadState)->nativeThreadState = (long) jsdstate;
|
||||
unhand(threadState)->continueState = netscape_jsdebug_JSThreadState_DEBUG_STATE_RUN;
|
||||
|
||||
/* XXX FILL IN THE REST... */
|
||||
|
||||
|
||||
/* find and call the appropriate Hook */
|
||||
if( JSD_HOOK_INTERRUPTED == type )
|
||||
{
|
||||
JHandle* hook;
|
||||
|
||||
/* clear the JSD level hook (must reset on next sendInterrupt0()*/
|
||||
JSD_ClearInterruptHook(context);
|
||||
|
||||
hook = (JHandle*) unhand(controller)->interruptHook;
|
||||
if( ! hook )
|
||||
return JSD_HOOK_RETURN_HOOK_ERROR;
|
||||
|
||||
/* call the hook */
|
||||
execute_java_dynamic_method(
|
||||
ee, hook, "aboutToExecute",
|
||||
"(Lnetscape/jsdebug/ThreadStateBase;Lnetscape/jsdebug/PC;)V",
|
||||
threadState, pcOb );
|
||||
}
|
||||
else if( JSD_HOOK_DEBUG_REQUESTED == type )
|
||||
{
|
||||
JHandle* hook;
|
||||
|
||||
hook = (JHandle*) unhand(controller)->debugBreakHook;
|
||||
if( ! hook )
|
||||
return JSD_HOOK_RETURN_HOOK_ERROR;
|
||||
|
||||
/* call the hook */
|
||||
execute_java_dynamic_method(
|
||||
ee, hook, "aboutToExecute",
|
||||
"(Lnetscape/jsdebug/ThreadStateBase;Lnetscape/jsdebug/PC;)V",
|
||||
threadState, pcOb );
|
||||
}
|
||||
else if( JSD_HOOK_BREAKPOINT == type )
|
||||
{
|
||||
JHandle* hook;
|
||||
|
||||
hook = (JHandle*)
|
||||
execute_java_dynamic_method(
|
||||
ee,(JHandle*)controller,
|
||||
"getInstructionHook0",
|
||||
"(Lnetscape/jsdebug/PC;)Lnetscape/jsdebug/InstructionHook;",
|
||||
pcOb );
|
||||
if( ! hook )
|
||||
return JSD_HOOK_RETURN_HOOK_ERROR;
|
||||
|
||||
/* call the hook */
|
||||
execute_java_dynamic_method(
|
||||
ee, hook, "aboutToExecute",
|
||||
"(Lnetscape/jsdebug/ThreadStateBase;)V",
|
||||
threadState );
|
||||
}
|
||||
|
||||
if( netscape_jsdebug_JSThreadState_DEBUG_STATE_THROW ==
|
||||
unhand(threadState)->continueState )
|
||||
return JSD_HOOK_RETURN_ABORT;
|
||||
|
||||
return JSD_HOOK_RETURN_CONTINUE;
|
||||
}
|
||||
|
||||
PRUintn PR_CALLBACK
|
||||
_errorReporter( JSDContext* jsdc,
|
||||
JSContext* cx,
|
||||
const char* message,
|
||||
JSErrorReport* report,
|
||||
void* callerdata )
|
||||
{
|
||||
JHandle* reporter;
|
||||
JHandle* msg = NULL;
|
||||
JHandle* filename = NULL;
|
||||
int lineno = 0;
|
||||
JHandle* linebuf = NULL;
|
||||
int tokenOffset = 0;
|
||||
ExecEnv* ee = EE();
|
||||
|
||||
if( ! context || ! controller || ! ee )
|
||||
return JSD_ERROR_REPORTER_PASS_ALONG;
|
||||
|
||||
reporter = (JHandle*) unhand(controller)->errorReporter;
|
||||
if( ! reporter )
|
||||
return JSD_ERROR_REPORTER_PASS_ALONG;
|
||||
|
||||
if( message )
|
||||
msg = (JHandle*) makeJavaString((char*)message, strlen(message));
|
||||
if( report && report->filename )
|
||||
filename = (JHandle*) makeJavaString((char*)report->filename, strlen(report->filename));
|
||||
if( report && report->linebuf )
|
||||
linebuf = (JHandle*) makeJavaString((char*)report->linebuf, strlen(report->linebuf));
|
||||
if( report )
|
||||
lineno = report->lineno;
|
||||
if( report && report->linebuf && report->tokenptr )
|
||||
tokenOffset = report->tokenptr - report->linebuf;
|
||||
|
||||
return (int)
|
||||
execute_java_dynamic_method(
|
||||
ee, reporter, "reportError",
|
||||
"(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;I)I",
|
||||
msg,
|
||||
filename,
|
||||
lineno,
|
||||
linebuf,
|
||||
tokenOffset );
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* from "_gen\netscape_jsdebug_DebugController.h" */
|
||||
|
||||
|
||||
/* XXX HACK */
|
||||
JSDContext* _simContext = 0;
|
||||
|
||||
void netscape_jsdebug_DebugController__setController(struct Hnetscape_jsdebug_DebugController * self,/*boolean*/ long on)
|
||||
{
|
||||
if(on)
|
||||
{
|
||||
context = JSD_DebuggerOn();
|
||||
if( ! context )
|
||||
return;
|
||||
|
||||
_simContext = context; /* XXX HACK */
|
||||
|
||||
unhand(self)->_nativeContext = (long) context;
|
||||
controller = self;
|
||||
JSD_SetScriptHook(context, _scriptHook, (void*)1 );
|
||||
JSD_SetErrorReporter(context, _errorReporter, (void*)1 );
|
||||
JSD_SetDebugBreakHook(context, _executionHook, (void*)1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX stop somehow... */
|
||||
/* kill context */
|
||||
JSD_SetDebugBreakHook(context, NULL, NULL );
|
||||
JSD_SetErrorReporter(context, NULL, NULL);
|
||||
JSD_SetScriptHook(context, NULL, NULL);
|
||||
context = 0;
|
||||
controller = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void netscape_jsdebug_DebugController_setInstructionHook0(struct Hnetscape_jsdebug_DebugController * self,struct Hnetscape_jsdebug_PC * pcOb)
|
||||
{
|
||||
Hnetscape_jsdebug_Script* script;
|
||||
JSDScript* jsdscript;
|
||||
PRUintn pc;
|
||||
ExecEnv* ee = EE();
|
||||
|
||||
if( ! context || ! controller || ! ee )
|
||||
return;
|
||||
|
||||
script = (Hnetscape_jsdebug_Script*)
|
||||
execute_java_dynamic_method(ee, (JHandle*)pcOb, "getScript","()Lnetscape/jsdebug/Script;");
|
||||
|
||||
if( ! script )
|
||||
return;
|
||||
|
||||
jsdscript = (JSDScript*) unhand(script)->_nativePtr;
|
||||
if( ! jsdscript )
|
||||
return;
|
||||
|
||||
pc = (PRUintn)
|
||||
execute_java_dynamic_method(ee, (JHandle*)pcOb, "getPC","()I");
|
||||
|
||||
JSD_SetExecutionHook(context, jsdscript, pc, _executionHook, 0);
|
||||
}
|
||||
|
||||
void netscape_jsdebug_DebugController_sendInterrupt0(struct Hnetscape_jsdebug_DebugController * self)
|
||||
{
|
||||
if( ! context || ! controller )
|
||||
return;
|
||||
JSD_SetInterruptHook(context, _executionHook, 0);
|
||||
}
|
||||
|
||||
struct Hjava_lang_String *netscape_jsdebug_DebugController_executeScriptInStackFrame0(struct Hnetscape_jsdebug_DebugController *self,struct Hnetscape_jsdebug_JSStackFrameInfo *frame,struct Hjava_lang_String *src,struct Hjava_lang_String *filename,long lineno)
|
||||
{
|
||||
struct Hnetscape_jsdebug_JSThreadState* threadStateOb;
|
||||
JSDThreadState* jsdthreadstate;
|
||||
JSDStackFrameInfo* jsdframe;
|
||||
char* filenameC;
|
||||
char* srcC;
|
||||
JSString* jsstr;
|
||||
jsval rval;
|
||||
JSBool success;
|
||||
int srclen;
|
||||
|
||||
threadStateOb = (struct Hnetscape_jsdebug_JSThreadState*)unhand(frame)->threadState;
|
||||
jsdthreadstate = (JSDThreadState*) unhand(threadStateOb)->nativeThreadState;
|
||||
|
||||
jsdframe = (JSDStackFrameInfo*) unhand(frame)->_nativePtr;
|
||||
|
||||
if( ! context || ! controller || ! jsdframe )
|
||||
return NULL;
|
||||
|
||||
filenameC = allocCString(filename);
|
||||
if( ! filenameC )
|
||||
return NULL;
|
||||
srcC = allocCString(src);
|
||||
if( ! srcC )
|
||||
{
|
||||
free(filenameC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
srclen = strlen(srcC);
|
||||
|
||||
success = JSD_EvaluateScriptInStackFrame(context, jsdthreadstate, jsdframe,
|
||||
srcC, srclen,
|
||||
filenameC, lineno, &rval);
|
||||
|
||||
/* XXX crashing on Windows under Symantec (though I can't see why!)*/
|
||||
|
||||
free(filenameC);
|
||||
free(srcC);
|
||||
|
||||
|
||||
if( ! success )
|
||||
return NULL;
|
||||
|
||||
if( JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval) )
|
||||
return NULL;
|
||||
|
||||
jsstr = JSD_ValToStringInStackFrame(context,jsdthreadstate,jsdframe,rval);
|
||||
if( ! jsstr )
|
||||
return NULL;
|
||||
|
||||
/* XXXbe should use JS_GetStringChars and preserve Unicode. */
|
||||
return makeJavaString((char*)JS_GetStringBytes(jsstr), JS_GetStringLength(jsstr));
|
||||
}
|
||||
|
||||
long netscape_jsdebug_DebugController_getNativeMajorVersion(struct Hnetscape_jsdebug_DebugController* self)
|
||||
{
|
||||
return (long) JSD_GetMajorVersion();
|
||||
}
|
||||
|
||||
long netscape_jsdebug_DebugController_getNativeMinorVersion(struct Hnetscape_jsdebug_DebugController* self)
|
||||
{
|
||||
return (long) JSD_GetMinorVersion();
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* from "_gen\netscape_jsdebug_Script.h" */
|
||||
|
||||
struct Hnetscape_jsdebug_JSPC *netscape_jsdebug_Script_getClosestPC(struct Hnetscape_jsdebug_Script * self,long line)
|
||||
{
|
||||
PRUintn pc;
|
||||
JSDScript* jsdscript;
|
||||
|
||||
if( ! context || ! controller )
|
||||
return 0;
|
||||
|
||||
jsdscript = (JSDScript*) unhand(self)->_nativePtr;
|
||||
if( ! jsdscript )
|
||||
return 0;
|
||||
|
||||
pc = JSD_GetClosestPC(context, jsdscript, line);
|
||||
|
||||
if( -1 == pc )
|
||||
return 0;
|
||||
return _constructJSPC( 0, self, pc);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* from "_gen\netscape_jsdebug_JSThreadState.h" */
|
||||
|
||||
long netscape_jsdebug_JSThreadState_countStackFrames(struct Hnetscape_jsdebug_JSThreadState * self)
|
||||
{
|
||||
JSDThreadState* jsdstate;
|
||||
|
||||
if( ! context || ! controller )
|
||||
return 0;
|
||||
|
||||
jsdstate = (JSDThreadState*) unhand(self)->nativeThreadState;
|
||||
|
||||
if( ! jsdstate )
|
||||
return 0;
|
||||
|
||||
return (long) JSD_GetCountOfStackFrames(context, jsdstate);
|
||||
}
|
||||
|
||||
struct Hnetscape_jsdebug_StackFrameInfo *netscape_jsdebug_JSThreadState_getCurrentFrame(struct Hnetscape_jsdebug_JSThreadState * self)
|
||||
{
|
||||
JSDThreadState* jsdstate;
|
||||
JSDStackFrameInfo* jsdframe;
|
||||
|
||||
if( ! context || ! controller )
|
||||
return NULL;
|
||||
|
||||
jsdstate = (JSDThreadState*) unhand(self)->nativeThreadState;
|
||||
|
||||
if( ! jsdstate )
|
||||
return NULL;
|
||||
|
||||
jsdframe = JSD_GetStackFrame(context, jsdstate);
|
||||
if( ! jsdframe )
|
||||
return NULL;
|
||||
|
||||
return (struct Hnetscape_jsdebug_StackFrameInfo*)
|
||||
_constructJSStackFrameInfo( 0, jsdframe, self );
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* from "_gen\netscape_jsdebug_JSStackFrameInfo.h" */
|
||||
|
||||
struct Hnetscape_jsdebug_StackFrameInfo *netscape_jsdebug_JSStackFrameInfo_getCaller0(struct Hnetscape_jsdebug_JSStackFrameInfo * self)
|
||||
{
|
||||
JSDStackFrameInfo* jsdframeCur;
|
||||
JSDStackFrameInfo* jsdframeCaller;
|
||||
struct Hnetscape_jsdebug_JSThreadState* threadState;
|
||||
JSDThreadState* jsdthreadstate;
|
||||
|
||||
if( ! context || ! controller )
|
||||
return NULL;
|
||||
|
||||
jsdframeCur = (JSDStackFrameInfo*) unhand(self)->_nativePtr;
|
||||
if( ! jsdframeCur )
|
||||
return NULL;
|
||||
|
||||
threadState = (struct Hnetscape_jsdebug_JSThreadState*) unhand(self)->threadState;
|
||||
if( ! threadState )
|
||||
return NULL;
|
||||
|
||||
jsdthreadstate = (JSDThreadState*) unhand(threadState)->nativeThreadState;
|
||||
if( ! jsdthreadstate )
|
||||
return NULL;
|
||||
|
||||
jsdframeCaller = JSD_GetCallingStackFrame(context, jsdthreadstate, jsdframeCur);
|
||||
if( ! jsdframeCaller )
|
||||
return NULL;
|
||||
|
||||
return (struct Hnetscape_jsdebug_StackFrameInfo*)
|
||||
_constructJSStackFrameInfo( 0, jsdframeCaller, threadState );
|
||||
}
|
||||
struct Hnetscape_jsdebug_PC *netscape_jsdebug_JSStackFrameInfo_getPC(struct Hnetscape_jsdebug_JSStackFrameInfo * self)
|
||||
{
|
||||
JSDScript* jsdscript;
|
||||
JSDStackFrameInfo* jsdframe;
|
||||
struct Hnetscape_jsdebug_Script* script;
|
||||
struct Hnetscape_jsdebug_JSThreadState* threadState;
|
||||
JSDThreadState* jsdthreadstate;
|
||||
int pc;
|
||||
ExecEnv* ee = EE();
|
||||
|
||||
if( ! context || ! controller || ! ee )
|
||||
return NULL;
|
||||
|
||||
jsdframe = (JSDStackFrameInfo*) unhand(self)->_nativePtr;
|
||||
if( ! jsdframe )
|
||||
return NULL;
|
||||
|
||||
threadState = (struct Hnetscape_jsdebug_JSThreadState*) unhand(self)->threadState;
|
||||
if( ! threadState )
|
||||
return NULL;
|
||||
|
||||
jsdthreadstate = (JSDThreadState*) unhand(threadState)->nativeThreadState;
|
||||
if( ! jsdthreadstate )
|
||||
return NULL;
|
||||
|
||||
jsdscript = JSD_GetScriptForStackFrame(context, jsdthreadstate, jsdframe );
|
||||
if( ! jsdscript )
|
||||
return NULL;
|
||||
|
||||
script = _scriptObFromJSDScriptPtr(ee, jsdscript);
|
||||
if( ! script )
|
||||
return NULL;
|
||||
|
||||
pc = JSD_GetPCForStackFrame(context, jsdthreadstate, jsdframe);
|
||||
if( ! pc )
|
||||
return NULL;
|
||||
|
||||
return (struct Hnetscape_jsdebug_PC*) _constructJSPC(ee, script, pc);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* from "_gen\netscape_jsdebug_JSPC.h" */
|
||||
|
||||
struct Hnetscape_jsdebug_SourceLocation *netscape_jsdebug_JSPC_getSourceLocation(struct Hnetscape_jsdebug_JSPC * self)
|
||||
{
|
||||
JSDScript* jsdscript;
|
||||
struct Hnetscape_jsdebug_Script* script;
|
||||
struct Hnetscape_jsdebug_JSPC* newPCOb;
|
||||
int line;
|
||||
int newpc;
|
||||
int pc;
|
||||
ExecEnv* ee = EE();
|
||||
|
||||
if( ! context || ! controller || ! ee )
|
||||
return NULL;
|
||||
|
||||
script = unhand(self)->script;
|
||||
|
||||
if( ! script )
|
||||
return NULL;
|
||||
|
||||
jsdscript = (JSDScript*) unhand(script)->_nativePtr;
|
||||
if( ! jsdscript )
|
||||
return NULL;
|
||||
pc = unhand(self)->pc;
|
||||
|
||||
line = JSD_GetClosestLine(context, jsdscript, pc);
|
||||
newpc = JSD_GetClosestPC(context, jsdscript, line);
|
||||
|
||||
newPCOb = _constructJSPC(ee, script, newpc );
|
||||
if( ! newPCOb )
|
||||
return NULL;
|
||||
|
||||
return (struct Hnetscape_jsdebug_SourceLocation *)
|
||||
execute_java_constructor( ee, "netscape/jsdebug/JSSourceLocation", 0,
|
||||
"(Lnetscape/jsdebug/JSPC;I)",
|
||||
newPCOb, line );
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* from "_gen\netscape_jsdebug_JSSourceTextProvider.h" */
|
||||
|
||||
struct Hnetscape_jsdebug_SourceTextItem *netscape_jsdebug_JSSourceTextProvider_loadSourceTextItem0(struct Hnetscape_jsdebug_JSSourceTextProvider * self,struct Hjava_lang_String * url)
|
||||
{
|
||||
/* this should attempt to load the source for the indicated URL */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void netscape_jsdebug_JSSourceTextProvider_refreshSourceTextVector(struct Hnetscape_jsdebug_JSSourceTextProvider * self)
|
||||
{
|
||||
|
||||
JHandle* vec;
|
||||
JHandle* itemOb;
|
||||
JSDSourceText* iterp = 0;
|
||||
JSDSourceText* item;
|
||||
const char* url;
|
||||
struct Hjava_lang_String* urlOb;
|
||||
ExecEnv* ee = EE();
|
||||
|
||||
if( ! context || ! controller || ! ee )
|
||||
return;
|
||||
|
||||
/* create new vector */
|
||||
vec = (JHandle*) execute_java_constructor(ee, "netscape/util/Vector", 0, "()");
|
||||
if( ! vec )
|
||||
return;
|
||||
|
||||
/* lock the native subsystem */
|
||||
JSD_LockSourceTextSubsystem(context);
|
||||
|
||||
/* iterate through the native items */
|
||||
while( 0 != (item = JSD_IterateSources(context, &iterp)) )
|
||||
{
|
||||
int urlStrLen;
|
||||
int status = JSD_GetSourceStatus(context,item);
|
||||
|
||||
/* try to find Java object */
|
||||
url = JSD_GetSourceURL(context, item);
|
||||
if( ! url || 0 == (urlStrLen = strlen(url)) ) /* ignoring those with no url */
|
||||
continue;
|
||||
|
||||
urlOb = makeJavaString((char*)url,urlStrLen);
|
||||
if( ! urlOb )
|
||||
continue;
|
||||
|
||||
itemOb = (JHandle*)
|
||||
execute_java_dynamic_method( ee, (JHandle*)self, "findSourceTextItem0",
|
||||
"(Ljava/lang/String;)Lnetscape/jsdebug/SourceTextItem;",
|
||||
urlOb );
|
||||
|
||||
if( ! itemOb )
|
||||
{
|
||||
/* if not found then generate new item */
|
||||
struct Hjava_lang_String* textOb;
|
||||
const char* str;
|
||||
int length;
|
||||
|
||||
if( ! JSD_GetSourceText(context, item, &str, &length ) )
|
||||
{
|
||||
str = "";
|
||||
length = 0;
|
||||
}
|
||||
textOb = makeJavaString((char*)str, length);
|
||||
|
||||
itemOb = (JHandle*)
|
||||
execute_java_constructor(ee, "netscape/jsdebug/SourceTextItem",0,
|
||||
"(Ljava/lang/String;Ljava/lang/String;I)",
|
||||
urlOb, textOb, status );
|
||||
}
|
||||
else if( JSD_IsSourceDirty(context, item) &&
|
||||
JSD_SOURCE_CLEARED != status )
|
||||
{
|
||||
/* if found and dirty then update */
|
||||
struct Hjava_lang_String* textOb;
|
||||
const char* str;
|
||||
int length;
|
||||
|
||||
if( ! JSD_GetSourceText(context, item, &str, &length ) )
|
||||
{
|
||||
str = "";
|
||||
length = 0;
|
||||
}
|
||||
textOb = makeJavaString((char*)str, length);
|
||||
execute_java_dynamic_method(ee, itemOb, "setText",
|
||||
"(Ljava/lang/String;)V", textOb);
|
||||
execute_java_dynamic_method(ee, itemOb, "setStatus",
|
||||
"(I)V", status );
|
||||
execute_java_dynamic_method(ee, itemOb, "setDirty", "(Z)V", 1 );
|
||||
}
|
||||
|
||||
/* we have our copy; clear the native cached text */
|
||||
if( JSD_SOURCE_INITED != status &&
|
||||
JSD_SOURCE_PARTIAL != status &&
|
||||
JSD_SOURCE_CLEARED != status )
|
||||
{
|
||||
JSD_ClearSourceText(context, item);
|
||||
}
|
||||
|
||||
/* set the item clean */
|
||||
JSD_SetSourceDirty(context, item, FALSE );
|
||||
|
||||
/* add the item to the vector */
|
||||
if( itemOb )
|
||||
execute_java_dynamic_method(ee, vec, "addElement",
|
||||
"(Ljava/lang/Object;)V", itemOb );
|
||||
}
|
||||
/* unlock the native subsystem */
|
||||
JSD_UnlockSourceTextSubsystem(context);
|
||||
|
||||
/* set main vector to our new vector */
|
||||
|
||||
unhand(self)->_sourceTextVector = (struct Hnetscape_util_Vector*) vec;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,255 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - Locking and threading support
|
||||
*/
|
||||
|
||||
/*
|
||||
* ifdef JSD_USE_NSPR_LOCKS then you musat build and run against NSPR2.
|
||||
* Otherwise, there are stubs that can be filled in with your own locking
|
||||
* code. Also, note that these stubs include a jsd_CurrentThread()
|
||||
* implementation that only works on Win32 - this is needed for the inprocess
|
||||
* Java-based debugger.
|
||||
*/
|
||||
|
||||
#include "jsd.h"
|
||||
|
||||
#ifdef JSD_THREADSAFE
|
||||
|
||||
#ifdef JSD_USE_NSPR_LOCKS
|
||||
|
||||
#include "prlock.h"
|
||||
#include "prthread.h"
|
||||
|
||||
#ifdef JSD_ATTACH_THREAD_HACK
|
||||
#include "pprthred.h" /* need this as long as JS_AttachThread is needed */
|
||||
#endif
|
||||
|
||||
struct JSDStaticLock
|
||||
{
|
||||
void* owner;
|
||||
PRLock* lock;
|
||||
int count;
|
||||
#ifdef DEBUG
|
||||
uint16 sig;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* This exists to wrap non-NSPR theads (e.g. Java threads) in NSPR wrappers.
|
||||
* XXX We ignore the memory leak issue.
|
||||
* It is claimed that future versions of NSPR will automatically wrap on
|
||||
* the call to PR_GetCurrentThread.
|
||||
*
|
||||
* XXX We ignore the memory leak issue - i.e. we never call PR_DetachThread.
|
||||
*
|
||||
*/
|
||||
#undef _CURRENT_THREAD
|
||||
#ifdef JSD_ATTACH_THREAD_HACK
|
||||
#define _CURRENT_THREAD(out) \
|
||||
JS_BEGIN_MACRO \
|
||||
out = (void*) PR_GetCurrentThread(); \
|
||||
if(!out) \
|
||||
out = (void*) JS_AttachThread(PR_USER_THREAD,PR_PRIORITY_NORMAL,NULL);\
|
||||
JS_ASSERT(out); \
|
||||
JS_END_MACRO
|
||||
#else
|
||||
#define _CURRENT_THREAD(out) \
|
||||
JS_BEGIN_MACRO \
|
||||
out = (void*) PR_GetCurrentThread(); \
|
||||
JS_ASSERT(out); \
|
||||
JS_END_MACRO
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define JSD_LOCK_SIG 0x10CC10CC
|
||||
void ASSERT_VALID_LOCK(JSDStaticLock* lock)
|
||||
{
|
||||
JS_ASSERT(lock);
|
||||
JS_ASSERT(lock->lock);
|
||||
JS_ASSERT(lock->count >= 0);
|
||||
JS_ASSERT((! lock->count && ! lock->owner) || (lock->count && lock->owner));
|
||||
JS_ASSERT(lock->sig == (uint16) JSD_LOCK_SIG);
|
||||
}
|
||||
#else
|
||||
#define ASSERT_VALID_LOCK(x) ((void)0)
|
||||
#endif
|
||||
|
||||
void*
|
||||
jsd_CreateLock()
|
||||
{
|
||||
JSDStaticLock* lock;
|
||||
|
||||
if( ! (lock = calloc(1, sizeof(JSDStaticLock))) ||
|
||||
! (lock->lock = PR_NewLock()) )
|
||||
{
|
||||
if(lock)
|
||||
{
|
||||
free(lock);
|
||||
lock = NULL;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if(lock) lock->sig = (uint16) JSD_LOCK_SIG;
|
||||
#endif
|
||||
return lock;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_Lock(JSDStaticLock* lock)
|
||||
{
|
||||
void* me;
|
||||
|
||||
_CURRENT_THREAD(me);
|
||||
|
||||
ASSERT_VALID_LOCK(lock);
|
||||
|
||||
if(lock->owner == me)
|
||||
lock->count++;
|
||||
else
|
||||
{
|
||||
PR_Lock(lock->lock); /* this can block... */
|
||||
JS_ASSERT(lock->owner == 0);
|
||||
lock->count = 1;
|
||||
lock->owner = me;
|
||||
}
|
||||
ASSERT_VALID_LOCK(lock);
|
||||
}
|
||||
|
||||
void
|
||||
jsd_Unlock(JSDStaticLock* lock)
|
||||
{
|
||||
void* me;
|
||||
|
||||
ASSERT_VALID_LOCK(lock);
|
||||
_CURRENT_THREAD(me);
|
||||
|
||||
if(lock->owner != me)
|
||||
{
|
||||
JS_ASSERT(0); /* it's an error to unlock a lock you don't own */
|
||||
return;
|
||||
}
|
||||
if(--lock->count == 0)
|
||||
{
|
||||
lock->owner = NULL;
|
||||
PR_Unlock(lock->lock);
|
||||
}
|
||||
ASSERT_VALID_LOCK(lock);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JSBool
|
||||
jsd_IsLocked(JSDStaticLock* lock)
|
||||
{
|
||||
void* me;
|
||||
ASSERT_VALID_LOCK(lock);
|
||||
_CURRENT_THREAD(me);
|
||||
return lock->owner == me ? JS_TRUE : JS_FALSE;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
void*
|
||||
jsd_CurrentThread()
|
||||
{
|
||||
void* me;
|
||||
_CURRENT_THREAD(me);
|
||||
return me;
|
||||
}
|
||||
|
||||
|
||||
#else /* ! JSD_USE_NSPR_LOCKS */
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||
#pragma message("!! you are compiling the stubbed version of jsd_lock.c !!")
|
||||
#pragma message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NOTE: 'Real' versions of these locks must be reentrant in the sense that
|
||||
* they support nested calls to lock and unlock.
|
||||
*/
|
||||
|
||||
void*
|
||||
jsd_CreateLock()
|
||||
{
|
||||
return (void*)1;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_Lock(void* lock)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
jsd_Unlock(void* lock)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JSBool
|
||||
jsd_IsLocked(void* lock)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* This Windows only thread id code is here to allow the Java-based
|
||||
* JSDebugger to work with the single threaded js.c shell (even without
|
||||
* real locking and threading support).
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
/* bogus (but good enough) declaration*/
|
||||
extern void* __stdcall GetCurrentThreadId(void);
|
||||
#endif
|
||||
|
||||
void*
|
||||
jsd_CurrentThread()
|
||||
{
|
||||
#ifdef WIN32
|
||||
return GetCurrentThreadId();
|
||||
#else
|
||||
return (void*)1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* JSD_USE_NSPR_LOCKS */
|
||||
|
||||
#endif /* JSD_THREADSAFE */
|
||||
@@ -1,74 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Header for JavaScript Debugging support - Locking and threading functions
|
||||
*/
|
||||
|
||||
#ifndef jsd_lock_h___
|
||||
#define jsd_lock_h___
|
||||
|
||||
/*
|
||||
* If you want to support threading and locking, define JSD_THREADSAFE and
|
||||
* implement the functions below.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: These locks must be reentrant in the sense that they support
|
||||
* nested calls to lock and unlock.
|
||||
*/
|
||||
|
||||
typedef struct JSDStaticLock JSDStaticLock;
|
||||
|
||||
extern void*
|
||||
jsd_CreateLock();
|
||||
|
||||
extern void
|
||||
jsd_Lock(JSDStaticLock* lock);
|
||||
|
||||
extern void
|
||||
jsd_Unlock(JSDStaticLock* lock);
|
||||
|
||||
#ifdef DEBUG
|
||||
extern JSBool
|
||||
jsd_IsLocked(JSDStaticLock* lock);
|
||||
#endif /* DEBUG */
|
||||
|
||||
extern void*
|
||||
jsd_CurrentThread();
|
||||
|
||||
#endif /* jsd_lock_h___ */
|
||||
@@ -1,329 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - Object support
|
||||
*/
|
||||
|
||||
#include "jsd.h"
|
||||
|
||||
/*
|
||||
* #define JSD_TRACE 1
|
||||
*/
|
||||
|
||||
#ifdef JSD_TRACE
|
||||
#define TRACEOBJ(jsdc, jsdobj, which) _traceObj(jsdc, jsdobj, which)
|
||||
|
||||
static char *
|
||||
_describeObj(JSDContext* jsdc, JSDObject *jsdobj)
|
||||
{
|
||||
return
|
||||
JS_smprintf("%0x new'd in %s at line %d using ctor %s in %s at line %d",
|
||||
(int)jsdobj,
|
||||
JSD_GetObjectNewURL(jsdc, jsdobj),
|
||||
JSD_GetObjectNewLineNumber(jsdc, jsdobj),
|
||||
JSD_GetObjectConstructorName(jsdc, jsdobj),
|
||||
JSD_GetObjectConstructorURL(jsdc, jsdobj),
|
||||
JSD_GetObjectConstructorLineNumber(jsdc, jsdobj));
|
||||
}
|
||||
|
||||
static void
|
||||
_traceObj(JSDContext* jsdc, JSDObject* jsdobj, int which)
|
||||
{
|
||||
char* description;
|
||||
|
||||
if( !jsdobj )
|
||||
return;
|
||||
|
||||
description = _describeObj(jsdc, jsdobj);
|
||||
|
||||
printf("%s : %s\n",
|
||||
which == 0 ? "new " :
|
||||
which == 1 ? "final" :
|
||||
"ctor ",
|
||||
description);
|
||||
if(description)
|
||||
free(description);
|
||||
}
|
||||
#else
|
||||
#define TRACEOBJ(jsdc, jsdobj, which) ((void)0)
|
||||
#endif /* JSD_TRACE */
|
||||
|
||||
#ifdef DEBUG
|
||||
void JSD_ASSERT_VALID_OBJECT(JSDObject* jsdobj)
|
||||
{
|
||||
JS_ASSERT(jsdobj);
|
||||
JS_ASSERT(!JS_CLIST_IS_EMPTY(&jsdobj->links));
|
||||
JS_ASSERT(jsdobj->obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
_destroyJSDObject(JSDContext* jsdc, JSDObject* jsdobj)
|
||||
{
|
||||
JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
|
||||
|
||||
JS_REMOVE_LINK(&jsdobj->links);
|
||||
JS_HashTableRemove(jsdc->objectsTable, jsdobj->obj);
|
||||
|
||||
if(jsdobj->newURL)
|
||||
jsd_DropAtom(jsdc, jsdobj->newURL);
|
||||
if(jsdobj->ctorURL)
|
||||
jsd_DropAtom(jsdc, jsdobj->ctorURL);
|
||||
if(jsdobj->ctorName)
|
||||
jsd_DropAtom(jsdc, jsdobj->ctorName);
|
||||
free(jsdobj);
|
||||
}
|
||||
|
||||
static JSDObject*
|
||||
_createJSDObject(JSDContext* jsdc, JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSDObject* jsdobj;
|
||||
JSStackFrame* fp;
|
||||
JSStackFrame* iter = NULL;
|
||||
const char* newURL;
|
||||
jsbytecode* pc;
|
||||
|
||||
JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
|
||||
|
||||
jsdobj = (JSDObject*) calloc(1, sizeof(JSDObject));
|
||||
if (jsdobj)
|
||||
{
|
||||
JS_INIT_CLIST(&jsdobj->links);
|
||||
JS_APPEND_LINK(&jsdobj->links, &jsdc->objectsList);
|
||||
jsdobj->obj = obj;
|
||||
JS_HashTableAdd(jsdc->objectsTable, obj, jsdobj);
|
||||
|
||||
if (jsdc->flags & JSD_DISABLE_OBJECT_TRACE)
|
||||
return jsdobj;
|
||||
|
||||
/* walk the stack to find js frame (if any) causing creation */
|
||||
while (NULL != (fp = JS_FrameIterator(cx, &iter)))
|
||||
{
|
||||
if( !JS_IsNativeFrame(cx, fp) )
|
||||
{
|
||||
JSScript* script = JS_GetFrameScript(cx, fp);
|
||||
if( !script )
|
||||
continue;
|
||||
|
||||
newURL = JS_GetScriptFilename(cx, script);
|
||||
if( newURL )
|
||||
jsdobj->newURL = jsd_AddAtom(jsdc, newURL);
|
||||
|
||||
pc = JS_GetFramePC(cx, fp);
|
||||
if( pc )
|
||||
jsdobj->newLineno = JS_PCToLineNumber(cx, script, pc);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return jsdobj;
|
||||
}
|
||||
|
||||
void JS_DLL_CALLBACK
|
||||
jsd_ObjectHook(JSContext *cx, JSObject *obj, JSBool isNew, void *closure)
|
||||
{
|
||||
JSDObject* jsdobj;
|
||||
JSDContext* jsdc = (JSDContext*) closure;
|
||||
|
||||
if( ! jsdc || ! jsdc->inited )
|
||||
return;
|
||||
|
||||
JSD_LOCK_OBJECTS(jsdc);
|
||||
if(isNew)
|
||||
{
|
||||
jsdobj = _createJSDObject(jsdc, cx, obj);
|
||||
TRACEOBJ(jsdc, jsdobj, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
|
||||
if( jsdobj )
|
||||
{
|
||||
TRACEOBJ(jsdc, jsdobj, 1);
|
||||
_destroyJSDObject(jsdc, jsdobj);
|
||||
}
|
||||
}
|
||||
JSD_UNLOCK_OBJECTS(jsdc);
|
||||
}
|
||||
|
||||
void
|
||||
jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
|
||||
JSStackFrame *fp)
|
||||
{
|
||||
JSDObject* jsdobj;
|
||||
JSScript* script;
|
||||
JSDScript* jsdscript;
|
||||
const char* ctorURL;
|
||||
const char* ctorName;
|
||||
|
||||
JSD_LOCK_OBJECTS(jsdc);
|
||||
jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
|
||||
if( jsdobj && !jsdobj->ctorURL && !JS_IsNativeFrame(cx, fp) )
|
||||
{
|
||||
script = JS_GetFrameScript(cx, fp);
|
||||
if( script )
|
||||
{
|
||||
ctorURL = JS_GetScriptFilename(cx, script);
|
||||
if( ctorURL )
|
||||
jsdobj->ctorURL = jsd_AddAtom(jsdc, ctorURL);
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if( jsdscript )
|
||||
{
|
||||
ctorName = jsd_GetScriptFunctionName(jsdc, jsdscript);
|
||||
if( ctorName )
|
||||
jsdobj->ctorName = jsd_AddAtom(jsdc, ctorName);
|
||||
}
|
||||
jsdobj->ctorLineno = JS_GetScriptBaseLineNumber(cx, script);
|
||||
}
|
||||
}
|
||||
TRACEOBJ(jsdc, jsdobj, 3);
|
||||
JSD_UNLOCK_OBJECTS(jsdc);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSHashNumber)
|
||||
_hash_root(const void *key)
|
||||
{
|
||||
return ((JSHashNumber) key) >> 2; /* help lame MSVC1.5 on Win16 */
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_InitObjectManager(JSDContext* jsdc)
|
||||
{
|
||||
JS_INIT_CLIST(&jsdc->objectsList);
|
||||
jsdc->objectsTable = JS_NewHashTable(256, _hash_root,
|
||||
JS_CompareValues, JS_CompareValues,
|
||||
NULL, NULL);
|
||||
return (JSBool) jsdc->objectsTable;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_DestroyObjectManager(JSDContext* jsdc)
|
||||
{
|
||||
JSD_LOCK_OBJECTS(jsdc);
|
||||
while( !JS_CLIST_IS_EMPTY(&jsdc->objectsList) )
|
||||
_destroyJSDObject(jsdc, (JSDObject*)JS_NEXT_LINK(&jsdc->objectsList));
|
||||
JS_HashTableDestroy(jsdc->objectsTable);
|
||||
JSD_UNLOCK_OBJECTS(jsdc);
|
||||
}
|
||||
|
||||
JSDObject*
|
||||
jsd_IterateObjects(JSDContext* jsdc, JSDObject** iterp)
|
||||
{
|
||||
JSDObject *jsdobj = *iterp;
|
||||
|
||||
JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
|
||||
|
||||
if( !jsdobj )
|
||||
jsdobj = (JSDObject *)jsdc->objectsList.next;
|
||||
if( jsdobj == (JSDObject *)&jsdc->objectsList )
|
||||
return NULL;
|
||||
*iterp = (JSDObject*) jsdobj->links.next;
|
||||
return jsdobj;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
jsd_GetWrappedObject(JSDContext* jsdc, JSDObject* jsdobj)
|
||||
{
|
||||
return jsdobj->obj;
|
||||
}
|
||||
|
||||
const char*
|
||||
jsd_GetObjectNewURL(JSDContext* jsdc, JSDObject* jsdobj)
|
||||
{
|
||||
if( jsdobj->newURL )
|
||||
return JSD_ATOM_TO_STRING(jsdobj->newURL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetObjectNewLineNumber(JSDContext* jsdc, JSDObject* jsdobj)
|
||||
{
|
||||
return jsdobj->newLineno;
|
||||
}
|
||||
|
||||
const char*
|
||||
jsd_GetObjectConstructorURL(JSDContext* jsdc, JSDObject* jsdobj)
|
||||
{
|
||||
if( jsdobj->ctorURL )
|
||||
return JSD_ATOM_TO_STRING(jsdobj->ctorURL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetObjectConstructorLineNumber(JSDContext* jsdc, JSDObject* jsdobj)
|
||||
{
|
||||
return jsdobj->ctorLineno;
|
||||
}
|
||||
|
||||
const char*
|
||||
jsd_GetObjectConstructorName(JSDContext* jsdc, JSDObject* jsdobj)
|
||||
{
|
||||
if( jsdobj->ctorName )
|
||||
return JSD_ATOM_TO_STRING(jsdobj->ctorName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSDObject*
|
||||
jsd_GetJSDObjectForJSObject(JSDContext* jsdc, JSObject* jsobj)
|
||||
{
|
||||
JSDObject* jsdobj;
|
||||
|
||||
JSD_LOCK_OBJECTS(jsdc);
|
||||
jsdobj = (JSDObject*) JS_HashTableLookup(jsdc->objectsTable, jsobj);
|
||||
JSD_UNLOCK_OBJECTS(jsdc);
|
||||
return jsdobj;
|
||||
}
|
||||
|
||||
JSDObject*
|
||||
jsd_GetObjectForValue(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return jsd_GetJSDObjectForJSObject(jsdc, JSVAL_TO_OBJECT(jsdval->val));
|
||||
}
|
||||
|
||||
JSDValue*
|
||||
jsd_GetValueForObject(JSDContext* jsdc, JSDObject* jsdobj)
|
||||
{
|
||||
return jsd_NewValue(jsdc, OBJECT_TO_JSVAL(jsdobj->obj));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,865 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - Script support
|
||||
*/
|
||||
|
||||
#include "jsd.h"
|
||||
|
||||
/* Comment this out to disable (NT specific) dumping as we go */
|
||||
/*
|
||||
** #ifdef DEBUG
|
||||
** #define JSD_DUMP 1
|
||||
** #endif
|
||||
*/
|
||||
|
||||
#define NOT_SET_YET -1
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef DEBUG
|
||||
void JSD_ASSERT_VALID_SCRIPT(JSDScript* jsdscript)
|
||||
{
|
||||
JS_ASSERT(jsdscript);
|
||||
JS_ASSERT(jsdscript->script);
|
||||
}
|
||||
void JSD_ASSERT_VALID_EXEC_HOOK(JSDExecHook* jsdhook)
|
||||
{
|
||||
JS_ASSERT(jsdhook);
|
||||
JS_ASSERT(jsdhook->hook);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LIVEWIRE
|
||||
static JSBool
|
||||
HasFileExtention(const char* name, const char* ext)
|
||||
{
|
||||
int i;
|
||||
int len = strlen(ext);
|
||||
const char* p = strrchr(name,'.');
|
||||
if( !p )
|
||||
return JS_FALSE;
|
||||
p++;
|
||||
for(i = 0; i < len; i++ )
|
||||
{
|
||||
JS_ASSERT(islower(ext[i]));
|
||||
if( 0 == p[i] || tolower(p[i]) != ext[i] )
|
||||
return JS_FALSE;
|
||||
}
|
||||
if( 0 != p[i] )
|
||||
return JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif /* LIVEWIRE */
|
||||
|
||||
static JSDScript*
|
||||
_newJSDScript(JSDContext* jsdc,
|
||||
JSContext *cx,
|
||||
JSScript *script,
|
||||
JSFunction* function)
|
||||
{
|
||||
JSDScript* jsdscript;
|
||||
uintN lineno;
|
||||
const char* raw_filename;
|
||||
|
||||
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||
|
||||
/* these are inlined javascript: urls and we can't handle them now */
|
||||
lineno = (uintN) JS_GetScriptBaseLineNumber(cx, script);
|
||||
if( lineno == 0 )
|
||||
return NULL;
|
||||
|
||||
jsdscript = (JSDScript*) calloc(1, sizeof(JSDScript));
|
||||
if( ! jsdscript )
|
||||
return NULL;
|
||||
|
||||
raw_filename = JS_GetScriptFilename(cx,script);
|
||||
|
||||
JS_HashTableAdd(jsdc->scriptsTable, (void *)script, (void *)jsdscript);
|
||||
JS_APPEND_LINK(&jsdscript->links, &jsdc->scripts);
|
||||
jsdscript->jsdc = jsdc;
|
||||
jsdscript->script = script;
|
||||
jsdscript->function = function;
|
||||
jsdscript->lineBase = lineno;
|
||||
jsdscript->lineExtent = (uintN)NOT_SET_YET;
|
||||
jsdscript->data = NULL;
|
||||
#ifndef LIVEWIRE
|
||||
jsdscript->url = (char*) jsd_BuildNormalizedURL(raw_filename);
|
||||
#else
|
||||
jsdscript->app = LWDBG_GetCurrentApp();
|
||||
if( jsdscript->app && raw_filename )
|
||||
{
|
||||
jsdscript->url = jsdlw_BuildAppRelativeFilename(jsdscript->app, raw_filename);
|
||||
if( function )
|
||||
{
|
||||
jsdscript->lwscript =
|
||||
LWDBG_GetScriptOfFunction(jsdscript->app,
|
||||
JS_GetFunctionName(function));
|
||||
|
||||
/* also, make sure this file is added to filelist if is .js file */
|
||||
if( HasFileExtention(raw_filename,"js") ||
|
||||
HasFileExtention(raw_filename,"sjs") )
|
||||
{
|
||||
jsdlw_PreLoadSource(jsdc, jsdscript->app, raw_filename, JS_FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jsdscript->lwscript = LWDBG_GetCurrentTopLevelScript();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
JS_INIT_CLIST(&jsdscript->hooks);
|
||||
|
||||
return jsdscript;
|
||||
}
|
||||
|
||||
static void
|
||||
_destroyJSDScript(JSDContext* jsdc,
|
||||
JSDScript* jsdscript)
|
||||
{
|
||||
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||
|
||||
/* destroy all hooks */
|
||||
jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
|
||||
|
||||
JS_REMOVE_LINK(&jsdscript->links);
|
||||
if(jsdscript->url)
|
||||
free(jsdscript->url);
|
||||
|
||||
if (jsdscript->profileData)
|
||||
free(jsdscript->profileData);
|
||||
|
||||
if(jsdscript)
|
||||
free(jsdscript);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef JSD_DUMP
|
||||
#ifndef XP_WIN
|
||||
void
|
||||
OutputDebugString (char *buf)
|
||||
{
|
||||
fprintf (stderr, "%s", buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_dumpJSDScript(JSDContext* jsdc, JSDScript* jsdscript, const char* leadingtext)
|
||||
{
|
||||
const char* name;
|
||||
const char* fun;
|
||||
uintN base;
|
||||
uintN extent;
|
||||
char Buf[256];
|
||||
|
||||
name = jsd_GetScriptFilename(jsdc, jsdscript);
|
||||
fun = jsd_GetScriptFunctionName(jsdc, jsdscript);
|
||||
base = jsd_GetScriptBaseLineNumber(jsdc, jsdscript);
|
||||
extent = jsd_GetScriptLineExtent(jsdc, jsdscript);
|
||||
|
||||
sprintf( Buf, "%sscript=%08X, %s, %s, %d-%d\n",
|
||||
leadingtext,
|
||||
(unsigned) jsdscript->script,
|
||||
name ? name : "no URL",
|
||||
fun ? fun : "no fun",
|
||||
base, base + extent - 1 );
|
||||
OutputDebugString( Buf );
|
||||
}
|
||||
|
||||
static void
|
||||
_dumpJSDScriptList( JSDContext* jsdc )
|
||||
{
|
||||
JSDScript* iterp = NULL;
|
||||
JSDScript* jsdscript = NULL;
|
||||
|
||||
OutputDebugString( "*** JSDScriptDump\n" );
|
||||
while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
|
||||
_dumpJSDScript( jsdc, jsdscript, " script: " );
|
||||
}
|
||||
#endif /* JSD_DUMP */
|
||||
|
||||
/***************************************************************************/
|
||||
JS_STATIC_DLL_CALLBACK(JSHashNumber)
|
||||
jsd_hash_script(const void *key)
|
||||
{
|
||||
return ((JSHashNumber) key) >> 2; /* help lame MSVC1.5 on Win16 */
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void *)
|
||||
jsd_alloc_script_table(void *priv, size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
jsd_free_script_table(void *priv, void *item)
|
||||
{
|
||||
free(item);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSHashEntry *)
|
||||
jsd_alloc_script_entry(void *priv, const void *item)
|
||||
{
|
||||
return (JSHashEntry*) malloc(sizeof(JSHashEntry));
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
jsd_free_script_entry(void *priv, JSHashEntry *he, uintN flag)
|
||||
{
|
||||
if (flag == HT_FREE_ENTRY)
|
||||
{
|
||||
_destroyJSDScript((JSDContext*) priv, (JSDScript*) he->value);
|
||||
free(he);
|
||||
}
|
||||
}
|
||||
|
||||
static JSHashAllocOps script_alloc_ops = {
|
||||
jsd_alloc_script_table, jsd_free_script_table,
|
||||
jsd_alloc_script_entry, jsd_free_script_entry
|
||||
};
|
||||
|
||||
#ifndef JSD_SCRIPT_HASH_SIZE
|
||||
#define JSD_SCRIPT_HASH_SIZE 1024
|
||||
#endif
|
||||
|
||||
JSBool
|
||||
jsd_InitScriptManager(JSDContext* jsdc)
|
||||
{
|
||||
JS_INIT_CLIST(&jsdc->scripts);
|
||||
jsdc->scriptsTable = JS_NewHashTable(JSD_SCRIPT_HASH_SIZE, jsd_hash_script,
|
||||
JS_CompareValues, JS_CompareValues,
|
||||
&script_alloc_ops, (void*) jsdc);
|
||||
return (JSBool) jsdc->scriptsTable;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_DestroyScriptManager(JSDContext* jsdc)
|
||||
{
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
if (jsdc->scriptsTable)
|
||||
JS_HashTableDestroy(jsdc->scriptsTable);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
}
|
||||
|
||||
JSDScript*
|
||||
jsd_FindJSDScript( JSDContext* jsdc,
|
||||
JSScript *script )
|
||||
{
|
||||
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||
return (JSDScript*) JS_HashTableLookup(jsdc->scriptsTable, (void *)script);
|
||||
}
|
||||
|
||||
JSDProfileData*
|
||||
jsd_GetScriptProfileData(JSDContext* jsdc, JSDScript *script)
|
||||
{
|
||||
if (!script->profileData)
|
||||
script->profileData = (JSDProfileData*)calloc(1, sizeof(JSDProfileData));
|
||||
|
||||
return script->profileData;
|
||||
}
|
||||
|
||||
uint32
|
||||
jsd_GetScriptFlags(JSDContext *jsdc, JSDScript *script)
|
||||
{
|
||||
return script->flags;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_SetScriptFlags(JSDContext *jsdc, JSDScript *script, uint32 flags)
|
||||
{
|
||||
script->flags = flags;
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetScriptCallCount(JSDContext* jsdc, JSDScript *script)
|
||||
{
|
||||
if (script->profileData)
|
||||
return script->profileData->callCount;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script)
|
||||
{
|
||||
if (script->profileData)
|
||||
return script->profileData->maxRecurseDepth;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
jsdouble
|
||||
jsd_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script)
|
||||
{
|
||||
if (script->profileData)
|
||||
return script->profileData->minExecutionTime;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
jsdouble
|
||||
jsd_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script)
|
||||
{
|
||||
if (script->profileData)
|
||||
return script->profileData->maxExecutionTime;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
jsdouble
|
||||
jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script)
|
||||
{
|
||||
if (script->profileData)
|
||||
return script->profileData->totalExecutionTime;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
jsdouble
|
||||
jsd_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
|
||||
{
|
||||
if (script->profileData)
|
||||
return script->profileData->minOwnExecutionTime;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
jsdouble
|
||||
jsd_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
|
||||
{
|
||||
if (script->profileData)
|
||||
return script->profileData->maxOwnExecutionTime;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
jsdouble
|
||||
jsd_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
|
||||
{
|
||||
if (script->profileData)
|
||||
return script->profileData->totalOwnExecutionTime;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script)
|
||||
{
|
||||
if (script->profileData)
|
||||
{
|
||||
free(script->profileData);
|
||||
script->profileData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSScript *
|
||||
jsd_GetJSScript (JSDContext *jsdc, JSDScript *script)
|
||||
{
|
||||
return script->script;
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
jsd_GetJSFunction (JSDContext *jsdc, JSDScript *script)
|
||||
{
|
||||
return script->function;
|
||||
}
|
||||
|
||||
JSDScript*
|
||||
jsd_IterateScripts(JSDContext* jsdc, JSDScript **iterp)
|
||||
{
|
||||
JSDScript *jsdscript = *iterp;
|
||||
|
||||
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||
|
||||
if( !jsdscript )
|
||||
jsdscript = (JSDScript *)jsdc->scripts.next;
|
||||
if( jsdscript == (JSDScript *)&jsdc->scripts )
|
||||
return NULL;
|
||||
*iterp = (JSDScript*) jsdscript->links.next;
|
||||
return jsdscript;
|
||||
}
|
||||
|
||||
void *
|
||||
jsd_SetScriptPrivate(JSDScript *jsdscript, void *data)
|
||||
{
|
||||
void *rval = jsdscript->data;
|
||||
jsdscript->data = data;
|
||||
return rval;
|
||||
}
|
||||
|
||||
void *
|
||||
jsd_GetScriptPrivate(JSDScript *jsdscript)
|
||||
{
|
||||
return jsdscript->data;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsActiveScript(JSDContext* jsdc, JSDScript *jsdscript)
|
||||
{
|
||||
JSDScript *current;
|
||||
|
||||
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||
|
||||
for( current = (JSDScript *)jsdc->scripts.next;
|
||||
current != (JSDScript *)&jsdc->scripts;
|
||||
current = (JSDScript *)current->links.next )
|
||||
{
|
||||
if(jsdscript == current)
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
const char*
|
||||
jsd_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript)
|
||||
{
|
||||
return jsdscript->url;
|
||||
}
|
||||
|
||||
const char*
|
||||
jsd_GetScriptFunctionName(JSDContext* jsdc, JSDScript *jsdscript)
|
||||
{
|
||||
if( ! jsdscript->function )
|
||||
return NULL;
|
||||
return JS_GetFunctionName(jsdscript->function);
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetScriptBaseLineNumber(JSDContext* jsdc, JSDScript *jsdscript)
|
||||
{
|
||||
return jsdscript->lineBase;
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript)
|
||||
{
|
||||
if( NOT_SET_YET == (int)jsdscript->lineExtent )
|
||||
jsdscript->lineExtent = JS_GetScriptLineExtent(jsdc->dumbContext, jsdscript->script);
|
||||
return jsdscript->lineExtent;
|
||||
}
|
||||
|
||||
jsuword
|
||||
jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line)
|
||||
{
|
||||
#ifdef LIVEWIRE
|
||||
if( jsdscript && jsdscript->lwscript )
|
||||
{
|
||||
uintN newline;
|
||||
jsdlw_RawToProcessedLineNumber(jsdc, jsdscript, line, &newline);
|
||||
if( line != newline )
|
||||
line = newline;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (jsuword) JS_LineNumberToPC(jsdc->dumbContext,
|
||||
jsdscript->script, line );
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
|
||||
{
|
||||
uintN first = jsdscript->lineBase;
|
||||
uintN last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1;
|
||||
uintN line = JS_PCToLineNumber(jsdc->dumbContext,
|
||||
jsdscript->script, (jsbytecode*)pc);
|
||||
|
||||
if( line < first )
|
||||
return first;
|
||||
if( line > last )
|
||||
return last;
|
||||
|
||||
#ifdef LIVEWIRE
|
||||
if( jsdscript && jsdscript->lwscript )
|
||||
{
|
||||
uintN newline;
|
||||
jsdlw_ProcessedToRawLineNumber(jsdc, jsdscript, line, &newline);
|
||||
line = newline;
|
||||
}
|
||||
#endif
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata)
|
||||
{
|
||||
JSD_LOCK();
|
||||
jsdc->scriptHook = hook;
|
||||
jsdc->scriptHookData = callerdata;
|
||||
JSD_UNLOCK();
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata)
|
||||
{
|
||||
JSD_LOCK();
|
||||
if( hook )
|
||||
*hook = jsdc->scriptHook;
|
||||
if( callerdata )
|
||||
*callerdata = jsdc->scriptHookData;
|
||||
JSD_UNLOCK();
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void JS_DLL_CALLBACK
|
||||
jsd_NewScriptHookProc(
|
||||
JSContext *cx,
|
||||
const char *filename, /* URL this script loads from */
|
||||
uintN lineno, /* line where this script starts */
|
||||
JSScript *script,
|
||||
JSFunction *fun,
|
||||
void* callerdata )
|
||||
{
|
||||
JSDScript* jsdscript = NULL;
|
||||
JSDContext* jsdc = (JSDContext*) callerdata;
|
||||
JSD_ScriptHookProc hook;
|
||||
void* hookData;
|
||||
|
||||
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
||||
|
||||
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||
return;
|
||||
|
||||
#ifdef LIVEWIRE
|
||||
if( 1 == lineno )
|
||||
jsdlw_PreLoadSource(jsdc, LWDBG_GetCurrentApp(), filename, JS_TRUE );
|
||||
#endif
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = _newJSDScript(jsdc, cx, script, fun);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if( ! jsdscript )
|
||||
return;
|
||||
|
||||
#ifdef JSD_DUMP
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
_dumpJSDScript(jsdc, jsdscript, "***NEW Script: ");
|
||||
_dumpJSDScriptList( jsdc );
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
#endif /* JSD_DUMP */
|
||||
|
||||
/* local in case jsdc->scriptHook gets cleared on another thread */
|
||||
JSD_LOCK();
|
||||
hook = jsdc->scriptHook;
|
||||
hookData = jsdc->scriptHookData;
|
||||
JSD_UNLOCK();
|
||||
|
||||
if( hook )
|
||||
hook(jsdc, jsdscript, JS_TRUE, hookData);
|
||||
}
|
||||
|
||||
void JS_DLL_CALLBACK
|
||||
jsd_DestroyScriptHookProc(
|
||||
JSContext *cx,
|
||||
JSScript *script,
|
||||
void* callerdata )
|
||||
{
|
||||
JSDScript* jsdscript = NULL;
|
||||
JSDContext* jsdc = (JSDContext*) callerdata;
|
||||
JSD_ScriptHookProc hook;
|
||||
void* hookData;
|
||||
|
||||
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
||||
|
||||
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||
return;
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
|
||||
if( ! jsdscript )
|
||||
return;
|
||||
|
||||
#ifdef JSD_DUMP
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
_dumpJSDScript(jsdc, jsdscript, "***DESTROY Script: ");
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
#endif /* JSD_DUMP */
|
||||
|
||||
/* local in case hook gets cleared on another thread */
|
||||
JSD_LOCK();
|
||||
hook = jsdc->scriptHook;
|
||||
hookData = jsdc->scriptHookData;
|
||||
JSD_UNLOCK();
|
||||
|
||||
if( hook )
|
||||
hook(jsdc, jsdscript, JS_FALSE, hookData);
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
JS_HashTableRemove(jsdc->scriptsTable, (void *)script);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
|
||||
#ifdef JSD_DUMP
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
_dumpJSDScriptList(jsdc);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
#endif /* JSD_DUMP */
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static JSDExecHook*
|
||||
_findHook(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
|
||||
{
|
||||
JSDExecHook* jsdhook;
|
||||
JSCList* list = &jsdscript->hooks;
|
||||
|
||||
for( jsdhook = (JSDExecHook*)list->next;
|
||||
jsdhook != (JSDExecHook*)list;
|
||||
jsdhook = (JSDExecHook*)jsdhook->links.next )
|
||||
{
|
||||
if (jsdhook->pc == pc)
|
||||
return jsdhook;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
_isActiveHook(JSDContext* jsdc, JSScript *script, JSDExecHook* jsdhook)
|
||||
{
|
||||
JSDExecHook* current;
|
||||
JSCList* list;
|
||||
JSDScript* jsdscript;
|
||||
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||
if( ! jsdscript)
|
||||
{
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
list = &jsdscript->hooks;
|
||||
|
||||
for( current = (JSDExecHook*)list->next;
|
||||
current != (JSDExecHook*)list;
|
||||
current = (JSDExecHook*)current->links.next )
|
||||
{
|
||||
if(current == jsdhook)
|
||||
{
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
JSTrapStatus JS_DLL_CALLBACK
|
||||
jsd_TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
void *closure)
|
||||
{
|
||||
JSDExecHook* jsdhook = (JSDExecHook*) JSVAL_TO_PRIVATE(((jsval)closure));
|
||||
JSD_ExecutionHookProc hook;
|
||||
void* hookData;
|
||||
JSDContext* jsdc;
|
||||
JSDScript* jsdscript;
|
||||
|
||||
JSD_LOCK();
|
||||
|
||||
if( NULL == (jsdc = jsd_JSDContextForJSContext(cx)) ||
|
||||
! _isActiveHook(jsdc, script, jsdhook) )
|
||||
{
|
||||
JSD_UNLOCK();
|
||||
return JSTRAP_CONTINUE;
|
||||
}
|
||||
|
||||
JSD_ASSERT_VALID_EXEC_HOOK(jsdhook);
|
||||
JS_ASSERT(jsdhook->pc == (jsuword)pc);
|
||||
JS_ASSERT(jsdhook->jsdscript->script == script);
|
||||
JS_ASSERT(jsdhook->jsdscript->jsdc == jsdc);
|
||||
|
||||
hook = jsdhook->hook;
|
||||
hookData = jsdhook->callerdata;
|
||||
jsdscript = jsdhook->jsdscript;
|
||||
|
||||
/* do not use jsdhook-> after this point */
|
||||
JSD_UNLOCK();
|
||||
|
||||
if( ! jsdc || ! jsdc->inited )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
#ifdef LIVEWIRE
|
||||
if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (jsuword)pc) )
|
||||
return JSTRAP_CONTINUE;
|
||||
#endif
|
||||
|
||||
return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_BREAKPOINT,
|
||||
hook, hookData, rval);
|
||||
}
|
||||
|
||||
|
||||
|
||||
JSBool
|
||||
jsd_SetExecutionHook(JSDContext* jsdc,
|
||||
JSDScript* jsdscript,
|
||||
jsuword pc,
|
||||
JSD_ExecutionHookProc hook,
|
||||
void* callerdata)
|
||||
{
|
||||
JSDExecHook* jsdhook;
|
||||
|
||||
JSD_LOCK();
|
||||
if( ! hook )
|
||||
{
|
||||
jsd_ClearExecutionHook(jsdc, jsdscript, pc);
|
||||
JSD_UNLOCK();
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
jsdhook = _findHook(jsdc, jsdscript, pc);
|
||||
if( jsdhook )
|
||||
{
|
||||
jsdhook->hook = hook;
|
||||
jsdhook->callerdata = callerdata;
|
||||
return JS_TRUE;
|
||||
}
|
||||
/* else... */
|
||||
|
||||
jsdhook = (JSDExecHook*)calloc(1, sizeof(JSDExecHook));
|
||||
if( ! jsdhook )
|
||||
return JS_FALSE;
|
||||
jsdhook->jsdscript = jsdscript;
|
||||
jsdhook->pc = pc;
|
||||
jsdhook->hook = hook;
|
||||
jsdhook->callerdata = callerdata;
|
||||
|
||||
if( ! JS_SetTrap(jsdc->dumbContext, jsdscript->script,
|
||||
(jsbytecode*)pc, jsd_TrapHandler,
|
||||
(void*) PRIVATE_TO_JSVAL(jsdhook)) )
|
||||
{
|
||||
free(jsdhook);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_APPEND_LINK(&jsdhook->links, &jsdscript->hooks);
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_ClearExecutionHook(JSDContext* jsdc,
|
||||
JSDScript* jsdscript,
|
||||
jsuword pc)
|
||||
{
|
||||
JSDExecHook* jsdhook;
|
||||
|
||||
JSD_LOCK();
|
||||
|
||||
jsdhook = _findHook(jsdc, jsdscript, pc);
|
||||
if( ! jsdhook )
|
||||
{
|
||||
JS_ASSERT(0);
|
||||
JSD_UNLOCK();
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_ClearTrap(jsdc->dumbContext, jsdscript->script,
|
||||
(jsbytecode*)pc, NULL, NULL );
|
||||
|
||||
JS_REMOVE_LINK(&jsdhook->links);
|
||||
free(jsdhook);
|
||||
|
||||
JSD_UNLOCK();
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript)
|
||||
{
|
||||
JSDExecHook* jsdhook;
|
||||
JSCList* list = &jsdscript->hooks;
|
||||
|
||||
JSD_LOCK();
|
||||
|
||||
while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) )
|
||||
{
|
||||
JS_REMOVE_LINK(&jsdhook->links);
|
||||
free(jsdhook);
|
||||
}
|
||||
|
||||
JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script);
|
||||
JSD_UNLOCK();
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_ClearAllExecutionHooks(JSDContext* jsdc)
|
||||
{
|
||||
JSDScript* jsdscript;
|
||||
JSDScript* iterp = NULL;
|
||||
|
||||
JSD_LOCK();
|
||||
while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
|
||||
jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
|
||||
JSD_UNLOCK();
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_ScriptCreated(JSDContext* jsdc,
|
||||
JSContext *cx,
|
||||
const char *filename, /* URL this script loads from */
|
||||
uintN lineno, /* line where this script starts */
|
||||
JSScript *script,
|
||||
JSFunction *fun)
|
||||
{
|
||||
jsd_NewScriptHookProc(cx, filename, lineno, script, fun, jsdc);
|
||||
}
|
||||
|
||||
void
|
||||
jsd_ScriptDestroyed(JSDContext* jsdc,
|
||||
JSContext *cx,
|
||||
JSScript *script)
|
||||
{
|
||||
jsd_DestroyScriptHookProc(cx, script, jsdc);
|
||||
}
|
||||
@@ -1,607 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - Call stack support
|
||||
*/
|
||||
|
||||
#include "jsd.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
void JSD_ASSERT_VALID_THREAD_STATE(JSDThreadState* jsdthreadstate)
|
||||
{
|
||||
JS_ASSERT(jsdthreadstate);
|
||||
JS_ASSERT(jsdthreadstate->stackDepth > 0);
|
||||
}
|
||||
|
||||
void JSD_ASSERT_VALID_STACK_FRAME(JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
JS_ASSERT(jsdframe);
|
||||
JS_ASSERT(jsdframe->jsdthreadstate);
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSDStackFrameInfo*
|
||||
_addNewFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSScript* script,
|
||||
jsuword pc,
|
||||
JSStackFrame* fp)
|
||||
{
|
||||
JSDStackFrameInfo* jsdframe;
|
||||
JSDScript* jsdscript = NULL;
|
||||
|
||||
if (!JS_IsNativeFrame(jsdthreadstate->context, fp))
|
||||
{
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if (!jsdscript || (jsdc->flags & JSD_HIDE_DISABLED_FRAMES &&
|
||||
!JSD_IS_DEBUG_ENABLED(jsdc, jsdscript)))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!JSD_IS_DEBUG_ENABLED(jsdc, jsdscript))
|
||||
jsdthreadstate->flags |= TS_HAS_DISABLED_FRAME;
|
||||
}
|
||||
|
||||
jsdframe = (JSDStackFrameInfo*) calloc(1, sizeof(JSDStackFrameInfo));
|
||||
if( ! jsdframe )
|
||||
return NULL;
|
||||
|
||||
jsdframe->jsdthreadstate = jsdthreadstate;
|
||||
jsdframe->jsdscript = jsdscript;
|
||||
jsdframe->pc = pc;
|
||||
jsdframe->fp = fp;
|
||||
|
||||
JS_APPEND_LINK(&jsdframe->links, &jsdthreadstate->stack);
|
||||
jsdthreadstate->stackDepth++;
|
||||
|
||||
return jsdframe;
|
||||
}
|
||||
|
||||
static void
|
||||
_destroyFrame(JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
/* kill any alloc'd objects in frame here... */
|
||||
|
||||
if( jsdframe )
|
||||
free(jsdframe);
|
||||
}
|
||||
|
||||
JSDThreadState*
|
||||
jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
|
||||
{
|
||||
JSDThreadState* jsdthreadstate;
|
||||
JSStackFrame * iter = NULL;
|
||||
JSStackFrame * fp;
|
||||
|
||||
jsdthreadstate = (JSDThreadState*)calloc(1, sizeof(JSDThreadState));
|
||||
if( ! jsdthreadstate )
|
||||
return NULL;
|
||||
|
||||
jsdthreadstate->context = cx;
|
||||
jsdthreadstate->thread = JSD_CURRENT_THREAD();
|
||||
JS_INIT_CLIST(&jsdthreadstate->stack);
|
||||
jsdthreadstate->stackDepth = 0;
|
||||
|
||||
while( NULL != (fp = JS_FrameIterator(cx, &iter)) )
|
||||
{
|
||||
JSScript* script = JS_GetFrameScript(cx, fp);
|
||||
jsuword pc = (jsuword) JS_GetFramePC(cx, fp);
|
||||
|
||||
/*
|
||||
* don't construct a JSDStackFrame for dummy frames (those without a
|
||||
* |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES
|
||||
* isn't set.
|
||||
*/
|
||||
if (JS_GetFrameThis(cx, fp) &&
|
||||
((jsdc->flags & JSD_INCLUDE_NATIVE_FRAMES) ||
|
||||
!JS_IsNativeFrame(cx, fp)))
|
||||
{
|
||||
JSDStackFrameInfo *frame;
|
||||
|
||||
frame = _addNewFrame( jsdc, jsdthreadstate, script, pc, fp );
|
||||
|
||||
if ((jsdthreadstate->stackDepth == 0 && !frame) ||
|
||||
(jsdthreadstate->stackDepth == 1 && frame &&
|
||||
frame->jsdscript && !JSD_IS_DEBUG_ENABLED(jsdc, frame->jsdscript)))
|
||||
{
|
||||
/*
|
||||
* if we failed to create the first frame, or the top frame
|
||||
* is not enabled for debugging, fail the entire thread state.
|
||||
*/
|
||||
JS_INIT_CLIST(&jsdthreadstate->links);
|
||||
jsd_DestroyThreadState(jsdc, jsdthreadstate);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jsdthreadstate->stackDepth == 0)
|
||||
{
|
||||
free(jsdthreadstate);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
JS_APPEND_LINK(&jsdthreadstate->links, &jsdc->threadsStates);
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
return jsdthreadstate;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_DestroyThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||
{
|
||||
JSDStackFrameInfo* jsdframe;
|
||||
JSCList* list;
|
||||
|
||||
JSD_ASSERT_VALID_THREAD_STATE(jsdthreadstate);
|
||||
JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread);
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
JS_REMOVE_LINK(&jsdthreadstate->links);
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
list = &jsdthreadstate->stack;
|
||||
while( (JSDStackFrameInfo*)list != (jsdframe = (JSDStackFrameInfo*)list->next) )
|
||||
{
|
||||
JS_REMOVE_LINK(&jsdframe->links);
|
||||
_destroyFrame(jsdframe);
|
||||
}
|
||||
free(jsdthreadstate);
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetCountOfStackFrames(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||
{
|
||||
uintN count = 0;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidThreadState(jsdc, jsdthreadstate) )
|
||||
count = jsdthreadstate->stackDepth;
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
JSDStackFrameInfo*
|
||||
jsd_GetStackFrame(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||
{
|
||||
JSDStackFrameInfo* jsdframe = NULL;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidThreadState(jsdc, jsdthreadstate) )
|
||||
jsdframe = (JSDStackFrameInfo*) JS_LIST_HEAD(&jsdthreadstate->stack);
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
return jsdframe;
|
||||
}
|
||||
|
||||
JSContext *
|
||||
jsd_GetJSContext (JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||
{
|
||||
JSContext* cx = NULL;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
if( jsd_IsValidThreadState(jsdc, jsdthreadstate) )
|
||||
cx = jsdthreadstate->context;
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
return cx;
|
||||
}
|
||||
|
||||
JSDStackFrameInfo*
|
||||
jsd_GetCallingStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
JSDStackFrameInfo* nextjsdframe = NULL;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
if( JS_LIST_HEAD(&jsdframe->links) != &jsdframe->jsdthreadstate->stack )
|
||||
nextjsdframe = (JSDStackFrameInfo*) JS_LIST_HEAD(&jsdframe->links);
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
return nextjsdframe;
|
||||
}
|
||||
|
||||
JSDScript*
|
||||
jsd_GetScriptForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
JSDScript* jsdscript = NULL;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
jsdscript = jsdframe->jsdscript;
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
return jsdscript;
|
||||
}
|
||||
|
||||
jsuword
|
||||
jsd_GetPCForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
jsuword pc = 0;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
pc = jsdframe->pc;
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
JSDValue*
|
||||
jsd_GetCallObjectForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
JSObject* obj;
|
||||
JSDValue* jsdval = NULL;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
obj = JS_GetFrameCallObject(jsdthreadstate->context, jsdframe->fp);
|
||||
if(obj)
|
||||
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
return jsdval;
|
||||
}
|
||||
|
||||
JSDValue*
|
||||
jsd_GetScopeChainForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
JSObject* obj;
|
||||
JSDValue* jsdval = NULL;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
obj = JS_GetFrameScopeChain(jsdthreadstate->context, jsdframe->fp);
|
||||
if(obj)
|
||||
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
return jsdval;
|
||||
}
|
||||
|
||||
JSDValue*
|
||||
jsd_GetThisForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
JSObject* obj;
|
||||
JSDValue* jsdval = NULL;
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
obj = JS_GetFrameThis(jsdthreadstate->context, jsdframe->fp);
|
||||
if(obj)
|
||||
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
return jsdval;
|
||||
}
|
||||
|
||||
const char*
|
||||
jsd_GetNameForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
const char *rv = NULL;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
JSFunction *fun = JS_GetFrameFunction (jsdthreadstate->context,
|
||||
jsdframe->fp);
|
||||
if (fun)
|
||||
rv = JS_GetFunctionName (fun);
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
return rv;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsStackFrameNative(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
JSBool rv;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
rv = JS_IsNativeFrame(jsdthreadstate->context, jsdframe->fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = JS_FALSE;
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
return rv;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsStackFrameDebugger(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
JSBool rv = JS_TRUE;
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
rv = JS_IsDebuggerFrame(jsdthreadstate->context, jsdframe->fp);
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
return rv;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsStackFrameConstructing(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
JSBool rv = JS_TRUE;
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||
{
|
||||
rv = JS_IsConstructorFrame(jsdthreadstate->context, jsdframe->fp);
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
return rv;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe,
|
||||
const jschar *bytes, uintN length,
|
||||
const char *filename, uintN lineno,
|
||||
JSBool eatExceptions, jsval *rval)
|
||||
{
|
||||
JSBool retval;
|
||||
JSBool valid;
|
||||
JSExceptionState* exceptionState = NULL;
|
||||
JSContext* cx;
|
||||
|
||||
JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread);
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe);
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( ! valid )
|
||||
return JS_FALSE;
|
||||
|
||||
cx = jsdthreadstate->context;
|
||||
JS_ASSERT(cx);
|
||||
|
||||
if (eatExceptions)
|
||||
exceptionState = JS_SaveExceptionState(cx);
|
||||
JS_ClearPendingException(cx);
|
||||
jsd_StartingEvalUsingFilename(jsdc, filename);
|
||||
retval = JS_EvaluateUCInStackFrame(cx, jsdframe->fp, bytes, length,
|
||||
filename, lineno, rval);
|
||||
jsd_FinishedEvalUsingFilename(jsdc, filename);
|
||||
if (eatExceptions)
|
||||
JS_RestoreExceptionState(cx, exceptionState);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_EvaluateScriptInStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe,
|
||||
const char *bytes, uintN length,
|
||||
const char *filename, uintN lineno,
|
||||
JSBool eatExceptions, jsval *rval)
|
||||
{
|
||||
JSBool retval;
|
||||
JSBool valid;
|
||||
JSExceptionState* exceptionState = NULL;
|
||||
JSContext *cx;
|
||||
|
||||
JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread);
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe);
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
if (!valid)
|
||||
return JS_FALSE;
|
||||
|
||||
cx = jsdthreadstate->context;
|
||||
JS_ASSERT(cx);
|
||||
|
||||
if (eatExceptions)
|
||||
exceptionState = JS_SaveExceptionState(cx);
|
||||
JS_ClearPendingException(cx);
|
||||
jsd_StartingEvalUsingFilename(jsdc, filename);
|
||||
retval = JS_EvaluateInStackFrame(cx, jsdframe->fp, bytes, length,
|
||||
filename, lineno, rval);
|
||||
jsd_FinishedEvalUsingFilename(jsdc, filename);
|
||||
if (eatExceptions)
|
||||
JS_RestoreExceptionState(cx, exceptionState);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
JSString*
|
||||
jsd_ValToStringInStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe,
|
||||
jsval val)
|
||||
{
|
||||
JSBool valid;
|
||||
JSString* retval;
|
||||
JSExceptionState* exceptionState;
|
||||
JSContext* cx;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe);
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
||||
if( ! valid )
|
||||
return NULL;
|
||||
|
||||
cx = jsdthreadstate->context;
|
||||
JS_ASSERT(cx);
|
||||
|
||||
exceptionState = JS_SaveExceptionState(cx);
|
||||
retval = JS_ValueToString(cx, val);
|
||||
JS_RestoreExceptionState(cx, exceptionState);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValidThreadState(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate)
|
||||
{
|
||||
JSDThreadState *cur;
|
||||
|
||||
JS_ASSERT( JSD_THREADSTATES_LOCKED(jsdc) );
|
||||
|
||||
for( cur = (JSDThreadState*)jsdc->threadsStates.next;
|
||||
cur != (JSDThreadState*)&jsdc->threadsStates;
|
||||
cur = (JSDThreadState*)cur->links.next )
|
||||
{
|
||||
if( cur == jsdthreadstate )
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValidFrameInThreadState(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
JS_ASSERT(JSD_THREADSTATES_LOCKED(jsdc));
|
||||
|
||||
if( ! jsd_IsValidThreadState(jsdc, jsdthreadstate) )
|
||||
return JS_FALSE;
|
||||
if( jsdframe->jsdthreadstate != jsdthreadstate )
|
||||
return JS_FALSE;
|
||||
|
||||
JSD_ASSERT_VALID_THREAD_STATE(jsdthreadstate);
|
||||
JSD_ASSERT_VALID_STACK_FRAME(jsdframe);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSContext*
|
||||
_getContextForThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||
{
|
||||
JSBool valid;
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
valid = jsd_IsValidThreadState(jsdc, jsdthreadstate);
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
if( valid )
|
||||
return jsdthreadstate->context;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSDValue*
|
||||
jsd_GetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||
{
|
||||
JSContext* cx;
|
||||
jsval val;
|
||||
|
||||
if(!(cx = _getContextForThreadState(jsdc, jsdthreadstate)))
|
||||
return NULL;
|
||||
|
||||
if(JS_GetPendingException(cx, &val))
|
||||
return jsd_NewValue(jsdc, val);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_SetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate,
|
||||
JSDValue* jsdval)
|
||||
{
|
||||
JSContext* cx;
|
||||
|
||||
if(!(cx = _getContextForThreadState(jsdc, jsdthreadstate)))
|
||||
return JS_FALSE;
|
||||
|
||||
if(jsdval)
|
||||
JS_SetPendingException(cx, JSD_GetValueWrappedJSVal(jsdc, jsdval));
|
||||
else
|
||||
JS_ClearPendingException(cx);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@@ -1,320 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - Stepping support
|
||||
*/
|
||||
|
||||
#include "jsd.h"
|
||||
|
||||
/*
|
||||
* #define JSD_TRACE 1
|
||||
*/
|
||||
|
||||
#ifdef JSD_TRACE
|
||||
|
||||
static char*
|
||||
_indentSpaces(int i)
|
||||
{
|
||||
#define MAX_INDENT 63
|
||||
static char* p = NULL;
|
||||
if(!p)
|
||||
{
|
||||
p = calloc(1, MAX_INDENT+1);
|
||||
if(!p) return "";
|
||||
memset(p, ' ', MAX_INDENT);
|
||||
}
|
||||
if(i > MAX_INDENT) return p;
|
||||
return p + MAX_INDENT-i;
|
||||
}
|
||||
|
||||
static void
|
||||
_interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
|
||||
JSBool before)
|
||||
{
|
||||
JSDScript* jsdscript = NULL;
|
||||
JSScript * script;
|
||||
static indent = 0;
|
||||
char* buf;
|
||||
const char* funName = NULL;
|
||||
|
||||
script = JS_GetFrameScript(cx, fp);
|
||||
if(script)
|
||||
{
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
if(jsdscript)
|
||||
funName = JSD_GetScriptFunctionName(jsdc, jsdscript);
|
||||
}
|
||||
if(!funName)
|
||||
funName = "TOP_LEVEL";
|
||||
|
||||
if(before)
|
||||
{
|
||||
buf = JS_smprintf("%sentering %s %s this: %0x\n",
|
||||
_indentSpaces(indent++),
|
||||
funName,
|
||||
JS_IsConstructorFrame(cx, fp) ? "constructing":"",
|
||||
(int)JS_GetFrameThis(cx, fp));
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = JS_smprintf("%sleaving %s\n",
|
||||
_indentSpaces(--indent),
|
||||
funName);
|
||||
}
|
||||
JS_ASSERT(indent >= 0);
|
||||
|
||||
if(!buf)
|
||||
return;
|
||||
|
||||
printf(buf);
|
||||
free(buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
JSBool
|
||||
_callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
uintN type, JSD_CallHookProc hook, void *hookData)
|
||||
{
|
||||
JSDScript* jsdscript;
|
||||
JSScript* jsscript;
|
||||
JSBool hookresult = JS_TRUE;
|
||||
|
||||
if (!jsdc || !jsdc->inited)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!hook && !(jsdc->flags & JSD_COLLECT_PROFILE_DATA) &&
|
||||
jsdc->flags & JSD_DISABLE_OBJECT_TRACE)
|
||||
{
|
||||
/* no hook to call, no profile data needs to be collected, and
|
||||
* the client has object tracing disabled, so there is nothing
|
||||
* to do here.
|
||||
*/
|
||||
return hookresult;
|
||||
}
|
||||
|
||||
if (before && JS_IsConstructorFrame(cx, fp))
|
||||
jsd_Constructing(jsdc, cx, JS_GetFrameThis(cx, fp), fp);
|
||||
|
||||
jsscript = JS_GetFrameScript(cx, fp);
|
||||
if (jsscript)
|
||||
{
|
||||
JSD_LOCK_SCRIPTS(jsdc);
|
||||
jsdscript = jsd_FindJSDScript(jsdc, jsscript);
|
||||
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||
|
||||
if (jsdscript)
|
||||
{
|
||||
if (JSD_IS_PROFILE_ENABLED(jsdc, jsdscript))
|
||||
{
|
||||
JSDProfileData *pdata;
|
||||
pdata = jsd_GetScriptProfileData (jsdc, jsdscript);
|
||||
if (pdata)
|
||||
{
|
||||
if (before)
|
||||
{
|
||||
if (JSLL_IS_ZERO(pdata->lastCallStart))
|
||||
{
|
||||
int64 now;
|
||||
JSDProfileData *callerpdata;
|
||||
|
||||
/* Get the time just the once, for consistency. */
|
||||
now = JS_Now();
|
||||
/* This contains a pointer to the profile data for
|
||||
* the caller of this function. */
|
||||
callerpdata = jsdc->callingFunctionPData;
|
||||
if (callerpdata)
|
||||
{
|
||||
int64 ll_delta;
|
||||
pdata->caller = callerpdata;
|
||||
/* We need to 'stop' the timer for the caller.
|
||||
* Use time since last return if appropriate. */
|
||||
if (JSLL_IS_ZERO(jsdc->lastReturnTime))
|
||||
{
|
||||
JSLL_SUB(ll_delta, now, callerpdata->lastCallStart);
|
||||
} else {
|
||||
JSLL_SUB(ll_delta, now, jsdc->lastReturnTime);
|
||||
}
|
||||
JSLL_ADD(callerpdata->runningTime, callerpdata->runningTime, ll_delta);
|
||||
}
|
||||
/* We're the new current function, and no return
|
||||
* has happened yet. */
|
||||
jsdc->callingFunctionPData = pdata;
|
||||
jsdc->lastReturnTime = JSLL_ZERO;
|
||||
/* This function has no running time (just been
|
||||
* called!), and we'll need the call start time. */
|
||||
pdata->runningTime = JSLL_ZERO;
|
||||
pdata->lastCallStart = now;
|
||||
} else {
|
||||
if (++pdata->recurseDepth > pdata->maxRecurseDepth)
|
||||
pdata->maxRecurseDepth = pdata->recurseDepth;
|
||||
}
|
||||
/* make sure we're called for the return too. */
|
||||
hookresult = JS_TRUE;
|
||||
} else if (!pdata->recurseDepth &&
|
||||
!JSLL_IS_ZERO(pdata->lastCallStart)) {
|
||||
int64 now, ll_delta;
|
||||
jsdouble delta;
|
||||
now = JS_Now();
|
||||
JSLL_SUB(ll_delta, now, pdata->lastCallStart);
|
||||
JSLL_L2D(delta, ll_delta);
|
||||
delta /= 1000.0;
|
||||
pdata->totalExecutionTime += delta;
|
||||
/* minExecutionTime starts as 0, so we need to overwrite
|
||||
* it on the first call always. */
|
||||
if ((0 == pdata->callCount) ||
|
||||
delta < pdata->minExecutionTime)
|
||||
{
|
||||
pdata->minExecutionTime = delta;
|
||||
}
|
||||
if (delta > pdata->maxExecutionTime)
|
||||
pdata->maxExecutionTime = delta;
|
||||
|
||||
/* If we last returned from a function (as opposed to
|
||||
* having last entered this function), we need to inc.
|
||||
* the running total by the time delta since the last
|
||||
* return, and use the running total instead of the
|
||||
* delta calculated above. */
|
||||
if (!JSLL_IS_ZERO(jsdc->lastReturnTime))
|
||||
{
|
||||
/* Add last chunk to running time, and use total
|
||||
* running time as 'delta'. */
|
||||
JSLL_SUB(ll_delta, now, jsdc->lastReturnTime);
|
||||
JSLL_ADD(pdata->runningTime, pdata->runningTime, ll_delta);
|
||||
JSLL_L2D(delta, pdata->runningTime);
|
||||
delta /= 1000.0;
|
||||
}
|
||||
|
||||
pdata->totalOwnExecutionTime += delta;
|
||||
/* See minExecutionTime comment above. */
|
||||
if ((0 == pdata->callCount) ||
|
||||
delta < pdata->minOwnExecutionTime)
|
||||
{
|
||||
pdata->minOwnExecutionTime = delta;
|
||||
}
|
||||
if (delta > pdata->maxOwnExecutionTime)
|
||||
pdata->maxOwnExecutionTime = delta;
|
||||
|
||||
/* Current function is now our caller. */
|
||||
jsdc->callingFunctionPData = pdata->caller;
|
||||
/* No hanging pointers, please. */
|
||||
pdata->caller = NULL;
|
||||
/* Mark the time we returned, and indicate this
|
||||
* function is no longer running. */
|
||||
jsdc->lastReturnTime = now;
|
||||
pdata->lastCallStart = JSLL_ZERO;
|
||||
++pdata->callCount;
|
||||
} else if (pdata->recurseDepth) {
|
||||
--pdata->recurseDepth;
|
||||
++pdata->callCount;
|
||||
}
|
||||
}
|
||||
if (hook)
|
||||
jsd_CallCallHook (jsdc, cx, type, hook, hookData);
|
||||
} else {
|
||||
if (hook)
|
||||
hookresult =
|
||||
jsd_CallCallHook (jsdc, cx, type, hook, hookData);
|
||||
else
|
||||
hookresult = JS_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JSD_TRACE
|
||||
_interpreterTrace(jsdc, cx, fp, before);
|
||||
return JS_TRUE;
|
||||
#else
|
||||
return hookresult;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void * JS_DLL_CALLBACK
|
||||
jsd_FunctionCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
JSBool *ok, void *closure)
|
||||
{
|
||||
JSDContext* jsdc;
|
||||
JSD_CallHookProc hook;
|
||||
void* hookData;
|
||||
|
||||
jsdc = (JSDContext*) closure;
|
||||
|
||||
/* local in case jsdc->functionHook gets cleared on another thread */
|
||||
JSD_LOCK();
|
||||
hook = jsdc->functionHook;
|
||||
hookData = jsdc->functionHookData;
|
||||
JSD_UNLOCK();
|
||||
|
||||
if (_callHook (jsdc, cx, fp, before,
|
||||
(before) ? JSD_HOOK_FUNCTION_CALL : JSD_HOOK_FUNCTION_RETURN,
|
||||
hook, hookData))
|
||||
{
|
||||
return closure;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * JS_DLL_CALLBACK
|
||||
jsd_TopLevelCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
JSBool *ok, void *closure)
|
||||
{
|
||||
JSDContext* jsdc;
|
||||
JSD_CallHookProc hook;
|
||||
void* hookData;
|
||||
|
||||
jsdc = (JSDContext*) closure;
|
||||
|
||||
/* local in case jsdc->toplevelHook gets cleared on another thread */
|
||||
JSD_LOCK();
|
||||
hook = jsdc->toplevelHook;
|
||||
hookData = jsdc->toplevelHookData;
|
||||
JSD_UNLOCK();
|
||||
|
||||
if (_callHook (jsdc, cx, fp, before,
|
||||
(before) ? JSD_HOOK_TOPLEVEL_START : JSD_HOOK_TOPLEVEL_END,
|
||||
hook, hookData))
|
||||
{
|
||||
return closure;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
@@ -1,567 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - Source Text functions
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "jsd.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
void JSD_ASSERT_VALID_SOURCE_TEXT(JSDSourceText* jsdsrc)
|
||||
{
|
||||
JS_ASSERT(jsdsrc);
|
||||
JS_ASSERT(jsdsrc->url);
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
/* XXX add notification */
|
||||
|
||||
static void
|
||||
_clearText(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
if( jsdsrc->text )
|
||||
free(jsdsrc->text);
|
||||
jsdsrc->text = NULL;
|
||||
jsdsrc->textLength = 0;
|
||||
jsdsrc->textSpace = 0;
|
||||
jsdsrc->status = JSD_SOURCE_CLEARED;
|
||||
jsdsrc->dirty = JS_TRUE;
|
||||
jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
|
||||
jsdsrc->doingEval = JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
_appendText(JSDContext* jsdc, JSDSourceText* jsdsrc,
|
||||
const char* text, size_t length)
|
||||
{
|
||||
#define MEMBUF_GROW 1000
|
||||
|
||||
uintN neededSize = jsdsrc->textLength + length;
|
||||
|
||||
if( neededSize > jsdsrc->textSpace )
|
||||
{
|
||||
char* newBuf;
|
||||
uintN iNewSize;
|
||||
|
||||
/* if this is the first alloc, the req might be all that's needed*/
|
||||
if( ! jsdsrc->textSpace )
|
||||
iNewSize = length;
|
||||
else
|
||||
iNewSize = (neededSize * 5 / 4) + MEMBUF_GROW;
|
||||
|
||||
newBuf = (char*) realloc(jsdsrc->text, iNewSize);
|
||||
if( ! newBuf )
|
||||
{
|
||||
/* try again with the minimal size really asked for */
|
||||
iNewSize = neededSize;
|
||||
newBuf = (char*) realloc(jsdsrc->text, iNewSize);
|
||||
if( ! newBuf )
|
||||
{
|
||||
/* out of memory */
|
||||
_clearText( jsdc, jsdsrc );
|
||||
jsdsrc->status = JSD_SOURCE_FAILED;
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
jsdsrc->text = newBuf;
|
||||
jsdsrc->textSpace = iNewSize;
|
||||
}
|
||||
|
||||
memcpy(jsdsrc->text + jsdsrc->textLength, text, length);
|
||||
jsdsrc->textLength += length;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSDSourceText*
|
||||
_newSource(JSDContext* jsdc, const char* url)
|
||||
{
|
||||
JSDSourceText* jsdsrc = (JSDSourceText*)calloc(1,sizeof(JSDSourceText));
|
||||
if( ! jsdsrc )
|
||||
return NULL;
|
||||
|
||||
jsdsrc->url = (char*) url; /* already a copy */
|
||||
jsdsrc->status = JSD_SOURCE_INITED;
|
||||
jsdsrc->dirty = JS_TRUE;
|
||||
jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
|
||||
|
||||
return jsdsrc;
|
||||
}
|
||||
|
||||
static void
|
||||
_destroySource(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
JS_ASSERT(NULL == jsdsrc->text); /* must _clearText() first */
|
||||
free(jsdsrc->url);
|
||||
free(jsdsrc);
|
||||
}
|
||||
|
||||
static void
|
||||
_removeSource(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
JS_REMOVE_LINK(&jsdsrc->links);
|
||||
_clearText(jsdc, jsdsrc);
|
||||
_destroySource(jsdc, jsdsrc);
|
||||
}
|
||||
|
||||
static JSDSourceText*
|
||||
_addSource(JSDContext* jsdc, const char* url)
|
||||
{
|
||||
JSDSourceText* jsdsrc = _newSource(jsdc, url);
|
||||
if( ! jsdsrc )
|
||||
return NULL;
|
||||
JS_INSERT_LINK(&jsdsrc->links, &jsdc->sources);
|
||||
return jsdsrc;
|
||||
}
|
||||
|
||||
static void
|
||||
_moveSourceToFront(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
JS_REMOVE_LINK(&jsdsrc->links);
|
||||
JS_INSERT_LINK(&jsdsrc->links, &jsdc->sources);
|
||||
}
|
||||
|
||||
static void
|
||||
_moveSourceToRemovedList(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
_clearText(jsdc, jsdsrc);
|
||||
JS_REMOVE_LINK(&jsdsrc->links);
|
||||
JS_INSERT_LINK(&jsdsrc->links, &jsdc->removedSources);
|
||||
}
|
||||
|
||||
static void
|
||||
_removeSourceFromRemovedList( JSDContext* jsdc, JSDSourceText* jsdsrc )
|
||||
{
|
||||
JS_REMOVE_LINK(&jsdsrc->links);
|
||||
_destroySource( jsdc, jsdsrc );
|
||||
}
|
||||
|
||||
static JSBool
|
||||
_isSourceInSourceList(JSDContext* jsdc, JSDSourceText* jsdsrcToFind)
|
||||
{
|
||||
JSDSourceText *jsdsrc;
|
||||
|
||||
for( jsdsrc = (JSDSourceText*)jsdc->sources.next;
|
||||
jsdsrc != (JSDSourceText*)&jsdc->sources;
|
||||
jsdsrc = (JSDSourceText*)jsdsrc->links.next )
|
||||
{
|
||||
if( jsdsrc == jsdsrcToFind )
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* compare strings in a case insensitive manner with a length limit
|
||||
*/
|
||||
|
||||
static int
|
||||
strncasecomp (const char* one, const char * two, int n)
|
||||
{
|
||||
const char *pA;
|
||||
const char *pB;
|
||||
|
||||
for(pA=one, pB=two;; pA++, pB++)
|
||||
{
|
||||
int tmp;
|
||||
if (pA == one+n)
|
||||
return 0;
|
||||
if (!(*pA && *pB))
|
||||
return *pA - *pB;
|
||||
tmp = tolower(*pA) - tolower(*pB);
|
||||
if (tmp)
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static char file_url_prefix[] = "file:";
|
||||
#define FILE_URL_PREFIX_LEN (sizeof file_url_prefix - 1)
|
||||
|
||||
const char*
|
||||
jsd_BuildNormalizedURL( const char* url_string )
|
||||
{
|
||||
char *new_url_string;
|
||||
|
||||
if( ! url_string )
|
||||
return NULL;
|
||||
|
||||
if (!strncasecomp(url_string, file_url_prefix, FILE_URL_PREFIX_LEN) &&
|
||||
url_string[FILE_URL_PREFIX_LEN + 0] == '/' &&
|
||||
url_string[FILE_URL_PREFIX_LEN + 1] == '/') {
|
||||
new_url_string = JS_smprintf("%s%s",
|
||||
file_url_prefix,
|
||||
url_string + FILE_URL_PREFIX_LEN + 2);
|
||||
} else {
|
||||
new_url_string = strdup(url_string);
|
||||
}
|
||||
return new_url_string;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void
|
||||
jsd_DestroyAllSources( JSDContext* jsdc )
|
||||
{
|
||||
JSDSourceText *jsdsrc;
|
||||
JSDSourceText *next;
|
||||
|
||||
for( jsdsrc = (JSDSourceText*)jsdc->sources.next;
|
||||
jsdsrc != (JSDSourceText*)&jsdc->sources;
|
||||
jsdsrc = next )
|
||||
{
|
||||
next = (JSDSourceText*)jsdsrc->links.next;
|
||||
_removeSource( jsdc, jsdsrc );
|
||||
}
|
||||
|
||||
for( jsdsrc = (JSDSourceText*)jsdc->removedSources.next;
|
||||
jsdsrc != (JSDSourceText*)&jsdc->removedSources;
|
||||
jsdsrc = next )
|
||||
{
|
||||
next = (JSDSourceText*)jsdsrc->links.next;
|
||||
_removeSourceFromRemovedList( jsdc, jsdsrc );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
JSDSourceText*
|
||||
jsd_IterateSources(JSDContext* jsdc, JSDSourceText **iterp)
|
||||
{
|
||||
JSDSourceText *jsdsrc = *iterp;
|
||||
|
||||
if( !jsdsrc )
|
||||
jsdsrc = (JSDSourceText *)jsdc->sources.next;
|
||||
if( jsdsrc == (JSDSourceText *)&jsdc->sources )
|
||||
return NULL;
|
||||
*iterp = (JSDSourceText *)jsdsrc->links.next;
|
||||
return jsdsrc;
|
||||
}
|
||||
|
||||
JSDSourceText*
|
||||
jsd_FindSourceForURL(JSDContext* jsdc, const char* url)
|
||||
{
|
||||
JSDSourceText *jsdsrc;
|
||||
|
||||
for( jsdsrc = (JSDSourceText *)jsdc->sources.next;
|
||||
jsdsrc != (JSDSourceText *)&jsdc->sources;
|
||||
jsdsrc = (JSDSourceText *)jsdsrc->links.next )
|
||||
{
|
||||
if( 0 == strcmp(jsdsrc->url, url) )
|
||||
return jsdsrc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char*
|
||||
jsd_GetSourceURL(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
return jsdsrc->url;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_GetSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc,
|
||||
const char** ppBuf, intN* pLen )
|
||||
{
|
||||
*ppBuf = jsdsrc->text;
|
||||
*pLen = jsdsrc->textLength;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_ClearSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
if( JSD_SOURCE_INITED != jsdsrc->status &&
|
||||
JSD_SOURCE_PARTIAL != jsdsrc->status )
|
||||
{
|
||||
_clearText(jsdc, jsdsrc);
|
||||
}
|
||||
}
|
||||
|
||||
JSDSourceStatus
|
||||
jsd_GetSourceStatus(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
return jsdsrc->status;
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsSourceDirty(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
return jsdsrc->dirty;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_SetSourceDirty(JSDContext* jsdc, JSDSourceText* jsdsrc, JSBool dirty)
|
||||
{
|
||||
jsdsrc->dirty = dirty;
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
return jsdsrc->alterCount;
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_IncrementSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||
{
|
||||
return jsdsrc->alterCount = jsdc->sourceAlterCount++;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#if defined(DEBUG) && 0
|
||||
void DEBUG_ITERATE_SOURCES( JSDContext* jsdc )
|
||||
{
|
||||
JSDSourceText* iterp = NULL;
|
||||
JSDSourceText* jsdsrc = NULL;
|
||||
int dummy;
|
||||
|
||||
while( NULL != (jsdsrc = jsd_IterateSources(jsdc, &iterp)) )
|
||||
{
|
||||
const char* url;
|
||||
const char* text;
|
||||
int len;
|
||||
JSBool dirty;
|
||||
JSDStreamStatus status;
|
||||
JSBool gotSrc;
|
||||
|
||||
url = JSD_GetSourceURL(jsdc, jsdsrc);
|
||||
dirty = JSD_IsSourceDirty(jsdc, jsdsrc);
|
||||
status = JSD_GetSourceStatus(jsdc, jsdsrc);
|
||||
gotSrc = JSD_GetSourceText(jsdc, jsdsrc, &text, &len );
|
||||
|
||||
dummy = 0; /* gives us a line to set breakpoint... */
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define DEBUG_ITERATE_SOURCES(x) ((void)x)
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
JSDSourceText*
|
||||
jsd_NewSourceText(JSDContext* jsdc, const char* url)
|
||||
{
|
||||
JSDSourceText* jsdsrc;
|
||||
const char* new_url_string;
|
||||
|
||||
JSD_LOCK_SOURCE_TEXT(jsdc);
|
||||
|
||||
#ifdef LIVEWIRE
|
||||
new_url_string = url; /* we take ownership of alloc'd string */
|
||||
#else
|
||||
new_url_string = jsd_BuildNormalizedURL(url);
|
||||
#endif
|
||||
if( ! new_url_string )
|
||||
return NULL;
|
||||
|
||||
jsdsrc = jsd_FindSourceForURL(jsdc, new_url_string);
|
||||
|
||||
if( jsdsrc )
|
||||
{
|
||||
if( jsdsrc->doingEval )
|
||||
{
|
||||
#ifdef LIVEWIRE
|
||||
free((char*)new_url_string);
|
||||
#endif
|
||||
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
_moveSourceToRemovedList(jsdc, jsdsrc);
|
||||
}
|
||||
|
||||
jsdsrc = _addSource( jsdc, new_url_string );
|
||||
|
||||
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||
|
||||
return jsdsrc;
|
||||
}
|
||||
|
||||
JSDSourceText*
|
||||
jsd_AppendSourceText(JSDContext* jsdc,
|
||||
JSDSourceText* jsdsrc,
|
||||
const char* text, /* *not* zero terminated */
|
||||
size_t length,
|
||||
JSDSourceStatus status)
|
||||
{
|
||||
JSD_LOCK_SOURCE_TEXT(jsdc);
|
||||
|
||||
if( jsdsrc->doingEval )
|
||||
{
|
||||
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( ! _isSourceInSourceList( jsdc, jsdsrc ) )
|
||||
{
|
||||
_removeSourceFromRemovedList( jsdc, jsdsrc );
|
||||
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( text && length && ! _appendText( jsdc, jsdsrc, text, length ) )
|
||||
{
|
||||
jsdsrc->dirty = JS_TRUE;
|
||||
jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
|
||||
jsdsrc->status = JSD_SOURCE_FAILED;
|
||||
_moveSourceToRemovedList(jsdc, jsdsrc);
|
||||
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jsdsrc->dirty = JS_TRUE;
|
||||
jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
|
||||
jsdsrc->status = status;
|
||||
DEBUG_ITERATE_SOURCES(jsdc);
|
||||
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||
return jsdsrc;
|
||||
}
|
||||
|
||||
JSDSourceText*
|
||||
jsd_AppendUCSourceText(JSDContext* jsdc,
|
||||
JSDSourceText* jsdsrc,
|
||||
const jschar* text, /* *not* zero terminated */
|
||||
size_t length,
|
||||
JSDSourceStatus status)
|
||||
{
|
||||
#define UNICODE_TRUNCATE_BUF_SIZE 1024
|
||||
static char* buf = NULL;
|
||||
int remaining = length;
|
||||
|
||||
if(!text || !length)
|
||||
return jsd_AppendSourceText(jsdc, jsdsrc, NULL, 0, status);
|
||||
|
||||
JSD_LOCK_SOURCE_TEXT(jsdc);
|
||||
if(!buf)
|
||||
{
|
||||
buf = malloc(UNICODE_TRUNCATE_BUF_SIZE);
|
||||
if(!buf)
|
||||
{
|
||||
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
while(remaining && jsdsrc) {
|
||||
int bytes = JS_MIN(remaining, UNICODE_TRUNCATE_BUF_SIZE);
|
||||
int i;
|
||||
for(i = 0; i < bytes; i++)
|
||||
buf[i] = (const char) *(text++);
|
||||
jsdsrc = jsd_AppendSourceText(jsdc,jsdsrc,
|
||||
buf, bytes,
|
||||
JSD_SOURCE_PARTIAL);
|
||||
remaining -= bytes;
|
||||
}
|
||||
if(jsdsrc && status != JSD_SOURCE_PARTIAL)
|
||||
jsdsrc = jsd_AppendSourceText(jsdc, jsdsrc, NULL, 0, status);
|
||||
|
||||
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||
return jsdsrc;
|
||||
}
|
||||
|
||||
/* convienence function for adding complete source of url in one call */
|
||||
JSBool
|
||||
jsd_AddFullSourceText(JSDContext* jsdc,
|
||||
const char* text, /* *not* zero terminated */
|
||||
size_t length,
|
||||
const char* url)
|
||||
{
|
||||
JSDSourceText* jsdsrc;
|
||||
|
||||
JSD_LOCK_SOURCE_TEXT(jsdc);
|
||||
|
||||
jsdsrc = jsd_NewSourceText(jsdc, url);
|
||||
if( jsdsrc )
|
||||
jsdsrc = jsd_AppendSourceText(jsdc, jsdsrc,
|
||||
text, length, JSD_SOURCE_PARTIAL );
|
||||
if( jsdsrc )
|
||||
jsdsrc = jsd_AppendSourceText(jsdc, jsdsrc,
|
||||
NULL, 0, JSD_SOURCE_COMPLETED );
|
||||
|
||||
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||
|
||||
return jsdsrc ? JS_TRUE : JS_FALSE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void
|
||||
jsd_StartingEvalUsingFilename(JSDContext* jsdc, const char* url)
|
||||
{
|
||||
JSDSourceText* jsdsrc;
|
||||
|
||||
/* NOTE: We leave it locked! */
|
||||
JSD_LOCK_SOURCE_TEXT(jsdc);
|
||||
|
||||
jsdsrc = jsd_FindSourceForURL(jsdc, url);
|
||||
if(jsdsrc)
|
||||
{
|
||||
#if 0
|
||||
#ifndef JSD_LOWLEVEL_SOURCE
|
||||
JS_ASSERT(! jsdsrc->doingEval);
|
||||
#endif
|
||||
#endif
|
||||
jsdsrc->doingEval = JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
jsd_FinishedEvalUsingFilename(JSDContext* jsdc, const char* url)
|
||||
{
|
||||
JSDSourceText* jsdsrc;
|
||||
|
||||
/* NOTE: We ASSUME it is locked! */
|
||||
|
||||
jsdsrc = jsd_FindSourceForURL(jsdc, url);
|
||||
if(jsdsrc)
|
||||
{
|
||||
#if 0
|
||||
#ifndef JSD_LOWLEVEL_SOURCE
|
||||
/*
|
||||
* when using this low level source addition, this jsdsrc might
|
||||
* not have existed before the eval, but does exist now (without
|
||||
* this flag set!)
|
||||
*/
|
||||
JS_ASSERT(jsdsrc->doingEval);
|
||||
#endif
|
||||
#endif
|
||||
jsdsrc->doingEval = JS_FALSE;
|
||||
}
|
||||
|
||||
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||
}
|
||||
@@ -1,633 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - Value and Property support
|
||||
*/
|
||||
|
||||
#include "jsd.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval)
|
||||
{
|
||||
JS_ASSERT(jsdval);
|
||||
JS_ASSERT(jsdval->nref > 0);
|
||||
if(!JS_CLIST_IS_EMPTY(&jsdval->props))
|
||||
{
|
||||
JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS));
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
|
||||
}
|
||||
|
||||
if(jsdval->proto)
|
||||
{
|
||||
JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO));
|
||||
JS_ASSERT(jsdval->proto->nref > 0);
|
||||
}
|
||||
if(jsdval->parent)
|
||||
{
|
||||
JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT));
|
||||
JS_ASSERT(jsdval->parent->nref > 0);
|
||||
}
|
||||
if(jsdval->ctor)
|
||||
{
|
||||
JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR));
|
||||
JS_ASSERT(jsdval->ctor->nref > 0);
|
||||
}
|
||||
}
|
||||
|
||||
void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop)
|
||||
{
|
||||
JS_ASSERT(jsdprop);
|
||||
JS_ASSERT(jsdprop->name);
|
||||
JS_ASSERT(jsdprop->name->nref > 0);
|
||||
JS_ASSERT(jsdprop->val);
|
||||
JS_ASSERT(jsdprop->val->nref > 0);
|
||||
if(jsdprop->alias)
|
||||
JS_ASSERT(jsdprop->alias->nref > 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
JSBool
|
||||
jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return JSVAL_IS_OBJECT(jsdval->val);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return JSVAL_IS_NUMBER(jsdval->val);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return JSVAL_IS_INT(jsdval->val);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return JSVAL_IS_DOUBLE(jsdval->val);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return JSVAL_IS_STRING(jsdval->val);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return JSVAL_IS_BOOLEAN(jsdval->val);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return JSVAL_IS_NULL(jsdval->val);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return JSVAL_IS_VOID(jsdval->val);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return JSVAL_IS_PRIMITIVE(jsdval->val);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return JSVAL_IS_FUNCTION(jsdc->dumbContext, jsdval->val);
|
||||
}
|
||||
|
||||
JSBool
|
||||
jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
JSContext* cx = jsdc->dumbContext;
|
||||
jsval val = jsdval->val;
|
||||
JSFunction* fun;
|
||||
JSExceptionState* exceptionState;
|
||||
|
||||
if(!JSVAL_IS_OBJECT(val))
|
||||
return JS_FALSE;
|
||||
|
||||
if(JSVAL_IS_FUNCTION(cx, val))
|
||||
{
|
||||
exceptionState = JS_SaveExceptionState(cx);
|
||||
fun = JS_ValueToFunction(cx, val);
|
||||
JS_RestoreExceptionState(cx, exceptionState);
|
||||
if(!fun)
|
||||
{
|
||||
JS_ASSERT(0);
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE;
|
||||
}
|
||||
return JSVAL_TO_OBJECT(val) && OBJ_IS_NATIVE(JSVAL_TO_OBJECT(val));
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
JSBool
|
||||
jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
jsval val = jsdval->val;
|
||||
if(!JSVAL_IS_BOOLEAN(val))
|
||||
return JS_FALSE;
|
||||
return JSVAL_TO_BOOLEAN(val);
|
||||
}
|
||||
|
||||
int32
|
||||
jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
jsval val = jsdval->val;
|
||||
if(!JSVAL_IS_INT(val))
|
||||
return 0;
|
||||
return JSVAL_TO_INT(val);
|
||||
}
|
||||
|
||||
jsdouble*
|
||||
jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
jsval val = jsdval->val;
|
||||
if(!JSVAL_IS_DOUBLE(val))
|
||||
return 0;
|
||||
return JSVAL_TO_DOUBLE(val);
|
||||
}
|
||||
|
||||
JSString*
|
||||
jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
JSContext* cx = jsdc->dumbContext;
|
||||
JSExceptionState* exceptionState;
|
||||
|
||||
if(!jsdval->string)
|
||||
{
|
||||
/* if the jsval is a string, then we don't need to double root it */
|
||||
if(JSVAL_IS_STRING(jsdval->val))
|
||||
jsdval->string = JSVAL_TO_STRING(jsdval->val);
|
||||
else
|
||||
{
|
||||
exceptionState = JS_SaveExceptionState(cx);
|
||||
jsdval->string = JS_ValueToString(cx, jsdval->val);
|
||||
JS_RestoreExceptionState(cx, exceptionState);
|
||||
if(jsdval->string)
|
||||
{
|
||||
if(!JS_AddNamedRoot(cx, &jsdval->string, "ValueString"))
|
||||
jsdval->string = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return jsdval->string;
|
||||
}
|
||||
|
||||
const char*
|
||||
jsd_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
JSContext* cx = jsdc->dumbContext;
|
||||
jsval val = jsdval->val;
|
||||
JSFunction* fun;
|
||||
JSExceptionState* exceptionState;
|
||||
|
||||
if(!jsdval->funName && JSVAL_IS_FUNCTION(cx, val))
|
||||
{
|
||||
exceptionState = JS_SaveExceptionState(cx);
|
||||
fun = JS_ValueToFunction(cx, val);
|
||||
JS_RestoreExceptionState(cx, exceptionState);
|
||||
if(!fun)
|
||||
return NULL;
|
||||
jsdval->funName = JS_GetFunctionName(fun);
|
||||
}
|
||||
return jsdval->funName;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
JSDValue*
|
||||
jsd_NewValue(JSDContext* jsdc, jsval val)
|
||||
{
|
||||
JSDValue* jsdval;
|
||||
|
||||
if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
|
||||
return NULL;
|
||||
|
||||
if(JSVAL_IS_GCTHING(val))
|
||||
{
|
||||
if(!JS_AddNamedRoot(jsdc->dumbContext, &jsdval->val, "JSDValue"))
|
||||
{
|
||||
free(jsdval);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
jsdval->val = val;
|
||||
jsdval->nref = 1;
|
||||
JS_INIT_CLIST(&jsdval->props);
|
||||
|
||||
return jsdval;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
JS_ASSERT(jsdval->nref > 0);
|
||||
if(0 == --jsdval->nref)
|
||||
{
|
||||
jsd_RefreshValue(jsdc, jsdval);
|
||||
if(JSVAL_IS_GCTHING(jsdval->val))
|
||||
JS_RemoveRoot(jsdc->dumbContext, &jsdval->val);
|
||||
free(jsdval);
|
||||
}
|
||||
}
|
||||
|
||||
jsval
|
||||
jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
return jsdval->val;
|
||||
}
|
||||
|
||||
static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
|
||||
uintN additionalFlags)
|
||||
{
|
||||
JSDProperty* jsdprop;
|
||||
|
||||
if(!(jsdprop = (JSDProperty*) calloc(1, sizeof(JSDProperty))))
|
||||
return NULL;
|
||||
|
||||
JS_INIT_CLIST(&jsdprop->links);
|
||||
jsdprop->nref = 1;
|
||||
jsdprop->flags = pd->flags | additionalFlags;
|
||||
jsdprop->slot = pd->slot;
|
||||
|
||||
if(!(jsdprop->name = jsd_NewValue(jsdc, pd->id)))
|
||||
goto new_prop_fail;
|
||||
|
||||
if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value)))
|
||||
goto new_prop_fail;
|
||||
|
||||
if((jsdprop->flags & JSDPD_ALIAS) &&
|
||||
!(jsdprop->alias = jsd_NewValue(jsdc, pd->alias)))
|
||||
goto new_prop_fail;
|
||||
|
||||
return jsdprop;
|
||||
new_prop_fail:
|
||||
jsd_DropProperty(jsdc, jsdprop);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _freeProps(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
JSDProperty* jsdprop;
|
||||
|
||||
while(jsdprop = (JSDProperty*)jsdval->props.next,
|
||||
jsdprop != (JSDProperty*)&jsdval->props)
|
||||
{
|
||||
JS_REMOVE_AND_INIT_LINK(&jsdprop->links);
|
||||
jsd_DropProperty(jsdc, jsdprop);
|
||||
}
|
||||
JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
|
||||
CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
|
||||
}
|
||||
|
||||
static JSBool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
JSContext* cx = jsdc->dumbContext;
|
||||
JSPropertyDescArray pda;
|
||||
uintN i;
|
||||
|
||||
JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
|
||||
JS_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
|
||||
|
||||
if(!JSVAL_IS_OBJECT(jsdval->val) || JSVAL_IS_NULL(jsdval->val))
|
||||
return JS_FALSE;
|
||||
|
||||
if(!JS_GetPropertyDescArray(cx, JSVAL_TO_OBJECT(jsdval->val), &pda))
|
||||
return JS_FALSE;
|
||||
|
||||
for(i = 0; i < pda.length; i++)
|
||||
{
|
||||
JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0);
|
||||
if(!prop)
|
||||
{
|
||||
_freeProps(jsdc, jsdval);
|
||||
break;
|
||||
}
|
||||
JS_APPEND_LINK(&prop->links, &jsdval->props);
|
||||
}
|
||||
JS_PutPropertyDescArray(cx, &pda);
|
||||
SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
|
||||
return !JS_CLIST_IS_EMPTY(&jsdval->props);
|
||||
}
|
||||
|
||||
#undef DROP_CLEAR_VALUE
|
||||
#define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = NULL;}
|
||||
|
||||
void
|
||||
jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
JSContext* cx = jsdc->dumbContext;
|
||||
|
||||
if(jsdval->string)
|
||||
{
|
||||
/* if the jsval is a string, then we didn't need to root the string */
|
||||
if(!JSVAL_IS_STRING(jsdval->val))
|
||||
JS_RemoveRoot(cx, &jsdval->string);
|
||||
jsdval->string = NULL;
|
||||
}
|
||||
|
||||
jsdval->funName = NULL;
|
||||
jsdval->className = NULL;
|
||||
DROP_CLEAR_VALUE(jsdc, jsdval->proto);
|
||||
DROP_CLEAR_VALUE(jsdc, jsdval->parent);
|
||||
DROP_CLEAR_VALUE(jsdc, jsdval->ctor);
|
||||
_freeProps(jsdc, jsdval);
|
||||
jsdval->flags = 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
uintN
|
||||
jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
JSDProperty* jsdprop;
|
||||
uintN count = 0;
|
||||
|
||||
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
|
||||
if(!_buildProps(jsdc, jsdval))
|
||||
return 0;
|
||||
|
||||
for(jsdprop = (JSDProperty*)jsdval->props.next;
|
||||
jsdprop != (JSDProperty*)&jsdval->props;
|
||||
jsdprop = (JSDProperty*)jsdprop->links.next)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
JSDProperty*
|
||||
jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp)
|
||||
{
|
||||
JSDProperty* jsdprop = *iterp;
|
||||
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
|
||||
{
|
||||
JS_ASSERT(!jsdprop);
|
||||
if(!_buildProps(jsdc, jsdval))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!jsdprop)
|
||||
jsdprop = (JSDProperty*)jsdval->props.next;
|
||||
if(jsdprop == (JSDProperty*)&jsdval->props)
|
||||
return NULL;
|
||||
*iterp = (JSDProperty*)jsdprop->links.next;
|
||||
|
||||
JS_ASSERT(jsdprop);
|
||||
jsdprop->nref++;
|
||||
return jsdprop;
|
||||
}
|
||||
|
||||
JSDProperty*
|
||||
jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
|
||||
{
|
||||
JSContext* cx = jsdc->dumbContext;
|
||||
JSDProperty* jsdprop;
|
||||
JSDProperty* iter = NULL;
|
||||
JSObject* obj;
|
||||
uintN attrs = 0;
|
||||
JSBool found;
|
||||
JSPropertyDesc pd;
|
||||
const jschar * nameChars;
|
||||
size_t nameLen;
|
||||
jsval val;
|
||||
|
||||
if(!jsd_IsValueObject(jsdc, jsdval))
|
||||
return NULL;
|
||||
|
||||
/* If we already have the prop, then return it */
|
||||
while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
|
||||
{
|
||||
JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
|
||||
if(propName && !JS_CompareStrings(propName, name))
|
||||
return jsdprop;
|
||||
JSD_DropProperty(jsdc, jsdprop);
|
||||
}
|
||||
/* Not found in property list, look it up explicitly */
|
||||
|
||||
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
|
||||
return NULL;
|
||||
|
||||
nameChars = JS_GetStringChars(name);
|
||||
nameLen = JS_GetStringLength(name);
|
||||
|
||||
JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
|
||||
if (!found)
|
||||
return NULL;
|
||||
|
||||
JS_ClearPendingException(cx);
|
||||
|
||||
if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val))
|
||||
{
|
||||
if (JS_IsExceptionPending(cx))
|
||||
{
|
||||
if (!JS_GetPendingException(cx, &pd.value))
|
||||
return NULL;
|
||||
pd.flags = JSPD_EXCEPTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
pd.flags = JSPD_ERROR;
|
||||
pd.value = JSVAL_VOID;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pd.value = val;
|
||||
}
|
||||
|
||||
pd.id = STRING_TO_JSVAL(name);
|
||||
pd.alias = pd.slot = pd.spare = 0;
|
||||
pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
|
||||
| (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0
|
||||
| (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
|
||||
|
||||
return _newProperty(jsdc, &pd, JSDPD_HINTED);
|
||||
}
|
||||
|
||||
|
||||
JSDValue*
|
||||
jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
|
||||
{
|
||||
JSObject* obj;
|
||||
JSObject* proto;
|
||||
JS_ASSERT(!jsdval->proto);
|
||||
SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
|
||||
if(!JSVAL_IS_OBJECT(jsdval->val))
|
||||
return NULL;
|
||||
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
|
||||
return NULL;
|
||||
if(!(proto = OBJ_GET_PROTO(jsdc->dumbContext,obj)))
|
||||
return NULL;
|
||||
jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
|
||||
}
|
||||
if(jsdval->proto)
|
||||
jsdval->proto->nref++;
|
||||
return jsdval->proto;
|
||||
}
|
||||
|
||||
JSDValue*
|
||||
jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
|
||||
{
|
||||
JSObject* obj;
|
||||
JSObject* parent;
|
||||
JS_ASSERT(!jsdval->parent);
|
||||
SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
|
||||
if(!JSVAL_IS_OBJECT(jsdval->val))
|
||||
return NULL;
|
||||
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
|
||||
return NULL;
|
||||
if(!(parent = OBJ_GET_PARENT(jsdc->dumbContext,obj)))
|
||||
return NULL;
|
||||
jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
|
||||
}
|
||||
if(jsdval->parent)
|
||||
jsdval->parent->nref++;
|
||||
return jsdval->parent;
|
||||
}
|
||||
|
||||
JSDValue*
|
||||
jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
|
||||
{
|
||||
JSObject* obj;
|
||||
JSObject* proto;
|
||||
JSObject* ctor;
|
||||
JS_ASSERT(!jsdval->ctor);
|
||||
SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
|
||||
if(!JSVAL_IS_OBJECT(jsdval->val))
|
||||
return NULL;
|
||||
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
|
||||
return NULL;
|
||||
if(!(proto = OBJ_GET_PROTO(jsdc->dumbContext,obj)))
|
||||
return NULL;
|
||||
if(!(ctor = JS_GetConstructor(jsdc->dumbContext,proto)))
|
||||
return NULL;
|
||||
jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
|
||||
}
|
||||
if(jsdval->ctor)
|
||||
jsdval->ctor->nref++;
|
||||
return jsdval->ctor;
|
||||
}
|
||||
|
||||
const char*
|
||||
jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
jsval val = jsdval->val;
|
||||
if(!jsdval->className && JSVAL_IS_OBJECT(val))
|
||||
{
|
||||
JSObject* obj;
|
||||
if(!(obj = JSVAL_TO_OBJECT(val)))
|
||||
return NULL;
|
||||
if(OBJ_GET_CLASS(jsdc->dumbContext, obj))
|
||||
jsdval->className = OBJ_GET_CLASS(jsdc->dumbContext, obj)->name;
|
||||
}
|
||||
return jsdval->className;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
JSDValue*
|
||||
jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||
{
|
||||
jsdprop->name->nref++;
|
||||
return jsdprop->name;
|
||||
}
|
||||
|
||||
JSDValue*
|
||||
jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||
{
|
||||
jsdprop->val->nref++;
|
||||
return jsdprop->val;
|
||||
}
|
||||
|
||||
JSDValue*
|
||||
jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||
{
|
||||
if(jsdprop->alias)
|
||||
jsdprop->alias->nref++;
|
||||
return jsdprop->alias;
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||
{
|
||||
return jsdprop->flags;
|
||||
}
|
||||
|
||||
uintN
|
||||
jsd_GetPropertyVarArgSlot(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||
{
|
||||
return jsdprop->slot;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||
{
|
||||
JS_ASSERT(jsdprop->nref > 0);
|
||||
if(0 == --jsdprop->nref)
|
||||
{
|
||||
JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdprop->links));
|
||||
DROP_CLEAR_VALUE(jsdc, jsdprop->val);
|
||||
DROP_CLEAR_VALUE(jsdc, jsdprop->name);
|
||||
DROP_CLEAR_VALUE(jsdc, jsdprop->alias);
|
||||
free(jsdprop);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,403 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Robert Ginda, <rginda@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef JSDSERVICE_H___
|
||||
#define JSDSERVICE_H___
|
||||
|
||||
#include "jsdIDebuggerService.h"
|
||||
#include "jsdebug.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nspr.h"
|
||||
|
||||
// #if defined(DEBUG_rginda_l)
|
||||
// # define DEBUG_verbose
|
||||
// #endif
|
||||
|
||||
struct LiveEphemeral {
|
||||
/* link in a chain of live values list */
|
||||
PRCList links;
|
||||
jsdIEphemeral *value;
|
||||
void *key;
|
||||
};
|
||||
|
||||
struct PCMapEntry {
|
||||
PRUint32 pc, line;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* reflected jsd data structures
|
||||
*******************************************************************************/
|
||||
|
||||
class jsdObject : public jsdIObject
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_JSDIOBJECT
|
||||
|
||||
/* you'll normally use use FromPtr() instead of directly constructing one */
|
||||
jsdObject (JSDContext *aCx, JSDObject *aObject) :
|
||||
mCx(aCx), mObject(aObject)
|
||||
{
|
||||
}
|
||||
|
||||
static jsdIObject *FromPtr (JSDContext *aCx,
|
||||
JSDObject *aObject)
|
||||
{
|
||||
if (!aObject)
|
||||
return nsnull;
|
||||
|
||||
jsdIObject *rv = new jsdObject (aCx, aObject);
|
||||
NS_IF_ADDREF(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
jsdObject(); /* no implementation */
|
||||
jsdObject(const jsdObject&); /* no implementation */
|
||||
|
||||
JSDContext *mCx;
|
||||
JSDObject *mObject;
|
||||
};
|
||||
|
||||
|
||||
class jsdProperty : public jsdIProperty
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_JSDIPROPERTY
|
||||
NS_DECL_JSDIEPHEMERAL
|
||||
|
||||
jsdProperty (JSDContext *aCx, JSDProperty *aProperty);
|
||||
virtual ~jsdProperty ();
|
||||
|
||||
static jsdIProperty *FromPtr (JSDContext *aCx,
|
||||
JSDProperty *aProperty)
|
||||
{
|
||||
if (!aProperty)
|
||||
return nsnull;
|
||||
|
||||
jsdIProperty *rv = new jsdProperty (aCx, aProperty);
|
||||
NS_IF_ADDREF(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void InvalidateAll();
|
||||
|
||||
private:
|
||||
jsdProperty(); /* no implementation */
|
||||
jsdProperty(const jsdProperty&); /* no implementation */
|
||||
|
||||
PRBool mValid;
|
||||
LiveEphemeral mLiveListEntry;
|
||||
JSDContext *mCx;
|
||||
JSDProperty *mProperty;
|
||||
};
|
||||
|
||||
class jsdScript : public jsdIScript
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_JSDISCRIPT
|
||||
NS_DECL_JSDIEPHEMERAL
|
||||
|
||||
/* you'll normally use use FromPtr() instead of directly constructing one */
|
||||
jsdScript (JSDContext *aCx, JSDScript *aScript);
|
||||
virtual ~jsdScript();
|
||||
|
||||
static jsdIScript *FromPtr (JSDContext *aCx, JSDScript *aScript)
|
||||
{
|
||||
if (!aScript)
|
||||
return nsnull;
|
||||
|
||||
void *data = JSD_GetScriptPrivate (aScript);
|
||||
jsdIScript *rv;
|
||||
|
||||
if (data) {
|
||||
rv = NS_STATIC_CAST(jsdIScript *, data);
|
||||
} else {
|
||||
rv = new jsdScript (aCx, aScript);
|
||||
NS_IF_ADDREF(rv); /* addref for the SetScriptPrivate, released in
|
||||
* Invalidate() */
|
||||
JSD_SetScriptPrivate (aScript, NS_STATIC_CAST(void *, rv));
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(rv); /* addref for return value */
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void InvalidateAll();
|
||||
|
||||
private:
|
||||
static PRUint32 LastTag;
|
||||
|
||||
jsdScript(); /* no implementation */
|
||||
jsdScript (const jsdScript&); /* no implementation */
|
||||
PCMapEntry* CreatePPLineMap();
|
||||
PRUint32 PPPcToLine(PRUint32 aPC);
|
||||
PRUint32 PPLineToPc(PRUint32 aLine);
|
||||
|
||||
PRBool mValid;
|
||||
PRUint32 mTag;
|
||||
JSDContext *mCx;
|
||||
JSDScript *mScript;
|
||||
nsCString *mFileName;
|
||||
nsCString *mFunctionName;
|
||||
PRUint32 mBaseLineNumber, mLineExtent;
|
||||
PCMapEntry *mPPLineMap;
|
||||
PRUint32 mPCMapSize;
|
||||
jsuword mFirstPC;
|
||||
};
|
||||
|
||||
PRUint32 jsdScript::LastTag = 0;
|
||||
|
||||
class jsdContext : public jsdIContext
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_JSDICONTEXT
|
||||
NS_DECL_JSDIEPHEMERAL
|
||||
|
||||
jsdContext (JSDContext *aJSDCx, JSContext *aJSCx, nsISupports *aISCx);
|
||||
virtual ~jsdContext();
|
||||
|
||||
static void InvalidateAll();
|
||||
static jsdIContext *FromPtr (JSDContext *aJSDCx, JSContext *aJSCx);
|
||||
private:
|
||||
static PRUint32 LastTag;
|
||||
|
||||
jsdContext (); /* no implementation */
|
||||
jsdContext (const jsdContext&); /* no implementation */
|
||||
|
||||
PRBool mValid;
|
||||
LiveEphemeral mLiveListEntry;
|
||||
PRUint32 mTag;
|
||||
JSDContext *mJSDCx;
|
||||
JSContext *mJSCx;
|
||||
nsCOMPtr<nsISupports> mISCx;
|
||||
};
|
||||
|
||||
PRUint32 jsdContext::LastTag = 0;
|
||||
|
||||
class jsdStackFrame : public jsdIStackFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_JSDISTACKFRAME
|
||||
NS_DECL_JSDIEPHEMERAL
|
||||
|
||||
/* you'll normally use use FromPtr() instead of directly constructing one */
|
||||
jsdStackFrame (JSDContext *aCx, JSDThreadState *aThreadState,
|
||||
JSDStackFrameInfo *aStackFrameInfo);
|
||||
virtual ~jsdStackFrame();
|
||||
|
||||
static void InvalidateAll();
|
||||
static jsdIStackFrame* FromPtr (JSDContext *aCx,
|
||||
JSDThreadState *aThreadState,
|
||||
JSDStackFrameInfo *aStackFrameInfo);
|
||||
|
||||
private:
|
||||
jsdStackFrame(); /* no implementation */
|
||||
jsdStackFrame(const jsdStackFrame&); /* no implementation */
|
||||
|
||||
PRBool mValid;
|
||||
LiveEphemeral mLiveListEntry;
|
||||
JSDContext *mCx;
|
||||
JSDThreadState *mThreadState;
|
||||
JSDStackFrameInfo *mStackFrameInfo;
|
||||
};
|
||||
|
||||
class jsdValue : public jsdIValue
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_JSDIVALUE
|
||||
NS_DECL_JSDIEPHEMERAL
|
||||
|
||||
/* you'll normally use use FromPtr() instead of directly constructing one */
|
||||
jsdValue (JSDContext *aCx, JSDValue *aValue);
|
||||
virtual ~jsdValue();
|
||||
|
||||
static jsdIValue *FromPtr (JSDContext *aCx, JSDValue *aValue);
|
||||
static void InvalidateAll();
|
||||
|
||||
private:
|
||||
jsdValue(); /* no implementation */
|
||||
jsdValue (const jsdScript&); /* no implementation */
|
||||
|
||||
PRBool mValid;
|
||||
LiveEphemeral mLiveListEntry;
|
||||
JSDContext *mCx;
|
||||
JSDValue *mValue;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* debugger service
|
||||
******************************************************************************/
|
||||
|
||||
class jsdService : public jsdIDebuggerService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_JSDIDEBUGGERSERVICE
|
||||
|
||||
jsdService() : mInitAtStartup(triUnknown), mOn(PR_FALSE), mPauseLevel(0),
|
||||
mNestedLoopLevel(0), mCx(0), mRuntime(0), mErrorHook(0),
|
||||
mBreakpointHook(0), mDebugHook(0), mDebuggerHook(0),
|
||||
mInterruptHook(0), mScriptHook(0), mThrowHook(0),
|
||||
mTopLevelHook(0), mFunctionHook(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~jsdService();
|
||||
|
||||
static jsdService *GetService ();
|
||||
|
||||
private:
|
||||
enum Tristate {
|
||||
triUnknown = 0U,
|
||||
triYes = 1U,
|
||||
triNo = 2U
|
||||
};
|
||||
|
||||
Tristate mInitAtStartup;
|
||||
PRBool mOn;
|
||||
PRUint32 mPauseLevel;
|
||||
PRUint32 mNestedLoopLevel;
|
||||
JSDContext *mCx;
|
||||
JSRuntime *mRuntime;
|
||||
|
||||
nsCOMPtr<jsdIErrorHook> mErrorHook;
|
||||
nsCOMPtr<jsdIExecutionHook> mBreakpointHook;
|
||||
nsCOMPtr<jsdIExecutionHook> mDebugHook;
|
||||
nsCOMPtr<jsdIExecutionHook> mDebuggerHook;
|
||||
nsCOMPtr<jsdIExecutionHook> mInterruptHook;
|
||||
nsCOMPtr<jsdIScriptHook> mScriptHook;
|
||||
nsCOMPtr<jsdIExecutionHook> mThrowHook;
|
||||
nsCOMPtr<jsdICallHook> mTopLevelHook;
|
||||
nsCOMPtr<jsdICallHook> mFunctionHook;
|
||||
|
||||
};
|
||||
|
||||
#endif /* JSDSERVICE_H___ */
|
||||
|
||||
|
||||
/* graveyard */
|
||||
|
||||
#if 0
|
||||
|
||||
class jsdContext : public jsdIContext
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_JSDICONTEXT
|
||||
|
||||
/* you'll normally use use FromPtr() instead of directly constructing one */
|
||||
jsdContext (JSDContext *aCx) : mCx(aCx)
|
||||
{
|
||||
printf ("++++++ jsdContext\n");
|
||||
}
|
||||
|
||||
static jsdIContext *FromPtr (JSDContext *aCx)
|
||||
{
|
||||
if (!aCx)
|
||||
return nsnull;
|
||||
|
||||
void *data = JSD_GetContextPrivate (aCx);
|
||||
jsdIContext *rv;
|
||||
|
||||
if (data) {
|
||||
rv = NS_STATIC_CAST(jsdIContext *, data);
|
||||
} else {
|
||||
rv = new jsdContext (aCx);
|
||||
NS_IF_ADDREF(rv); // addref for the SetContextPrivate
|
||||
JSD_SetContextPrivate (aCx, NS_STATIC_CAST(void *, rv));
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(rv); // addref for the return value
|
||||
return rv;
|
||||
}
|
||||
|
||||
virtual ~jsdContext() { printf ("------ ~jsdContext\n"); }
|
||||
private:
|
||||
jsdContext(); /* no implementation */
|
||||
jsdContext(const jsdContext&); /* no implementation */
|
||||
|
||||
JSDContext *mCx;
|
||||
};
|
||||
|
||||
class jsdThreadState : public jsdIThreadState
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_JSDITHREADSTATE
|
||||
|
||||
/* you'll normally use use FromPtr() instead of directly constructing one */
|
||||
jsdThreadState (JSDContext *aCx, JSDThreadState *aThreadState) :
|
||||
mCx(aCx), mThreadState(aThreadState)
|
||||
{
|
||||
}
|
||||
|
||||
/* XXX These things are only valid for a short period of time, they reflect
|
||||
* state in the js engine that will go away after stepping past wherever
|
||||
* we were stopped at when this was created. We could keep a list of every
|
||||
* instance of this we've created, and "invalidate" them before we let the
|
||||
* engine continue. The next time we need a threadstate, we can search the
|
||||
* list to find an invalidated one, and just reuse it.
|
||||
*/
|
||||
static jsdIThreadState *FromPtr (JSDContext *aCx,
|
||||
JSDThreadState *aThreadState)
|
||||
{
|
||||
if (!aThreadState)
|
||||
return nsnull;
|
||||
|
||||
jsdIThreadState *rv = new jsdThreadState (aCx, aThreadState);
|
||||
NS_IF_ADDREF(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
jsdThreadState(); /* no implementation */
|
||||
jsdThreadState(const jsdThreadState&); /* no implementation */
|
||||
|
||||
JSDContext *mCx;
|
||||
JSDThreadState *mThreadState;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,112 +0,0 @@
|
||||
|
||||
PROJ = jsdshell
|
||||
JSD = .
|
||||
JSDJAVA = $(JSD)\java
|
||||
JS = $(JSD)\..\src
|
||||
RUN = $(JSD)\run
|
||||
JSPROJ = js32
|
||||
JSDPROJ = jsd
|
||||
JSDJAVAPROJ = jsdjava
|
||||
|
||||
!IF "$(BUILD_OPT)" != ""
|
||||
OPT = BUILD_OPT=1
|
||||
OBJ = Release
|
||||
CC_FLAGS = /DNDEBUG
|
||||
!ELSE
|
||||
OPT =
|
||||
OBJ = Debug
|
||||
CC_FLAGS = /DDEBUG
|
||||
LINK_FLAGS = /DEBUG
|
||||
!ENDIF
|
||||
|
||||
QUIET=@
|
||||
|
||||
CFLAGS = /nologo /MDd /W3 /Gm /GX /Zi /Od\
|
||||
/I $(JS)\
|
||||
/I $(JSD)\
|
||||
/DDEBUG /DWIN32 /D_CONSOLE /DXP_WIN /D_WINDOWS /D_WIN32\
|
||||
/DJSDEBUGGER\
|
||||
!IF "$(JSDEBUGGER_JAVA_UI)" != ""
|
||||
/I $(JSDJAVA)\
|
||||
/DJSDEBUGGER_JAVA_UI\
|
||||
/DJSD_STANDALONE_JAVA_VM\
|
||||
!ENDIF
|
||||
/DJSD_LOWLEVEL_SOURCE\
|
||||
/DJSFILE\
|
||||
$(CC_FLAGS)\
|
||||
/c /Fp$(OBJ)\$(PROJ).pch /Fd$(OBJ)\$(PROJ).pdb /YX -Fo$@ $<
|
||||
|
||||
LFLAGS = /nologo /subsystem:console /incremental:no /machine:I386 \
|
||||
$(LINK_FLAGS) /pdb:$(OBJ)\$(PROJ).pdb -out:$(OBJ)\$(PROJ).exe
|
||||
|
||||
LLIBS = kernel32.lib advapi32.lib \
|
||||
$(JS)\$(OBJ)\$(JSPROJ).lib \
|
||||
$(JSD)\$(OBJ)\$(JSDPROJ).lib \
|
||||
$(JSDJAVA)\$(OBJ)\$(JSDJAVAPROJ).lib
|
||||
|
||||
CPP=cl.exe
|
||||
LINK32=link.exe
|
||||
|
||||
all: $(OBJ) $(RUN) dlls $(OBJ)\$(PROJ).exe copy_binaries
|
||||
|
||||
$(OBJ)\$(PROJ).exe: \
|
||||
$(OBJ)\js.obj
|
||||
$(QUIET)$(LINK32) $(LFLAGS) $** $(LLIBS)
|
||||
|
||||
|
||||
{$(JS)}.c{$(OBJ)}.obj :
|
||||
$(QUIET)$(CPP) $(CFLAGS)
|
||||
|
||||
dlls :
|
||||
$(QUIET)cd ..\src
|
||||
!IF "$(BUILD_OPT)" != ""
|
||||
$(QUIET)nmake -f js.mak CFG="js - Win32 Release"
|
||||
!ELSE
|
||||
$(QUIET)nmake -f js.mak CFG="js - Win32 Debug"
|
||||
!ENDIF
|
||||
$(QUIET)cd ..\jsd
|
||||
$(QUIET)nmake -f jsd.mak JSD_THREADSAFE=1 $(OPT)
|
||||
$(QUIET)cd java
|
||||
$(QUIET)nmake -f jsdjava.mak JSD_STANDALONE_JAVA_VM=1 $(OPT)
|
||||
$(QUIET)cd ..
|
||||
|
||||
copy_binaries :
|
||||
@echo copying binaries
|
||||
$(QUIET)copy $(JS)\$(OBJ)\$(JSPROJ).dll $(RUN) >NUL
|
||||
$(QUIET)copy $(JS)\$(OBJ)\$(JSPROJ).pdb $(RUN) >NUL
|
||||
$(QUIET)copy $(JSD)\$(OBJ)\$(JSDPROJ).dll $(RUN) >NUL
|
||||
$(QUIET)copy $(JSD)\$(OBJ)\$(JSDPROJ).pdb $(RUN) >NUL
|
||||
$(QUIET)copy $(JSDJAVA)\$(OBJ)\$(JSDJAVAPROJ).dll $(RUN) >NUL
|
||||
$(QUIET)copy $(JSDJAVA)\$(OBJ)\$(JSDJAVAPROJ).pdb $(RUN) >NUL
|
||||
$(QUIET)copy $(OBJ)\$(PROJ).pdb $(RUN) >NUL
|
||||
$(QUIET)copy $(OBJ)\$(PROJ).exe $(RUN) >NUL
|
||||
|
||||
$(OBJ) :
|
||||
$(QUIET)mkdir $(OBJ)
|
||||
|
||||
$(RUN) :
|
||||
$(QUIET)mkdir $(RUN)
|
||||
|
||||
clean:
|
||||
@echo deleting old output
|
||||
$(QUIET)del $(OBJ)\js.obj >NUL
|
||||
$(QUIET)del $(OBJ)\$(PROJ).pch >NUL
|
||||
$(QUIET)del $(OBJ)\$(PROJ)*.idb >NUL
|
||||
$(QUIET)del $(OBJ)\$(PROJ).pdb >NUL
|
||||
$(QUIET)del $(OBJ)\$(PROJ).exe >NUL
|
||||
$(QUIET)del $(RUN)\*.pdb >NUL
|
||||
$(QUIET)del $(RUN)\*.exe >NUL
|
||||
$(QUIET)del $(RUN)\*.dll >NUL
|
||||
|
||||
deep_clean: clean
|
||||
$(QUIET)cd ..\src
|
||||
!IF "$(BUILD_OPT)" != ""
|
||||
$(QUIET)nmake -f js.mak CFG="js - Win32 Release" clean
|
||||
!ELSE
|
||||
$(QUIET)nmake -f js.mak CFG="js - Win32 Debug" clean
|
||||
!ENDIF
|
||||
$(QUIET)cd ..\jsd
|
||||
$(QUIET)nmake -f jsd.mak clean
|
||||
$(QUIET)cd java
|
||||
$(QUIET)nmake -f jsdjava.mak clean
|
||||
$(QUIET)cd ..
|
||||
@@ -1,49 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* this is all going away... replaced by code in js/jsd/java */
|
||||
|
||||
#if 0
|
||||
|
||||
#include "_stubs/netscape_jsdebug_Script.c"
|
||||
#include "_stubs/netscape_jsdebug_DebugController.c"
|
||||
#include "_stubs/netscape_jsdebug_JSThreadState.c"
|
||||
#include "_stubs/netscape_jsdebug_JSStackFrameInfo.c"
|
||||
#include "_stubs/netscape_jsdebug_JSPC.c"
|
||||
#include "_stubs/netscape_jsdebug_JSSourceTextProvider.c"
|
||||
|
||||
#endif
|
||||
@@ -1,4 +0,0 @@
|
||||
@echo off
|
||||
REM nmake -f jsdshell.mak JSDEBUGGER_JAVA_UI=1 LIVECONNECT=1 %1 %2 %3 %4 %5
|
||||
@echo on
|
||||
nmake -f jsdshell.mak JSDEBUGGER_JAVA_UI=1 %1 %2 %3 %4 %5
|
||||
@@ -1,52 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by jsd3240.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,3 +0,0 @@
|
||||
# This file is required as a placeholder to silence cvs warnings
|
||||
# as this file is individually listed in the cvs module file
|
||||
# and cvs complains when this file does not exist.
|
||||
@@ -1,391 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = js
|
||||
LIBRARY_NAME = mozjs
|
||||
LIB_IS_C_ONLY = 1
|
||||
GRE_MODULE = 1
|
||||
|
||||
ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
|
||||
LIBRARY_NAME = js$(MOZ_BITS)$(VERSION_NUMBER)
|
||||
RESFILE = js$(MOZ_BITS)40.res
|
||||
endif
|
||||
|
||||
PACKAGE_FILE = js.pkg
|
||||
|
||||
# JavaScript must be built shared, even for static builds, as it is used by
|
||||
# other modules which are always built shared. Failure to do so results in
|
||||
# the js code getting copied into xpinstall and jsd as well as mozilla-bin,
|
||||
# and then the static data cells used for locking no longer work.
|
||||
FORCE_SHARED_LIB = 1
|
||||
|
||||
CSRCS = \
|
||||
jsapi.c \
|
||||
jsarena.c \
|
||||
jsarray.c \
|
||||
jsatom.c \
|
||||
jsbool.c \
|
||||
jscntxt.c \
|
||||
jsdate.c \
|
||||
jsdbgapi.c \
|
||||
jsdhash.c \
|
||||
jsdtoa.c \
|
||||
jsemit.c \
|
||||
jsexn.c \
|
||||
jsfun.c \
|
||||
jsgc.c \
|
||||
jshash.c \
|
||||
jsinterp.c \
|
||||
jslock.c \
|
||||
jslog2.c \
|
||||
jslong.c \
|
||||
jsmath.c \
|
||||
jsnum.c \
|
||||
jsobj.c \
|
||||
jsopcode.c \
|
||||
jsparse.c \
|
||||
jsprf.c \
|
||||
jsregexp.c \
|
||||
jsscan.c \
|
||||
jsscope.c \
|
||||
jsscript.c \
|
||||
jsstr.c \
|
||||
jsutil.c \
|
||||
jsxdrapi.c \
|
||||
jsxml.c \
|
||||
prmjtime.c \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
jsautocfg.h \
|
||||
js.msg \
|
||||
jsapi.h \
|
||||
jsarray.h \
|
||||
jsarena.h \
|
||||
jsatom.h \
|
||||
jsbit.h \
|
||||
jsbool.h \
|
||||
jsclist.h \
|
||||
jscntxt.h \
|
||||
jscompat.h \
|
||||
jsconfig.h \
|
||||
jsdate.h \
|
||||
jsdbgapi.h \
|
||||
jsdhash.h \
|
||||
jsemit.h \
|
||||
jsfun.h \
|
||||
jsgc.h \
|
||||
jshash.h \
|
||||
jsinterp.h \
|
||||
jslock.h \
|
||||
jslong.h \
|
||||
jsmath.h \
|
||||
jsnum.h \
|
||||
jsobj.h \
|
||||
jsopcode.tbl \
|
||||
jsopcode.h \
|
||||
jsosdep.h \
|
||||
jsotypes.h \
|
||||
jsparse.h \
|
||||
jsprf.h \
|
||||
jsprvtd.h \
|
||||
jspubtd.h \
|
||||
jsregexp.h \
|
||||
jsscan.h \
|
||||
jsscope.h \
|
||||
jsscript.h \
|
||||
jsstddef.h \
|
||||
jsstr.h \
|
||||
jstypes.h \
|
||||
jsutil.h \
|
||||
jsxdrapi.h \
|
||||
jsxml.h \
|
||||
$(NULL)
|
||||
|
||||
ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
|
||||
EXPORTS += jscpucfg.h
|
||||
endif
|
||||
|
||||
FDLIBM_LIBRARY = fdlibm/$(LIB_PREFIX)fdm.$(LIB_SUFFIX)
|
||||
JSMATH_PRELINK = jsmathtemp.o
|
||||
JS_SAFE_ARENA = 1
|
||||
|
||||
DASH_R = -r
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
EXTRA_DSO_LDOPTS += $(NSPR_LIBS)
|
||||
|
||||
ifeq (,$(filter-out OS2 WINNT WINCE,$(OS_ARCH)))
|
||||
SHARED_LIBRARY_LIBS += $(FDLIBM_LIBRARY)
|
||||
endif
|
||||
|
||||
# When using gcc the assembly is inlined in the C-file (see jslock.c)
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
ifneq ($(OS_TEST),i86pc)
|
||||
ifndef GNU_CC
|
||||
ASFILES = lock_$(OS_ARCH).s
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef BUILD_OPT
|
||||
MOCHAFILE = 1
|
||||
endif
|
||||
|
||||
ifndef NSBUILDROOT
|
||||
JSJAVA_STUBHEADERS = \
|
||||
-I$(topsrcdir)/sun-java/include/_gen \
|
||||
-I$(topsrcdir)/sun-java/netscape/javascript/_jri \
|
||||
-I$(topsrcdir)/sun-java/netscape/security/_jri
|
||||
else
|
||||
JSJAVA_STUBHEADERS = -I$(JRI_GEN_DIR) -I$(JDK_GEN_DIR)
|
||||
endif
|
||||
|
||||
JSJAVA_CFLAGS = \
|
||||
-I$(topsrcdir)/sun-java/md-include \
|
||||
-I$(topsrcdir)/sun-java/include \
|
||||
$(JSJAVA_STUBHEADERS)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES += -DEXPORT_JS_API
|
||||
|
||||
INCLUDES += -I$(srcdir)
|
||||
|
||||
# MSVC '-Gy' cc flag and '/OPT:REF' linker flag cause JS_GetArgument and
|
||||
# JS_GetLocalVariable to be folded to the same address by the linker,
|
||||
# leading to a crash on startup. See bug 151066. So, in optimized builds,
|
||||
# add the /OPT:NOICF flag, which turns off 'identical COMDAT folding'.
|
||||
#
|
||||
# N.B.: 'identical COMDAT folding' that folds functions whose addresses
|
||||
# are taken violates the ISO C and C++ standards.
|
||||
ifndef MOZ_DEBUG
|
||||
ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
|
||||
LDFLAGS += -OPT:NOICF
|
||||
endif
|
||||
endif
|
||||
|
||||
GARBAGE += $(JSMATH_PRELINK) jscpucfg.o jsautocfg.h jsautocfg.tmp jscpucfg
|
||||
|
||||
ifneq (,$(CROSS_COMPILE)$(filter-out WINNT,$(OS_ARCH)))
|
||||
TARGETS += jscpucfg$(HOST_BIN_SUFFIX)
|
||||
endif
|
||||
|
||||
ifdef JS_SAFE_ARENA
|
||||
DEFINES += -DJS_USE_SAFE_ARENA
|
||||
endif
|
||||
|
||||
ifdef JS_THREADSAFE
|
||||
DEFINES += -DJS_THREADSAFE
|
||||
endif
|
||||
|
||||
ifdef JS_NO_THIN_LOCKS
|
||||
DEFINES += -DJS_USE_ONLY_NSPR_LOCKS
|
||||
endif
|
||||
|
||||
ifdef JS_VERSION
|
||||
DEFINES += -DJS_VERSION=$(JS_VERSION)
|
||||
endif
|
||||
|
||||
ifneq ($(findstring -L,$(NSPR_LIBS)),)
|
||||
NSPR_STATIC_PATH = $(subst -L,,$(findstring -L,$(NSPR_LIBS)))
|
||||
else
|
||||
NSPR_STATIC_PATH = $(DIST)/lib
|
||||
endif
|
||||
|
||||
LDFLAGS += $(pathsubst -l%,$(NSPR_STATIC_PATH)/%.a,$(NSPR_LIBS))
|
||||
|
||||
# BeOS and HP-UX do not require the extra linking of "-lm"
|
||||
ifeq (,$(filter BeOS HP-UX WINNT WINCE OpenVMS,$(OS_ARCH)))
|
||||
LDFLAGS += -lm
|
||||
endif
|
||||
|
||||
# Prevent floating point errors caused by VC++ optimizations
|
||||
ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
|
||||
ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER)))
|
||||
CFLAGS += -Op
|
||||
else
|
||||
CFLAGS += -fp:precise
|
||||
endif
|
||||
endif # WINNT
|
||||
|
||||
ifeq ($(OS_ARCH),FreeBSD)
|
||||
LDFLAGS += -pthread
|
||||
endif
|
||||
ifeq ($(OS_ARCH),IRIX)
|
||||
ifdef USE_N32
|
||||
DASH_R += -n32
|
||||
endif
|
||||
endif
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
ifeq ($(OS_ARCH),OSF1)
|
||||
LDFLAGS += -lc_r
|
||||
endif
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
ifeq ($(TARGET_CPU),sparc)
|
||||
|
||||
ifdef JS_ULTRASPARC_OPTS
|
||||
DEFINES += -DULTRA_SPARC
|
||||
ifdef GNU_CC
|
||||
CFLAGS += -Wa,-xarch=v8plus,-DULTRA_SPARC,-P,-L,-D_ASM,-D__STDC__=0
|
||||
CXXFLAGS += -Wa,-xarch=v8plus,-DULTRA_SPARC,-P,-L,-D_ASM,-D__STDC__=0,-K,PIC
|
||||
else
|
||||
ASFLAGS += -xarch=v8plus -DULTRA_SPARC -P -L -D_ASM -D__STDC__=0 -K PIC
|
||||
endif # GNU_CC
|
||||
endif # JS_ULTRASPARC_OPTS
|
||||
|
||||
endif
|
||||
ifeq ($(OS_RELEASE),4.1)
|
||||
LDFLAGS += -ldl -lnsl
|
||||
else
|
||||
LDFLAGS += -lposix4 -ldl -lnsl -lsocket
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),QNX)
|
||||
ifneq ($(OS_TARGET),NTO)
|
||||
# Don't use wildcard here, because we only want this resolved at link time.
|
||||
OBJS += fdlibm/*.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),IRIX)
|
||||
ifndef GNU_CC
|
||||
_COMPILE_CFLAGS = $(patsubst -O%,-O1,$(COMPILE_CFLAGS))
|
||||
jsapi.o jsarena.o jsarray.o jsatom.o jsemit.o jsfun.o jsinterp.o jsregexp.o jsparse.o jsopcode.o jsscript.o: %.o: %.c Makefile.in
|
||||
$(REPORT_BUILD)
|
||||
@$(MAKE_DEPS_AUTO)
|
||||
$(CC) -o $@ -c $(_COMPILE_CFLAGS) $<
|
||||
endif
|
||||
endif
|
||||
|
||||
# On OS/2 & win32 we are already linking against fdlibm, so don't bother
|
||||
# creating jsmathtemp
|
||||
ifeq (,$(filter OS2 WINNT OpenVMS,$(OS_ARCH)))
|
||||
# special rule for jsmath.o since we want to incrementally link
|
||||
# against fdlibm to pull in only what is needed
|
||||
# Do this in a single step to avoid dependency problems
|
||||
jsmath.o: jsmath.c $(FDLIBM_LIBRARY) Makefile.in
|
||||
$(REPORT_BUILD)
|
||||
@$(MAKE_DEPS_AUTO)
|
||||
$(ELOG) $(CC) $(OUTOPTION)$(JSMATH_PRELINK) -c $(COMPILE_CFLAGS) $<
|
||||
ifeq ($(OS_ARCH),QNX)
|
||||
ifneq ($(OS_TARGET),NTO)
|
||||
@cp $(JSMATH_PRELINK) $@
|
||||
else
|
||||
$(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY)
|
||||
endif
|
||||
else
|
||||
$(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY)
|
||||
endif
|
||||
@$(RM) -f $(JSMATH_PRELINK)
|
||||
else
|
||||
# Create dependency so we build fdlibm
|
||||
jsmath.o: $(FDLIBM_LIBRARY) Makefile.in
|
||||
endif
|
||||
|
||||
# An AIX Optimization bug causes PR_dtoa() & JS_dtoa to produce wrong result.
|
||||
# This suppresses optimization for this single compilation unit.
|
||||
ifeq ($(OS_ARCH),AIX)
|
||||
jsatom.o: jsatom.c Makefile.in
|
||||
$(REPORT_BUILD)
|
||||
@$(MAKE_DEPS_AUTO)
|
||||
$(CC) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
|
||||
jsdtoa.o: jsdtoa.c Makefile.in
|
||||
$(REPORT_BUILD)
|
||||
@$(MAKE_DEPS_AUTO)
|
||||
$(CC) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
|
||||
endif
|
||||
|
||||
$(FDLIBM_LIBRARY):
|
||||
$(MAKE) -C $(@D) $(@F)
|
||||
|
||||
jsopcode.h jsopcode.c: jsopcode.tbl
|
||||
|
||||
ifeq (,$(CROSS_COMPILE)$(filter-out WINNT,$(OS_ARCH)))
|
||||
jsautocfg.h:
|
||||
touch $@
|
||||
else
|
||||
ifeq ($(OS_ARCH),WINCE)
|
||||
jsautocfg.h:
|
||||
touch $@
|
||||
else
|
||||
jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX)
|
||||
@rm -f $@ jsautocfg.tmp
|
||||
./jscpucfg > jsautocfg.tmp
|
||||
mv jsautocfg.tmp $@
|
||||
endif
|
||||
endif
|
||||
|
||||
# jscpucfg is a strange target
|
||||
# Needs to be built with the host compiler but needs to include
|
||||
# the mdcpucfg for the target so it needs the appropriate target defines
|
||||
ifdef HOST_NSPR_MDCPUCFG
|
||||
HOST_CC := $(HOST_CC) -DMDCPUCFG=$(TARGET_NSPR_MDCPUCFG)
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),QNX)
|
||||
ifneq ($(OS_TARGET),NTO)
|
||||
# QNX's compiler apparently can't build a binary directly from a source file.
|
||||
jscpucfg.o: jscpucfg.c Makefile.in
|
||||
$(HOST_CC) $(HOST_CFLAGS) -c $(DEFINES) $(NSPR_CFLAGS) -o $@ $<
|
||||
|
||||
jscpucfg: jscpucfg.o
|
||||
$(HOST_CC) $(HOST_CFLAGS) $(DEFINES) -o $@ $<
|
||||
endif
|
||||
else
|
||||
ifeq ($(OS_ARCH),WINCE)
|
||||
jscpucfg$(HOST_BIN_SUFFIX):
|
||||
echo no need to build jscpucfg $<
|
||||
else
|
||||
jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.c Makefile.in
|
||||
$(HOST_CC) $(HOST_CFLAGS) $(DEFINES) $(NSPR_CFLAGS) $(OUTOPTION)$@ $<
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -1,374 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Michael Ang <mang@subcarrier.org>
|
||||
# Kevin Buhr <buhr@stat.wisc.edu>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# JSRef GNUmake makefile.
|
||||
#
|
||||
# Note: dependency rules are missing for some files (some
|
||||
# .h, all .msg, etc.) Re-make clean if in doubt.
|
||||
#
|
||||
|
||||
|
||||
DEPTH = .
|
||||
|
||||
include config.mk
|
||||
|
||||
#NS_USE_NATIVE = 1
|
||||
|
||||
ifdef USE_MSVC
|
||||
OTHER_LIBS += fdlibm/$(OBJDIR)/fdlibm.lib
|
||||
else
|
||||
OTHER_LIBS += -Lfdlibm/$(OBJDIR) -lfdm
|
||||
endif
|
||||
|
||||
ifdef JS_THREADSAFE
|
||||
DEFINES += -DJS_THREADSAFE
|
||||
INCLUDES += -I../../dist/$(OBJDIR)/include
|
||||
ifdef USE_MSVC
|
||||
OTHER_LIBS += ../../dist/$(OBJDIR)/lib/libnspr${NSPR_LIBSUFFIX}.lib
|
||||
else
|
||||
OTHER_LIBS += -L../../dist/$(OBJDIR)/lib -lnspr${NSPR_LIBSUFFIX}
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef JS_NO_THIN_LOCKS
|
||||
DEFINES += -DJS_USE_ONLY_NSPR_LOCKS
|
||||
endif
|
||||
|
||||
ifdef JS_HAS_FILE_OBJECT
|
||||
DEFINES += -DJS_HAS_FILE_OBJECT
|
||||
endif
|
||||
|
||||
#
|
||||
# XCFLAGS may be set in the environment or on the gmake command line
|
||||
#
|
||||
CFLAGS += $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS)
|
||||
|
||||
LDFLAGS = $(XLDFLAGS)
|
||||
|
||||
ifndef NO_LIBM
|
||||
LDFLAGS += -lm
|
||||
endif
|
||||
|
||||
# Prevent floating point errors caused by VC++ optimizations
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
CFLAGS += /Op
|
||||
endif # WINNT
|
||||
|
||||
#
|
||||
# Ask perl what flags it was built with, so we can build js with similar flags
|
||||
# and link properly. Viva gmake.
|
||||
#
|
||||
ifdef JS_PERLCONNECT
|
||||
DEFINES += -DPERLCONNECT -D_GNU_SOURCE
|
||||
|
||||
PERLCFLAGS := $(shell perl -MExtUtils::Embed -e ccopts)
|
||||
PERLLDFLAGS := $(shell perl -MExtUtils::Embed -e ldopts)
|
||||
|
||||
# perl erroneously reports compiler flag -rdynamic (interpreted by ld
|
||||
# as -r) when it really meant -export-dynamic.
|
||||
PERLLDFLAGS := $(subst -rdynamic,-export-dynamic,$(PERLLDFLAGS))
|
||||
|
||||
CFLAGS += $(PERLCFLAGS)
|
||||
#LDFLAGS += $(PERLLDFLAGS) #PH removed this assgnment
|
||||
INCLUDES += -I. #needed for perlconnect/jsperl.c
|
||||
endif
|
||||
|
||||
#
|
||||
# Server-related changes :
|
||||
#
|
||||
ifdef NES40
|
||||
DEFINES += -DNES40
|
||||
endif
|
||||
|
||||
#
|
||||
# Line editing support.
|
||||
# Define JS_READLINE or JS_EDITLINE to enable line editing in the
|
||||
# js command-line interpreter.
|
||||
#
|
||||
ifdef JS_READLINE
|
||||
# For those platforms with the readline library installed.
|
||||
DEFINES += -DEDITLINE
|
||||
PROG_LIBS += -lreadline -ltermcap
|
||||
else
|
||||
ifdef JS_EDITLINE
|
||||
# Use the editline library, built locally.
|
||||
PREDIRS += editline
|
||||
DEFINES += -DEDITLINE
|
||||
PROG_LIBS += editline/$(OBJDIR)/libedit.a
|
||||
endif
|
||||
endif
|
||||
|
||||
# For purify
|
||||
PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \
|
||||
$(INCLUDES) $(XCFLAGS)
|
||||
|
||||
#
|
||||
# JS file lists
|
||||
#
|
||||
JS_HFILES = \
|
||||
jsarray.h \
|
||||
jsatom.h \
|
||||
jsbool.h \
|
||||
jsconfig.h \
|
||||
jscntxt.h \
|
||||
jsdate.h \
|
||||
jsemit.h \
|
||||
jsexn.h \
|
||||
jsfun.h \
|
||||
jsgc.h \
|
||||
jsinterp.h \
|
||||
jslibmath.h \
|
||||
jslock.h \
|
||||
jsmath.h \
|
||||
jsnum.h \
|
||||
jsobj.h \
|
||||
jsopcode.h \
|
||||
jsparse.h \
|
||||
jsarena.h \
|
||||
jsclist.h \
|
||||
jsdhash.h \
|
||||
jsdtoa.h \
|
||||
jshash.h \
|
||||
jslong.h \
|
||||
jsosdep.h \
|
||||
jstypes.h \
|
||||
jsprvtd.h \
|
||||
jspubtd.h \
|
||||
jsregexp.h \
|
||||
jsscan.h \
|
||||
jsscope.h \
|
||||
jsscript.h \
|
||||
jsstr.h \
|
||||
jsxdrapi.h \
|
||||
jsxml.h \
|
||||
$(NULL)
|
||||
|
||||
API_HFILES = \
|
||||
jsapi.h \
|
||||
jsdbgapi.h \
|
||||
$(NULL)
|
||||
|
||||
OTHER_HFILES = \
|
||||
jsbit.h \
|
||||
jscompat.h \
|
||||
jscpucfg.h \
|
||||
jsotypes.h \
|
||||
jsstddef.h \
|
||||
prmjtime.h \
|
||||
resource.h \
|
||||
jsopcode.tbl \
|
||||
js.msg \
|
||||
jsshell.msg \
|
||||
$(NULL)
|
||||
|
||||
ifndef PREBUILT_CPUCFG
|
||||
OTHER_HFILES += $(OBJDIR)/jsautocfg.h
|
||||
endif
|
||||
|
||||
HFILES = $(JS_HFILES) $(API_HFILES) $(OTHER_HFILES)
|
||||
|
||||
JS_CFILES = \
|
||||
jsapi.c \
|
||||
jsarena.c \
|
||||
jsarray.c \
|
||||
jsatom.c \
|
||||
jsbool.c \
|
||||
jscntxt.c \
|
||||
jsdate.c \
|
||||
jsdbgapi.c \
|
||||
jsdhash.c \
|
||||
jsdtoa.c \
|
||||
jsemit.c \
|
||||
jsexn.c \
|
||||
jsfun.c \
|
||||
jsgc.c \
|
||||
jshash.c \
|
||||
jsinterp.c \
|
||||
jslock.c \
|
||||
jslog2.c \
|
||||
jslong.c \
|
||||
jsmath.c \
|
||||
jsnum.c \
|
||||
jsobj.c \
|
||||
jsopcode.c \
|
||||
jsparse.c \
|
||||
jsprf.c \
|
||||
jsregexp.c \
|
||||
jsscan.c \
|
||||
jsscope.c \
|
||||
jsscript.c \
|
||||
jsstr.c \
|
||||
jsutil.c \
|
||||
jsxdrapi.c \
|
||||
jsxml.c \
|
||||
prmjtime.c \
|
||||
$(NULL)
|
||||
|
||||
PREDIRS += fdlibm
|
||||
|
||||
ifdef USE_MSVC
|
||||
FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/fdlibm.lib
|
||||
else
|
||||
FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/libfdm.a
|
||||
endif
|
||||
JSMATH_PRELINK = $(OBJDIR)/jsmathtemp.o
|
||||
# Flag for incremental linking
|
||||
DASH_R = -r
|
||||
|
||||
ifeq ($(OS_ARCH),QNX)
|
||||
ifneq ($(OS_TARGET),NTO)
|
||||
# Don't use wildcard here, because we only want this resolved at link time.
|
||||
OBJS += fdlibm/*.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef JS_LIVECONNECT
|
||||
DIRS += liveconnect
|
||||
endif
|
||||
|
||||
ifdef JS_PERLCONNECT
|
||||
JS_CFILES += perlconnect/jsperl.c
|
||||
endif
|
||||
|
||||
ifdef JS_HAS_FILE_OBJECT
|
||||
JS_CFILES += jsfile.c
|
||||
JS_HFILES += jsfile.h
|
||||
endif
|
||||
|
||||
LIB_CFILES = $(JS_CFILES)
|
||||
LIB_ASFILES := $(wildcard *_$(OS_ARCH).s)
|
||||
PROG_CFILES = js.c
|
||||
|
||||
ifdef USE_MSVC
|
||||
LIBRARY = $(OBJDIR)/js32.lib
|
||||
SHARED_LIBRARY = $(OBJDIR)/js32.dll
|
||||
PROGRAM = $(OBJDIR)/js.exe
|
||||
else
|
||||
LIBRARY = $(OBJDIR)/libjs.a
|
||||
SHARED_LIBRARY = $(OBJDIR)/libjs.$(SO_SUFFIX)
|
||||
PROGRAM = $(OBJDIR)/js
|
||||
ifdef JS_PERLCONNECT
|
||||
PROG_LIBS += $(PERLLDFLAGS)
|
||||
endif
|
||||
endif
|
||||
|
||||
include rules.mk
|
||||
|
||||
MOZ_DEPTH = ../..
|
||||
include jsconfig.mk
|
||||
|
||||
nsinstall-target:
|
||||
cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR)
|
||||
ifdef USE_MSVC
|
||||
$(PROGRAM): $(PROG_OBJS) $(LIBRARY) $(FDLIBM_LIBRARY)
|
||||
link.exe -out:"$@" $(EXE_LINK_FLAGS) $^
|
||||
else
|
||||
$(PROGRAM): $(PROG_OBJS) $(LIBRARY) $(FDLIBM_LIBRARY)
|
||||
$(CC) -o $@ $(CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) $(OTHER_LIBS) \
|
||||
$(PROG_LIBS)
|
||||
endif
|
||||
|
||||
$(PROGRAM).pure: $(PROG_OBJS) $(LIBRARY)
|
||||
purify $(PUREFLAGS) \
|
||||
$(CC) -o $@ $(PURE_OS_CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) \
|
||||
$(OTHER_LIBS) $(PROG_LIBS)
|
||||
|
||||
ifndef PREBUILT_CPUCFG
|
||||
$(HFILES) $(CFILES): $(OBJDIR)/jsautocfg.h
|
||||
|
||||
$(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg
|
||||
rm -f $@
|
||||
$(OBJDIR)/jscpucfg > $@
|
||||
|
||||
$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o
|
||||
$(CC) -o $@ $(OBJDIR)/jscpucfg.o
|
||||
|
||||
# Look in OBJDIR to find jsautocfg.h
|
||||
INCLUDES += -I$(OBJDIR)
|
||||
|
||||
# Add to TARGETS for clobber rule
|
||||
TARGETS += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg \
|
||||
$(OBJDIR)/jscpucfg.o $(OBJDIR)/jsmathtemp.o
|
||||
endif
|
||||
|
||||
|
||||
# special rule for jsmath.o since we want to incrementally link
|
||||
# against fdlibm to pull in only what is needed
|
||||
$(OBJDIR)/jsmath.o: jsmath.c jsmath.h jslibmath.h $(FDLIBM_LIBRARY)
|
||||
ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
|
||||
$(CC) -Fo$(JSMATH_PRELINK) -c $(CFLAGS) $<
|
||||
else
|
||||
$(CC) -o $(JSMATH_PRELINK) -c $(CFLAGS) $<
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),QNX)
|
||||
ifneq ($(OS_TARGET),NTO)
|
||||
@cp $(JSMATH_PRELINK) $@
|
||||
else
|
||||
$(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY)
|
||||
endif
|
||||
else
|
||||
ifdef USE_MSVC
|
||||
@echo Warning: to use $(LIBRARY) must also link against $(FDLIBM_LIBRARY)
|
||||
@cp $(JSMATH_PRELINK) $@
|
||||
endif
|
||||
$(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY)
|
||||
endif
|
||||
|
||||
# Note: generated headers must be built before descending
|
||||
# into fdlibm directory
|
||||
$(FDLIBM_LIBRARY) :
|
||||
$(MAKE) -C fdlibm -f Makefile.ref $(@F)
|
||||
|
||||
#
|
||||
# Hardwire dependencies on jsopcode.tbl
|
||||
#
|
||||
jsopcode.h jsopcode.c: jsopcode.tbl
|
||||
|
||||
-include $(DEPENDENCIES)
|
||||
|
||||
TARNAME = jsref.tar
|
||||
TARFILES = files `cat files`
|
||||
|
||||
SUFFIXES: .i
|
||||
%.i: %.c
|
||||
$(CC) -C -E $(CFLAGS) $< > $*.i
|
||||
@@ -1,826 +0,0 @@
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- 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 Communicator client code, released
|
||||
- March 31, 1998.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- Netscape Communications Corporation.
|
||||
- Portions created by the Initial Developer are Copyright (C) 1998-1999
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
- or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
<!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.5 [en] (WinNT; I) [Netscape]">
|
||||
<title>JavaScript Reference Implementation (JSRef) README</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>
|
||||
Table of Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#Introduction">Introduction</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#Build">Build conventions (standalone JS engine and shell)</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#Debugging">Debugging notes</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#Conventions">Naming and coding conventions</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#JSAPI">Using the JS API</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#Design">Design walk-through</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#Resources">Additional Resources (links, API docs, and newsgroups)</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<a NAME="Introduction"></a>Introduction</h2>
|
||||
This is the README file for the <span CLASS=LXRSHORTDESC>JavaScript
|
||||
Reference (JSRef, now better known as SpiderMonkey) implementation.</span>
|
||||
It consists of build conventions
|
||||
and instructions, source code conventions, a design walk-through, and a
|
||||
brief file-by-file description of the source.
|
||||
<p><span CLASS=LXRLONGDESC>JSRef builds a library or DLL containing the
|
||||
JavaScript runtime (compiler, interpreter, decompiler, garbage collector,
|
||||
atom manager, standard classes). It then compiles a small "shell" program
|
||||
and links that with the library to make an interpreter that can be used
|
||||
interactively and with test .js files to run scripts. The code has
|
||||
no dependencies on the rest of the Mozilla codebase.</span>
|
||||
<p><i>Quick start tip</i>: skip to "Using the JS API" below, build the
|
||||
js shell, and play with the object named "it" (start by setting 'it.noisy
|
||||
= true').
|
||||
<h2>
|
||||
<a NAME="Build"></a>Build conventions (standalone JS engine and shell)
|
||||
(OUT OF DATE!)</h2>
|
||||
These build directions refer only to building the standalone JavaScript
|
||||
engine and shell. To build within the browser, refer to the <a
|
||||
href="http://www.mozilla.org/build/">build
|
||||
directions</a> on the mozilla.org website.
|
||||
<p>By default, all platforms build a version of the JS engine that is <i>not</i>
|
||||
threadsafe. If you require thread-safety, you must also populate
|
||||
the <tt>mozilla/dist</tt> directory with <a href="http://www.mozilla.org/projects/nspr/reference/html/"
|
||||
>NSPR</a>
|
||||
headers and libraries. (NSPR implements a portable threading library,
|
||||
among other things. The source is downloadable via <a href="http://www.mozilla.org/cvs.html">CVS</a>
|
||||
from <tt><a href="http://lxr.mozilla.org/mozilla/source/nsprpub">mozilla/nsprpub</a></tt>.)
|
||||
Next, you must define <tt>JS_THREADSAFE</tt> when building the JS engine,
|
||||
either on the command-line (gmake/nmake) or in a universal header file.
|
||||
<h3>
|
||||
Windows</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Use MSVC 4.2 or 5.0.</li>
|
||||
|
||||
<li>
|
||||
For building from the IDE use <tt>js/src/js.mdp</tt>. (<tt>js.mdp</tt>
|
||||
is an MSVC4.2 project file, but if you load it into MSVC5, it will be converted
|
||||
to the newer project file format.) <font color="#CC0000">NOTE: makefile.win
|
||||
is an nmake file used only for building the JS-engine in the Mozilla browser.
|
||||
Don't attempt to use it to build the standalone JS-engine.</font></li>
|
||||
|
||||
<li>
|
||||
If you prefer to build from the command-line, use '<tt>nmake -f js.mak</tt>'</li>
|
||||
|
||||
<li>
|
||||
Executable shell <tt>js.exe</tt> and runtime library <tt>js32.dll</tt>
|
||||
are created in either <tt>js/src/Debug</tt> or <tt>js/src/Release</tt>.</li>
|
||||
</ul>
|
||||
|
||||
<h3>
|
||||
Macintosh</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Use CodeWarrior 3.x</li>
|
||||
|
||||
<li>
|
||||
Load the project file <tt>js:src:macbuild:JSRef.mcp </tt>and select "Make"
|
||||
from the menu.</li>
|
||||
</ul>
|
||||
|
||||
<h3>
|
||||
Unix</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Use '<tt>gmake -f Makefile.ref</tt>' to build. To compile optimized code,
|
||||
pass <tt>BUILD_OPT=1</tt> on the gmake command line or preset it in the
|
||||
environment or <tt>Makefile.ref</tt>. <font color="#CC0000">NOTE:
|
||||
Do not attempt to use Makefile to build the standalone JavaScript engine.
|
||||
This file is used only for building the JS-engine in the Mozilla browser.</font></li>
|
||||
|
||||
<li>
|
||||
<font color="#000000">Each platform on which JS is built must have a <tt>*.mk</tt>
|
||||
configuration file in the <tt>js/src/config</tt> directory. The configuration
|
||||
file specifies the compiler/linker to be used and allows for customization
|
||||
of command-line options. To date, the build system has been tested
|
||||
on Solaris, AIX, HP/UX, OSF, IRIX, x86 Linux and Windows NT.</font></li>
|
||||
|
||||
<li>
|
||||
<font color="#000000">Most platforms will work with either the vendor compiler
|
||||
</font>or
|
||||
<a href="ftp://prep.ai.mit.edu/pub/gnu">gcc</a>.
|
||||
(Except that HP builds only work using the native compiler. gcc won't
|
||||
link correctly with shared libraries on that platform. If someone
|
||||
knows a way to fix this, <a href="mailto:wynholds@netscape.com">let us
|
||||
know</a>.)</li>
|
||||
|
||||
<li>
|
||||
<font color="#000000">If you define <tt>JS_LIVECONNECT</tt>, gmake will
|
||||
descend into the liveconnect directory and build
|
||||
<a href="http://lxr.mozilla.org/mozilla/source/js/src/liveconnect/README.html">LiveConnect</a>
|
||||
after building the JS engine.</font></li>
|
||||
|
||||
<li>
|
||||
To build a binary drop (a zip'ed up file of headers, libraries, binaries),
|
||||
check out <tt>mozilla/config</tt> and <tt>mozilla/nsprpub/config</tt>.
|
||||
Use '<tt>gmake -f Makefile.ref nsinstall-target all export ship</tt>'</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<a NAME="Debugging"></a>Debugging notes</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
To turn on GC instrumentation, define <tt>JS_GCMETER</tt>.</li>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
To turn on GC mark-phase debugging, useful to find leaked objects by their
|
||||
address, and to dump the GC heap, define <tt>GC_MARK_DEBUG</tt>.
|
||||
See the code in jsgc.c around the declaration and use of
|
||||
<tt>js_LiveThingToFind</tt>.</li>
|
||||
|
||||
<li>
|
||||
To turn on the arena package's instrumentation, define <tt>JS_ARENAMETER</tt>.</li>
|
||||
|
||||
<li>
|
||||
To turn on the hash table package's metering, define <tt>JS_HASHMETER</tt>.</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<a NAME="Conventions"></a>Naming and coding conventions</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Public function names begin with <tt>JS_</tt> followed by capitalized "intercaps",
|
||||
e.g. <tt>JS_NewObject</tt>.</li>
|
||||
|
||||
<li>
|
||||
Extern but library-private function names use a <tt>js_</tt> prefix and
|
||||
mixed case, e.g. <tt>js_SearchScope</tt>.</li>
|
||||
|
||||
<li>
|
||||
Most static function names have unprefixed, mixed-case names: <tt>GetChar</tt>.</li>
|
||||
|
||||
<li>
|
||||
But static native methods of JS objects have lowercase, underscore-separated
|
||||
or intercaps names, e.g., <tt>str_indexOf</tt>.</li>
|
||||
|
||||
<li>
|
||||
And library-private and static data use underscores, not intercaps (but
|
||||
library-private data do use a <tt>js_</tt> prefix).</li>
|
||||
|
||||
<li>
|
||||
Scalar type names are lowercase and js-prefixed: <tt>jsdouble</tt>.</li>
|
||||
|
||||
<li>
|
||||
Aggregate type names are JS-prefixed and mixed-case: <tt>JSObject.</tt></li>
|
||||
|
||||
<li>
|
||||
Macros are generally <tt>ALL_CAPS </tt>and underscored, to call out potential
|
||||
side effects, multiple uses of a formal argument, etc.</li>
|
||||
|
||||
<li>
|
||||
Four spaces of indentation per statement nesting level.</li>
|
||||
|
||||
<li>
|
||||
Tabs are taken to be eight spaces, and an Emacs magic comment at the top
|
||||
of each file tries to help. If you're using MSVC or similar, you'll want
|
||||
to set tab width to 8, and help convert these files to be space-filled.
|
||||
<font color="#CC0000">Do not add hard tabs to source files; do remove them
|
||||
whenever possible.</font></li>
|
||||
|
||||
<li>
|
||||
DLL entry points have their return type expanded within a <tt>JS_PUBLIC_API()</tt>
|
||||
macro call, to get the right Windows secret type qualifiers in the right
|
||||
places for all build variants.</li>
|
||||
|
||||
<li>
|
||||
Callback functions that might be called from a DLL are similarly macroized
|
||||
with <tt>JS_STATIC_DLL_CALLBACK</tt> (if the function otherwise would be
|
||||
static to hide its name) or <tt>JS_DLL_CALLBACK</tt> (this macro takes
|
||||
no type argument; it should be used after the return type and before the
|
||||
function name).</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<a NAME="JSAPI"></a>Using the JS API</h2>
|
||||
|
||||
<h4>
|
||||
Starting up</h4>
|
||||
|
||||
<pre><tt> /*
|
||||
* Tune this to avoid wasting space for shallow stacks, while saving on
|
||||
* malloc overhead/fragmentation for deep or highly-variable stacks.
|
||||
*/
|
||||
#define STACK_CHUNK_SIZE 8192
|
||||
|
||||
JSRuntime *rt;
|
||||
JSContext *cx;
|
||||
|
||||
/* You need a runtime and one or more contexts to do anything with JS. */
|
||||
rt = JS_NewRuntime(0x400000L);
|
||||
if (!rt)
|
||||
fail("can't create JavaScript runtime");
|
||||
cx = JS_NewContext(rt, STACK_CHUNK_SIZE);
|
||||
if (!cx)
|
||||
fail("can't create JavaScript context");
|
||||
|
||||
/*
|
||||
* The context definitely wants a global object, in order to have standard
|
||||
* classes and functions like Date and parseInt. See below for details on
|
||||
* JS_NewObject.
|
||||
*/
|
||||
JSObject *globalObj;
|
||||
|
||||
globalObj = JS_NewObject(cx, &my_global_class, 0, 0);
|
||||
JS_InitStandardClasses(cx, globalObj);</tt></pre>
|
||||
|
||||
<h4>
|
||||
Defining objects and properties</h4>
|
||||
|
||||
<pre><tt> /* Statically initialize a class to make "one-off" objects. */
|
||||
JSClass my_class = {
|
||||
"MyClass",
|
||||
|
||||
/* All of these can be replaced with the corresponding JS_*Stub
|
||||
function pointers. */
|
||||
my_addProperty, my_delProperty, my_getProperty, my_setProperty,
|
||||
my_enumerate, my_resolve, my_convert, my_finalize
|
||||
};
|
||||
|
||||
JSObject *obj;
|
||||
|
||||
/*
|
||||
* Define an object named in the global scope that can be enumerated by
|
||||
* for/in loops. The parent object is passed as the second argument, as
|
||||
* with all other API calls that take an object/name pair. The prototype
|
||||
* passed in is null, so the default object prototype will be used.
|
||||
*/
|
||||
obj = JS_DefineObject(cx, globalObj, "myObject", &my_class, NULL,
|
||||
JSPROP_ENUMERATE);
|
||||
|
||||
/*
|
||||
* Define a bunch of properties with a JSPropertySpec array statically
|
||||
* initialized and terminated with a null-name entry. Besides its name,
|
||||
* each property has a "tiny" identifier (MY_COLOR, e.g.) that can be used
|
||||
* in switch statements (in a common my_getProperty function, for example).
|
||||
*/
|
||||
enum my_tinyid {
|
||||
MY_COLOR, MY_HEIGHT, MY_WIDTH, MY_FUNNY, MY_ARRAY, MY_RDONLY
|
||||
};
|
||||
|
||||
static JSPropertySpec my_props[] = {
|
||||
{"color", MY_COLOR, JSPROP_ENUMERATE},
|
||||
{"height", MY_HEIGHT, JSPROP_ENUMERATE},
|
||||
{"width", MY_WIDTH, JSPROP_ENUMERATE},
|
||||
{"funny", MY_FUNNY, JSPROP_ENUMERATE},
|
||||
{"array", MY_ARRAY, JSPROP_ENUMERATE},
|
||||
{"rdonly", MY_RDONLY, JSPROP_READONLY},
|
||||
{0}
|
||||
};
|
||||
|
||||
JS_DefineProperties(cx, obj, my_props);
|
||||
|
||||
/*
|
||||
* Given the above definitions and call to JS_DefineProperties, obj will
|
||||
* need this sort of "getter" method in its class (my_class, above). See
|
||||
* the example for the "It" class in js.c.
|
||||
*/
|
||||
static JSBool
|
||||
my_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
if (JSVAL_IS_INT(id)) {
|
||||
switch (JSVAL_TO_INT(id)) {
|
||||
case MY_COLOR: *vp = . . .; break;
|
||||
case MY_HEIGHT: *vp = . . .; break;
|
||||
case MY_WIDTH: *vp = . . .; break;
|
||||
case MY_FUNNY: *vp = . . .; break;
|
||||
case MY_ARRAY: *vp = . . .; break;
|
||||
case MY_RDONLY: *vp = . . .; break;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}</tt></pre>
|
||||
|
||||
<h4>
|
||||
Defining functions</h4>
|
||||
|
||||
<pre><tt> /* Define a bunch of native functions first: */
|
||||
static JSBool
|
||||
my_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!JS_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = (x < 0) ? -x : x;
|
||||
return JS_NewDoubleValue(cx, z, rval);
|
||||
}
|
||||
|
||||
. . .
|
||||
|
||||
/*
|
||||
* Use a JSFunctionSpec array terminated with a null name to define a
|
||||
* bunch of native functions.
|
||||
*/
|
||||
static JSFunctionSpec my_functions[] = {
|
||||
/* name native nargs */
|
||||
{"abs", my_abs, 1},
|
||||
{"acos", my_acos, 1},
|
||||
{"asin", my_asin, 1},
|
||||
. . .
|
||||
{0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Pass a particular object to define methods for it alone. If you pass
|
||||
* a prototype object, the methods will apply to all instances past and
|
||||
* future of the prototype's class (see below for classes).
|
||||
*/
|
||||
JS_DefineFunctions(cx, globalObj, my_functions);</tt></pre>
|
||||
|
||||
<h4>
|
||||
Defining classes</h4>
|
||||
|
||||
<pre><tt> /*
|
||||
* This pulls together the above API elements by defining a constructor
|
||||
* function, a prototype object, and properties of the prototype and of
|
||||
* the constructor, all with one API call.
|
||||
*
|
||||
* Initialize a class by defining its constructor function, prototype, and
|
||||
* per-instance and per-class properties. The latter are called "static"
|
||||
* below by analogy to Java. They are defined in the constructor object's
|
||||
* scope, so that 'MyClass.myStaticProp' works along with 'new MyClass()'.
|
||||
*
|
||||
* JS_InitClass takes a lot of arguments, but you can pass null for any of
|
||||
* the last four if there are no such properties or methods.
|
||||
*
|
||||
* Note that you do not need to call JS_InitClass to make a new instance of
|
||||
* that class -- otherwise there would be a chicken-and-egg problem making
|
||||
* the global object -- but you should call JS_InitClass if you require a
|
||||
* constructor function for script authors to call via new, and/or a class
|
||||
* prototype object ('MyClass.prototype') for authors to extend with new
|
||||
* properties at run-time. In general, if you want to support multiple
|
||||
* instances that share behavior, use JS_InitClass.
|
||||
*/
|
||||
protoObj = JS_InitClass(cx, globalObj, NULL, &my_class,
|
||||
|
||||
/* native constructor function and min arg count */
|
||||
MyClass, 0,
|
||||
|
||||
/* prototype object properties and methods -- these
|
||||
will be "inherited" by all instances through
|
||||
delegation up the instance's prototype link. */
|
||||
my_props, my_methods,
|
||||
|
||||
/* class constructor properties and methods */
|
||||
my_static_props, my_static_methods);</tt></pre>
|
||||
|
||||
<h4>
|
||||
Running scripts</h4>
|
||||
|
||||
<pre><tt> /* These should indicate source location for diagnostics. */
|
||||
char *filename;
|
||||
uintN lineno;
|
||||
|
||||
/*
|
||||
* The return value comes back here -- if it could be a GC thing, you must
|
||||
* add it to the GC's "root set" with JS_AddRoot(cx, &thing) where thing
|
||||
* is a JSString *, JSObject *, or jsdouble *, and remove the root before
|
||||
* rval goes out of scope, or when rval is no longer needed.
|
||||
*/
|
||||
jsval rval;
|
||||
JSBool ok;
|
||||
|
||||
/*
|
||||
* Some example source in a C string. Larger, non-null-terminated buffers
|
||||
* can be used, if you pass the buffer length to JS_EvaluateScript.
|
||||
*/
|
||||
char *source = "x * f(y)";
|
||||
|
||||
ok = JS_EvaluateScript(cx, globalObj, source, strlen(source),
|
||||
filename, lineno, &rval);
|
||||
|
||||
if (ok) {
|
||||
/* Should get a number back from the example source. */
|
||||
jsdouble d;
|
||||
|
||||
ok = JS_ValueToNumber(cx, rval, &d);
|
||||
. . .
|
||||
}</tt></pre>
|
||||
|
||||
<h4>
|
||||
Calling functions</h4>
|
||||
|
||||
<pre><tt> /* Call a global function named "foo" that takes no arguments. */
|
||||
ok = JS_CallFunctionName(cx, globalObj, "foo", 0, 0, &rval);
|
||||
|
||||
jsval argv[2];
|
||||
|
||||
/* Call a function in obj's scope named "method", passing two arguments. */
|
||||
argv[0] = . . .;
|
||||
argv[1] = . . .;
|
||||
ok = JS_CallFunctionName(cx, obj, "method", 2, argv, &rval);</tt></pre>
|
||||
|
||||
<h4>
|
||||
Shutting down</h4>
|
||||
|
||||
<pre><tt> /* For each context you've created: */
|
||||
JS_DestroyContext(cx);
|
||||
|
||||
/* For each runtime: */
|
||||
JS_DestroyRuntime(rt);
|
||||
|
||||
/* And finally: */
|
||||
JS_ShutDown();</tt></pre>
|
||||
|
||||
<h4>
|
||||
Debugging API</h4>
|
||||
See the<tt> trap, untrap, watch, unwatch, line2pc</tt>, and <tt>pc2line</tt>
|
||||
commands in <tt>js.c</tt>. Also the (scant) comments in <i>jsdbgapi.h</i>.
|
||||
<h2>
|
||||
<a NAME="Design"></a>Design walk-through</h2>
|
||||
This section must be brief for now -- it could easily turn into a book.
|
||||
<h4>
|
||||
JS "JavaScript Proper"</h4>
|
||||
JS modules declare and implement the JavaScript compiler, interpreter,
|
||||
decompiler, GC and atom manager, and standard classes.
|
||||
<p>JavaScript uses untyped bytecode and runtime type tagging of data values.
|
||||
The <tt>jsval</tt> type is a signed machine word that contains either a
|
||||
signed integer value (if the low bit is set), or a type-tagged pointer
|
||||
or boolean value (if the low bit is clear). Tagged pointers all refer to
|
||||
8-byte-aligned things in the GC heap.
|
||||
<p>Objects consist of a possibly shared structural description, called
|
||||
the map or scope; and unshared property values in a vector, called the
|
||||
slots. Object properties are associated with nonnegative integers stored
|
||||
in <tt>jsval</tt>'s, or with atoms (unique string descriptors) if named
|
||||
by an identifier or a non-integral index expression.
|
||||
<p>Scripts contain bytecode, source annotations, and a pool of string,
|
||||
number, and identifier literals. Functions are objects that extend scripts
|
||||
or native functions with formal parameters, a literal syntax, and a distinct
|
||||
primitive type ("function").
|
||||
<p>The compiler consists of a recursive-descent parser and a random-logic
|
||||
rather than table-driven lexical scanner. Semantic and lexical feedback
|
||||
are used to disambiguate hard cases such as missing semicolons, assignable
|
||||
expressions ("lvalues" in C parlance), etc. The parser generates bytecode
|
||||
as it parses, using fixup lists for downward branches and code buffering
|
||||
and rewriting for exceptional cases such as for loops. It attempts no error
|
||||
recovery. The interpreter executes the bytecode of top-level scripts, and
|
||||
calls itself indirectly to interpret function bodies (which are also scripts).
|
||||
All state associated with an interpreter instance is passed through formal
|
||||
parameters to the interpreter entry point; most implicit state is collected
|
||||
in a type named JSContext. Therefore, all API and almost all other functions
|
||||
in JSRef take a JSContext pointer as their first argument.
|
||||
<p>The decompiler translates postfix bytecode into infix source by consulting
|
||||
a separate byte-sized code, called source notes, to disambiguate bytecodes
|
||||
that result from more than one grammatical production.
|
||||
<p>The GC is a mark-and-sweep, non-conservative (exact) collector. It
|
||||
can allocate only fixed-sized things -- the current size is two machine
|
||||
words. It is used to hold JS object and string descriptors (but not property
|
||||
lists or string bytes), and double-precision floating point numbers. It
|
||||
runs automatically only when maxbytes (as passed to <tt>JS_NewRuntime()</tt>)
|
||||
bytes of GC things have been allocated and another thing-allocation request
|
||||
is made. JS API users should call <tt>JS_GC()</tt> or <tt>JS_MaybeGC()</tt>
|
||||
between script executions or from the branch callback, as often as necessary.
|
||||
<p>An important point about the GC's "exactness": you must add roots for
|
||||
new objects created by your native methods if you store references to them
|
||||
into a non-JS structure in the malloc heap or in static data. Also, if
|
||||
you make a new object in a native method, but do not store it through the
|
||||
<tt>rval</tt>
|
||||
result parameter (see math_abs in the "Using the JS API" section above)
|
||||
so that it is in a known root, the object is guaranteed to survive only
|
||||
until another new object is created. Either lock the first new object when
|
||||
making two in a row, or store it in a root you've added, or store it via
|
||||
rval.
|
||||
See the <a href="http://www.mozilla.org/js/spidermonkey/gctips.html">GC tips</a>
|
||||
document for more.
|
||||
<p>The atom manager consists of a hash table associating strings uniquely
|
||||
with scanner/parser information such as keyword type, index in script or
|
||||
function literal pool, etc. Atoms play three roles in JSRef: as literals
|
||||
referred to by unaligned 16-bit immediate bytecode operands, as unique
|
||||
string descriptors for efficient property name hashing, and as members
|
||||
of the root GC set for exact GC.
|
||||
<p>Native objects and methods for arrays, booleans, dates, functions, numbers,
|
||||
and strings are implemented using the JS API and certain internal interfaces
|
||||
used as "fast paths".
|
||||
<p>In general, errors are signaled by false or unoverloaded-null return
|
||||
values, and are reported using <tt>JS_ReportError()</tt> or one of its
|
||||
variants by the lowest level in order to provide the most detail. Client
|
||||
code can substitute its own error reporting function and suppress errors,
|
||||
or reflect them into Java or some other runtime system as exceptions, GUI
|
||||
dialogs, etc..
|
||||
<h2>
|
||||
File walk-through (OUT OF DATE!)</h2>
|
||||
|
||||
<h4>
|
||||
jsapi.c, jsapi.h</h4>
|
||||
The public API to be used by almost all client code. If your client
|
||||
code can't make do with <tt>jsapi.h</tt>, and must reach into a friend
|
||||
or private js* file, please let us know so we can extend <tt>jsapi.h</tt>
|
||||
to include what you need in a fashion that we can support over the long
|
||||
run.
|
||||
<h4>
|
||||
jspubtd.h, jsprvtd.h</h4>
|
||||
These files exist to group struct and scalar typedefs so they can be used
|
||||
everywhere without dragging in struct definitions from N different files.
|
||||
The <tt>jspubtd.h</tt> file contains public typedefs, and is included by
|
||||
<tt>jsapi.h</tt>.
|
||||
The <tt>jsprvtd.h</tt> file contains private typedefs and is included by
|
||||
various .h files that need type names, but not type sizes or declarations.
|
||||
<h4>
|
||||
jsdbgapi.c, jsdbgapi.h</h4>
|
||||
The Debugging API, still very much under development. Provided so far:
|
||||
<ul>
|
||||
<li>
|
||||
Traps, with which breakpoints, single-stepping, step over, step out, and
|
||||
so on can be implemented. The debugger will have to consult jsopcode.def
|
||||
on its own to figure out where to plant trap instructions to implement
|
||||
functions like step out, but a future jsdbgapi.h will provide convenience
|
||||
interfaces to do these things. At most one trap per bytecode can be set.
|
||||
When a script (<tt>JSScript</tt>) is destroyed, all traps set in its bytecode
|
||||
are cleared.</li>
|
||||
|
||||
<li>
|
||||
Watchpoints, for intercepting set operations on properties and running
|
||||
a debugger-supplied function that receives the old value and a pointer
|
||||
to the new one, which it can use to modify the new value being set.</li>
|
||||
|
||||
<li>
|
||||
Line number to PC and back mapping functions. The line-to-PC direction
|
||||
"rounds" toward the next bytecode generated from a line greater than or
|
||||
equal to the input line, and may return the PC of a for-loop update part,
|
||||
if given the line number of the loop body's closing brace. Any line after
|
||||
the last one in a script or function maps to a PC one byte beyond the last
|
||||
bytecode in the script. An example, from perfect.js:</li>
|
||||
|
||||
<pre><tt>14 function perfect(n)
|
||||
15 {
|
||||
16 print("The perfect numbers up to " + n + " are:");
|
||||
17
|
||||
18 // We build sumOfDivisors[i] to hold a string expression for
|
||||
19 // the sum of the divisors of i, excluding i itself.
|
||||
20 var sumOfDivisors = new ExprArray(n+1,1);
|
||||
21 for (var divisor = 2; divisor <= n; divisor++) {
|
||||
22 for (var j = divisor + divisor; j <= n; j += divisor) {
|
||||
23 sumOfDivisors[j] += " + " + divisor;
|
||||
24 }
|
||||
25 // At this point everything up to 'divisor' has its sumOfDivisors
|
||||
26 // expression calculated, so we can determine whether it's perfect
|
||||
27 // already by evaluating.
|
||||
28 if (eval(sumOfDivisors[divisor]) == divisor) {
|
||||
29 print("" + divisor + " = " + sumOfDivisors[divisor]);
|
||||
30 }
|
||||
31 }
|
||||
32 delete sumOfDivisors;
|
||||
33 print("That's all.");
|
||||
34 }</tt></pre>
|
||||
The line number to PC and back mappings can be tested using the js program
|
||||
with the following script:
|
||||
<pre><tt> load("perfect.js")
|
||||
print(perfect)
|
||||
dis(perfect)
|
||||
|
||||
print()
|
||||
for (var ln = 0; ln <= 40; ln++) {
|
||||
var pc = line2pc(perfect,ln)
|
||||
var ln2 = pc2line(perfect,pc)
|
||||
print("\tline " + ln + " => pc " + pc + " => line " + ln2)
|
||||
}</tt></pre>
|
||||
The result of the for loop over lines 0 to 40 inclusive is:
|
||||
<pre><tt> line 0 => pc 0 => line 16
|
||||
line 1 => pc 0 => line 16
|
||||
line 2 => pc 0 => line 16
|
||||
line 3 => pc 0 => line 16
|
||||
line 4 => pc 0 => line 16
|
||||
line 5 => pc 0 => line 16
|
||||
line 6 => pc 0 => line 16
|
||||
line 7 => pc 0 => line 16
|
||||
line 8 => pc 0 => line 16
|
||||
line 9 => pc 0 => line 16
|
||||
line 10 => pc 0 => line 16
|
||||
line 11 => pc 0 => line 16
|
||||
line 12 => pc 0 => line 16
|
||||
line 13 => pc 0 => line 16
|
||||
line 14 => pc 0 => line 16
|
||||
line 15 => pc 0 => line 16
|
||||
line 16 => pc 0 => line 16
|
||||
line 17 => pc 19 => line 20
|
||||
line 18 => pc 19 => line 20
|
||||
line 19 => pc 19 => line 20
|
||||
line 20 => pc 19 => line 20
|
||||
line 21 => pc 36 => line 21
|
||||
line 22 => pc 53 => line 22
|
||||
line 23 => pc 74 => line 23
|
||||
line 24 => pc 92 => line 22
|
||||
line 25 => pc 106 => line 28
|
||||
line 26 => pc 106 => line 28
|
||||
line 27 => pc 106 => line 28
|
||||
line 28 => pc 106 => line 28
|
||||
line 29 => pc 127 => line 29
|
||||
line 30 => pc 154 => line 21
|
||||
line 31 => pc 154 => line 21
|
||||
line 32 => pc 161 => line 32
|
||||
line 33 => pc 172 => line 33
|
||||
line 34 => pc 172 => line 33
|
||||
line 35 => pc 172 => line 33
|
||||
line 36 => pc 172 => line 33
|
||||
line 37 => pc 172 => line 33
|
||||
line 38 => pc 172 => line 33
|
||||
line 39 => pc 172 => line 33
|
||||
line 40 => pc 172 => line 33</tt></pre>
|
||||
</ul>
|
||||
|
||||
<h4>
|
||||
jsconfig.h</h4>
|
||||
Various configuration macros defined as 0 or 1 depending on how <tt>JS_VERSION</tt>
|
||||
is defined (as 10 for JavaScript 1.0, 11 for JavaScript 1.1, etc.). Not
|
||||
all macros are tested around related code yet. In particular, JS 1.0 support
|
||||
is missing from JSRef. JS 1.2 support will appear in a future JSRef release.
|
||||
<br>
|
||||
<h4>
|
||||
js.c</h4>
|
||||
The "JS shell", a simple interpreter program that uses the JS API and more
|
||||
than a few internal interfaces (some of these internal interfaces could
|
||||
be replaced by <tt>jsapi.h</tt> calls). The js program built from this
|
||||
source provides a test vehicle for evaluating scripts and calling functions,
|
||||
trying out new debugger primitives, etc.
|
||||
<h4>
|
||||
jsarray.*, jsbool.*, jdsdate.*, jsfun.*, jsmath.*, jsnum.*, jsstr.*</h4>
|
||||
These file pairs implement the standard classes and (where they exist)
|
||||
their underlying primitive types. They have similar structure, generally
|
||||
starting with class definitions and continuing with internal constructors,
|
||||
finalizers, and helper functions.
|
||||
<h4>
|
||||
jsobj.*, jsscope.*</h4>
|
||||
These two pairs declare and implement the JS object system. All of the
|
||||
following happen here:
|
||||
<ul>
|
||||
<li>
|
||||
creating objects by class and prototype, and finalizing objects;</li>
|
||||
|
||||
<li>
|
||||
defining, looking up, getting, setting, and deleting properties;</li>
|
||||
|
||||
<li>
|
||||
creating and destroying properties and binding names to them.</li>
|
||||
</ul>
|
||||
The details of a native object's map (scope) are mostly hidden in
|
||||
<tt>jsscope.[ch]</tt>.
|
||||
<h4>
|
||||
jsatom.c, jsatom.h</h4>
|
||||
The atom manager. Contains well-known string constants, their atoms, the
|
||||
global atom hash table and related state, the js_Atomize() function that
|
||||
turns a counted string of bytes into an atom, and literal pool (<tt>JSAtomMap</tt>)
|
||||
methods.
|
||||
<h4>
|
||||
jsgc.c, jsgc.h</h4>
|
||||
[TBD]
|
||||
<h4>
|
||||
jsinterp.*, jscntxt.*</h4>
|
||||
The bytecode interpreter, and related functions such as Call and AllocStack,
|
||||
live in <i>jsinterp.c</i>. The JSContext constructor and destructor are
|
||||
factored out into <i>jscntxt.c</i> for minimal linking when the compiler
|
||||
part of JS is split from the interpreter part into a separate program.
|
||||
<h4>
|
||||
jsemit.*, jsopcode.tbl, jsopcode.*, jsparse.*, jsscan.*, jsscript.*</h4>
|
||||
Compiler and decompiler modules. The <i>jsopcode.tbl</i> file is a C preprocessor
|
||||
source that defines almost everything there is to know about JS bytecodes.
|
||||
See its major comment for how to use it. For now, a debugger will use it
|
||||
and its dependents such as <i>jsopcode.h</i> directly, but over time we
|
||||
intend to extend <i>jsdbgapi.h</i> to hide uninteresting details and provide
|
||||
conveniences. The code generator is split across paragraphs of code in
|
||||
<i>jsparse.c</i>,
|
||||
and the utility methods called on <tt>JSCodeGenerator</tt> appear in <i>jsemit.c</i>.
|
||||
Source notes generated by <i>jsparse.c</i> and
|
||||
<i>jsemit.c</i> are used
|
||||
in <i>jsscript.c</i> to map line number to program counter and back.
|
||||
<h4>
|
||||
jstypes.h, jslog2.c</h4>
|
||||
Fundamental representation types and utility macros. This file alone among
|
||||
all .h files in JSRef must be included first by .c files. It is not nested
|
||||
in .h files, as other prerequisite .h files generally are, since it is
|
||||
also a direct dependency of most .c files and would be over-included if
|
||||
nested in addition to being directly included. The one "not-quite-a-macro
|
||||
macro" is the <tt>JS_CeilingLog2()</tt> function in <i>jslog2.c</i>.
|
||||
<h4>
|
||||
jsarena.c, jsarena.h</h4>
|
||||
Last-In-First-Out allocation macros that amortize malloc costs and allow
|
||||
for en-masse freeing. See the paper mentioned in prarena.h's major comment.
|
||||
<h4>
|
||||
jsutil.c, jsutil.h</h4>
|
||||
The <tt>JS_ASSERT</tt> macro is used throughout JSRef source as a proof
|
||||
device to make invariants and preconditions clear to the reader, and to
|
||||
hold the line during maintenance and evolution against regressions or violations
|
||||
of assumptions that it would be too expensive to test unconditionally at
|
||||
run-time. Certain assertions are followed by run-time tests that cope with
|
||||
assertion failure, but only where I'm too smart or paranoid to believe
|
||||
the assertion will never fail...
|
||||
<h4>
|
||||
jsclist.h</h4>
|
||||
Doubly-linked circular list struct and macros.
|
||||
<h4>
|
||||
jscpucfg.c</h4>
|
||||
This standalone program generates <i>jscpucfg.h</i>, a header file containing
|
||||
bytes per word and other constants that depend on CPU architecture and
|
||||
C compiler type model. It tries to discover most of these constants by
|
||||
running its own experiments on the build host, so if you are cross-compiling,
|
||||
beware.
|
||||
<h4>
|
||||
prdtoa.c, prdtoa.h</h4>
|
||||
David Gay's portable double-precision floating point to string conversion
|
||||
code, with Permission To Use notice included.
|
||||
<h4>
|
||||
prhash.c, prhash.h</h4>
|
||||
Portable, extensible hash tables. These use multiplicative hash for strength
|
||||
reduction over division hash, yet with very good key distribution over
|
||||
power of two table sizes. Collisions resolve via chaining, so each entry
|
||||
burns a malloc and can fragment the heap.
|
||||
<h4>
|
||||
prlong.c, prlong.h</h4>
|
||||
64-bit integer emulation, and compatible macros that use C's long long
|
||||
type where it exists (my last company mapped long long to a 128-bit type,
|
||||
but no real architecture does 128-bit ints yet).
|
||||
<h4>
|
||||
jsosdep.h</h4>
|
||||
Annoying OS dependencies rationalized into a few "feature-test" macros
|
||||
such as <tt>JS_HAVE_LONG_LONG</tt>.
|
||||
<h4>
|
||||
jsprf.*</h4>
|
||||
Portable, buffer-overrun-resistant sprintf and friends. For no good reason
|
||||
save lack of time, the %e, %f, and %g formats cause your system's native
|
||||
sprintf, rather than <tt>JS_dtoa()</tt>, to be used. This bug doesn't affect
|
||||
JSRef, because it uses its own <tt>JS_dtoa()</tt> call in <i>jsnum.c</i>
|
||||
to convert from double to string, but it's a bug that we'll fix later,
|
||||
and one you should be aware of if you intend to use a <tt>JS_*printf()</tt>
|
||||
function with your own floating type arguments - various vendor sprintf's
|
||||
mishandle NaN, +/-Inf, and some even print normal floating values inaccurately.
|
||||
<h4>
|
||||
prmjtime.c, prmjtime.h</h4>
|
||||
Time functions. These interfaces are named in a way that makes local vs.
|
||||
universal time confusion likely. Caveat emptor, and we're working on it.
|
||||
To make matters worse, Java (and therefore JavaScript) uses "local" time
|
||||
numbers (offsets from the epoch) in its Date class.
|
||||
|
||||
|
||||
<h2>
|
||||
<a NAME="Resources"></a>Additional Resources (links, API docs, and newsgroups)</h2>
|
||||
<ul>
|
||||
<li><a href ="http://www.mozilla.org/js/">http://www.mozilla.org/js/</a>
|
||||
<li><a href ="http://www.mozilla.org/js/spidermonkey/">http://www.mozilla.org/js/spidermonkey/</a>
|
||||
<li><a href ="news://news.mozilla.org/netscape.public.mozilla.jseng">news://news.mozilla.org/netscape.public.mozilla.jseng</a>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,12 +0,0 @@
|
||||
mozilla/js/src/*
|
||||
mozilla/js/src/config/*
|
||||
mozilla/js/src/fdlibm/*
|
||||
mozilla/js/src/liveconnect/*
|
||||
mozilla/js/src/liveconnect/_jni/*
|
||||
mozilla/js/src/liveconnect/classes/*
|
||||
mozilla/js/src/liveconnect/classes/netscape/*
|
||||
mozilla/js/src/liveconnect/classes/netscape/javascript/*
|
||||
mozilla/js/src/liveconnect/config/*
|
||||
mozilla/js/src/liveconnect/macbuild/*
|
||||
mozilla/js/src/liveconnect/macbuild/JavaSession/*
|
||||
mozilla/js/src/macbuild/*
|
||||
@@ -1,166 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-1999
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
ifdef JS_DIST
|
||||
DIST = $(JS_DIST)
|
||||
else
|
||||
DIST = $(DEPTH)/../../dist/$(OBJDIR)
|
||||
endif
|
||||
|
||||
# Set os+release dependent make variables
|
||||
OS_ARCH := $(subst /,_,$(shell uname -s | sed /\ /s//_/))
|
||||
|
||||
# Attempt to differentiate between SunOS 5.4 and x86 5.4
|
||||
OS_CPUARCH := $(shell uname -m)
|
||||
ifeq ($(OS_CPUARCH),i86pc)
|
||||
OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH)
|
||||
else
|
||||
ifeq ($(OS_ARCH),AIX)
|
||||
OS_RELEASE := $(shell uname -v).$(shell uname -r)
|
||||
else
|
||||
OS_RELEASE := $(shell uname -r)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(OS_ARCH),IRIX64)
|
||||
OS_ARCH := IRIX
|
||||
endif
|
||||
|
||||
# Handle output from win32 unames other than Netscape's version
|
||||
ifeq (,$(filter-out Windows_95 Windows_98 CYGWIN_95-4.0 CYGWIN_98-4.10, $(OS_ARCH)))
|
||||
OS_ARCH := WIN95
|
||||
endif
|
||||
ifeq ($(OS_ARCH),WIN95)
|
||||
OS_ARCH := WINNT
|
||||
OS_RELEASE := 4.0
|
||||
endif
|
||||
ifeq ($(OS_ARCH), Windows_NT)
|
||||
OS_ARCH := WINNT
|
||||
OS_MINOR_RELEASE := $(shell uname -v)
|
||||
ifeq ($(OS_MINOR_RELEASE),00)
|
||||
OS_MINOR_RELEASE = 0
|
||||
endif
|
||||
OS_RELEASE := $(OS_RELEASE).$(OS_MINOR_RELEASE)
|
||||
endif
|
||||
ifeq (CYGWIN_NT,$(findstring CYGWIN_NT,$(OS_ARCH)))
|
||||
OS_RELEASE := $(patsubst CYGWIN_NT-%,%,$(OS_ARCH))
|
||||
OS_ARCH := WINNT
|
||||
endif
|
||||
ifeq ($(OS_ARCH), CYGWIN32_NT)
|
||||
OS_ARCH := WINNT
|
||||
endif
|
||||
|
||||
# Virtually all Linux versions are identical.
|
||||
# Any distinctions are handled in linux.h
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
OS_CONFIG := Linux_All
|
||||
else
|
||||
ifeq ($(OS_ARCH),dgux)
|
||||
OS_CONFIG := dgux
|
||||
else
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
OS_CONFIG := Darwin
|
||||
else
|
||||
OS_CONFIG := $(OS_ARCH)$(OS_OBJTYPE)$(OS_RELEASE)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ASFLAGS =
|
||||
DEFINES =
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
INSTALL = nsinstall
|
||||
CP = cp
|
||||
else
|
||||
INSTALL = $(DEPTH)/../../dist/$(OBJDIR)/bin/nsinstall
|
||||
CP = cp
|
||||
endif
|
||||
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER = -O
|
||||
DEFINES += -UDEBUG -DNDEBUG -UDEBUG_$(shell whoami)
|
||||
OBJDIR_TAG = _OPT
|
||||
else
|
||||
ifdef USE_MSVC
|
||||
OPTIMIZER = -Zi
|
||||
else
|
||||
OPTIMIZER = -g
|
||||
endif
|
||||
DEFINES += -DDEBUG -DDEBUG_$(shell whoami)
|
||||
OBJDIR_TAG = _DBG
|
||||
endif
|
||||
|
||||
SO_SUFFIX = so
|
||||
|
||||
NS_USE_NATIVE = 1
|
||||
|
||||
# Java stuff
|
||||
CLASSDIR = $(DEPTH)/liveconnect/classes
|
||||
JAVA_CLASSES = $(patsubst %.java,%.class,$(JAVA_SRCS))
|
||||
TARGETS += $(addprefix $(CLASSDIR)/$(OBJDIR)/$(JARPATH)/, $(JAVA_CLASSES))
|
||||
JAVAC = $(JDK)/bin/javac
|
||||
JAVAC_FLAGS = -classpath "$(CLASSPATH)" -d $(CLASSDIR)/$(OBJDIR)
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
SEP = ;
|
||||
else
|
||||
SEP = :
|
||||
endif
|
||||
CLASSPATH = $(JDK)/lib/classes.zip$(SEP)$(CLASSDIR)/$(OBJDIR)
|
||||
|
||||
include $(DEPTH)/config/$(OS_CONFIG).mk
|
||||
|
||||
# Name of the binary code directories
|
||||
ifdef BUILD_IDG
|
||||
OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).OBJD
|
||||
else
|
||||
OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).OBJ
|
||||
endif
|
||||
VPATH = $(OBJDIR)
|
||||
|
||||
# Automatic make dependencies file
|
||||
DEPENDENCIES = $(OBJDIR)/.md
|
||||
|
||||
LCJAR = js15lc30.jar
|
||||
|
||||
# Library name
|
||||
LIBDIR := lib
|
||||
ifeq ($(CPU_ARCH), x86_64)
|
||||
LIBDIR := lib64
|
||||
endif
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for AIX
|
||||
#
|
||||
|
||||
CC = xlC_r
|
||||
CCC = xlC_r
|
||||
|
||||
RANLIB = ranlib
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
ARCH := aix
|
||||
CPU_ARCH = rs6000
|
||||
GFX_ARCH = x
|
||||
INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1
|
||||
|
||||
OS_CFLAGS = -qarch=com -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DHAVE_LOCALTIME_R
|
||||
OS_LIBS = -lbsd -lsvld -lm
|
||||
#-lpthreads -lc_r
|
||||
|
||||
MKSHLIB = $(LD) -bM:SRE -bh:4 -bnoentry -berok
|
||||
XLDFLAGS += -lc
|
||||
|
||||
ifdef JS_THREADSAFE
|
||||
XLDFLAGS += -lsvld
|
||||
endif
|
||||
@@ -1,64 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for AIX
|
||||
#
|
||||
|
||||
CC = xlC_r
|
||||
CCC = xlC_r
|
||||
CFLAGS += -qarch=com -qnoansialias -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DHAVE_LOCALTIME_R
|
||||
|
||||
RANLIB = ranlib
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
ARCH := aix
|
||||
CPU_ARCH = rs6000
|
||||
GFX_ARCH = x
|
||||
INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1
|
||||
|
||||
#-lpthreads -lc_r
|
||||
|
||||
MKSHLIB = /usr/lpp/xlC/bin/makeC++SharedLib_r -p 0 -G -berok
|
||||
|
||||
ifdef JS_THREADSAFE
|
||||
XLDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for AIX
|
||||
#
|
||||
|
||||
CC = xlC_r
|
||||
CCC = xlC_r
|
||||
CFLAGS += -qarch=com -qnoansialias -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DAIX4_3 -DHAVE_LOCALTIME_R
|
||||
|
||||
RANLIB = ranlib
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
ARCH := aix
|
||||
CPU_ARCH = rs6000
|
||||
GFX_ARCH = x
|
||||
INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1
|
||||
|
||||
#-lpthreads -lc_r
|
||||
|
||||
MKSHLIB_BIN = /usr/ibmcxx/bin/makeC++SharedLib_r
|
||||
MKSHLIB = $(MKSHLIB_BIN) -p 0 -G -berok -bM:UR
|
||||
|
||||
ifdef JS_THREADSAFE
|
||||
XLDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Steve Zellers (zellers@apple.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config for Mac OS X as of PR3
|
||||
# Just ripped from Linux config
|
||||
#
|
||||
|
||||
CC = cc
|
||||
CCC = g++
|
||||
CFLAGS += -Wall -Wno-format
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
|
||||
|
||||
RANLIB = ranlib
|
||||
MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = $(shell uname -m)
|
||||
ifeq (86,$(findstring 86,$(CPU_ARCH)))
|
||||
CPU_ARCH = x86
|
||||
OS_CFLAGS+= -DX86_LINUX
|
||||
endif
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_LIBS = -lc -framework System
|
||||
|
||||
ASFLAGS += -x assembler-with-cpp
|
||||
|
||||
ifeq ($(CPU_ARCH),alpha)
|
||||
|
||||
# Ask the C compiler on alpha linux to let us work with denormalized
|
||||
# double values, which are required by the ECMA spec.
|
||||
|
||||
OS_CFLAGS += -mieee
|
||||
endif
|
||||
|
||||
# Use the editline library to provide line-editing support.
|
||||
JS_EDITLINE = 1
|
||||
|
||||
# Don't allow Makefile.ref to use libmath
|
||||
NO_LIBM = 1
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Steve Zellers (zellers@apple.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config for Mac OS X as of PR3
|
||||
# Just ripped from Linux config
|
||||
#
|
||||
|
||||
CC = cc
|
||||
CCC = g++
|
||||
CFLAGS += -Wall -Wno-format
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DRHAPSODY
|
||||
|
||||
RANLIB = ranlib
|
||||
MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = $(shell uname -m)
|
||||
ifeq (86,$(findstring 86,$(CPU_ARCH)))
|
||||
CPU_ARCH = x86
|
||||
OS_CFLAGS+= -DX86_LINUX
|
||||
endif
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_LIBS = -lc -framework System
|
||||
|
||||
ASFLAGS += -x assembler-with-cpp
|
||||
|
||||
ifeq ($(CPU_ARCH),alpha)
|
||||
|
||||
# Ask the C compiler on alpha linux to let us work with denormalized
|
||||
# double values, which are required by the ECMA spec.
|
||||
|
||||
OS_CFLAGS += -mieee
|
||||
endif
|
||||
|
||||
# Use the editline library to provide line-editing support.
|
||||
JS_EDITLINE = 1
|
||||
|
||||
# Don't allow Makefile.ref to use libmath
|
||||
NO_LIBM = 1
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mike McCabe <mike+mozilla@meer.net>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
include $(DEPTH)/config/Darwin1.3.mk
|
||||
@@ -1,81 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Steve Zellers (zellers@apple.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config for Mac OS X as of PR3
|
||||
# Just ripped from Linux config
|
||||
#
|
||||
|
||||
CC = cc
|
||||
CCC = g++
|
||||
CFLAGS += -Wall -Wno-format
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
|
||||
|
||||
RANLIB = ranlib
|
||||
MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = $(shell uname -m)
|
||||
ifeq (86,$(findstring 86,$(CPU_ARCH)))
|
||||
CPU_ARCH = x86
|
||||
OS_CFLAGS+= -DX86_LINUX
|
||||
endif
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_LIBS = -lc -framework System
|
||||
|
||||
ASFLAGS += -x assembler-with-cpp
|
||||
|
||||
ifeq ($(CPU_ARCH),alpha)
|
||||
|
||||
# Ask the C compiler on alpha linux to let us work with denormalized
|
||||
# double values, which are required by the ECMA spec.
|
||||
|
||||
OS_CFLAGS += -mieee
|
||||
endif
|
||||
|
||||
# Use the editline library to provide line-editing support.
|
||||
JS_EDITLINE = 1
|
||||
|
||||
# Don't allow Makefile.ref to use libmath
|
||||
NO_LIBM = 1
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Steve Zellers (zellers@apple.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config for Mac OS X as of PR3
|
||||
# Just ripped from Linux config
|
||||
#
|
||||
|
||||
CC = cc
|
||||
CCC = g++
|
||||
CFLAGS += -Wall -Wno-format
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
|
||||
|
||||
RANLIB = ranlib
|
||||
MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = $(shell uname -m)
|
||||
ifeq (86,$(findstring 86,$(CPU_ARCH)))
|
||||
CPU_ARCH = x86
|
||||
OS_CFLAGS+= -DX86_LINUX
|
||||
endif
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_LIBS = -lc -framework System
|
||||
|
||||
ASFLAGS += -x assembler-with-cpp
|
||||
|
||||
ifeq ($(CPU_ARCH),alpha)
|
||||
|
||||
# Ask the C compiler on alpha linux to let us work with denormalized
|
||||
# double values, which are required by the ECMA spec.
|
||||
|
||||
OS_CFLAGS += -mieee
|
||||
endif
|
||||
|
||||
# Use the editline library to provide line-editing support.
|
||||
JS_EDITLINE = 1
|
||||
|
||||
# Don't allow Makefile.ref to use libmath
|
||||
NO_LIBM = 1
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for HPUX
|
||||
#
|
||||
|
||||
# CC = gcc
|
||||
# CCC = g++
|
||||
# CFLAGS += -Wall -Wno-format -fPIC
|
||||
|
||||
CC = cc -Ae +Z
|
||||
CCC = CC -Ae +a1 +eh +Z
|
||||
|
||||
RANLIB = echo
|
||||
MKSHLIB = $(LD) -b
|
||||
|
||||
SO_SUFFIX = sl
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = hppa
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -DHAVE_LOCALTIME_R
|
||||
OS_LIBS = -ldld
|
||||
|
||||
ifeq ($(OS_RELEASE),B.10)
|
||||
PLATFORM_FLAGS += -DHPUX10 -Dhpux10
|
||||
PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H
|
||||
ifeq ($(OS_VERSION),.10)
|
||||
PLATFORM_FLAGS += -DHPUX10_10
|
||||
endif
|
||||
ifeq ($(OS_VERSION),.20)
|
||||
PLATFORM_FLAGS += -DHPUX10_20
|
||||
endif
|
||||
ifeq ($(OS_VERSION),.30)
|
||||
PLATFORM_FLAGS += -DHPUX10_30
|
||||
endif
|
||||
endif
|
||||
@@ -1,77 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for HPUX
|
||||
#
|
||||
|
||||
# CC = gcc
|
||||
# CCC = g++
|
||||
# CFLAGS += -Wall -Wno-format -fPIC
|
||||
|
||||
CC = cc -Ae +Z
|
||||
CCC = CC -Ae +a1 +eh +Z
|
||||
|
||||
RANLIB = echo
|
||||
MKSHLIB = $(LD) -b
|
||||
|
||||
SO_SUFFIX = sl
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = hppa
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -DHAVE_LOCALTIME_R
|
||||
OS_LIBS = -ldld
|
||||
|
||||
ifeq ($(OS_RELEASE),B.10)
|
||||
PLATFORM_FLAGS += -DHPUX10 -Dhpux10
|
||||
PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H
|
||||
ifeq ($(OS_VERSION),.10)
|
||||
PLATFORM_FLAGS += -DHPUX10_10
|
||||
endif
|
||||
ifeq ($(OS_VERSION),.20)
|
||||
PLATFORM_FLAGS += -DHPUX10_20
|
||||
endif
|
||||
ifeq ($(OS_VERSION),.30)
|
||||
PLATFORM_FLAGS += -DHPUX10_30
|
||||
endif
|
||||
endif
|
||||
@@ -1,80 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for HPUX
|
||||
#
|
||||
|
||||
ifdef NS_USE_NATIVE
|
||||
CC = cc +Z +DAportable +DS2.0 +u4
|
||||
# LD = aCC +Z -b -Wl,+s -Wl,-B,symbolic
|
||||
else
|
||||
CC = gcc -Wall -Wno-format -fPIC
|
||||
CCC = g++ -Wall -Wno-format -fPIC
|
||||
endif
|
||||
|
||||
RANLIB = echo
|
||||
MKSHLIB = $(LD) -b
|
||||
|
||||
SO_SUFFIX = sl
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = hppa
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -D_HPUX -DNATIVE -D_POSIX_C_SOURCE=199506L -DHAVE_LOCALTIME_R
|
||||
OS_LIBS = -ldld
|
||||
|
||||
XLDFLAGS = -lpthread
|
||||
|
||||
ifeq ($(OS_RELEASE),B.10)
|
||||
PLATFORM_FLAGS += -DHPUX10 -Dhpux10
|
||||
PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H
|
||||
ifeq ($(OS_VERSION),.10)
|
||||
PLATFORM_FLAGS += -DHPUX10_10
|
||||
endif
|
||||
ifeq ($(OS_VERSION),.20)
|
||||
PLATFORM_FLAGS += -DHPUX10_20
|
||||
endif
|
||||
ifeq ($(OS_VERSION),.30)
|
||||
PLATFORM_FLAGS += -DHPUX10_30
|
||||
endif
|
||||
endif
|
||||
@@ -1,87 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for IRIX
|
||||
#
|
||||
|
||||
CPU_ARCH = mips
|
||||
GFX_ARCH = x
|
||||
|
||||
RANLIB = /bin/true
|
||||
|
||||
#NS_USE_GCC = 1
|
||||
|
||||
ifndef NS_USE_NATIVE
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
AS = $(CC) -x assembler-with-cpp
|
||||
ODD_CFLAGS = -Wall -Wno-format
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER = -O6
|
||||
endif
|
||||
else
|
||||
ifeq ($(OS_RELEASE),6.2)
|
||||
CC = cc -n32 -DIRIX6_2
|
||||
endif
|
||||
ifeq ($(OS_RELEASE),6.3)
|
||||
CC = cc -n32 -DIRIX6_3
|
||||
endif
|
||||
ifeq ($(OS_RELEASE),6.5)
|
||||
CC = cc -n32 -DIRIX6_5
|
||||
endif
|
||||
CCC = CC
|
||||
# LD = CC
|
||||
ODD_CFLAGS = -fullwarn -xansi
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER += -Olimit 4000
|
||||
endif
|
||||
endif
|
||||
|
||||
# For purify
|
||||
HAVE_PURIFY = 1
|
||||
PURE_OS_CFLAGS = $(ODD_CFLAGS) -DXP_UNIX -DSVR4 -DSW_THREADS -DIRIX -DHAVE_LOCALTIME_R
|
||||
|
||||
OS_CFLAGS = $(PURE_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
|
||||
|
||||
BSDECHO = echo
|
||||
MKSHLIB = $(LD) -n32 -shared
|
||||
|
||||
# Use the editline library to provide line-editing support.
|
||||
JS_EDITLINE = 1
|
||||
@@ -1,44 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for IRIX5.3
|
||||
#
|
||||
|
||||
include $(DEPTH)/config/IRIX.mk
|
||||
@@ -1,44 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for IRIX6.3
|
||||
#
|
||||
|
||||
include $(DEPTH)/config/IRIX.mk
|
||||
@@ -1,44 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for IRIX6.3
|
||||
#
|
||||
|
||||
include $(DEPTH)/config/IRIX.mk
|
||||
@@ -1,44 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for IRIX6.3
|
||||
#
|
||||
|
||||
include $(DEPTH)/config/IRIX.mk
|
||||
@@ -1,44 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for IRIX6.3
|
||||
#
|
||||
|
||||
include $(DEPTH)/config/IRIX.mk
|
||||
@@ -1,103 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config for all versions of Linux
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
CFLAGS += -Wall -Wno-format
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R
|
||||
|
||||
RANLIB = echo
|
||||
MKSHLIB = $(LD) -shared $(XMKSHLIBOPTS)
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = $(shell uname -m)
|
||||
# don't filter in x86-64 architecture
|
||||
ifneq (x86_64,$(CPU_ARCH))
|
||||
ifeq (86,$(findstring 86,$(CPU_ARCH)))
|
||||
CPU_ARCH = x86
|
||||
OS_CFLAGS+= -DX86_LINUX
|
||||
|
||||
ifeq (gcc, $(CC))
|
||||
# if using gcc on x86, check version for opt bug
|
||||
# (http://bugzilla.mozilla.org/show_bug.cgi?id=24892)
|
||||
GCC_VERSION := $(shell gcc -v 2>&1 | grep version | awk '{ print $$3 }')
|
||||
GCC_LIST:=$(sort 2.91.66 $(GCC_VERSION) )
|
||||
|
||||
ifeq (2.91.66, $(firstword $(GCC_LIST)))
|
||||
CFLAGS+= -DGCC_OPT_BUG
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_LIBS = -lm -lc
|
||||
|
||||
ASFLAGS += -x assembler-with-cpp
|
||||
|
||||
|
||||
ifeq ($(CPU_ARCH),alpha)
|
||||
|
||||
# Ask the C compiler on alpha linux to let us work with denormalized
|
||||
# double values, which are required by the ECMA spec.
|
||||
|
||||
OS_CFLAGS += -mieee
|
||||
endif
|
||||
|
||||
# Use the editline library to provide line-editing support.
|
||||
JS_EDITLINE = 1
|
||||
|
||||
ifeq ($(CPU_ARCH),x86_64)
|
||||
# Use VA_COPY() standard macro on x86-64
|
||||
# FIXME: better use it everywhere
|
||||
OS_CFLAGS += -DHAVE_VA_COPY -DVA_COPY=va_copy
|
||||
endif
|
||||
|
||||
ifeq ($(CPU_ARCH),x86_64)
|
||||
# We need PIC code for shared libraries
|
||||
# FIXME: better patch rules.mk & fdlibm/Makefile*
|
||||
OS_CFLAGS += -DPIC -fPIC
|
||||
endif
|
||||
@@ -1,82 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Steve Zellers (zellers@apple.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config for Mac OS X as of PR3
|
||||
# Just ripped from Linux config
|
||||
#
|
||||
|
||||
CC = cc
|
||||
CCC = g++
|
||||
CFLAGS += -Wall -Wno-format
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE
|
||||
-DRHAPSODY
|
||||
|
||||
RANLIB = ranlib
|
||||
MKSHLIB = libtool -dynamic $(XMKSHLIBOPTS) -framework System
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = $(shell uname -m)
|
||||
ifeq (86,$(findstring 86,$(CPU_ARCH)))
|
||||
CPU_ARCH = x86
|
||||
OS_CFLAGS+= -DX86_LINUX
|
||||
endif
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_LIBS = -lc -framework System
|
||||
|
||||
ASFLAGS += -x assembler-with-cpp
|
||||
|
||||
ifeq ($(CPU_ARCH),alpha)
|
||||
|
||||
# Ask the C compiler on alpha linux to let us work with denormalized
|
||||
# double values, which are required by the ECMA spec.
|
||||
|
||||
OS_CFLAGS += -mieee
|
||||
endif
|
||||
|
||||
# Use the editline library to provide line-editing support.
|
||||
JS_EDITLINE = 1
|
||||
|
||||
# Don't allow Makefile.ref to use libmath
|
||||
NO_LIBM = 1
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for Data General DG/UX
|
||||
#
|
||||
|
||||
#
|
||||
# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com)
|
||||
#
|
||||
|
||||
ifndef NS_USE_NATIVE
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
CFLAGS += -mieee -Wall -Wno-format
|
||||
else
|
||||
CC = cc
|
||||
CCC = cxx
|
||||
CFLAGS += -ieee -std
|
||||
# LD = cxx
|
||||
endif
|
||||
|
||||
RANLIB = echo
|
||||
MKSHLIB = $(LD) -shared -taso -all -expect_unresolved "*"
|
||||
|
||||
#
|
||||
# _DGUX_SOURCE is needed to turn on a lot of stuff in the headers if
|
||||
# you're not using DG's compiler. It shouldn't hurt if you are.
|
||||
#
|
||||
# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in
|
||||
# prtime.c
|
||||
#
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DDGUX -D_DGUX_SOURCE -D_POSIX4A_DRAFT10_SOURCE -DOSF1 -DHAVE_LOCALTIME_R
|
||||
OS_LIBS = -lsocket -lnsl
|
||||
|
||||
NOSUCHFILE = /no-such-file
|
||||
@@ -1,69 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for Tru64 Unix 5.0
|
||||
#
|
||||
|
||||
#
|
||||
# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com)
|
||||
#
|
||||
|
||||
ifndef NS_USE_NATIVE
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
CFLAGS += -mieee -Wall -Wno-format
|
||||
else
|
||||
CC = cc
|
||||
CCC = cxx
|
||||
CFLAGS += -ieee -std -pthread
|
||||
# LD = cxx
|
||||
endif
|
||||
|
||||
RANLIB = echo
|
||||
MKSHLIB = $(LD) -shared -all -expect_unresolved "*"
|
||||
|
||||
#
|
||||
# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in
|
||||
# prtime.c
|
||||
#
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_POSIX4A_DRAFT10_SOURCE -DOSF1 -DHAVE_LOCALTIME_R
|
||||
OS_LIBS = -lsocket -lnsl
|
||||
|
||||
NOSUCHFILE = /no-such-file
|
||||
@@ -1,101 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for SunOS4.1
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
RANLIB = ranlib
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = sparc
|
||||
GFX_ARCH = x
|
||||
|
||||
# A pile of -D's to build xfe on sunos
|
||||
MOZ_CFLAGS = -DSTRINGS_ALIGNED -DNO_REGEX -DNO_ISDIR -DUSE_RE_COMP \
|
||||
-DNO_REGCOMP -DUSE_GETWD -DNO_MEMMOVE -DNO_ALLOCA \
|
||||
-DBOGUS_MB_MAX -DNO_CONST
|
||||
|
||||
# Purify doesn't like -MDupdate
|
||||
NOMD_OS_CFLAGS = -DXP_UNIX -Wall -Wno-format -DSW_THREADS -DSUNOS4 -DNEED_SYSCALL \
|
||||
$(MOZ_CFLAGS)
|
||||
|
||||
OS_CFLAGS = $(NOMD_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
|
||||
OS_LIBS = -ldl -lm
|
||||
|
||||
MKSHLIB = $(LD) -L$(MOTIF)/lib
|
||||
|
||||
HAVE_PURIFY = 1
|
||||
MOTIF = /home/motif/usr
|
||||
MOTIFLIB = -L$(MOTIF)/lib -lXm
|
||||
INCLUDES += -I/usr/X11R5/include -I$(MOTIF)/include
|
||||
|
||||
NOSUCHFILE = /solaris-rm-f-sucks
|
||||
|
||||
LOCALE_MAP = $(DEPTH)/cmd/xfe/intl/sunos.lm
|
||||
|
||||
EN_LOCALE = en_US
|
||||
DE_LOCALE = de
|
||||
FR_LOCALE = fr
|
||||
JP_LOCALE = ja
|
||||
SJIS_LOCALE = ja_JP.SJIS
|
||||
KR_LOCALE = ko
|
||||
CN_LOCALE = zh
|
||||
TW_LOCALE = zh_TW
|
||||
I2_LOCALE = i2
|
||||
IT_LOCALE = it
|
||||
SV_LOCALE = sv
|
||||
ES_LOCALE = es
|
||||
NL_LOCALE = nl
|
||||
PT_LOCALE = pt
|
||||
|
||||
LOC_LIB_DIR = /usr/openwin/lib/locale
|
||||
|
||||
BSDECHO = echo
|
||||
|
||||
#
|
||||
# These defines are for building unix plugins
|
||||
#
|
||||
BUILD_UNIX_PLUGINS = 1
|
||||
DSO_LDOPTS =
|
||||
DSO_LDFLAGS =
|
||||
@@ -1,91 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for SunOS5.3
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
CFLAGS += -Wall -Wno-format
|
||||
|
||||
#CC = /opt/SUNWspro/SC3.0.1/bin/cc
|
||||
RANLIB = echo
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = sparc
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R
|
||||
OS_LIBS = -lsocket -lnsl -ldl
|
||||
|
||||
ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
|
||||
|
||||
HAVE_PURIFY = 1
|
||||
|
||||
NOSUCHFILE = /solaris-rm-f-sucks
|
||||
|
||||
ifndef JS_NO_ULTRA
|
||||
ULTRA_OPTIONS := -xarch=v8plus
|
||||
ULTRA_OPTIONSD := -DULTRA_SPARC
|
||||
else
|
||||
ULTRA_OPTIONS := -xarch=v8
|
||||
ULTRA_OPTIONSD :=
|
||||
endif
|
||||
|
||||
ifeq ($(OS_CPUARCH),sun4u)
|
||||
DEFINES += $(ULTRA_OPTIONSD)
|
||||
ifeq ($(findstring gcc,$(CC)),gcc)
|
||||
DEFINES += -Wa,$(ULTRA_OPTIONS),$(ULTRA_OPTIONSD)
|
||||
else
|
||||
ASFLAGS += $(ULTRA_OPTIONS) $(ULTRA_OPTIONSD)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_CPUARCH),sun4m)
|
||||
ifeq ($(findstring gcc,$(CC)),gcc)
|
||||
DEFINES += -Wa,-xarch=v8
|
||||
else
|
||||
ASFLAGS += -xarch=v8
|
||||
endif
|
||||
endif
|
||||
|
||||
MKSHLIB = $(LD) -G
|
||||
@@ -1,92 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for SunOS5.4
|
||||
#
|
||||
|
||||
ifdef NS_USE_NATIVE
|
||||
CC = cc
|
||||
CCC = CC
|
||||
else
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
CFLAGS += -Wall -Wno-format
|
||||
endif
|
||||
|
||||
RANLIB = echo
|
||||
|
||||
CPU_ARCH = sparc
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D__svr4 -DSOLARIS -DHAVE_LOCALTIME_R
|
||||
OS_LIBS = -lsocket -lnsl -ldl
|
||||
|
||||
ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
|
||||
|
||||
HAVE_PURIFY = 1
|
||||
|
||||
NOSUCHFILE = /solaris-rm-f-sucks
|
||||
|
||||
ifndef JS_NO_ULTRA
|
||||
ULTRA_OPTIONS := -xarch=v8plus
|
||||
ULTRA_OPTIONSD := -DULTRA_SPARC
|
||||
else
|
||||
ULTRA_OPTIONS := -xarch=v8
|
||||
ULTRA_OPTIONSD :=
|
||||
endif
|
||||
|
||||
ifeq ($(OS_CPUARCH),sun4u)
|
||||
DEFINES += $(ULTRA_OPTIONSD)
|
||||
ifeq ($(findstring gcc,$(CC)),gcc)
|
||||
DEFINES += -Wa,$(ULTRA_OPTIONS),$(ULTRA_OPTIONSD)
|
||||
else
|
||||
ASFLAGS += $(ULTRA_OPTIONS) $(ULTRA_OPTIONSD)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_CPUARCH),sun4m)
|
||||
ifeq ($(findstring gcc,$(CC)),gcc)
|
||||
DEFINES += -Wa,-xarch=v8
|
||||
else
|
||||
ASFLAGS += -xarch=v8
|
||||
endif
|
||||
endif
|
||||
|
||||
MKSHLIB = $(LD) -G
|
||||
@@ -1,44 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for SunOS5.5.1
|
||||
#
|
||||
|
||||
include $(DEPTH)/config/SunOS5.5.mk
|
||||
@@ -1,87 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for SunOS5.5
|
||||
#
|
||||
|
||||
AS = /usr/ccs/bin/as
|
||||
ifndef NS_USE_NATIVE
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
CFLAGS += -Wall -Wno-format
|
||||
else
|
||||
CC = cc
|
||||
CCC = CC
|
||||
endif
|
||||
|
||||
RANLIB = echo
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = sparc
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R
|
||||
OS_LIBS = -lsocket -lnsl -ldl
|
||||
|
||||
ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
|
||||
|
||||
HAVE_PURIFY = 1
|
||||
|
||||
NOSUCHFILE = /solaris-rm-f-sucks
|
||||
|
||||
ifeq ($(OS_CPUARCH),sun4u) # ultra sparc?
|
||||
ifeq ($(CC),gcc) # using gcc?
|
||||
ifndef JS_NO_ULTRA # do we want ultra?
|
||||
ifdef JS_THREADSAFE # only in thread-safe mode
|
||||
DEFINES += -DULTRA_SPARC
|
||||
DEFINES += -Wa,-xarch=v8plus,-DULTRA_SPARC
|
||||
else
|
||||
ASFLAGS += -xarch=v8plus -DULTRA_SPARC
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
MKSHLIB = $(LD) -G
|
||||
|
||||
# Use the editline library to provide line-editing support.
|
||||
JS_EDITLINE = 1
|
||||
@@ -1,89 +0,0 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Communicator client code, released
|
||||
# March 31, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# Config stuff for SunOS5.5
|
||||
#
|
||||
|
||||
AS = /usr/ccs/bin/as
|
||||
ifndef NS_USE_NATIVE
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
CFLAGS += -Wall -Wno-format
|
||||
else
|
||||
CC = cc
|
||||
CCC = CC
|
||||
CFLAGS += -mt -KPIC
|
||||
# LD = CC
|
||||
endif
|
||||
|
||||
RANLIB = echo
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = sparc
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R
|
||||
OS_LIBS = -lsocket -lnsl -ldl
|
||||
|
||||
ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
|
||||
|
||||
HAVE_PURIFY = 1
|
||||
|
||||
NOSUCHFILE = /solaris-rm-f-sucks
|
||||
|
||||
ifeq ($(OS_CPUARCH),sun4u) # ultra sparc?
|
||||
ifeq ($(CC),gcc) # using gcc?
|
||||
ifndef JS_NO_ULTRA # do we want ultra?
|
||||
ifdef JS_THREADSAFE # only in thread-safe mode
|
||||
DEFINES += -DULTRA_SPARC
|
||||
DEFINES += -Wa,-xarch=v8plus,-DULTRA_SPARC
|
||||
else
|
||||
ASFLAGS += -xarch=v8plus -DULTRA_SPARC
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
MKSHLIB = $(LD) -G
|
||||
|
||||
# Use the editline library to provide line-editing support.
|
||||
JS_EDITLINE = 1
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user