Compare commits
22 Commits
regalloc_c
...
jsd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e99fb1da7b | ||
|
|
a4156ea8c1 | ||
|
|
4e17e7d0b6 | ||
|
|
0b9f4a6066 | ||
|
|
88e2efb86c | ||
|
|
f70c006cd2 | ||
|
|
2d43318eeb | ||
|
|
464cfb0128 | ||
|
|
ccd9fea75c | ||
|
|
adbbf081d4 | ||
|
|
087895e0d4 | ||
|
|
f53236bbe5 | ||
|
|
4525a93346 | ||
|
|
92ce8e0953 | ||
|
|
4f506cbcbc | ||
|
|
53fed9d6ad | ||
|
|
a7fb2e53b5 | ||
|
|
cddacc3fc7 | ||
|
|
6f925ed79a | ||
|
|
91ff9d9174 | ||
|
|
cb5c11135f | ||
|
|
d02f29a398 |
@@ -1,134 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
// Return the next bit after index set to true or -1 if none.
|
||||
//
|
||||
Int32 BitSet::nextOne(Int32 pos) const
|
||||
{
|
||||
++pos;
|
||||
|
||||
if (pos < 0 || Uint32(pos) >= universeSize)
|
||||
return -1;
|
||||
|
||||
Uint32 offset = getWordOffset(pos);
|
||||
Uint8 index = getBitOffset(pos);
|
||||
Word* ptr = &word[offset];
|
||||
Word currentWord = *ptr++ >> index;
|
||||
|
||||
if (currentWord != Word(0)) {
|
||||
while ((currentWord & Word(1)) == 0) {
|
||||
++index;
|
||||
currentWord >>= 1;
|
||||
}
|
||||
return (offset << nBitsInWordLog2) + index;
|
||||
}
|
||||
|
||||
Word* limit = &word[getSizeInWords(universeSize)];
|
||||
while (ptr < limit) {
|
||||
++offset;
|
||||
currentWord = *ptr++;
|
||||
if (currentWord != Word(0)) {
|
||||
index = 0;
|
||||
while ((currentWord & Word(1)) == 0) {
|
||||
++index;
|
||||
currentWord >>= 1;
|
||||
}
|
||||
return (offset << nBitsInWordLog2) + index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return the next bit after index set to false or -1 if none.
|
||||
//
|
||||
Int32 BitSet::nextZero(Int32 pos) const
|
||||
{
|
||||
++pos;
|
||||
|
||||
if (pos < 0 || Uint32(pos) >= universeSize)
|
||||
return -1;
|
||||
|
||||
Uint32 offset = getWordOffset(pos);
|
||||
Uint8 index = getBitOffset(pos);
|
||||
Word* ptr = &word[offset];
|
||||
Word currentWord = *ptr++ >> index;
|
||||
|
||||
if (currentWord != Word(~0)) {
|
||||
for (; index < nBitsInWord; ++index) {
|
||||
if ((currentWord & Word(1)) == 0) {
|
||||
Int32 ret = (offset << nBitsInWordLog2) + index;
|
||||
return (Uint32(ret) < universeSize) ? ret : -1;
|
||||
}
|
||||
currentWord >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
Word* limit = &word[getSizeInWords(universeSize)];
|
||||
while (ptr < limit) {
|
||||
++offset;
|
||||
currentWord = *ptr++;
|
||||
if (currentWord != Word(~0)) {
|
||||
for (index = 0; index < nBitsInWord; ++index) {
|
||||
if ((currentWord & Word(1)) == 0) {
|
||||
Int32 ret = (offset << nBitsInWordLog2) + index;
|
||||
return (Uint32(ret) < universeSize) ? ret : -1;
|
||||
}
|
||||
currentWord >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
// Print the set.
|
||||
//
|
||||
void BitSet::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("[ "));
|
||||
|
||||
for (Int32 i = firstOne(); i != -1; i = nextOne(i)) {
|
||||
Int32 currentBit = i;
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", currentBit));
|
||||
|
||||
Int32 nextBit = nextOne(currentBit);
|
||||
if (nextBit != currentBit + 1) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" "));
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((nextBit != -1) && (nextBit == (currentBit + 1))) {
|
||||
currentBit = nextBit;
|
||||
nextBit = nextOne(nextBit);
|
||||
}
|
||||
|
||||
if (currentBit > (i+1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("-%d ", currentBit));
|
||||
else
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" %d ", currentBit));
|
||||
|
||||
i = currentBit;
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("]\n"));
|
||||
}
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
@@ -1,195 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _BITSET_H_
|
||||
#define _BITSET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "Pool.h"
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// BitSet -
|
||||
|
||||
class BitSet
|
||||
{
|
||||
private:
|
||||
|
||||
#if (PR_BITS_PER_WORD == 64)
|
||||
typedef Uint64 Word;
|
||||
#elif (PR_BITS_PER_WORD == 32)
|
||||
typedef Uint32 Word;
|
||||
#endif
|
||||
|
||||
static const nBitsInWord = PR_BITS_PER_WORD;
|
||||
static const nBytesInWord = PR_BYTES_PER_WORD;
|
||||
static const nBitsInWordLog2 = PR_BITS_PER_WORD_LOG2;
|
||||
static const nBytesInWordLog2 = PR_BYTES_PER_WORD_LOG2;
|
||||
|
||||
// Return the number of Word need to store the universe.
|
||||
static Uint32 getSizeInWords(Uint32 sizeOfUniverse) {return (sizeOfUniverse + (nBitsInWord - 1)) >> nBitsInWordLog2;}
|
||||
// Return the given element offset in its containing Word.
|
||||
static Uint32 getBitOffset(Uint32 element) {return element & (nBitsInWord - 1);}
|
||||
// Return the Word offset for the given element int the universe.
|
||||
static Uint32 getWordOffset(Uint32 element) {return element >> nBitsInWordLog2;}
|
||||
// Return the mask for the given bit index.
|
||||
static Word getMask(Uint8 index) {return Word(1) << index;}
|
||||
|
||||
private:
|
||||
|
||||
Uint32 universeSize; // Size of the universe
|
||||
Word* word; // universe memory.
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
BitSet(const BitSet&);
|
||||
|
||||
// Check if the given set's universe is of the same size than this universe.
|
||||
void checkUniverseCompatibility(const BitSet& set) const {assert(set.universeSize == universeSize);}
|
||||
// Check if pos is valid for this set's universe.
|
||||
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
|
||||
|
||||
public:
|
||||
|
||||
// Create a bitset of universeSize bits.
|
||||
BitSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {word = new(pool) Word[getSizeInWords(universeSize)]; clear();}
|
||||
|
||||
// Return the size of this bitset.
|
||||
Uint32 getSize() const {return universeSize;}
|
||||
|
||||
// Clear the bitset.
|
||||
void clear() {memset(word, 0x00, getSizeInWords(universeSize) << nBytesInWordLog2);}
|
||||
// Clear the bit at index.
|
||||
void clear(Uint32 index) {checkMember(index); word[getWordOffset(index)] &= ~getMask(index);}
|
||||
// Set the bitset.
|
||||
void set() {memset(word, 0xFF, getSizeInWords(universeSize) << nBytesInWordLog2);}
|
||||
// Set the bit at index.
|
||||
void set(Uint32 index) {checkMember(index); word[getWordOffset(index)] |= getMask(index);}
|
||||
// Return true if the bit at index is set.
|
||||
bool test(Uint32 index) const {checkMember(index); return (word[getWordOffset(index)] & getMask(index)) != 0;}
|
||||
// Union with the given bitset.
|
||||
inline void or(const BitSet& set);
|
||||
// Intersection with the given bitset.
|
||||
inline void and(const BitSet& set);
|
||||
// Difference with the given bitset.
|
||||
inline void difference(const BitSet& set);
|
||||
// Copy set.
|
||||
inline BitSet& operator = (const BitSet& set);
|
||||
// Return true if the bitset are identical.
|
||||
friend bool operator == (const BitSet& set1, const BitSet& set2);
|
||||
// Return true if the bitset are different.
|
||||
friend bool operator != (const BitSet& set1, const BitSet& set2);
|
||||
|
||||
// Logical operators.
|
||||
BitSet& operator |= (const BitSet& set) {or(set); return *this;}
|
||||
BitSet& operator &= (const BitSet& set) {and(set); return *this;}
|
||||
BitSet& operator -= (const BitSet& set) {difference(set); return *this;}
|
||||
|
||||
// Return the first bit at set to true or -1 if none.
|
||||
Int32 firstOne() const {return nextOne(-1);}
|
||||
// Return the next bit after index set to true or -1 if none.
|
||||
Int32 nextOne(Int32 pos) const;
|
||||
// Return the first bit at set to false or -1 if none.
|
||||
Int32 firstZero() const {return nextZero(-1);}
|
||||
// Return the next bit after index set to false or -1 if none.
|
||||
Int32 nextZero(Int32 pos) const;
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef Int32 iterator;
|
||||
// Return true if the walk is ordered.
|
||||
static bool isOrdered() {return true;}
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const {return firstOne();}
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const {return nextOne(pos);}
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos == -1;}
|
||||
// Return the element corresponding to the given iterator.
|
||||
Uint32 get(iterator pos) const {return pos;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
// Union with the given bitset.
|
||||
//
|
||||
inline void BitSet::or(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ |= *src++;
|
||||
}
|
||||
|
||||
// Intersection with the given bitset.
|
||||
//
|
||||
inline void BitSet::and(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ &= *src++;
|
||||
}
|
||||
|
||||
// Difference with the given bitset.
|
||||
//
|
||||
inline void BitSet::difference(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ &= ~*src++;
|
||||
}
|
||||
|
||||
// Copy the given set into this set.
|
||||
//
|
||||
inline BitSet& BitSet::operator = (const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
if (this != &set)
|
||||
memcpy(word, set.word, getSizeInWords(universeSize) << nBytesInWordLog2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Return true if the given set is identical to this set.
|
||||
inline bool operator == (const BitSet& set1, const BitSet& set2)
|
||||
{
|
||||
set1.checkUniverseCompatibility(set2);
|
||||
|
||||
if (&set1 == &set2)
|
||||
return true;
|
||||
|
||||
return memcmp(set1.word, set2.word, BitSet::getSizeInWords(set1.universeSize) << BitSet::nBytesInWordLog2) == 0;
|
||||
}
|
||||
|
||||
inline bool operator != (const BitSet& set1, const BitSet& set2) {return !(set1 == set2);}
|
||||
|
||||
#endif // _BITSET_H
|
||||
@@ -1,159 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _COALESCING_H_
|
||||
#define _COALESCING_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "SparseSet.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
#if 1
|
||||
// Performing an ultra conservative coalescing meens that when we look at
|
||||
// candidates (source,destination) for coalescing we need to make sure
|
||||
// that the combined interference of the source and destination register
|
||||
// will not exceed the total number of register available for the register
|
||||
// class.
|
||||
#define ULTRA_CONSERVATIVE_COALESCING
|
||||
#else
|
||||
// If we are not doing an ultra conservative coalescing we have to make sure
|
||||
// that the total number of neighbor whose degree is greater than the total
|
||||
// number of register is not greater than the total number of register.
|
||||
#undef ULTRA_CONSERVATIVE_COALESCING
|
||||
#endif
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Coalescing
|
||||
{
|
||||
static bool coalesce(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coalescing<RegisterPressure>::coalesce(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
|
||||
// Initialize the lookup table
|
||||
//
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* newRange = new RegisterName[2 * rangeCount];
|
||||
RegisterName* coalescedRange = &newRange[rangeCount];
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
init(coalescedRange, rangeCount);
|
||||
|
||||
SparseSet interferences(pool, rangeCount);
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
bool removedInstructions = false;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.lndList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
|
||||
// Walk the nodes in the loop nesting depth list.
|
||||
for (Int32 n = nNodes - 1; n >= 0; n--) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
InstructionList::iterator it = instructions.begin();
|
||||
while (!instructions.done(it)) {
|
||||
Instruction& instruction = instructions.get(it);
|
||||
it = instructions.advance(it);
|
||||
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
|
||||
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
|
||||
|
||||
RegisterName source = findRoot(name2range[instruction.getInstructionUseBegin()[0].getRegisterName()], coalescedRange);
|
||||
RegisterName destination = findRoot(name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()], coalescedRange);
|
||||
|
||||
if (source == destination) {
|
||||
instruction.remove();
|
||||
} else if (!iGraph.interfere(source, destination)) {
|
||||
InterferenceVector* sourceVector = iGraph.getInterferenceVector(source);
|
||||
InterferenceVector* destinationVector = iGraph.getInterferenceVector(destination);
|
||||
|
||||
#ifdef ULTRA_CONSERVATIVE_COALESCING
|
||||
interferences.clear();
|
||||
|
||||
InterferenceVector* vector;
|
||||
for (vector = sourceVector; vector != NULL; vector = vector->next) {
|
||||
RegisterName* neighbors = vector->neighbors;
|
||||
for (Uint32 i = 0; i < vector->count; i++)
|
||||
interferences.set(findRoot(neighbors[i], coalescedRange));
|
||||
}
|
||||
for (vector = destinationVector; vector != NULL; vector = vector->next) {
|
||||
RegisterName* neighbors = vector->neighbors;
|
||||
for (Uint32 i = 0; i < vector->count; i++)
|
||||
interferences.set(findRoot(neighbors[i], coalescedRange));
|
||||
}
|
||||
|
||||
Uint32 count = interferences.getSize();
|
||||
#else // ULTRA_CONSERVATIVE_COALESCING
|
||||
trespass("not implemented");
|
||||
Uint32 count = 0;
|
||||
#endif // ULTRA_CONSERVATIVE_COALESCING
|
||||
|
||||
if (count < 6 /* FIX: should get the number from the class */) {
|
||||
// Update the interferences vector.
|
||||
if (sourceVector == NULL) {
|
||||
iGraph.setInterferenceVector(source, destinationVector);
|
||||
sourceVector = destinationVector;
|
||||
} else if (destinationVector == NULL)
|
||||
iGraph.setInterferenceVector(destination, sourceVector);
|
||||
else {
|
||||
InterferenceVector* last = NULL;
|
||||
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next)
|
||||
last = v;
|
||||
assert(last);
|
||||
last->next = destinationVector;
|
||||
iGraph.setInterferenceVector(destination, sourceVector);
|
||||
}
|
||||
// Update the interference matrix.
|
||||
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next) {
|
||||
RegisterName* neighbors = v->neighbors;
|
||||
for (Uint32 i = 0; i < v->count; i++) {
|
||||
RegisterName neighbor = findRoot(neighbors[i], coalescedRange);
|
||||
iGraph.setInterference(neighbor, source);
|
||||
iGraph.setInterference(neighbor, destination);
|
||||
}
|
||||
}
|
||||
|
||||
instruction.remove();
|
||||
coalescedRange[source] = destination;
|
||||
removedInstructions = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerAllocator.rangeCount = compress(registerAllocator.name2range, coalescedRange, registerAllocator.nameCount, rangeCount);
|
||||
delete newRange;
|
||||
|
||||
return removedInstructions;
|
||||
}
|
||||
|
||||
#endif // _COALESCING_H_
|
||||
@@ -1,283 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef NEW_LAURENTM_CODE
|
||||
|
||||
#include "Coloring.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "FastBitSet.h"
|
||||
#include "FastBitMatrix.h"
|
||||
#include "CpuInfo.h"
|
||||
|
||||
bool Coloring::
|
||||
assignRegisters(FastBitMatrix& interferenceMatrix)
|
||||
{
|
||||
PRUint32 *stackPtr = new(pool) PRUint32[vRegManager.count()];
|
||||
|
||||
return select(interferenceMatrix, stackPtr, simplify(interferenceMatrix, stackPtr));
|
||||
}
|
||||
|
||||
PRInt32 Coloring::
|
||||
getLowestSpillCostRegister(FastBitSet& bitset)
|
||||
{
|
||||
PRInt32 lowest = bitset.firstOne();
|
||||
if (lowest != -1)
|
||||
{
|
||||
Flt32 cost = vRegManager.getVirtualRegister(lowest).spillInfo.spillCost;
|
||||
for (PRInt32 r = bitset.nextOne(lowest); r != -1; r = bitset.nextOne(r))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
if (!vReg.spillInfo.infiniteSpillCost && (vReg.spillInfo.spillCost < cost))
|
||||
{
|
||||
cost = vReg.spillInfo.spillCost;
|
||||
lowest = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
|
||||
PRUint32* Coloring::
|
||||
simplify(FastBitMatrix interferenceMatrix, PRUint32* stackPtr)
|
||||
{
|
||||
// first we construct the sets low and high. low contains all nodes of degree
|
||||
// inferior to the number of register available on the processor. All the
|
||||
// nodes with an high degree and a finite spill cost are placed in high.
|
||||
// Nodes of high degree and infinite spill cost are not included in either sets.
|
||||
|
||||
PRUint32 nRegisters = vRegManager.count();
|
||||
FastBitSet low(pool, nRegisters);
|
||||
FastBitSet high(pool, nRegisters);
|
||||
FastBitSet stack(pool, nRegisters);
|
||||
|
||||
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
|
||||
|
||||
if (vReg.getClass() == vrcStackSlot)
|
||||
{
|
||||
stack.set(i);
|
||||
vReg.colorRegister(nRegisters);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vReg.colorInfo.interferenceDegree < NUMBER_OF_REGISTERS)
|
||||
low.set(i);
|
||||
else // if (!vReg.spillInfo.infiniteSpillCost)
|
||||
high.set(i);
|
||||
|
||||
// Set coloring info.
|
||||
vReg.spillInfo.willSpill = false;
|
||||
|
||||
switch(vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
vReg.colorRegister(LAST_GREGISTER + 1);
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
vReg.colorRegister(LAST_FPREGISTER + 1);
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false); // Cannot happen.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// push the stack registers
|
||||
PRInt32 j;
|
||||
for (j = stack.firstOne(); j != -1; j = stack.nextOne(j))
|
||||
*stackPtr++ = j;
|
||||
|
||||
// simplify
|
||||
while (true)
|
||||
{
|
||||
PRInt32 r;
|
||||
while ((r = getLowestSpillCostRegister(low)) != -1)
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
|
||||
/* update low and high */
|
||||
FastBitSet inter(interferenceMatrix.getRow(r), nRegisters);
|
||||
for (j = inter.firstOne(); j != -1; j = inter.nextOne(j))
|
||||
{
|
||||
VirtualRegister& neighbor = vRegManager.getVirtualRegister(j);
|
||||
// if the new interference degree of one of his neighbor becomes
|
||||
// NUMBER_OF_REGISTERS - 1 then it is added to the set 'low'.
|
||||
|
||||
PRUint32 maxInterference = 0;
|
||||
switch (neighbor.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
maxInterference = NUMBER_OF_GREGISTERS;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
maxInterference = NUMBER_OF_FPREGISTERS;
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false);
|
||||
}
|
||||
if ((vRegManager.getVirtualRegister(j).colorInfo.interferenceDegree-- == maxInterference))
|
||||
{
|
||||
high.clear(j);
|
||||
low.set(j);
|
||||
}
|
||||
vReg.colorInfo.interferenceDegree--;
|
||||
interferenceMatrix.clear(r, j);
|
||||
interferenceMatrix.clear(j, r);
|
||||
}
|
||||
low.clear(r);
|
||||
|
||||
// Push this register.
|
||||
*stackPtr++ = r;
|
||||
}
|
||||
if ((r = getLowestSpillCostRegister(high)) != -1)
|
||||
{
|
||||
high.clear(r);
|
||||
low.set(r);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return stackPtr;
|
||||
}
|
||||
|
||||
bool Coloring::
|
||||
select(FastBitMatrix& interferenceMatrix, PRUint32* stackBase, PRUint32* stackPtr)
|
||||
{
|
||||
PRUint32 nRegisters = vRegManager.count();
|
||||
FastBitSet usedRegisters(NUMBER_OF_REGISTERS + 1); // usedRegisters if used for both GR & FPR.
|
||||
FastBitSet preColoredRegisters(NUMBER_OF_REGISTERS + 1);
|
||||
FastBitSet usedStack(nRegisters + 1);
|
||||
bool success = true;
|
||||
Int32 lastUsedSSR = -1;
|
||||
|
||||
// select
|
||||
while (stackPtr != stackBase)
|
||||
{
|
||||
// Pop one register.
|
||||
PRUint32 r = *--stackPtr;
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
|
||||
FastBitSet neighbors(interferenceMatrix.getRow(r), nRegisters);
|
||||
|
||||
if (vReg.getClass() == vrcStackSlot)
|
||||
// Stack slots coloring.
|
||||
{
|
||||
usedStack.clear();
|
||||
|
||||
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
|
||||
usedStack.set(vRegManager.getVirtualRegister(i).getColor());
|
||||
|
||||
Int32 color = usedStack.firstZero();
|
||||
vReg.colorRegister(color);
|
||||
if (color > lastUsedSSR)
|
||||
lastUsedSSR = color;
|
||||
}
|
||||
else
|
||||
// Integer & Floating point register coloring.
|
||||
{
|
||||
usedRegisters.clear();
|
||||
preColoredRegisters.clear();
|
||||
|
||||
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
|
||||
{
|
||||
VirtualRegister& nvReg = vRegManager.getVirtualRegister(i);
|
||||
usedRegisters.set(nvReg.getColor());
|
||||
if (nvReg.isPreColored())
|
||||
preColoredRegisters.set(nvReg.getPreColor());
|
||||
}
|
||||
if (vReg.hasSpecialInterference)
|
||||
usedRegisters |= vReg.specialInterference;
|
||||
|
||||
PRInt8 c = -1;
|
||||
PRInt8 maxColor = 0;
|
||||
PRInt8 firstColor = 0;
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
firstColor = FIRST_GREGISTER;
|
||||
maxColor = LAST_GREGISTER;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
firstColor = FIRST_FPREGISTER;
|
||||
maxColor = LAST_FPREGISTER;
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false);
|
||||
}
|
||||
|
||||
if (vReg.isPreColored())
|
||||
{
|
||||
c = vReg.getPreColor();
|
||||
if (usedRegisters.test(c))
|
||||
c = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = usedRegisters.nextZero(firstColor - 1); (c >= 0) && (c <= maxColor) && (preColoredRegisters.test(c));
|
||||
c = usedRegisters.nextZero(c)) {}
|
||||
}
|
||||
|
||||
if ((c >= 0) && (c <= maxColor))
|
||||
{
|
||||
vReg.colorRegister(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
VirtualRegister& stackRegister = vRegManager.newVirtualRegister(vrcStackSlot);
|
||||
vReg.equivalentRegister[vrcStackSlot] = &stackRegister;
|
||||
vReg.spillInfo.willSpill = true;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (success)
|
||||
{
|
||||
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
if (vReg.getColor() > LAST_GREGISTER)
|
||||
PR_ASSERT(false);
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
#if NUMBER_OF_FPREGISTERS != 0
|
||||
if (vReg.getColor() > LAST_FPREGISTER)
|
||||
PR_ASSERT(false);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vRegManager.nUsedStackSlots = lastUsedSSR + 1;
|
||||
return success;
|
||||
}
|
||||
#endif // NEW_LAURENTM_CODE
|
||||
@@ -1,284 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "SparseSet.h"
|
||||
#include "Spilling.h"
|
||||
#include "Splits.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
template <class RegisterPressure>
|
||||
class Coloring
|
||||
{
|
||||
private:
|
||||
static RegisterName* simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack);
|
||||
static bool select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr);
|
||||
|
||||
public:
|
||||
static bool color(RegisterAllocator& registerAllocator);
|
||||
static void finalColoring(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Coloring<RegisterPressure>::finalColoring(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
RegisterName* color = registerAllocator.color;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
usePtr->setRegisterName(color[name2range[usePtr->getRegisterName()]]);
|
||||
#ifdef DEBUG
|
||||
RegisterID rid = usePtr->getRegisterID();
|
||||
setColoredRegister(rid);
|
||||
usePtr->setRegisterID(rid);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
definePtr->setRegisterName(color[name2range[definePtr->getRegisterName()]]);
|
||||
#ifdef DEBUG
|
||||
RegisterID rid = definePtr->getRegisterID();
|
||||
setColoredRegister(rid);
|
||||
definePtr->setRegisterID(rid);
|
||||
#endif // DEBUG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coloring<RegisterPressure>::select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* color = new RegisterName[rangeCount];
|
||||
registerAllocator.color = color;
|
||||
|
||||
for (Uint32 r = 1; r < rangeCount; r++)
|
||||
color[r] = RegisterName(6); // FIX;
|
||||
|
||||
// Color the preColored registers.
|
||||
//
|
||||
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
|
||||
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
|
||||
if (machinePtr->id != invalidID) {
|
||||
color[name2range[getName(machinePtr->id)]] = machinePtr->color;
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill preColor range %d as %d\n", name2range[getName(machinePtr->id)], machinePtr->color));
|
||||
}
|
||||
|
||||
SpillCost* cost = registerAllocator.spillCost;
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet& spill = *new(pool) SparseSet(pool, rangeCount);
|
||||
registerAllocator.willSpill = &spill;
|
||||
SparseSet neighborColors(pool, 6); // FIX
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
|
||||
bool coloringFailed = false;
|
||||
while (coloringStackPtr > coloringStack) {
|
||||
RegisterName range = *--coloringStackPtr;
|
||||
|
||||
if (!cost[range].infinite && cost[range].cost < 0) {
|
||||
coloringFailed = true;
|
||||
spill.set(range);
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, will spill.\n", range));
|
||||
} else {
|
||||
neighborColors.clear();
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = vector->count - 1; i >= 0; --i) {
|
||||
RegisterName neighborColor = color[vector->neighbors[i]];
|
||||
if (neighborColor < 6) // FIX
|
||||
neighborColors.set(neighborColor);
|
||||
}
|
||||
|
||||
if (neighborColors.getSize() == 6) { // FIX
|
||||
coloringFailed = true;
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, ", range));
|
||||
|
||||
if (!Splits<RegisterPressure>::findSplit(registerAllocator, color, range)) {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will spill.\n"));
|
||||
spill.set(range);
|
||||
} else
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will split.\n"));
|
||||
} else {
|
||||
for (Uint32 i = 0; i < 6; i++) // FIX
|
||||
if (!neighborColors.test(i)) {
|
||||
fprintf(stdout, "\twill color %d as %d\n", range, i);
|
||||
color[range] = RegisterName(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
if (coloringFailed) {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring failed:\n"));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill spill: "));
|
||||
spill.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
} else {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring succeeded:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\trange %d colored as %d\n", i, color[i]));
|
||||
}
|
||||
#endif
|
||||
|
||||
return !coloringFailed;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
RegisterName* Coloring<RegisterPressure>::simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack)
|
||||
{
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
SpillCost* spillCost = registerAllocator.spillCost;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
|
||||
Uint32* degree = new Uint32[rangeCount];
|
||||
for (RegisterName i = RegisterName(1); i < rangeCount; i = RegisterName(i + 1)) {
|
||||
InterferenceVector* vector = iGraph.getInterferenceVector(i);
|
||||
degree[i] = (vector != NULL) ? vector->count : 0;
|
||||
}
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet low(pool, rangeCount);
|
||||
SparseSet high(pool, rangeCount);
|
||||
SparseSet highInfinite(pool, rangeCount);
|
||||
SparseSet preColored(pool, rangeCount);
|
||||
|
||||
// Get the precolored registers.
|
||||
//
|
||||
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
|
||||
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
|
||||
if (machinePtr->id != invalidID)
|
||||
preColored.set(name2range[getName(machinePtr->id)]);
|
||||
|
||||
// Insert the live ranges in the sets.
|
||||
//
|
||||
for (Uint32 range = 1; range < rangeCount; range++)
|
||||
if (!preColored.test(range))
|
||||
if (degree[range] < 6) // FIX
|
||||
low.set(range);
|
||||
else if (!spillCost[range].infinite)
|
||||
high.set(range);
|
||||
else
|
||||
highInfinite.set(range);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring sets:\n\tlow = "));
|
||||
low.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thigh = "));
|
||||
high.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thighInfinite = "));
|
||||
highInfinite.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tpreColored = "));
|
||||
preColored.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
RegisterName* coloringStackPtr = coloringStack;
|
||||
|
||||
while (low.getSize() != 0 || high.getSize() != 0) {
|
||||
while (low.getSize() != 0) {
|
||||
RegisterName range = RegisterName(low.getOne());
|
||||
low.clear(range);
|
||||
*coloringStackPtr++ = range;
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = (vector->count - 1); i >= 0; --i) {
|
||||
RegisterName neighbor = vector->neighbors[i];
|
||||
degree[neighbor]--;
|
||||
|
||||
if (degree[neighbor] < 6) // FIX
|
||||
if (high.test(neighbor)) {
|
||||
high.clear(neighbor);
|
||||
low.set(neighbor);
|
||||
} else if (highInfinite.test(neighbor)) {
|
||||
highInfinite.clear(neighbor);
|
||||
low.set(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (high.getSize() != 0) {
|
||||
RegisterName best = RegisterName(high.getOne());
|
||||
double bestCost = spillCost[best].cost;
|
||||
double bestDegree = degree[best];
|
||||
|
||||
// Choose the next best candidate.
|
||||
//
|
||||
for (SparseSet::iterator i = high.begin(); !high.done(i); i = high.advance(i)) {
|
||||
RegisterName range = RegisterName(high.get(i));
|
||||
double thisCost = spillCost[range].cost;
|
||||
double thisDegree = degree[range];
|
||||
|
||||
if (thisCost * bestDegree < bestCost * thisDegree) {
|
||||
best = range;
|
||||
bestCost = thisCost;
|
||||
bestDegree = thisDegree;
|
||||
}
|
||||
}
|
||||
|
||||
high.clear(best);
|
||||
low.set(best);
|
||||
}
|
||||
}
|
||||
assert(highInfinite.getSize() == 0);
|
||||
|
||||
delete degree;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring stack:\n\t"));
|
||||
for (RegisterName* sp = coloringStack; sp < coloringStackPtr; ++sp)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("%d ", *sp));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\n"));
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
return coloringStackPtr;
|
||||
}
|
||||
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coloring<RegisterPressure>::color(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
RegisterName* coloringStack = new RegisterName[registerAllocator.rangeCount];
|
||||
return select(registerAllocator, coloringStack, simplify(registerAllocator, coloringStack));
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
|
||||
#include "DominatorGraph.h"
|
||||
|
||||
DominatorGraph::DominatorGraph(ControlGraph& controlGraph) : controlGraph(controlGraph)
|
||||
{
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
GtoV = new Uint32[nNodes + 1];
|
||||
VtoG = new Uint32[nNodes + 1];
|
||||
|
||||
Uint32 v = 1;
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
VtoG[v] = n;
|
||||
GtoV[n] = v++;
|
||||
}
|
||||
|
||||
// Initialize all the 1-based arrays.
|
||||
//
|
||||
parent = new Uint32[v];
|
||||
semi = new Uint32[v];
|
||||
vertex = new Uint32[v];
|
||||
label = new Uint32[v];
|
||||
size = new Uint32[v];
|
||||
ancestor = new Uint32[v];
|
||||
child = new Uint32[v];
|
||||
dom = new Uint32[v];
|
||||
bucket = new DGLinkedList*[v];
|
||||
|
||||
memset(semi, '\0', v * sizeof(Uint32));
|
||||
memset(bucket, '\0', v * sizeof(DGLinkedList*));
|
||||
|
||||
vCount = v;
|
||||
|
||||
build();
|
||||
|
||||
delete parent;
|
||||
delete semi;
|
||||
delete vertex;
|
||||
delete label;
|
||||
delete size;
|
||||
delete ancestor;
|
||||
delete child;
|
||||
delete dom;
|
||||
delete bucket;
|
||||
}
|
||||
|
||||
Uint32 DominatorGraph::DFS(Uint32 vx, Uint32 n)
|
||||
{
|
||||
semi[vx] = ++n;
|
||||
vertex[n] = label[vx] = vx;
|
||||
ancestor[vx] = child[vx] = 0;
|
||||
size[vx] = 1;
|
||||
|
||||
|
||||
ControlNode& node = *controlGraph.dfsList[VtoG[vx]];
|
||||
ControlEdge* successorEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorPtr = node.getSuccessorsBegin(); successorPtr < successorEnd; successorPtr++) {
|
||||
Uint32 w = GtoV[successorPtr->getTarget().dfsNum];
|
||||
if (semi[w] == 0) {
|
||||
parent[w] = vx;
|
||||
n = DFS(w, n);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void DominatorGraph::LINK(Uint32 vx, Uint32 w)
|
||||
{
|
||||
Uint32 s = w;
|
||||
|
||||
while (semi[label[w]] < semi[label[child[s]]]) {
|
||||
if (size[s] + size[child[child[s]]] >= (size[child[s]] << 1)) {
|
||||
ancestor[child[s]] = s;
|
||||
child[s] = child[child[s]];
|
||||
} else {
|
||||
size[child[s]] = size[s];
|
||||
s = ancestor[s] = child[s];
|
||||
}
|
||||
}
|
||||
label[s] = label[w];
|
||||
size[vx] += size[w];
|
||||
if(size[vx] < (size[w] << 1)) {
|
||||
Uint32 t = s;
|
||||
s = child[vx];
|
||||
child[vx] = t;
|
||||
}
|
||||
while( s != 0 ) {
|
||||
ancestor[s] = vx;
|
||||
s = child[s];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DominatorGraph::COMPRESS(Uint32 vx)
|
||||
{
|
||||
if(ancestor[ancestor[vx]] != 0) {
|
||||
COMPRESS(ancestor[vx]);
|
||||
if(semi[label[ancestor[vx]]] < semi[label[vx]])
|
||||
label[vx] = label[ancestor[vx]];
|
||||
ancestor[vx] = ancestor[ancestor[vx]];
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 DominatorGraph::EVAL(Uint32 vx)
|
||||
{
|
||||
if(ancestor[vx] == 0)
|
||||
return label[vx];
|
||||
COMPRESS(vx);
|
||||
return (semi[label[ancestor[vx]]] >= semi[label[vx]]) ? label[vx] : label[ancestor[vx]];
|
||||
}
|
||||
|
||||
void DominatorGraph::build()
|
||||
{
|
||||
Uint32 n = DFS(GtoV[0], 0);
|
||||
size[0] = label[0] = semi[0];
|
||||
|
||||
for (Uint32 i = n; i >= 2; i--) {
|
||||
Uint32 w = vertex[i];
|
||||
|
||||
ControlNode& node = *controlGraph.dfsList[VtoG[w]];
|
||||
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
|
||||
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p)) {
|
||||
Uint32 vx = GtoV[predecessors.get(p).getSource().dfsNum];
|
||||
Uint32 u = EVAL(vx);
|
||||
|
||||
if(semi[u] < semi[w])
|
||||
semi[w] = semi[u];
|
||||
}
|
||||
|
||||
DGLinkedList* elem = new DGLinkedList();
|
||||
elem->next = bucket[vertex[semi[w]]];
|
||||
elem->index = w;
|
||||
bucket[vertex[semi[w]]] = elem;
|
||||
|
||||
LINK(parent[w], w);
|
||||
|
||||
elem = bucket[parent[w]];
|
||||
while(elem != NULL) {
|
||||
Uint32 vx = elem->index;
|
||||
Uint32 u = EVAL(vx);
|
||||
dom[vx] = (semi[u] < semi[vx]) ? u : parent[w];
|
||||
elem = elem->next;
|
||||
}
|
||||
}
|
||||
|
||||
memset(size, '\0', n * sizeof(Uint32));
|
||||
Pool& pool = controlGraph.pool;
|
||||
nodes = new(pool) DGNode[n];
|
||||
|
||||
for(Uint32 j = 2; j <= n; j++) {
|
||||
Uint32 w = vertex[j];
|
||||
Uint32 d = dom[w];
|
||||
if(d != vertex[semi[w]]) {
|
||||
d = dom[d];
|
||||
dom[w] = d;
|
||||
}
|
||||
size[d]++;
|
||||
}
|
||||
dom[GtoV[0]] = 0;
|
||||
|
||||
for (Uint32 k = 1; k <= n; k++) {
|
||||
DGNode& node = nodes[VtoG[k]];
|
||||
Uint32 count = size[k];
|
||||
node.successorsEnd = node.successorsBegin = (count) ? new(pool) Uint32[count] : (Uint32*) 0;
|
||||
}
|
||||
|
||||
for (Uint32 l = 2; l <= n; l++)
|
||||
*(nodes[VtoG[dom[l]]].successorsEnd)++ = VtoG[l];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void DominatorGraph::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Dominator Graph:\n"));
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
for (Uint32 i = 0; i < nNodes; i++) {
|
||||
DGNode& node = nodes[i];
|
||||
if (node.successorsBegin != node.successorsEnd) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tN%d dominates ", i));
|
||||
for (Uint32* successorsPtr = node.successorsBegin; successorsPtr < node.successorsEnd; successorsPtr++)
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d ", *successorsPtr));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DOMINATOR_GRAPH_H_
|
||||
#define _DOMINATOR_GRAPH_H_
|
||||
|
||||
#include "LogModule.h"
|
||||
|
||||
class ControlGraph;
|
||||
|
||||
struct DGNode
|
||||
{
|
||||
Uint32* successorsBegin;
|
||||
Uint32* successorsEnd;
|
||||
};
|
||||
|
||||
struct DGLinkedList
|
||||
{
|
||||
DGLinkedList* next;
|
||||
Uint32 index;
|
||||
};
|
||||
|
||||
class DominatorGraph
|
||||
{
|
||||
private:
|
||||
|
||||
ControlGraph& controlGraph;
|
||||
|
||||
Uint32 vCount;
|
||||
|
||||
Uint32* VtoG;
|
||||
Uint32* GtoV;
|
||||
Uint32* parent;
|
||||
Uint32* semi;
|
||||
Uint32* vertex;
|
||||
Uint32* label;
|
||||
Uint32* size;
|
||||
Uint32* ancestor;
|
||||
Uint32* child;
|
||||
Uint32* dom;
|
||||
DGLinkedList** bucket;
|
||||
DGNode* nodes;
|
||||
|
||||
private:
|
||||
|
||||
void build();
|
||||
|
||||
Uint32 DFS(Uint32 vx, Uint32 n);
|
||||
void LINK(Uint32 vx, Uint32 w);
|
||||
void COMPRESS(Uint32 vx);
|
||||
Uint32 EVAL(Uint32 vx);
|
||||
|
||||
public:
|
||||
|
||||
DominatorGraph(ControlGraph& controlGraph);
|
||||
|
||||
Uint32* getSuccessorsBegin(Uint32 n) const {return nodes[n].successorsBegin;}
|
||||
Uint32* getSuccessorsEnd(Uint32 n) const {return nodes[n].successorsEnd;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
#endif // _DOMINATOR_GRAPH_H_
|
||||
@@ -1,97 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _HASH_SET_H_
|
||||
#define _HASH_SET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include <string.h>
|
||||
|
||||
struct HashSetElement
|
||||
{
|
||||
Uint32 index;
|
||||
HashSetElement* next;
|
||||
};
|
||||
|
||||
class HashSet
|
||||
{
|
||||
private:
|
||||
|
||||
static const hashSize = 64;
|
||||
|
||||
// Return the hash code for the given element index.
|
||||
static Uint32 getHashCode(Uint32 index) {return index & (hashSize - 1);} // Could be better !
|
||||
|
||||
private:
|
||||
|
||||
Pool& allocationPool;
|
||||
HashSetElement** bucket;
|
||||
HashSetElement* free;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
HashSet(const HashSet&);
|
||||
// No copy operator.
|
||||
void operator = (const HashSet&);
|
||||
|
||||
public:
|
||||
|
||||
// Create a new HashSet.
|
||||
inline HashSet(Pool& pool, Uint32 universeSize);
|
||||
|
||||
// Clear the hashset.
|
||||
void clear();
|
||||
// Clear the element for the given index.
|
||||
void clear(Uint32 index);
|
||||
// Set the element for the given index.
|
||||
void set(Uint32 index);
|
||||
// Return true if the element at index is a member.
|
||||
bool test(Uint32 index) const;
|
||||
// Union with the given hashset.
|
||||
inline void or(const HashSet& set);
|
||||
// Intersection with the given hashset.
|
||||
inline void and(const HashSet& set);
|
||||
// Difference with the given hashset.
|
||||
inline void difference(const HashSet& set);
|
||||
|
||||
// Logical operators.
|
||||
HashSet& operator |= (const HashSet& set) {or(set); return *this;}
|
||||
HashSet& operator &= (const HashSet& set) {and(set); return *this;}
|
||||
HashSet& operator -= (const HashSet& set) {difference(set); return *this;}
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef HashSetElement* iterator;
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const;
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const;
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos == NULL;}
|
||||
};
|
||||
|
||||
|
||||
inline HashSet::HashSet(Pool& pool, Uint32 /*universeSize*/)
|
||||
: allocationPool(pool), free(NULL)
|
||||
{
|
||||
bucket = new(pool) HashSetElement*[hashSize];
|
||||
memset(bucket, '\0', sizeof(HashSetElement*));
|
||||
}
|
||||
|
||||
#endif // _HASH_SET_H_
|
||||
@@ -1,213 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _INDEXED_POOL_H_
|
||||
#define _INDEXED_POOL_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedPool<IndexedObjectSubclass> is an indexed pool of objects. The
|
||||
// template parameter 'IndexedObjectSubclass' must be a subclass of the struct
|
||||
// IndexedObject.
|
||||
//
|
||||
// When the indexed pool is ask to allocate and initialize a new object (using
|
||||
// the operator new(anIndexedPool) it will zero the memory used to store the
|
||||
// object and initialize the field 'index' of this object to its position in
|
||||
// the pool.
|
||||
//
|
||||
// An object allocated by the indexed pool can be freed by calling the method
|
||||
// IndexedPool::release(IndexedElement& objectIndex).
|
||||
//
|
||||
// example:
|
||||
//
|
||||
// IndexedPool<IndexedElement> elementPool;
|
||||
//
|
||||
// IndexedElement& element1 = *new(elementPool) IndexedElement();
|
||||
// IndexedElement& element2 = *new(elementPool) IndexedElement();
|
||||
//
|
||||
// indexedPool.release(element1);
|
||||
// IndexedElement& element3 = *new(elementPool) IndexedElement();
|
||||
//
|
||||
// At this point element1 is no longer a valid object, element2 is at
|
||||
// index 2 and element3 is at index 1.
|
||||
//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedObject -
|
||||
//
|
||||
|
||||
template<class Object>
|
||||
struct IndexedObject
|
||||
{
|
||||
Uint32 index; // Index in the pool.
|
||||
Object* next; // Used to link IndexedObject together.
|
||||
|
||||
Uint32 getIndex() {return index;}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedPool<IndexedObject> -
|
||||
//
|
||||
|
||||
template <class IndexedObject>
|
||||
class IndexedPool
|
||||
{
|
||||
private:
|
||||
|
||||
static const blockSize = 4; // Size of one block.
|
||||
|
||||
Uint32 nBlocks; // Number of blocks in the pool.
|
||||
IndexedObject** block; // Array of block pointers.
|
||||
IndexedObject* freeObjects; // Chained list of free IndexedObjects.
|
||||
Uint32 nextIndex; // Index of the next free object in the last block.
|
||||
|
||||
private:
|
||||
|
||||
void allocateAnotherBlock();
|
||||
IndexedObject& newObject();
|
||||
|
||||
public:
|
||||
|
||||
IndexedPool() : nBlocks(0), block(NULL), freeObjects(NULL), nextIndex(1) {}
|
||||
~IndexedPool();
|
||||
|
||||
IndexedObject& get(Uint32 index) const;
|
||||
void release(IndexedObject& object);
|
||||
|
||||
void setSize(Uint32 size) {assert(size < nextIndex); nextIndex = size;}
|
||||
|
||||
// Return the universe size.
|
||||
Uint32 getSize() {return nextIndex;}
|
||||
|
||||
friend void* operator new(size_t, IndexedPool<IndexedObject>& pool); // Needs to call newObject().
|
||||
};
|
||||
|
||||
// Free all the memory allocated for this object.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedPool<IndexedObject>::~IndexedPool()
|
||||
{
|
||||
for (Uint32 n = 0; n < nBlocks; n++)
|
||||
free(&((IndexedObject **) &block[n][n*blockSize])[-(n + 1)]);
|
||||
}
|
||||
|
||||
// Release the given. This object will be iserted in the chained
|
||||
// list of free IndexedObjects. To minimize the fragmentation the chained list
|
||||
// is ordered by ascending indexes.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void IndexedPool<IndexedObject>::release(IndexedObject& object)
|
||||
{
|
||||
Uint32 index = object.index;
|
||||
IndexedObject* list = freeObjects;
|
||||
|
||||
assert(&object == &get(index)); // Make sure that object is owned by this pool.
|
||||
|
||||
if (list == NULL) { // The list is empty.
|
||||
freeObjects = &object;
|
||||
object.next = NULL;
|
||||
} else { // The list contains at least 1 element.
|
||||
if (index < list->index) { // insert as first element.
|
||||
freeObjects = &object;
|
||||
object.next = list;
|
||||
} else { // Find this object's place.
|
||||
while ((list->next) != NULL && (list->next->index < index))
|
||||
list = list->next;
|
||||
|
||||
object.next = list->next;
|
||||
list->next = &object;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Sanity check to be sure that the list is correctly ordered.
|
||||
for (IndexedObject* obj = freeObjects; obj != NULL; obj = obj->next)
|
||||
if (obj->next != NULL)
|
||||
assert(obj->index < obj->next->index);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Create a new block of IndexedObjects. We will allocate the memory to
|
||||
// store IndexedPool::blockSize IndexedObject and the new Array of block
|
||||
// pointers.
|
||||
// The newly created IndexedObjects will not be initialized.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void IndexedPool<IndexedObject>::allocateAnotherBlock()
|
||||
{
|
||||
void* memory = (void *) malloc((nBlocks + 1) * sizeof(Uint32) + blockSize * sizeof(IndexedObject));
|
||||
|
||||
memcpy(memory, block, nBlocks * sizeof(Uint32));
|
||||
|
||||
block = (IndexedObject **) memory;
|
||||
IndexedObject* objects = (IndexedObject *) &block[nBlocks + 1];
|
||||
|
||||
block[nBlocks] = &objects[-(nBlocks * blockSize)];
|
||||
nBlocks++;
|
||||
}
|
||||
|
||||
// Return the IndexedObject at the position 'index' in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedObject& IndexedPool<IndexedObject>::get(Uint32 index) const
|
||||
{
|
||||
Uint32 blockIndex = index / blockSize;
|
||||
assert(blockIndex < nBlocks);
|
||||
|
||||
return block[blockIndex][index];
|
||||
}
|
||||
|
||||
// Return the reference of an unused object in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedObject& IndexedPool<IndexedObject>::newObject()
|
||||
{
|
||||
if (freeObjects != NULL) {
|
||||
IndexedObject& newObject = *freeObjects;
|
||||
freeObjects = newObject.next;
|
||||
return newObject;
|
||||
}
|
||||
|
||||
Uint32 nextIndex = this->nextIndex++;
|
||||
Uint32 blockIndex = nextIndex / blockSize;
|
||||
|
||||
while (blockIndex >= nBlocks)
|
||||
allocateAnotherBlock();
|
||||
|
||||
IndexedObject& newObject = block[blockIndex][nextIndex];
|
||||
newObject.index = nextIndex;
|
||||
|
||||
return newObject;
|
||||
}
|
||||
|
||||
// Return the address of the next unsused object in the given
|
||||
// indexed pool. The field index of the newly allocated object
|
||||
// will be initialized to the corresponding index of this object
|
||||
// in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void* operator new(size_t size, IndexedPool<IndexedObject>& pool)
|
||||
{
|
||||
assert(size == sizeof(IndexedObject));
|
||||
return (void *) &pool.newObject();
|
||||
}
|
||||
|
||||
#endif // _INDEXED_POOL_H_
|
||||
@@ -1,258 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _INTERFERENCE_GRAPH_H_
|
||||
#define _INTERFERENCE_GRAPH_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "Primitives.h"
|
||||
#include "Instruction.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "SparseSet.h"
|
||||
#include <string.h>
|
||||
|
||||
struct InterferenceVector
|
||||
{
|
||||
Uint32 count;
|
||||
InterferenceVector* next;
|
||||
RegisterName* neighbors;
|
||||
|
||||
InterferenceVector() : count(0), next(NULL) {}
|
||||
};
|
||||
|
||||
class RegisterAllocator;
|
||||
|
||||
template <class RegisterPressure>
|
||||
class InterferenceGraph
|
||||
{
|
||||
private:
|
||||
|
||||
RegisterAllocator& registerAllocator;
|
||||
|
||||
RegisterPressure::Set* interferences;
|
||||
InterferenceVector** vector;
|
||||
Uint32* offset;
|
||||
Uint32 rangeCount;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
InterferenceGraph(const InterferenceGraph&);
|
||||
// No copy operator.
|
||||
void operator = (const InterferenceGraph&);
|
||||
|
||||
// Check if reg is a member of the universe.
|
||||
void checkMember(RegisterName name) {assert(name < rangeCount);}
|
||||
// Return the edge index for the interference between name1 and name2.
|
||||
Uint32 getEdgeIndex(RegisterName name1, RegisterName name2);
|
||||
|
||||
public:
|
||||
InterferenceGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
|
||||
|
||||
// Calculate the interferences.
|
||||
void build();
|
||||
// Return true if reg1 and reg2 interfere.
|
||||
bool interfere(RegisterName name1, RegisterName name2);
|
||||
// Return the interference vector for the given register or NULL if there is none.
|
||||
InterferenceVector* getInterferenceVector(RegisterName name) {return vector[name];}
|
||||
// Set the interference between name1 and name2.
|
||||
void setInterference(RegisterName name1, RegisterName name2);
|
||||
// Set the interference vector for the given register.
|
||||
void setInterferenceVector(RegisterName name, InterferenceVector* v) {vector[name] = v;}
|
||||
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the interferences.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::build()
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
this->rangeCount = rangeCount;
|
||||
|
||||
// Initialize the structures.
|
||||
//
|
||||
offset = new(pool) Uint32[rangeCount + 1];
|
||||
vector = new(pool) InterferenceVector*[rangeCount];
|
||||
memset(vector, '\0', sizeof(InterferenceVector*) * rangeCount);
|
||||
|
||||
Uint32 o = 0;
|
||||
offset[0] = 0;
|
||||
for (Uint32 i = 1; i <= rangeCount; ++i) {
|
||||
offset[i] = o;
|
||||
o += i;
|
||||
}
|
||||
|
||||
interferences = new(pool) RegisterPressure::Set(pool, (rangeCount * rangeCount) / 2);
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
LivenessInfo<RegisterPressure> liveness = Liveness<RegisterPressure>::analysis(controlGraph, rangeCount, name2range);
|
||||
registerAllocator.liveness = liveness;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
currentLive = liveness.liveOut[n];
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
// Handle the copy instruction to avoid unnecessary interference between the 2 registers.
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
|
||||
}
|
||||
|
||||
// Create the interferences.
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName define = name2range[definePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator e = currentLive.begin(); !currentLive.done(e); e = currentLive.advance(e)) {
|
||||
RegisterName live = RegisterName(currentLive.get(e));
|
||||
|
||||
if ((live != define) && !interfere(live, define) && registerAllocator.canInterfere(live, define)) {
|
||||
|
||||
if (vector[define] == NULL)
|
||||
vector[define] = new(pool) InterferenceVector();
|
||||
vector[define]->count++;
|
||||
|
||||
if (vector[live] == NULL)
|
||||
vector[live] = new(pool) InterferenceVector();
|
||||
vector[live]->count++;
|
||||
|
||||
setInterference(live, define);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now update the liveness.
|
||||
//
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
currentLive.set(name2range[usePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the memory to store the interferences.
|
||||
//
|
||||
for (Uint32 e = 0; e < rangeCount; e++)
|
||||
if (vector[e] != NULL) {
|
||||
InterferenceVector& v = *vector[e];
|
||||
v.neighbors = new(pool) RegisterName[v.count];
|
||||
v.count = 0;
|
||||
}
|
||||
|
||||
// Initialize the edges.
|
||||
//
|
||||
if (RegisterPressure::Set::isOrdered()) {
|
||||
RegisterName name1 = RegisterName(0);
|
||||
|
||||
for (RegisterPressure::Set::iterator i = interferences->begin(); !interferences->done(i); i = interferences->advance(i)) {
|
||||
Uint32 interferenceIndex = interferences->get(i);
|
||||
|
||||
while(interferenceIndex >= offset[name1 + 1])
|
||||
name1 = RegisterName(name1 + 1);
|
||||
|
||||
assert((interferenceIndex >= offset[name1]) && (interferenceIndex < offset[name1 + 1]));
|
||||
|
||||
RegisterName name2 = RegisterName(interferenceIndex - offset[name1]);
|
||||
|
||||
assert(interfere(name1, name2));
|
||||
|
||||
InterferenceVector& vector1 = *vector[name1];
|
||||
vector1.neighbors[vector1.count++] = name2;
|
||||
|
||||
InterferenceVector& vector2 = *vector[name2];
|
||||
vector2.neighbors[vector2.count++] = name1;
|
||||
}
|
||||
} else {
|
||||
trespass("not Implemented"); // FIX: need one more pass to initialize the vectors.
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
Uint32 InterferenceGraph<RegisterPressure>::getEdgeIndex(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
checkMember(name1); checkMember(name2);
|
||||
assert(name1 != name2); // This is not possible.
|
||||
return (name1 < name2) ? offset[name2] + name1 : offset[name1] + name2;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::setInterference(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
interferences->set(getEdgeIndex(name1, name2));
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool InterferenceGraph<RegisterPressure>::interfere(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
return interferences->test(getEdgeIndex(name1, name2));
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Vectors:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
if (vector[i] != NULL) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tvr%d: (", i));
|
||||
for (InterferenceVector* v = vector[i]; v != NULL; v = v->next)
|
||||
for (Uint32 j = 0; j < v->count; j++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", v->neighbors[j]));
|
||||
if (v->next != NULL || j != (v->count - 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (","));
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (")\n"));
|
||||
}
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Matrix:\n"));
|
||||
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
|
||||
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && interfere(name1, name2)) ? '1' : '0'));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _INTERFERENCE_GRAPH_H_
|
||||
@@ -1,87 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LIVE_RANGE_H_
|
||||
#define _LIVE_RANGE_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Primitives.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct LiveRange
|
||||
{
|
||||
static void build(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRange<RegisterPressure>::build(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
// Intialize the lookup table.
|
||||
//
|
||||
Uint32 nameCount = registerAllocator.nameCount;
|
||||
RegisterName* nameTable = new(registerAllocator.pool) RegisterName[2*nameCount];
|
||||
RegisterName* rangeName = &nameTable[nameCount];
|
||||
|
||||
init(rangeName, nameCount);
|
||||
|
||||
// Walk the graph.
|
||||
//
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
SparseSet destination(registerAllocator.pool, nameCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
|
||||
destination.clear();
|
||||
for (InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
Instruction& phiNode = phiNodes.get(i);
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
destination.set(findRoot(phiNode.getInstructionDefineBegin()[0].getRegisterName(), rangeName));
|
||||
}
|
||||
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
RegisterName destinationName = phiNode.getInstructionDefineBegin()[0].getRegisterName();
|
||||
RegisterName destinationRoot = findRoot(destinationName, rangeName);
|
||||
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
|
||||
assert(usePtr->isRegister());
|
||||
RegisterName sourceName = usePtr->getRegisterName();
|
||||
RegisterName sourceRoot = findRoot(sourceName, rangeName);
|
||||
|
||||
if (sourceRoot != destinationRoot && !destination.test(sourceRoot))
|
||||
rangeName[sourceRoot] = destinationRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerAllocator.rangeCount = compress(registerAllocator.name2range, rangeName, nameCount, nameCount);
|
||||
}
|
||||
|
||||
#endif // _LIVE_RANGE_H_
|
||||
@@ -1,163 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LIVE_RANGE_GRAPH_
|
||||
#define _LIVE_RANGE_GRAPH_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
class RegisterAllocator;
|
||||
|
||||
template <class RegisterPressure>
|
||||
class LiveRangeGraph
|
||||
{
|
||||
private:
|
||||
|
||||
RegisterAllocator& registerAllocator;
|
||||
|
||||
RegisterPressure::Set* edges;
|
||||
Uint32 rangeCount;
|
||||
|
||||
public:
|
||||
//
|
||||
//
|
||||
LiveRangeGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
|
||||
|
||||
//
|
||||
//
|
||||
void build();
|
||||
|
||||
//
|
||||
//
|
||||
void addEdge(RegisterName name1, RegisterName name2);
|
||||
|
||||
//
|
||||
//
|
||||
bool haveEdge(RegisterName name1, RegisterName name2);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//
|
||||
//
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::build()
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
this->rangeCount = rangeCount;
|
||||
|
||||
edges = new(pool) RegisterPressure::Set(pool, rangeCount * rangeCount);
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
LivenessInfo<RegisterPressure>& liveness = registerAllocator.liveness;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
currentLive = liveness.liveOut[n];
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName define = name2range[definePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
|
||||
RegisterName live = RegisterName(currentLive.get(l));
|
||||
if (define != live && registerAllocator.canInterfere(define, live))
|
||||
addEdge(define, live);
|
||||
}
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
currentLive.set(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName use = name2range[usePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
|
||||
RegisterName live = RegisterName(currentLive.get(l));
|
||||
if (use != live && registerAllocator.canInterfere(use, live))
|
||||
addEdge(use, live);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::addEdge(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
assert(name1 != name2);
|
||||
edges->set(name1 * rangeCount + name2);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool LiveRangeGraph<RegisterPressure>::haveEdge(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
assert(name1 != name2);
|
||||
return edges->test(name1 * rangeCount + name2);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Live ranges graph:\n"));
|
||||
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
|
||||
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && haveEdge(name1, name2)) ? '1' : '0'));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _LIVE_RANGE_GRAPH_
|
||||
@@ -1,301 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LIVENESS_H_
|
||||
#define _LIVENESS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// LivenessInfo -
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct LivenessInfo
|
||||
{
|
||||
RegisterPressure::Set* liveIn;
|
||||
RegisterPressure::Set* liveOut;
|
||||
DEBUG_LOG_ONLY(Uint32 size);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Liveness
|
||||
//
|
||||
// The liveness is defined by the following data-flow equations:
|
||||
//
|
||||
// LiveIn(n) = LocalLive(n) U (LiveOut(n) - Killed(n)).
|
||||
// LiveOut(n) = U LiveIn(s) (s a successor of n).
|
||||
//
|
||||
// where LocalLive(n) is the set of used registers in the block n, Killed(n)
|
||||
// is the set of defined registers in the block n, LiveIn(n) is the set of
|
||||
// live registers at the begining of the block n and LiveOut(n) is the set
|
||||
// of live registers at the end of the block n.
|
||||
//
|
||||
//
|
||||
// We will compute the liveness analysis in two stages:
|
||||
//
|
||||
// 1- Build LocalLive(n) (wich is an approximation of LiveIn(n)) and Killed(n)
|
||||
// for each block n.
|
||||
// 2- Perform a backward data-flow analysis to propagate the liveness information
|
||||
// through the entire control-flow graph.
|
||||
//
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Liveness
|
||||
{
|
||||
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range);
|
||||
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 nameCount);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Allocate the temporary sets.
|
||||
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
|
||||
// Allocate the globals sets.
|
||||
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
|
||||
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
|
||||
//
|
||||
for (Uint32 n = 0; n < (nNodes - 1); n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLocalLive = liveIn[n];
|
||||
RegisterPressure::Set& currentKilled = killed[n];
|
||||
|
||||
// Find the instructions contributions to the sets LocalLive and Killed.
|
||||
//
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
Uint32 index = name2range[usePtr->getRegisterName()];
|
||||
|
||||
if (!currentKilled.test(index))
|
||||
currentLocalLive.set(index);
|
||||
}
|
||||
|
||||
// If a Virtualregister is 'defined' then we add it to the set Killed.
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentKilled.set(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
|
||||
// control-flow graph.
|
||||
//
|
||||
RegisterPressure::Set temp(pool, rangeCount);
|
||||
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
// For all nodes is this graph except the endNode.
|
||||
for (Int32 n = (nNodes - 2); n >= 0; n--) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLiveIn = liveIn[n];
|
||||
RegisterPressure::Set& currentLiveOut = liveOut[n];
|
||||
|
||||
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
|
||||
// temp will be the new LiveOut(n).
|
||||
Uint32 nSuccessors = node.nSuccessors();
|
||||
if (nSuccessors != 0) {
|
||||
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
|
||||
for (Uint32 s = 1; s < nSuccessors; s++)
|
||||
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
|
||||
} else
|
||||
temp.clear();
|
||||
|
||||
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
|
||||
// new LiveIn(n).
|
||||
if (currentLiveOut != temp) {
|
||||
currentLiveOut = temp;
|
||||
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
|
||||
temp |= currentLiveIn;
|
||||
|
||||
if (currentLiveIn != temp) {
|
||||
currentLiveIn = temp;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changed);
|
||||
|
||||
LivenessInfo<RegisterPressure> liveness;
|
||||
liveness.liveIn = liveIn;
|
||||
liveness.liveOut = liveOut;
|
||||
DEBUG_LOG_ONLY(liveness.size = nNodes);
|
||||
return liveness;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 nameCount)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Allocate the temporary sets.
|
||||
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
RegisterPressure::Set* usedByPhiNodes = NULL;
|
||||
|
||||
// Allocate the globals sets.
|
||||
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
|
||||
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
|
||||
//
|
||||
for (Uint32 n = 0; n < (nNodes - 1); n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLocalLive = liveIn[n];
|
||||
RegisterPressure::Set& currentKilled = killed[n];
|
||||
|
||||
InstructionList& phiNodes = node.getPhiNodeInstructions();
|
||||
|
||||
if ((usedByPhiNodes == NULL) && !phiNodes.empty())
|
||||
usedByPhiNodes = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
InstructionDefine& define = phiNode.getInstructionDefineBegin()[0];
|
||||
currentKilled.set(define.getRegisterName());
|
||||
|
||||
typedef DoublyLinkedList<ControlEdge> ControlEdgeList;
|
||||
const ControlEdgeList& predecessors = node.getPredecessors();
|
||||
ControlEdgeList::iterator p = predecessors.begin();
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++, p = predecessors.advance(p))
|
||||
if (usePtr->isRegister())
|
||||
usedByPhiNodes[predecessors.get(p).getSource().dfsNum].set(usePtr->getRegisterName());
|
||||
}
|
||||
|
||||
// Find the instructions contributions to the sets LocalLive and Killed.
|
||||
//
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
Uint32 index = usePtr->getRegisterName();
|
||||
|
||||
if (!currentKilled.test(index))
|
||||
currentLocalLive.set(index);
|
||||
}
|
||||
|
||||
// If a Virtualregister is 'defined' then we add it to the set Killed.
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentKilled.set(definePtr->getRegisterName());
|
||||
}
|
||||
}
|
||||
|
||||
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
|
||||
// control-flow graph.
|
||||
//
|
||||
RegisterPressure::Set temp(pool, nameCount);
|
||||
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
// For all nodes is this graph except the endNode.
|
||||
for (Int32 n = (nNodes - 2); n >= 0; n--) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLiveIn = liveIn[n];
|
||||
RegisterPressure::Set& currentLiveOut = liveOut[n];
|
||||
|
||||
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
|
||||
// temp will be the new LiveOut(n).
|
||||
Uint32 nSuccessors = node.nSuccessors();
|
||||
if (nSuccessors != 0) {
|
||||
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
|
||||
for (Uint32 s = 1; s < nSuccessors; s++)
|
||||
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
|
||||
} else
|
||||
temp.clear();
|
||||
|
||||
// Insert the phiNodes contribution.
|
||||
if (usedByPhiNodes != NULL)
|
||||
temp |= usedByPhiNodes[n];
|
||||
|
||||
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
|
||||
// new LiveIn(n).
|
||||
if (currentLiveOut != temp) {
|
||||
currentLiveOut = temp;
|
||||
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
|
||||
temp |= currentLiveIn;
|
||||
|
||||
if (currentLiveIn != temp) {
|
||||
currentLiveIn = temp;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changed);
|
||||
|
||||
LivenessInfo<RegisterPressure> liveness;
|
||||
liveness.liveIn = liveIn;
|
||||
liveness.liveOut = liveOut;
|
||||
DEBUG_LOG_ONLY(liveness.size = nNodes);
|
||||
return liveness;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void LivenessInfo<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
for (Uint32 n = 0; n < size; n++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Node N%d:\n\tliveIn = ", n));
|
||||
liveIn[n].printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tliveOut = "));
|
||||
liveOut[n].printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _LIVENESS_H_
|
||||
@@ -1,40 +0,0 @@
|
||||
#! gmake
|
||||
|
||||
DEPTH = ../..
|
||||
|
||||
MODULE_NAME = RegisterAllocator
|
||||
|
||||
include $(DEPTH)/config/config.mk
|
||||
|
||||
INCLUDES += \
|
||||
-I$(DEPTH)/Utilities/General \
|
||||
-I$(DEPTH)/Utilities/zlib \
|
||||
-I$(DEPTH)/Runtime/ClassReader \
|
||||
-I$(DEPTH)/Runtime/NativeMethods \
|
||||
-I$(DEPTH)/Runtime/System \
|
||||
-I$(DEPTH)/Runtime/ClassInfo \
|
||||
-I$(DEPTH)/Runtime/FileReader \
|
||||
-I$(DEPTH)/Compiler/PrimitiveGraph \
|
||||
-I$(DEPTH)/Compiler/FrontEnd \
|
||||
-I$(DEPTH)/Compiler/Optimizer \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator/md \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator/md/$(CPU_ARCH) \
|
||||
-I$(DEPTH)/Compiler/RegisterAllocator \
|
||||
-I$(DEPTH)/Driver/StandAloneJava \
|
||||
-I$(DEPTH)/Debugger \
|
||||
$(NULL)
|
||||
|
||||
CXXSRCS = \
|
||||
RegisterAllocator.cpp \
|
||||
RegisterAllocatorTools.cpp \
|
||||
DominatorGraph.cpp \
|
||||
VirtualRegister.cpp \
|
||||
BitSet.cpp \
|
||||
SparseSet.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
libs:: $(MODULE)
|
||||
@@ -1,392 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _PHI_NODE_REMOVER_H_
|
||||
#define _PHI_NODE_REMOVER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "DominatorGraph.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "Liveness.h"
|
||||
#include "Instruction.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "SparseSet.h"
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterNameNode -
|
||||
|
||||
struct RegisterNameNode
|
||||
{
|
||||
RegisterNameNode* next;
|
||||
RegisterName newName;
|
||||
Uint32 nextPushed;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CopyData -
|
||||
|
||||
struct CopyData
|
||||
{
|
||||
RegisterName source;
|
||||
RegisterClassKind classKind;
|
||||
Uint32 useCount;
|
||||
bool isLiveOut;
|
||||
RegisterName sourceNameToUse;
|
||||
RegisterName temporaryName;
|
||||
RegisterNameNode* newName;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// PhiNodeRemover<RegisterPressure> -
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct PhiNodeRemover
|
||||
{
|
||||
// Replace the phi nodes by copy instructions.
|
||||
static void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
};
|
||||
|
||||
// Split some of the critical edges and return true if there are still some
|
||||
// in the graph after that.
|
||||
//
|
||||
static bool splitCriticalEdges(ControlGraph& /*cg*/)
|
||||
{
|
||||
// FIX: not implemented.
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void pushName(Pool& pool, RegisterNameNode** stack, SparseSet& pushed, Uint32* nodeListPointer, RegisterName oldName, RegisterName newName)
|
||||
{
|
||||
RegisterNameNode& newNode = *new(pool) RegisterNameNode();
|
||||
|
||||
if (pushed.test(oldName))
|
||||
(*stack)->newName = newName;
|
||||
else {
|
||||
newNode.newName = newName;
|
||||
newNode.nextPushed = *nodeListPointer;
|
||||
*nodeListPointer = oldName;
|
||||
newNode.next = *stack;
|
||||
*stack = &newNode;
|
||||
pushed.set(oldName);
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void PhiNodeRemover<RegisterPressure>::replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Initialize the local variables.
|
||||
//
|
||||
|
||||
// When we insert the copies we will also need to create new VirtualRegisters for
|
||||
// the insertion of temporaries. The maximum number of temporary register will not
|
||||
// exceed the number of phiNodes in the primitive graph.
|
||||
Uint32 nameCount = vrManager.getSize();
|
||||
Uint32 maxNameCount = nameCount;
|
||||
for (Uint32 n = 0; n < nNodes; n++)
|
||||
maxNameCount += nodes[n]->getPhiNodes().length();
|
||||
|
||||
// If the CFG contains some critical edges (backward edge which source has more than one
|
||||
// outgoing edge and destination has more than one incomimg edge) then we need the liveness
|
||||
// information to be able to insert temporary copies.
|
||||
RegisterPressure::Set* liveOut = NULL;
|
||||
if (splitCriticalEdges(controlGraph))
|
||||
liveOut = Liveness<LowRegisterPressure>::analysis(controlGraph, nameCount).liveOut;
|
||||
|
||||
DominatorGraph dGraph(controlGraph);
|
||||
|
||||
SparseSet pushed(pool, maxNameCount);
|
||||
SparseSet destinationList(pool, maxNameCount);
|
||||
SparseSet workList(pool, maxNameCount);
|
||||
|
||||
CopyData* copyStats = new(pool) CopyData[maxNameCount];
|
||||
memset(copyStats, '\0', maxNameCount*sizeof(CopyData));
|
||||
|
||||
struct NodeStack {
|
||||
Uint32* next;
|
||||
Uint32* limit;
|
||||
Uint32 pushedList;
|
||||
};
|
||||
|
||||
// Allocate the node stack and initialize the node stack pointer.
|
||||
NodeStack* nodeStack = new(pool) NodeStack[nNodes + 1];
|
||||
NodeStack* nodeStackPtr = nodeStack;
|
||||
|
||||
// We start by the begin node.
|
||||
Uint32 startNode = 0;
|
||||
Uint32* next = &startNode;
|
||||
Uint32* limit = &startNode + 1;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (next == limit) {
|
||||
// If there are no more node in the sibling, we have to pop the current
|
||||
// frame from the stack and update the copyStats of the pushed nodes.
|
||||
//
|
||||
if (nodeStackPtr == nodeStack)
|
||||
// We are at the bottom of the stack and there are no more nodes
|
||||
// to look at. We are done !
|
||||
break;
|
||||
|
||||
--nodeStackPtr;
|
||||
// We are done with all the children of this node in the dominator tree.
|
||||
// We need to update the copy information of all the new names pushed
|
||||
// during the walk over this node.
|
||||
Uint32 pushedList = nodeStackPtr->pushedList;
|
||||
while (pushedList != 0) {
|
||||
Uint32 nextName = copyStats[pushedList].newName->nextPushed;
|
||||
copyStats[pushedList].newName = copyStats[pushedList].newName->next;
|
||||
pushedList = nextName;
|
||||
}
|
||||
|
||||
// restore the previous frame.
|
||||
next = nodeStackPtr->next;
|
||||
limit = nodeStackPtr->limit;
|
||||
} else {
|
||||
Uint32 currentNode = *next++;
|
||||
Uint32 pushedList = 0;
|
||||
|
||||
|
||||
// Initialize the sets.
|
||||
pushed.clear();
|
||||
destinationList.clear();
|
||||
|
||||
// STEP1:
|
||||
// Walk the instruction list and to replace all the instruction uses with their new name.
|
||||
// If the instruction is a phi node and its defined register is alive at the end of this
|
||||
// block then we push the defined register into the stack.
|
||||
//
|
||||
ControlNode& node = *nodes[currentNode];
|
||||
RegisterPressure::Set* currentLiveOut = (liveOut != NULL) ? &liveOut[currentNode] : (RegisterPressure::Set*) 0;
|
||||
|
||||
InstructionList& phiNodes = node.getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
|
||||
assert(usePtr->isRegister());
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
|
||||
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
|
||||
usePtr->setRegisterName(copyStats[name].newName->newName);
|
||||
}
|
||||
|
||||
if (currentLiveOut != NULL) {
|
||||
// This is a phi node and we have to push its defined name if it is live
|
||||
// at the end of the node. We only need to do this if the CFG has critical edges.
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
RegisterName name = phiNode.getInstructionDefineBegin()[0].getRegisterName();
|
||||
|
||||
if (currentLiveOut->test(name))
|
||||
pushName(pool, &(copyStats[name].newName), pushed, &pushedList, name, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
|
||||
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
|
||||
usePtr->setRegisterName(copyStats[name].newName->newName);
|
||||
}
|
||||
}
|
||||
|
||||
// STEP2:
|
||||
// Look at this node's successors' phiNodes. We keep track of the number of time
|
||||
// a VR will be used by another copy instruction and insert each definition into the
|
||||
// destinationList. This is the only pass over this node's successors as we will
|
||||
// get all the information we need in the CopyData structures.
|
||||
//
|
||||
ControlEdge* successorEdgeEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorEdgePtr = node.getSuccessorsBegin(); successorEdgePtr < successorEdgeEnd; successorEdgePtr++) {
|
||||
Uint32 useIndex = successorEdgePtr->getIndex();
|
||||
ControlNode& successor = successorEdgePtr->getTarget();
|
||||
|
||||
// Look at its phi nodes. The phi nodes are at the top of the instruction list. We exit
|
||||
// as soon as we find an instruction which is not a phi node
|
||||
InstructionList& phiNodes = successor.getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
assert((phiNode.getInstructionUseBegin() + useIndex) < phiNode.getInstructionUseEnd());
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd());
|
||||
|
||||
InstructionUse& source = phiNode.getInstructionUseBegin()[useIndex];
|
||||
InstructionDefine& destination = phiNode.getInstructionDefineBegin()[0];
|
||||
|
||||
assert(source.isRegister() && destination.isRegister());
|
||||
|
||||
RegisterName sourceName = source.getRegisterName();
|
||||
RegisterName destinationName = destination.getRegisterName();
|
||||
|
||||
// Get the correct name for the source.
|
||||
if (copyStats[sourceName].newName != NULL)
|
||||
sourceName = copyStats[sourceName].newName->newName;
|
||||
|
||||
// Update the CopyData structures.
|
||||
if ((sourceName != rnInvalid) && (sourceName != destinationName)) {
|
||||
copyStats[destinationName].source = sourceName;
|
||||
copyStats[destinationName].classKind = destination.getRegisterClass();
|
||||
copyStats[destinationName].isLiveOut = (currentLiveOut != NULL) ? currentLiveOut->test(destinationName) : false;
|
||||
copyStats[destinationName].sourceNameToUse = destinationName;
|
||||
copyStats[sourceName].sourceNameToUse = sourceName;
|
||||
copyStats[sourceName].useCount++;
|
||||
destinationList.set(destinationName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// STEP3:
|
||||
// Insert into the worklist only the destination registers that will be not used in
|
||||
// another copy instruction in this block.
|
||||
//
|
||||
assert(workList.getSize() == 0);
|
||||
for (SparseSet::iterator d = destinationList.begin(); !destinationList.done(d); d = destinationList.advance(d)) {
|
||||
Uint32 dest = destinationList.get(d);
|
||||
if (copyStats[dest].useCount == 0)
|
||||
workList.set(dest);
|
||||
}
|
||||
|
||||
// STEP4:
|
||||
// Insert the copy instructions.
|
||||
//
|
||||
Uint32 destinationListSize = destinationList.getSize();
|
||||
InstructionList::iterator endOfTheNode = instructions.end();
|
||||
|
||||
// Find the right place to insert the copy instructions.
|
||||
if (destinationListSize != 0)
|
||||
while (instructions.get(endOfTheNode).getFlags() & ifControl)
|
||||
endOfTheNode = instructions.retreat(endOfTheNode);
|
||||
|
||||
while (destinationListSize != 0) {
|
||||
while(workList.getSize()) {
|
||||
RegisterName destinationName = RegisterName(workList.getOne());
|
||||
RegisterName sourceName = copyStats[destinationName].source;
|
||||
|
||||
workList.clear(destinationName);
|
||||
if (copyStats[destinationName].isLiveOut && !copyStats[destinationName].temporaryName) {
|
||||
// Lost copy problem.
|
||||
copyStats[destinationName].isLiveOut = false;
|
||||
|
||||
RegisterName sourceName = destinationName;
|
||||
RegisterClassKind classKind = copyStats[sourceName].classKind;
|
||||
RegisterName destinationName = getName(vrManager.newVirtualRegister(classKind));
|
||||
assert(destinationName < maxNameCount);
|
||||
|
||||
copyStats[destinationName].classKind = classKind;
|
||||
copyStats[sourceName].useCount = 0;
|
||||
|
||||
// We need to insert a copy to a temporary register to keep the
|
||||
// source register valid at the end of the node defining it.
|
||||
// This copy will be inserted right after the phi node defining it.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
Instruction* definingPhiNode = vrManager.getVirtualRegister(from).getDefiningInstruction();
|
||||
assert(definingPhiNode && (definingPhiNode->getFlags() & ifPhiNode) != 0);
|
||||
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*definingPhiNode->getPrimitive(), fromID, toID);
|
||||
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
|
||||
definingPhiNode->getPrimitive()->getContainer()->getInstructions().addFirst(copy);
|
||||
|
||||
copyStats[sourceName].temporaryName = destinationName;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
}
|
||||
|
||||
// Insert the copy instruction at the end of the current node.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
|
||||
RegisterClassKind classKind = copyStats[destinationName].classKind;
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
|
||||
instructions.insertAfter(copy, endOfTheNode);
|
||||
endOfTheNode = instructions.advance(endOfTheNode);
|
||||
|
||||
copyStats[sourceName].useCount = 0;
|
||||
if (destinationList.test(sourceName) && copyStats[sourceName].isLiveOut)
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
copyStats[sourceName].isLiveOut = false;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
|
||||
if (destinationList.test(sourceName))
|
||||
workList.set(sourceName);
|
||||
destinationList.clear(destinationName);
|
||||
}
|
||||
|
||||
destinationListSize = destinationList.getSize();
|
||||
if (destinationListSize != 0) {
|
||||
RegisterName sourceName = RegisterName(destinationList.getOne());
|
||||
RegisterName destinationName;
|
||||
|
||||
if (!copyStats[sourceName].temporaryName) {
|
||||
// Cycle problem.
|
||||
RegisterClassKind classKind = copyStats[sourceName].classKind;
|
||||
destinationName = getName(vrManager.newVirtualRegister(classKind));
|
||||
assert(destinationName < maxNameCount);
|
||||
|
||||
copyStats[destinationName].classKind = classKind;
|
||||
copyStats[sourceName].temporaryName = destinationName;
|
||||
|
||||
// Insert the copy instruction at the end of the current node.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
|
||||
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
|
||||
instructions.insertAfter(copy, endOfTheNode);
|
||||
endOfTheNode = instructions.advance(endOfTheNode);
|
||||
} else
|
||||
destinationName = copyStats[sourceName].temporaryName;
|
||||
|
||||
copyStats[sourceName].useCount = 0;
|
||||
copyStats[sourceName].isLiveOut = false;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
|
||||
workList.set(sourceName);
|
||||
}
|
||||
}
|
||||
|
||||
nodeStackPtr->pushedList = pushedList;
|
||||
nodeStackPtr->next = next;
|
||||
nodeStackPtr->limit = limit;
|
||||
++nodeStackPtr;
|
||||
next = dGraph.getSuccessorsBegin(currentNode);
|
||||
limit = dGraph.getSuccessorsEnd(currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _PHI_NODE_REMOVER_H_
|
||||
@@ -1,155 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "PhiNodeRemover.h"
|
||||
#include "LiveRange.h"
|
||||
#include "Liveness.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "LiveRangeGraph.h"
|
||||
#include "Coalescing.h"
|
||||
#include "Spilling.h"
|
||||
#include "Coloring.h"
|
||||
#include "Splits.h"
|
||||
|
||||
class Pool;
|
||||
class ControlGraph;
|
||||
class VirtualRegisterManager;
|
||||
class InstructionEmitter;
|
||||
|
||||
UT_DEFINE_LOG_MODULE(RegAlloc);
|
||||
|
||||
void RegisterAllocator::allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
{
|
||||
// Insert the phi node instructions. We want to do this to have a single defined register per instruction.
|
||||
// If we keep the PhiNode (as a DataNode) and a PhiNode is of DoubleWordKind then we have to execute
|
||||
// some special code for the high word annotation.
|
||||
//
|
||||
RegisterAllocatorTools::insertPhiNodeInstructions(controlGraph, emitter);
|
||||
|
||||
// Perform some tests on the instruction graph.
|
||||
//
|
||||
DEBUG_ONLY(RegisterAllocatorTools::testTheInstructionGraph(controlGraph, vrManager));
|
||||
|
||||
// Replace the phi node instructions by their equivalent copy instructions.
|
||||
//
|
||||
PhiNodeRemover<LowRegisterPressure>::replacePhiNodes(controlGraph, vrManager, emitter);
|
||||
|
||||
// Do the register allocation.
|
||||
//
|
||||
RegisterAllocator registerAllocator(pool, controlGraph, vrManager, emitter);
|
||||
registerAllocator.doGraphColoring();
|
||||
}
|
||||
|
||||
void RegisterAllocator::doGraphColoring()
|
||||
{
|
||||
// Initialize the liverange map.
|
||||
//
|
||||
initLiveRanges();
|
||||
|
||||
// Build the live ranges. We do this to compress the number of RegisterNames
|
||||
// used in the insterference graph.
|
||||
//
|
||||
LiveRange<LowRegisterPressure>::build(*this);
|
||||
|
||||
// Remove unnecessary copies.
|
||||
//
|
||||
RegisterAllocatorTools::removeUnnecessaryCopies(*this);
|
||||
|
||||
for (Uint8 loop = 0; loop < 10; loop++) {
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********* RegisterAllocator loop %d *********\n", loop));
|
||||
|
||||
while(true) {
|
||||
// Build the interference graph.
|
||||
//
|
||||
iGraph.build();
|
||||
|
||||
// Coalesce the copy instructions.
|
||||
//
|
||||
if (!Coalescing<LowRegisterPressure>::coalesce(*this))
|
||||
break;
|
||||
}
|
||||
|
||||
// Print the interference graph.
|
||||
//
|
||||
DEBUG_LOG_ONLY(iGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
|
||||
|
||||
// Calculate the spill costs.
|
||||
//
|
||||
Spilling<LowRegisterPressure>::calculateSpillCosts(*this);
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSpillCosts(*this));
|
||||
|
||||
// Calculate the split costs.
|
||||
//
|
||||
Splits<LowRegisterPressure>::calculateSplitCosts(*this);
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSplitCosts(*this));
|
||||
|
||||
// Build the live range graph.
|
||||
//
|
||||
lGraph.build();
|
||||
DEBUG_LOG_ONLY(lGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
|
||||
|
||||
// Color the graph. If it succeeds then we're done with the
|
||||
// register allocation.
|
||||
//
|
||||
if (Coloring<LowRegisterPressure>::color(*this)) {
|
||||
// Write the final colors in the instruction graph.
|
||||
//
|
||||
Coloring<LowRegisterPressure>::finalColoring(*this);
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********** RegisterAllocator done **********\n"));
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printInstructions(*this));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to spill some registers.
|
||||
//
|
||||
Spilling<LowRegisterPressure>::insertSpillCode(*this);
|
||||
|
||||
// Insert the split instructions.
|
||||
//
|
||||
Splits<LowRegisterPressure>::insertSplitCode(*this);
|
||||
|
||||
// Update the live ranges.
|
||||
//
|
||||
// FIX
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
RegisterAllocatorTools::updateInstructionGraph(*this);
|
||||
RegisterAllocatorTools::printInstructions(*this);
|
||||
#endif
|
||||
fprintf(stderr, "!!! Coloring failed after 10 loops !!!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
void RegisterAllocator::initLiveRanges()
|
||||
{
|
||||
Uint32 count = this->nameCount;
|
||||
RegisterName* name2range = new(pool) RegisterName[nameCount];
|
||||
for (RegisterName r = RegisterName(1); r < count; r = RegisterName(r + 1))
|
||||
name2range[r] = r;
|
||||
this->name2range = name2range;
|
||||
rangeCount = count;
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_ALLOCATOR_H_
|
||||
#define _REGISTER_ALLOCATOR_H_
|
||||
|
||||
class Pool;
|
||||
class ControlGraph;
|
||||
class InstructionEmitter;
|
||||
struct SpillCost;
|
||||
struct SplitCost;
|
||||
|
||||
#include "Liveness.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h" // This should included by Backend.cpp
|
||||
#include "InterferenceGraph.h"
|
||||
#include "LiveRangeGraph.h"
|
||||
|
||||
//template <class RegisterPressure>
|
||||
class RegisterAllocator
|
||||
{
|
||||
public:
|
||||
|
||||
Pool& pool; //
|
||||
ControlGraph& controlGraph; //
|
||||
VirtualRegisterManager& vrManager; //
|
||||
InstructionEmitter& emitter; //
|
||||
|
||||
RegisterName* name2range; //
|
||||
RegisterName* color; //
|
||||
SpillCost* spillCost; //
|
||||
SparseSet* willSpill; //
|
||||
SplitCost* splitCost; //
|
||||
NameLinkedList** splitAround; //
|
||||
InterferenceGraph<LowRegisterPressure> iGraph; //
|
||||
LiveRangeGraph<LowRegisterPressure> lGraph; //
|
||||
LivenessInfo<LowRegisterPressure> liveness; //
|
||||
Uint32 nameCount; //
|
||||
Uint32 rangeCount; //
|
||||
bool splitFound; //
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
//
|
||||
void doGraphColoring();
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
//
|
||||
inline RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
|
||||
//
|
||||
//
|
||||
bool canInterfere(RegisterName /*name1*/, RegisterName /*name2*/) const {return true;}
|
||||
|
||||
//
|
||||
//
|
||||
void initLiveRanges();
|
||||
|
||||
//
|
||||
//
|
||||
static void allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
inline RegisterAllocator::RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
: pool(pool), controlGraph(controlGraph), vrManager(vrManager), emitter(emitter), iGraph(*this), lGraph(*this), nameCount(vrManager.getSize()) {}
|
||||
|
||||
#endif // _REGISTER_ALLOCATOR_H_
|
||||
|
||||
@@ -1,355 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Primitives.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "Spilling.h"
|
||||
#include "Splits.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
#ifdef DEBUG
|
||||
void RegisterAllocatorTools::testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
|
||||
{
|
||||
// Test the declared VirtualRegisters. The register allocator tries to condense the register universe.
|
||||
// Any gap in the VirtualRegister names will be a loss of efficiency !!!!
|
||||
|
||||
Uint32 nameCount = vrManager.getSize();
|
||||
BitSet registerSeen(controlGraph.pool, nameCount);
|
||||
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
registerSeen.set(usePtr->getRegisterName());
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
registerSeen.set(definePtr->getRegisterName());
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
registerSeen.set(usePtr->getRegisterName());
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
registerSeen.set(definePtr->getRegisterName());
|
||||
}
|
||||
}
|
||||
|
||||
bool renameRegisters = false;
|
||||
for (BitSet::iterator i = registerSeen.nextZero(0); !registerSeen.done(i); i = registerSeen.nextZero(i)) {
|
||||
renameRegisters = true;
|
||||
fprintf(stderr,
|
||||
"WARNING: The VirtualRegister vr%d has been allocated during CodeGeneration but\n"
|
||||
" is never used nor defined by any instruction in the instruction graph\n"
|
||||
" PLEASE FIX \n",
|
||||
i);
|
||||
}
|
||||
if (renameRegisters) {
|
||||
Instruction** definingInstruction = new Instruction*[nameCount];
|
||||
memset(definingInstruction, '\0', nameCount * sizeof(Instruction*));
|
||||
RegisterName* newName = new RegisterName[nameCount];
|
||||
memset(newName, '\0', nameCount * sizeof(RegisterName));
|
||||
RegisterName nextName = RegisterName(1);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
usePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName name = definePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
definePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
usePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName name = definePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
definePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vrManager.setSize(nextName);
|
||||
|
||||
for (RegisterName r = RegisterName(1); r < nextName; r = RegisterName(r + 1))
|
||||
vrManager.getVirtualRegister(r).definingInstruction = definingInstruction[r];
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("RegisterMap:\n"));
|
||||
for (Uint32 i = 1; i < nameCount; i++)
|
||||
if (newName[i] != 0)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d becomes vr%d.\n", i, newName[i]));
|
||||
else
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d is dead.\n", i));
|
||||
|
||||
|
||||
delete newName;
|
||||
delete definingInstruction;
|
||||
}
|
||||
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
void RegisterAllocatorTools::removeUnnecessaryCopies(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i);) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
i = instructions.advance(i);
|
||||
|
||||
if (instruction.getFlags() & ifCopy) {
|
||||
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
|
||||
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
|
||||
|
||||
RegisterName source = name2range[instruction.getInstructionUseBegin()[0].getRegisterName()];
|
||||
RegisterName destination = name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()];
|
||||
|
||||
if (source == destination)
|
||||
instruction.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllocatorTools::updateInstructionGraph(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllocatorTools::insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
DoublyLinkedList<PhiNode>& phiNodes = node.getPhiNodes();
|
||||
|
||||
if (!phiNodes.empty()) {
|
||||
|
||||
// Set the index of the incoming edges.
|
||||
Uint32 index = 0;
|
||||
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
|
||||
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p))
|
||||
predecessors.get(p).setIndex(index++);
|
||||
|
||||
// Insert the phi node instruction in the instruction list.
|
||||
for (DoublyLinkedList<PhiNode>::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
PhiNode& phiNode = phiNodes.get(i);
|
||||
ValueKind kind = phiNode.getKind();
|
||||
|
||||
if (!isStorableKind(kind))
|
||||
continue;
|
||||
|
||||
RegisterClassKind classKind = rckGeneral; // FIX: get class kind from phi node kind.
|
||||
Uint32 nInputs = phiNode.nInputs();
|
||||
|
||||
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
|
||||
|
||||
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drLow);
|
||||
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
|
||||
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drLow);
|
||||
|
||||
node.addPhiNodeInstruction(phiNodeInstruction);
|
||||
|
||||
if (isDoublewordKind(kind)) {
|
||||
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
|
||||
|
||||
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drHigh);
|
||||
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
|
||||
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drHigh);
|
||||
|
||||
node.addPhiNodeInstruction(phiNodeInstruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
void RegisterAllocatorTools::printSpillCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
SpillCost* cost = registerAllocator.spillCost;
|
||||
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Spill costs:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : ", i));
|
||||
if (cost[i].infinite)
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("infinite\n"));
|
||||
else
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%f\n", cost[i].cost));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAllocatorTools::printSplitCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
SplitCost* cost = registerAllocator.splitCost;
|
||||
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Split costs:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : loads = %f stores = %f\n", i, cost[i].loads, cost[i].stores));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAllocatorTools::printInstructions(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
ControlNode** nodes = registerAllocator.controlGraph.dfsList;
|
||||
Uint32 nNodes = registerAllocator.controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d:\n", n));
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
if (!phiNodes.empty()) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" PhiNodes:\n", n));
|
||||
for(InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
phiNodes.get(i).printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
if (!instructions.empty())
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" Instructions:\n", n));
|
||||
}
|
||||
|
||||
for(InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
instructions.get(i).printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
@@ -1,117 +0,0 @@
|
||||
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
|
||||
//
|
||||
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
|
||||
// NETSCAPE COMMUNICATIONS CORPORATION
|
||||
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
|
||||
// Reserved. Use of this Source Code is subject to the terms of the
|
||||
// applicable license agreement from Netscape Communications Corporation.
|
||||
// The copyright notice(s) in this Source Code does not indicate actual or
|
||||
// intended publication of this Source Code.
|
||||
//
|
||||
// $Id: RegisterAllocatorTools.h,v 1.1.2.1 1999-03-02 16:12:05 fur%netscape.com Exp $
|
||||
//
|
||||
|
||||
#ifndef _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
#define _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
|
||||
#include "LogModule.h"
|
||||
#include "RegisterTypes.h"
|
||||
#include <string.h>
|
||||
|
||||
class RegisterAllocator;
|
||||
class ControlGraph;
|
||||
class InstructionEmitter;
|
||||
class VirtualRegisterManager;
|
||||
|
||||
struct RegisterAllocatorTools
|
||||
{
|
||||
//
|
||||
//
|
||||
static void insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter);
|
||||
|
||||
//
|
||||
//
|
||||
static void updateInstructionGraph(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void removeUnnecessaryCopies(RegisterAllocator& registerAllocator);
|
||||
|
||||
#ifdef DEBUG
|
||||
//
|
||||
//
|
||||
static void testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
|
||||
#endif // DEBUG
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//
|
||||
//
|
||||
static void printInstructions(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void printSpillCosts(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void printSplitCosts(RegisterAllocator& registerAllocator);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
//
|
||||
// FIX: this should go in a class (LookupTable ?)
|
||||
//
|
||||
|
||||
inline RegisterName findRoot(RegisterName name, RegisterName* table)
|
||||
{
|
||||
RegisterName* stack = table;
|
||||
RegisterName* stackPtr = stack;
|
||||
|
||||
RegisterName newName;
|
||||
while((newName = table[name]) != name) {
|
||||
*--stackPtr = name;
|
||||
name = newName;
|
||||
}
|
||||
|
||||
while (stackPtr != stack)
|
||||
table[*stackPtr++] = name;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
inline void init(RegisterName* table, Uint32 nameCount)
|
||||
{
|
||||
for (RegisterName r = RegisterName(0); r < nameCount; r = RegisterName(r + 1))
|
||||
table[r] = r;
|
||||
}
|
||||
|
||||
inline Uint32 compress(RegisterName* name2range, RegisterName* table, Uint32 nameCount, Uint32 tableSize)
|
||||
{
|
||||
RegisterName* liveRange = new RegisterName[tableSize];
|
||||
memset(liveRange, '\0', tableSize * sizeof(RegisterName));
|
||||
|
||||
// Update the lookup table.
|
||||
for (RegisterName r = RegisterName(1); r < tableSize; r = RegisterName(r + 1))
|
||||
findRoot(r, table);
|
||||
|
||||
// Count the liveranges.
|
||||
Uint32 liveRangeCount = 1;
|
||||
for (RegisterName s = RegisterName(1); s < tableSize; s = RegisterName(s + 1))
|
||||
if (table[s] == s)
|
||||
liveRange[s] = RegisterName(liveRangeCount++);
|
||||
|
||||
for (RegisterName t = RegisterName(1); t < nameCount; t = RegisterName(t + 1))
|
||||
name2range[t] = liveRange[table[name2range[t]]];
|
||||
|
||||
return liveRangeCount;
|
||||
}
|
||||
|
||||
inline double doLog10(Uint32 power)
|
||||
{
|
||||
double log = 1.0;
|
||||
while (power--)
|
||||
log *= 10.0;
|
||||
return log;
|
||||
}
|
||||
|
||||
#endif // _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
@@ -1,104 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_TYPES_H_
|
||||
#define _REGISTER_TYPES_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterName -
|
||||
//
|
||||
|
||||
enum RegisterName {
|
||||
rnInvalid = 0,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterClassKind -
|
||||
//
|
||||
|
||||
enum RegisterClassKind {
|
||||
rckInvalid = 0,
|
||||
rckGeneral,
|
||||
rckStackSlot,
|
||||
|
||||
nRegisterClassKind
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterID -
|
||||
//
|
||||
|
||||
enum RegisterID {
|
||||
invalidID = 0
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterKind -
|
||||
//
|
||||
|
||||
enum RegisterKind {
|
||||
rkCallerSave = 0,
|
||||
rkCalleeSave,
|
||||
};
|
||||
|
||||
struct NameLinkedList {
|
||||
RegisterName name;
|
||||
NameLinkedList* next;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
const registerNameMask = 0x03ffffff;
|
||||
const coloredRegisterMask = 0x04000000;
|
||||
const machineRegisterMask = 0x08000000;
|
||||
const registerClassMask = 0xf0000000;
|
||||
|
||||
const registerNameShift = 0;
|
||||
const coloredRegisterShift = 26;
|
||||
const machineRegisterShift = 27;
|
||||
const registerClassShift = 28;
|
||||
|
||||
#else // DEBUG
|
||||
|
||||
const registerNameMask = 0x0fffffff;
|
||||
const registerClassMask = 0xf0000000;
|
||||
|
||||
const registerNameShift = 0;
|
||||
const registerClassShift = 28;
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
inline RegisterClassKind getClass(RegisterID registerID) {return RegisterClassKind((registerID & registerClassMask) >> registerClassShift);}
|
||||
inline RegisterName getName(RegisterID registerID) {return RegisterName((registerID & registerNameMask) >> registerNameShift);}
|
||||
inline void setClass(RegisterID& registerID, RegisterClassKind classKind) {registerID = RegisterID((registerID & ~registerClassMask) | ((classKind << registerClassShift) & registerClassMask));}
|
||||
inline void setName(RegisterID& registerID, RegisterName name) {assert((name & ~registerNameMask) == 0); registerID = RegisterID((registerID & ~registerNameMask) | ((name << registerNameShift) & registerNameMask));}
|
||||
inline RegisterID buildRegisterID(RegisterName name, RegisterClassKind classKind) {return RegisterID(((classKind << registerClassShift) & registerClassMask) | ((name << registerNameShift) & registerNameMask));}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
inline bool isMachineRegister(RegisterID rid) {return (rid & machineRegisterMask) != 0;}
|
||||
inline void setMachineRegister(RegisterID& rid) {rid = RegisterID(rid | machineRegisterMask);}
|
||||
inline bool isColoredRegister(RegisterID rid) {return (rid & coloredRegisterMask) != 0;}
|
||||
inline void setColoredRegister(RegisterID& rid) {rid = RegisterID(rid | coloredRegisterMask);}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
#endif // _REGISTER_TYPES_H_
|
||||
@@ -1,168 +0,0 @@
|
||||
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
|
||||
//
|
||||
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
|
||||
// NETSCAPE COMMUNICATIONS CORPORATION
|
||||
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
|
||||
// Reserved. Use of this Source Code is subject to the terms of the
|
||||
// applicable license agreement from Netscape Communications Corporation.
|
||||
// The copyright notice(s) in this Source Code does not indicate actual or
|
||||
// intended publication of this Source Code.
|
||||
//
|
||||
// $Id: SparseSet.h,v 1.1.2.1 1999-03-02 16:12:07 fur%netscape.com Exp $
|
||||
//
|
||||
|
||||
#ifndef _SPARSE_SET_H_
|
||||
#define _SPARSE_SET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "LogModule.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
class SparseSet
|
||||
{
|
||||
private:
|
||||
|
||||
struct Node {
|
||||
Uint32 element;
|
||||
Uint32 stackIndex;
|
||||
};
|
||||
|
||||
Node* node;
|
||||
Uint32 count;
|
||||
Uint32 universeSize;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
SparseSet(const SparseSet&);
|
||||
|
||||
// Check if the given set's universe is of the same size than this universe.
|
||||
void checkUniverseCompatibility(const SparseSet& set) const {assert(set.universeSize == universeSize);}
|
||||
// Check if pos is valid for this set's universe.
|
||||
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
|
||||
|
||||
public:
|
||||
|
||||
SparseSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {node = new(pool) Node[universeSize]; clear();}
|
||||
|
||||
// Clear the sparse set.
|
||||
void clear() {count = 0;}
|
||||
// Clear the element at index.
|
||||
inline void clear(Uint32 index);
|
||||
// Set the element at index.
|
||||
inline void set(Uint32 index);
|
||||
// Return true if the element at index is set.
|
||||
inline bool test(Uint32 index) const;
|
||||
// Union with the given sparse set.
|
||||
inline void or(const SparseSet& set);
|
||||
// Intersection with the given sparse set.
|
||||
inline void and(const SparseSet& set);
|
||||
// Difference with the given sparse set.
|
||||
inline void difference(const SparseSet& set);
|
||||
// Copy set.
|
||||
inline SparseSet& operator = (const SparseSet& set);
|
||||
inline SparseSet& operator = (const BitSet& set);
|
||||
// Return true if the sparse sets are identical.
|
||||
friend bool operator == (const SparseSet& set1, const SparseSet& set2);
|
||||
// Return true if the sparse sets are different.
|
||||
friend bool operator != (const SparseSet& set1, const SparseSet& set2);
|
||||
|
||||
// Logical operators.
|
||||
SparseSet& operator |= (const SparseSet& set) {or(set); return *this;}
|
||||
SparseSet& operator &= (const SparseSet& set) {and(set); return *this;}
|
||||
SparseSet& operator -= (const SparseSet& set) {difference(set); return *this;}
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef Int32 iterator;
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const {return count - 1;}
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const {return --pos;}
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos < 0;}
|
||||
// Return the element for the given iterator;
|
||||
Uint32 get(iterator pos) const {return node[pos].element;}
|
||||
// Return one element of this set.
|
||||
Uint32 getOne() const {assert(count > 0); return node[0].element;}
|
||||
// Return the size of this set.
|
||||
Uint32 getSize() const {return count;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
inline void SparseSet::clear(Uint32 element)
|
||||
{
|
||||
checkMember(element);
|
||||
Uint32 count = this->count;
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
|
||||
if ((stackIndex < count) && (node[stackIndex].element == element)) {
|
||||
Uint32 stackTop = node[count - 1].element;
|
||||
|
||||
node[stackIndex].element = stackTop;
|
||||
node[stackTop].stackIndex = stackIndex;
|
||||
this->count = count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SparseSet::set(Uint32 element)
|
||||
{
|
||||
checkMember(element);
|
||||
Uint32 count = this->count;
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
|
||||
if ((stackIndex >= count) || (node[stackIndex].element != element)) {
|
||||
node[count].element = element;
|
||||
node[element].stackIndex = count;
|
||||
this->count = count + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool SparseSet::test(Uint32 element) const
|
||||
{
|
||||
checkMember(element);
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
return ((stackIndex < count) && (node[stackIndex].element == element));
|
||||
}
|
||||
|
||||
inline SparseSet& SparseSet::operator = (const SparseSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Uint32 sourceCount = set.getSize();
|
||||
Node* node = this->node;
|
||||
|
||||
memcpy(node, set.node, sourceCount * sizeof(Node));
|
||||
|
||||
for (Uint32 i = 0; i < sourceCount; i++) {
|
||||
Uint32 element = node[i].element;
|
||||
node[element].stackIndex = i;
|
||||
}
|
||||
|
||||
count = sourceCount;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline SparseSet& SparseSet::operator = (const BitSet& set)
|
||||
{
|
||||
// FIX: there's room for optimization here.
|
||||
assert(universeSize == set.getSize());
|
||||
|
||||
clear();
|
||||
for (Int32 i = set.firstOne(); i != -1; i = set.nextOne(i))
|
||||
this->set(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // _SPARSE_SET_H_
|
||||
@@ -1,270 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef NEW_LAURENTM_CODE
|
||||
#define INCLUDE_EMITTER
|
||||
#include "CpuInfo.h"
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "Spilling.h"
|
||||
|
||||
|
||||
void Spilling::
|
||||
insertSpillCode(ControlNode** dfsList, Uint32 nNodes)
|
||||
{
|
||||
PRUint32 nVirtualRegisters = vRegManager.count();
|
||||
FastBitSet currentLive(vRegManager.pool, nVirtualRegisters);
|
||||
FastBitSet usedInThisInstruction(vRegManager.pool, nVirtualRegisters);
|
||||
RegisterFifo grNeedLoad(nVirtualRegisters);
|
||||
RegisterFifo fpNeedLoad(nVirtualRegisters);
|
||||
|
||||
for (PRInt32 n = nNodes - 1; n >= 0; n--)
|
||||
{
|
||||
PR_ASSERT(grNeedLoad.empty() & fpNeedLoad.empty());
|
||||
ControlNode& node = *dfsList[n];
|
||||
|
||||
currentLive = node.liveAtEnd;
|
||||
|
||||
PRUint32 nGeneralAlive = 0;
|
||||
PRUint32 nFloatingPointAlive = 0;
|
||||
|
||||
// Get the number of registers alive at the end of this node.
|
||||
for (PRInt32 j = currentLive.firstOne(); j != -1; j = currentLive.nextOne(j))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(j);
|
||||
if (vReg.spillInfo.willSpill)
|
||||
{
|
||||
currentLive.clear(j);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive++;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if(node.dfsNum == 8) printf("\n________Begin Node %d________\n", node.dfsNum);
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i))
|
||||
{
|
||||
Instruction& instruction = instructions.get(i);
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* defPtr;
|
||||
|
||||
// if(node.dfsNum == 8) { printf("\n");
|
||||
// instruction.printPretty(stdout);
|
||||
// printf("\n"); }
|
||||
|
||||
// Handle definitions
|
||||
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
||||
if (defPtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
||||
currentLive.clear(vReg.getRegisterIndex());
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive--;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for deaths
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
||||
if (!currentLive.test(vReg.getRegisterIndex()))
|
||||
// This is the last use of this register.
|
||||
{
|
||||
currentLive.set(vReg.getRegisterIndex());
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive++;
|
||||
while (/*(nGeneralAlive > NUMBER_OF_GREGISTERS) &&*/ !grNeedLoad.empty())
|
||||
{
|
||||
PRUint32 toLoad = grNeedLoad.get();
|
||||
currentLive.clear(toLoad);
|
||||
nGeneralAlive--;
|
||||
|
||||
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
||||
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
||||
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
||||
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
||||
nReg.releaseSelf();
|
||||
}
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive++;
|
||||
while (/*(nFloatingPointAlive > NUMBER_OF_FPREGISTERS) &&*/ !fpNeedLoad.empty())
|
||||
{
|
||||
PRUint32 toLoad = fpNeedLoad.get();
|
||||
currentLive.clear(toLoad);
|
||||
nFloatingPointAlive--;
|
||||
|
||||
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
||||
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
||||
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
||||
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
||||
nReg.releaseSelf();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle uses
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
||||
PRUint32 registerIndex = vReg.getRegisterIndex();
|
||||
|
||||
if (vReg.spillInfo.willSpill) {
|
||||
#if defined(GENERATE_FOR_X86)
|
||||
if (!instruction.switchUseToSpill((usePtr - useBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
||||
#endif
|
||||
{
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
if (!grNeedLoad.test(registerIndex))
|
||||
{
|
||||
grNeedLoad.put(registerIndex);
|
||||
VirtualRegister& alias = vRegManager.newVirtualRegister(vrcInteger);
|
||||
if (vReg.isPreColored())
|
||||
alias.preColorRegister(vReg.getPreColor());
|
||||
/* if (vReg.hasSpecialInterference) {
|
||||
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
||||
alias.specialInterference = vReg.specialInterference;
|
||||
alias.hasSpecialInterference = true;
|
||||
} */
|
||||
vReg.setAlias(alias);
|
||||
vReg.retainSelf();
|
||||
}
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
if (!fpNeedLoad.test(registerIndex))
|
||||
{
|
||||
fpNeedLoad.put(registerIndex);
|
||||
VirtualRegister& alias = vRegManager.newVirtualRegister(vReg.getClass());
|
||||
if (vReg.isPreColored())
|
||||
alias.preColorRegister(vReg.getPreColor());
|
||||
/*if (vReg.hasSpecialInterference) {
|
||||
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
||||
alias.specialInterference = vReg.specialInterference;
|
||||
alias.hasSpecialInterference = true;
|
||||
} */
|
||||
vReg.setAlias(alias);
|
||||
vReg.retainSelf();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
usePtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
||||
usedInThisInstruction.set(registerIndex);
|
||||
vReg.spillInfo.lastUsingInstruction = &instruction;
|
||||
}
|
||||
currentLive.clear(registerIndex);
|
||||
} else { // will not spill
|
||||
currentLive.set(registerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle definitions
|
||||
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
||||
if (defPtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
||||
|
||||
if (vReg.spillInfo.willSpill)
|
||||
#if defined(GENERATE_FOR_X86)
|
||||
if (!instruction.switchDefineToSpill((defPtr - defBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
||||
#endif
|
||||
{
|
||||
if (usedInThisInstruction.test(vReg.getRegisterIndex()))
|
||||
// this virtualRegister was used in this instruction and is also defined. We need to move
|
||||
// this virtual register to its alias first and then save it to memory.
|
||||
{
|
||||
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
||||
vReg.getAlias(), *vReg.equivalentRegister[vrcStackSlot]);
|
||||
defPtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
||||
}
|
||||
else
|
||||
{
|
||||
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
||||
vReg, *vReg.equivalentRegister[vrcStackSlot]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!grNeedLoad.empty())
|
||||
{
|
||||
PRUint32 nl = grNeedLoad.get();
|
||||
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
||||
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
||||
|
||||
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
||||
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
||||
nlReg.releaseSelf();
|
||||
}
|
||||
while (!fpNeedLoad.empty())
|
||||
{
|
||||
PRUint32 nl = fpNeedLoad.get();
|
||||
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
||||
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
||||
|
||||
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
||||
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
||||
nlReg.releaseSelf();
|
||||
}
|
||||
|
||||
// if(node.dfsNum == 8) printf("\n________End Node %d________\n", node.dfsNum);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,269 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SPILLING_H_
|
||||
#define _SPILLING_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "SparseSet.h"
|
||||
|
||||
template <class RegisterPressure>
|
||||
class Spilling
|
||||
{
|
||||
private:
|
||||
static void insertStoreAfter(Instruction& instruction, RegisterName name);
|
||||
static void insertLoadBefore(Instruction& instruction, RegisterName name);
|
||||
|
||||
public:
|
||||
static void calculateSpillCosts(RegisterAllocator& registerAllocator);
|
||||
static void insertSpillCode(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
struct SpillCost
|
||||
{
|
||||
double loads;
|
||||
double stores;
|
||||
double copies;
|
||||
double cost;
|
||||
bool infinite;
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertSpillCode(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
SparseSet needLoad(pool, rangeCount);
|
||||
SparseSet mustSpill(pool, rangeCount);
|
||||
SparseSet& willSpill = *registerAllocator.willSpill;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
needLoad.clear();
|
||||
currentLive = liveOut[n];
|
||||
mustSpill = currentLive;
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i);) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
i = instructions.retreat(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
bool foundLiveDefine = false;
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
if (currentLive.test(name2range[definePtr->getRegisterName()])) {
|
||||
foundLiveDefine = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
foundLiveDefine = true;
|
||||
break;
|
||||
}
|
||||
if (defineBegin != defineEnd && !foundLiveDefine) {
|
||||
fprintf(stderr, "!!! Removed instruction because it was only defining unused registers !!!\n");
|
||||
instruction.remove();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName range = name2range[definePtr->getRegisterName()];
|
||||
#ifdef DEBUG
|
||||
if (needLoad.test(range))
|
||||
if (!mustSpill.test(range) && registerAllocator.spillCost[range].infinite && willSpill.test(range)) {
|
||||
fprintf(stderr, "Tried to spill a register with infinite spill cost\n");
|
||||
abort();
|
||||
}
|
||||
#endif // DEBUG
|
||||
if (willSpill.test(range))
|
||||
insertStoreAfter(instruction, range);
|
||||
|
||||
needLoad.clear(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy)
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
if (!currentLive.test(range))
|
||||
for (SparseSet::iterator r = needLoad.begin(); !needLoad.done(r); r = needLoad.advance(r)) {
|
||||
RegisterName load = RegisterName(needLoad.get(r));
|
||||
if (willSpill.test(load))
|
||||
insertLoadBefore(instruction, load);
|
||||
mustSpill.set(load);
|
||||
}
|
||||
needLoad.clear();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
currentLive.set(range);
|
||||
needLoad.set(range);
|
||||
}
|
||||
}
|
||||
|
||||
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
|
||||
RegisterName load = RegisterName(needLoad.get(l));
|
||||
if (willSpill.test(load))
|
||||
insertLoadBefore(instructions.first(), load);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertLoadBefore(Instruction& /*instruction*/, RegisterName name)
|
||||
{
|
||||
fprintf(stdout, "will insert load for range %d\n", name);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertStoreAfter(Instruction& /*instruction*/, RegisterName name)
|
||||
{
|
||||
fprintf(stdout, "will insert store for range %d\n", name);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::calculateSpillCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet live(pool, rangeCount);
|
||||
SparseSet needLoad(pool, rangeCount);
|
||||
SparseSet mustSpill(pool, rangeCount);
|
||||
|
||||
SparseSet alreadyStored(pool, rangeCount); // FIX: should get this from previous spilling.
|
||||
|
||||
SpillCost* cost = new SpillCost[rangeCount];
|
||||
memset(cost, '\0', rangeCount * sizeof(SpillCost));
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
double weight = doLog10(node.loopDepth);
|
||||
|
||||
needLoad.clear();
|
||||
live = liveOut[n];
|
||||
mustSpill = live;
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName range = name2range[definePtr->getRegisterName()];
|
||||
|
||||
if (needLoad.test(range))
|
||||
if (!mustSpill.test(range))
|
||||
cost[range].infinite = true;
|
||||
|
||||
if ((false /* !rematerializable(range) */ || !needLoad.test(range)) && !alreadyStored.test(range))
|
||||
cost[range].stores += weight;
|
||||
|
||||
needLoad.clear(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy)
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
if (!live.test(name2range[usePtr->getRegisterName()])) {
|
||||
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
|
||||
Uint32 range = needLoad.get(l);
|
||||
cost[range].loads += weight;
|
||||
mustSpill.set(range);
|
||||
}
|
||||
needLoad.clear();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
live.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
|
||||
live.set(range);
|
||||
needLoad.set(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
assert(defineBegin != defineEnd && defineBegin[0].isRegister());
|
||||
|
||||
RegisterName source = name2range[useBegin[0].getRegisterName()];
|
||||
RegisterName destination = name2range[defineBegin[0].getRegisterName()];
|
||||
|
||||
cost[source].copies += weight;
|
||||
cost[destination].copies += weight;
|
||||
}
|
||||
}
|
||||
|
||||
for (SparseSet::iterator s = needLoad.begin(); !needLoad.done(s); s = needLoad.advance(s))
|
||||
cost[needLoad.get(s)].loads += weight;
|
||||
}
|
||||
|
||||
for (Uint32 r = 0; r < rangeCount; r++) {
|
||||
SpillCost& c = cost[r];
|
||||
c.cost = 2 * (c.loads + c.stores) - c.copies;
|
||||
}
|
||||
|
||||
registerAllocator.spillCost = cost;
|
||||
}
|
||||
|
||||
#endif // _SPILLING_H_
|
||||
@@ -1,239 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SPLITS_H_
|
||||
#define _SPLITS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Splits
|
||||
{
|
||||
static void calculateSplitCosts(RegisterAllocator& registerAllocator);
|
||||
static bool findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range);
|
||||
static void insertSplitCode(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
struct SplitCost
|
||||
{
|
||||
double loads;
|
||||
double stores;
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Splits<RegisterPressure>::insertSplitCode(RegisterAllocator& /*registerAllocator*/)
|
||||
{
|
||||
// FIX
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Splits<RegisterPressure>::findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
NameLinkedList** neighborsWithColor = new(pool) NameLinkedList*[6]; // FIX
|
||||
memset(neighborsWithColor, '\0', 6 * sizeof(NameLinkedList*));
|
||||
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = vector->count - 1; i >=0; --i) {
|
||||
RegisterName neighbor = vector->neighbors[i];
|
||||
RegisterName c = color[neighbor];
|
||||
|
||||
if (c < 6) { // FIX
|
||||
NameLinkedList* node = new(pool) NameLinkedList();
|
||||
node->name = neighbor;
|
||||
node->next = neighborsWithColor[c];
|
||||
neighborsWithColor[c] = node;
|
||||
}
|
||||
}
|
||||
|
||||
bool splitAroundName = true;
|
||||
|
||||
LiveRangeGraph<RegisterPressure>& lGraph = registerAllocator.lGraph;
|
||||
RegisterName bestColor = RegisterName(6); // FIX
|
||||
double bestCost = registerAllocator.spillCost[range].cost;
|
||||
SplitCost* splitCost = registerAllocator.splitCost;
|
||||
|
||||
for (RegisterName i = RegisterName(0); i < 6; i = RegisterName(i + 1)) { // FIX
|
||||
|
||||
double splitAroundNameCost = 0.0;
|
||||
bool canSplitAroundName = true;
|
||||
|
||||
SplitCost& sCost = splitCost[range];
|
||||
double addedCost = 2.0 * (sCost.stores + sCost.loads);
|
||||
|
||||
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
|
||||
RegisterName neighbor = node->name;
|
||||
if (lGraph.haveEdge(neighbor, range)) {
|
||||
canSplitAroundName = false;
|
||||
break;
|
||||
} else
|
||||
splitAroundNameCost += addedCost;
|
||||
}
|
||||
if (canSplitAroundName && splitAroundNameCost < bestCost) {
|
||||
bestCost = splitAroundNameCost;
|
||||
bestColor = i;
|
||||
splitAroundName = true;
|
||||
}
|
||||
|
||||
double splitAroundColorCost = 0.0;
|
||||
bool canSplitAroundColor = true;
|
||||
|
||||
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
|
||||
RegisterName neighbor = node->name;
|
||||
if (lGraph.haveEdge(range, neighbor)) {
|
||||
canSplitAroundColor = false;
|
||||
break;
|
||||
} else {
|
||||
SplitCost& sCost = splitCost[neighbor];
|
||||
double addedCost = 2.0 * (sCost.stores + sCost.loads);
|
||||
splitAroundColorCost += addedCost;
|
||||
}
|
||||
}
|
||||
if (canSplitAroundColor && splitAroundColorCost < bestCost) {
|
||||
bestCost = splitAroundColorCost;
|
||||
bestColor = i;
|
||||
splitAroundName = false;
|
||||
}
|
||||
}
|
||||
if (bestColor < RegisterName(6)) {
|
||||
color[range] = bestColor;
|
||||
registerAllocator.splitFound = true;
|
||||
|
||||
NameLinkedList** splitAround = registerAllocator.splitAround;
|
||||
|
||||
if (splitAroundName)
|
||||
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
|
||||
NameLinkedList* newNode = new(pool) NameLinkedList();
|
||||
newNode->name = node->name;
|
||||
newNode->next = splitAround[range];
|
||||
splitAround[range] = newNode;
|
||||
}
|
||||
else
|
||||
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
|
||||
NameLinkedList* newNode = new(pool) NameLinkedList();
|
||||
RegisterName neighbor = node->name;
|
||||
newNode->name = range;
|
||||
newNode->next = splitAround[neighbor];
|
||||
splitAround[neighbor] = newNode;
|
||||
}
|
||||
|
||||
trespass("Found a split");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Splits<RegisterPressure>::calculateSplitCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
SplitCost* splitCost = new(pool) SplitCost[rangeCount];
|
||||
memset(splitCost, '\0', rangeCount * sizeof(SplitCost));
|
||||
|
||||
SparseSet live(pool, rangeCount);
|
||||
RegisterPressure::Set* liveIn = registerAllocator.liveness.liveIn;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
double weight = doLog10(node.loopDepth);
|
||||
|
||||
live = liveOut[n];
|
||||
|
||||
ControlEdge* successorsEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++) {
|
||||
ControlNode& successor = successorsPtr->getTarget();
|
||||
|
||||
if (successor.getControlKind() != ckEnd) {
|
||||
RegisterPressure::Set& successorLiveIn = liveIn[successor.dfsNum];
|
||||
|
||||
for (SparseSet::iterator i = live.begin(); !live.done(i); i = live.advance(i)) {
|
||||
RegisterName name = RegisterName(live.get(i));
|
||||
if (!successorLiveIn.test(name))
|
||||
splitCost[name].loads += doLog10(successor.loopDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
splitCost[name2range[definePtr->getRegisterName()]].stores += weight;
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
if (!live.test(range)) {
|
||||
if (&instruction != &instructions.last())
|
||||
splitCost[range].loads += weight;
|
||||
else {
|
||||
ControlEdge* successorsEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++)
|
||||
splitCost[range].loads += doLog10(successorsPtr->getTarget().loopDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
live.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
live.set(name2range[usePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
NameLinkedList** splitAround = new(pool) NameLinkedList*[rangeCount];
|
||||
memset(splitAround, '\0', rangeCount * sizeof(NameLinkedList*));
|
||||
registerAllocator.splitAround = splitAround;
|
||||
|
||||
registerAllocator.splitCost = splitCost;
|
||||
registerAllocator.splitFound = false;
|
||||
}
|
||||
|
||||
#endif // _SPLITS_H_
|
||||
@@ -1,186 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashTable.h"
|
||||
#include "Timer.h"
|
||||
#include "Pool.h"
|
||||
|
||||
static Pool pool; // Pool for the Timer class.
|
||||
static HashTable<TimerEntry*> timerEntries(pool); // Timers hashtable.
|
||||
|
||||
const nTimersInABlock = 128; // Number of timers in a block.
|
||||
static PRTime *timers = new(pool) PRTime[nTimersInABlock]; // A block of timers.
|
||||
static Uint8 nextTimer = 0; // nextAvailableTimer.
|
||||
|
||||
//
|
||||
// Calibrate the call to PR_Now().
|
||||
//
|
||||
static PRTime calibrate()
|
||||
{
|
||||
PRTime t = PR_Now();
|
||||
PRTime& a = *new(pool) PRTime();
|
||||
|
||||
// Call 10 times the PR_Now() function.
|
||||
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
|
||||
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
|
||||
t = (PR_Now() - t + 9) / 10;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static PRTime adjust = calibrate();
|
||||
|
||||
//
|
||||
// Return the named timer..
|
||||
//
|
||||
TimerEntry& Timer::getTimerEntry(const char* name)
|
||||
{
|
||||
if (!timerEntries.exists(name)) {
|
||||
TimerEntry* newEntry = new(pool) TimerEntry();
|
||||
newEntry->accumulator = 0;
|
||||
newEntry->running = false;
|
||||
timerEntries.add(name, newEntry);
|
||||
}
|
||||
|
||||
return *timerEntries[name];
|
||||
}
|
||||
|
||||
//
|
||||
// Return a reference to a new timer.
|
||||
//
|
||||
PRTime& Timer::getNewTimer()
|
||||
{
|
||||
if (nextTimer >= nTimersInABlock) {
|
||||
timers = new(pool) PRTime[nTimersInABlock];
|
||||
nextTimer = 0;
|
||||
}
|
||||
return timers[nextTimer++];
|
||||
}
|
||||
|
||||
static Uint32 timersAreFrozen = 0;
|
||||
|
||||
//
|
||||
// Start the named timer.
|
||||
//
|
||||
void Timer::start(const char* name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
PR_ASSERT(!timer.running);
|
||||
|
||||
timer.accumulator = 0;
|
||||
timer.running = true;
|
||||
timer.done = false;
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
//
|
||||
// Stop the named timer.
|
||||
//
|
||||
void Timer::stop(const char* name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
PR_ASSERT(timer.running);
|
||||
timer.running = false;
|
||||
timer.done = true;
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
//
|
||||
// Freeze all the running timers.
|
||||
//
|
||||
void Timer::freezeTimers()
|
||||
{
|
||||
PRTime when = PR_Now() - adjust;
|
||||
|
||||
if (timersAreFrozen == 0) {
|
||||
Vector<TimerEntry*> entries = timerEntries;
|
||||
Uint32 count = entries.size();
|
||||
|
||||
for (Uint32 i = 0; i < count; i++) {
|
||||
TimerEntry& entry = *entries[i];
|
||||
if (entry.running) {
|
||||
entry.accumulator += (when - *entry.startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
timersAreFrozen++;
|
||||
}
|
||||
|
||||
//
|
||||
// Unfreeze all the running timers.
|
||||
//
|
||||
void Timer::unfreezeTimers()
|
||||
{
|
||||
PR_ASSERT(timersAreFrozen != 0);
|
||||
timersAreFrozen--;
|
||||
|
||||
if (timersAreFrozen == 0) {
|
||||
Vector<TimerEntry *> entries = timerEntries;
|
||||
Uint32 count = entries.size();
|
||||
|
||||
PRTime& newStart = getNewTimer();
|
||||
|
||||
for (Uint32 i = 0; i < count; i++) {
|
||||
TimerEntry& entry = *entries[i];
|
||||
if (entry.running) {
|
||||
entry.startTime = &newStart;
|
||||
}
|
||||
}
|
||||
|
||||
newStart = PR_Now();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Print the named timer in the file f.
|
||||
//
|
||||
void Timer::print(FILE* f, const char *name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
|
||||
PR_ASSERT(timer.done);
|
||||
PRTime elapsed = timer.accumulator;
|
||||
|
||||
if (elapsed >> 32) {
|
||||
fprintf(f, "[timer %s out of range]\n", name);
|
||||
} else {
|
||||
fprintf(f, "[%dus in %s]\n", Uint32(elapsed), name);
|
||||
}
|
||||
fflush(f);
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _TIMER_H_
|
||||
#define _TIMER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashTable.h"
|
||||
#include "prtime.h"
|
||||
|
||||
//
|
||||
// Naming convention:
|
||||
// As the class Timer contains only static methods, the timer's name should start with the
|
||||
// module name. Otherwise starting 2 timers with the same name will assert.
|
||||
//
|
||||
|
||||
#ifndef NO_TIMER
|
||||
|
||||
struct TimerEntry
|
||||
{
|
||||
PRTime *startTime; // Current time when we start the timer.
|
||||
PRTime accumulator; // Time spent in this timer.
|
||||
bool running; // True if the timer is running.
|
||||
bool done; // True if the timer was running and was stopped.
|
||||
};
|
||||
|
||||
class Timer
|
||||
{
|
||||
private:
|
||||
|
||||
// Return the named timer.
|
||||
static TimerEntry& getTimerEntry(const char* name);
|
||||
// Return a reference to a new Timer.
|
||||
static PRTime& getNewTimer();
|
||||
|
||||
public:
|
||||
|
||||
// Start the timer.
|
||||
static void start(const char* name);
|
||||
// Stop the timer.
|
||||
static void stop(const char* name);
|
||||
// Freeze all the running timers.
|
||||
static void freezeTimers();
|
||||
// Unfreeze all the running timers.
|
||||
static void unfreezeTimers();
|
||||
// Print the timer.
|
||||
static void print(FILE* f, const char *name);
|
||||
};
|
||||
|
||||
inline void startTimer(const char* name) {Timer::start(name);}
|
||||
inline void stopTimer(const char* name) {Timer::stop(name); Timer::print(stdout, name);}
|
||||
#define START_TIMER_SAFE Timer::freezeTimers();
|
||||
#define END_TIMER_SAFE Timer::unfreezeTimers();
|
||||
#define TIMER_SAFE(x) START_TIMER_SAFE x; END_TIMER_SAFE
|
||||
|
||||
#else /* NO_TIMER */
|
||||
|
||||
inline void startTimer(const char* /*name*/) {}
|
||||
inline void stopTimer(const char* /*name*/) {}
|
||||
#define START_TIMER_SAFE
|
||||
#define END_TIMER_SAFE
|
||||
#define TIMER_SAFE(x) x;
|
||||
|
||||
#endif /* NO_TIMER */
|
||||
#endif /* _TIMER_H_ */
|
||||
@@ -1,40 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "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;
|
||||
}
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _VIRTUAL_REGISTER_H_
|
||||
#define _VIRTUAL_REGISTER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "IndexedPool.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "RegisterTypes.h"
|
||||
#include "RegisterClass.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegister - 24b
|
||||
|
||||
class Instruction;
|
||||
|
||||
class VirtualRegister : public IndexedObject<VirtualRegister>
|
||||
{
|
||||
public:
|
||||
|
||||
Instruction* definingInstruction; // Instruction defining this VR.
|
||||
|
||||
// Initialize a VR of the given classKind.
|
||||
VirtualRegister(RegisterClassKind /*classKind*/) : definingInstruction(NULL) {}
|
||||
|
||||
// Return the defining instruction for this VR.
|
||||
Instruction* getDefiningInstruction() const {return definingInstruction;}
|
||||
// Set the defining instruction.
|
||||
void setDefiningInstruction(Instruction& insn);
|
||||
};
|
||||
|
||||
// Return true if the VirtualRegisters are equals. The only way 2 VRs can be equal is if
|
||||
// they have the same index. If they have the same index then they are at the same
|
||||
// address in the indexed pool.
|
||||
//
|
||||
inline bool operator == (const VirtualRegister& regA, const VirtualRegister& regB) {return ®A == ®B;}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegisterManager -
|
||||
|
||||
struct PreColoredRegister
|
||||
{
|
||||
RegisterID id;
|
||||
RegisterName color;
|
||||
};
|
||||
|
||||
class VirtualRegisterManager
|
||||
{
|
||||
private:
|
||||
|
||||
IndexedPool<VirtualRegister> registerPool;
|
||||
PreColoredRegister machineRegister[6];
|
||||
|
||||
public:
|
||||
VirtualRegisterManager()
|
||||
{
|
||||
for (Uint32 i = 0; i < 6; i++)
|
||||
machineRegister[i].id = invalidID;
|
||||
}
|
||||
|
||||
// Return the VirtualRegister at the given index.
|
||||
VirtualRegister& getVirtualRegister(RegisterName name) const {return registerPool.get(name);}
|
||||
|
||||
// Return a new VirtualRegister.
|
||||
RegisterID newVirtualRegister(RegisterClassKind classKind)
|
||||
{
|
||||
VirtualRegister& vReg = *new(registerPool) VirtualRegister(classKind);
|
||||
RegisterID rid;
|
||||
|
||||
setName(rid, RegisterName(vReg.getIndex()));
|
||||
setClass(rid, classKind);
|
||||
return rid;
|
||||
}
|
||||
|
||||
RegisterID newMachineRegister(RegisterName name, RegisterClassKind classKind)
|
||||
{
|
||||
RegisterID rid = machineRegister[name].id;
|
||||
|
||||
if (rid == invalidID) {
|
||||
rid = newVirtualRegister(classKind);
|
||||
DEBUG_ONLY(setMachineRegister(rid));
|
||||
machineRegister[name].id = rid;
|
||||
machineRegister[name].color = name;
|
||||
}
|
||||
|
||||
return rid;
|
||||
}
|
||||
|
||||
PreColoredRegister* getMachineRegistersBegin() const {return (PreColoredRegister*) machineRegister;} // FIX
|
||||
PreColoredRegister* getMachineRegistersEnd() const {return (PreColoredRegister*) &machineRegister[6];} // FIX
|
||||
|
||||
// Return the VirtualRegister universe size.
|
||||
Uint32 getSize() {return registerPool.getSize();}
|
||||
|
||||
void setSize(Uint32 size) {registerPool.setSize(size);}
|
||||
};
|
||||
|
||||
#endif // _VIRTUAL_REGISTER_H_
|
||||
31
mozilla/js/src/MANIFEST
Normal file
31
mozilla/js/src/MANIFEST
Normal file
@@ -0,0 +1,31 @@
|
||||
# This is a list of local files which get copied to the mozilla:dist directory
|
||||
#
|
||||
|
||||
jsapi.h
|
||||
jspubtd.h
|
||||
jsarray.h
|
||||
jsatom.h
|
||||
jsbool.h
|
||||
jscntxt.h
|
||||
jscompat.h
|
||||
jsconfig.h
|
||||
jsdate.h
|
||||
jsdbgapi.h
|
||||
jsemit.h
|
||||
jsfun.h
|
||||
jsgc.h
|
||||
jsinterp.h
|
||||
jslock.h
|
||||
jsmath.h
|
||||
jsnum.h
|
||||
jsobj.h
|
||||
jsopcode.def
|
||||
jsopcode.h
|
||||
jsparse.h
|
||||
jsprvtd.h
|
||||
jspubtd.h
|
||||
jsregexp.h
|
||||
jsscan.h
|
||||
jsscope.h
|
||||
jsscript.h
|
||||
jsstr.h
|
||||
236
mozilla/js/src/Makefile
Normal file
236
mozilla/js/src/Makefile
Normal file
@@ -0,0 +1,236 @@
|
||||
#! gmake
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH = ../..
|
||||
|
||||
include $(DEPTH)/config/config.mk
|
||||
|
||||
ifdef MOZ_OJI
|
||||
DIRS = liveconnect
|
||||
endif
|
||||
|
||||
LIBRARY_NAME = js
|
||||
|
||||
ifeq ($(subst /,_,$(shell uname -s)),OS2)
|
||||
ifndef XCFLAGS
|
||||
OS2_IMPLIB=1
|
||||
LIBRARY = js$(MOZ_BITS)$(VERSION_NUMBER).$(LIB_SUFFIX)
|
||||
DEF_FILE = jsos2$(VERSION_NUMBER).def
|
||||
EXTRA_LIBS = $(LIBNSPR) $(LIBNSJAVA)
|
||||
else
|
||||
EXTRA_LIBS = $(LIBNSPR) $(LIBNSJAVA) $(OBJDIR)/libjs.lib
|
||||
endif
|
||||
endif
|
||||
|
||||
MODULE = js
|
||||
|
||||
CSRCS = jsapi.c \
|
||||
jsarray.c \
|
||||
jsatom.c \
|
||||
jsbool.c \
|
||||
jscntxt.c \
|
||||
jsdate.c \
|
||||
jsdbgapi.c \
|
||||
jsemit.c \
|
||||
jsfun.c \
|
||||
jsgc.c \
|
||||
jsinterp.c \
|
||||
jsmath.c \
|
||||
jsnum.c \
|
||||
jsobj.c \
|
||||
jsopcode.c \
|
||||
jsparse.c \
|
||||
jsregexp.c \
|
||||
jsscan.c \
|
||||
jsscope.c \
|
||||
jsscript.c \
|
||||
jsstr.c \
|
||||
jslock.c \
|
||||
jsxdrapi.c \
|
||||
prmjtime.c \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = jsapi.h \
|
||||
jsarray.h \
|
||||
jsatom.h \
|
||||
jsbool.h \
|
||||
jscntxt.h \
|
||||
jscompat.h \
|
||||
jsconfig.h \
|
||||
jsdate.h \
|
||||
jsdbgapi.h \
|
||||
jsemit.h \
|
||||
jsfun.h \
|
||||
jsgc.h \
|
||||
jsinterp.h \
|
||||
jslock.h \
|
||||
jsmath.h \
|
||||
jsnum.h \
|
||||
jsobj.h \
|
||||
jsopcode.def \
|
||||
jsopcode.h \
|
||||
jsparse.h \
|
||||
jsprvtd.h \
|
||||
jspubtd.h \
|
||||
jsregexp.h \
|
||||
jsscan.h \
|
||||
jsscope.h \
|
||||
jsscript.h \
|
||||
jsstr.h \
|
||||
jsxdrapi.h \
|
||||
$(NULL)
|
||||
|
||||
# when using gcc the assembly is inlined in the C-file (see jslock.c)
|
||||
ifdef NS_USE_NATIVE
|
||||
ASFILES = $(wildcard *_$(OS_ARCH).s)
|
||||
endif
|
||||
|
||||
JS_SAFE_ARENA = 1
|
||||
|
||||
ifdef JS_SAFE_ARENA
|
||||
DEFINES += -DJS_USE_SAFE_ARENA
|
||||
CSRCS += prarena.c
|
||||
endif
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
ifndef BUILD_OPT
|
||||
MOCHAFILE = 1
|
||||
endif
|
||||
|
||||
ifdef JSFILE
|
||||
DEFINES += -DJSFILE
|
||||
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
|
||||
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
|
||||
ifndef JS_NO_ULTRA
|
||||
ULTRA_OPTIONS := -xarch=v8plus,-DULTRA_SPARC
|
||||
ULTRA_OPTIONSCC := -DULTRA_SPARC
|
||||
else
|
||||
ULTRA_OPTIONS := -xarch=v8
|
||||
ULTRA_OPTIONSCC :=
|
||||
endif
|
||||
|
||||
ifeq ($(shell uname -m),sun4u)
|
||||
ASFLAGS += -Wa,$(ULTRA_OPTIONS),-P,-L,-D_ASM,-D__STDC__=0 $(ULTRA_OPTIONSCC)
|
||||
else
|
||||
ASFLAGS += -Wa,-xarch=v8,-P,-L,-D_ASM,-D__STDC__=0
|
||||
endif
|
||||
|
||||
endif # sparc
|
||||
|
||||
INCLUDES += -I.
|
||||
|
||||
ifdef NSPR20
|
||||
INCLUDES += -I$(DIST)/include/nspr20/pr
|
||||
else
|
||||
INCLUDES += -I$(XPDIST)/public/nspr
|
||||
endif
|
||||
|
||||
ifndef NSBUILDROOT
|
||||
JSJAVA_STUBHEADERS = -I$(DEPTH)/sun-java/include/_gen \
|
||||
-I$(DEPTH)/sun-java/netscape/javascript/_jri \
|
||||
-I$(DEPTH)/sun-java/netscape/security/_jri
|
||||
else
|
||||
JSJAVA_STUBHEADERS = -I$(JRI_GEN_DIR) -I$(JDK_GEN_DIR)
|
||||
endif
|
||||
|
||||
JSJAVA_CFLAGS = -I$(DEPTH)/sun-java/md-include \
|
||||
-I$(DEPTH)/sun-java/include \
|
||||
$(JSJAVA_STUBHEADERS)
|
||||
|
||||
# LIBNSPR includes unneeded libmsgc21.a, but abstracts nspr version,
|
||||
# etc. nicely.
|
||||
LDFLAGS = $(LIBNSPR) -lm
|
||||
|
||||
ifeq ($(OS_ARCH), OSF1)
|
||||
LDFLAGS += -lc_r
|
||||
endif
|
||||
ifeq ($(OS_ARCH), SunOS)
|
||||
LDFLAGS += -lposix4 -ldl -lnsl -lsocket
|
||||
endif
|
||||
ifeq ($(OS_ARCH), Linux)
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
# this requires clobbering and recompiling with XCFLAGS=-DJSFILE
|
||||
js:
|
||||
$(MAKE) clobber
|
||||
$(MAKE) XCFLAGS=-DJSFILE $(OBJDIR)/js$(BIN_SUFFIX)
|
||||
|
||||
.PHONY: js$(BIN_SUFFIX)
|
||||
|
||||
ifneq ($(OS_ARCH),OS2)
|
||||
$(OBJDIR)/js$(BIN_SUFFIX): $(OBJDIR)/js.o $(LIBRARY)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -o $@ $(OBJDIR)/js.o $(LIBRARY) $(LDFLAGS)
|
||||
else
|
||||
OS_CFLAGS += -tm-
|
||||
$(OBJDIR)/js$(BIN_SUFFIX): $(OBJDIR)/js.o $(LIBRARY)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(LINK_EXE) -OUT:$@ $(OBJDIR)/js.o $(LIBRARIES) $(EXTRA_LIBS)
|
||||
endif
|
||||
|
||||
# hardwire dependencies on jsopcode.def
|
||||
jsopcode.h jsopcode.c: jsopcode.def
|
||||
|
||||
# this section was put in the merged by danda into the
|
||||
# JAVA_*_MERGE section and normally would have
|
||||
# been removed. However it looks like it shouldn't have
|
||||
# been put there in the first place, so we're leaving it
|
||||
# here until danda can confirm (we don't have OS/2 machines
|
||||
# to build on) - hshaw/sudu
|
||||
#
|
||||
ifeq ($(OS_ARCH),OS2)
|
||||
$(OBJDIR)/js.o: js.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $(JSJAVA_CFLAGS) js.c
|
||||
endif
|
||||
|
||||
|
||||
refdiff:
|
||||
@for f in `cat commfiles`; do \
|
||||
t=/tmp/refdiff.$$$$; \
|
||||
trap 'rm -f $$t' 0 1 2 15; \
|
||||
sed -f prconv.sed ../ref/$$f > $$t; \
|
||||
cmp -s $$t $$f; \
|
||||
if test $$? -ne 0; then \
|
||||
echo "=== $$f"; \
|
||||
diff $$f $$t; \
|
||||
fi; \
|
||||
rm -f $$t; \
|
||||
done
|
||||
|
||||
refconv:
|
||||
@for f in `cat commfiles`; do \
|
||||
echo "=== $$f"; \
|
||||
sed -f prconv.sed ../ref/$$f > $$f; \
|
||||
done
|
||||
|
||||
.PHONY: refdiff refconv
|
||||
241
mozilla/js/src/Makefile.in
Normal file
241
mozilla/js/src/Makefile.in
Normal file
@@ -0,0 +1,241 @@
|
||||
#! gmake
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifdef MOZ_OJI
|
||||
DIRS = liveconnect
|
||||
endif
|
||||
|
||||
LIBRARY_NAME = js
|
||||
|
||||
ifeq ($(subst /,_,$(shell uname -s)),OS2)
|
||||
ifndef XCFLAGS
|
||||
OS2_IMPLIB=1
|
||||
LIBRARY = js$(MOZ_BITS)$(VERSION_NUMBER).$(LIB_SUFFIX)
|
||||
DEF_FILE = jsos2$(VERSION_NUMBER).def
|
||||
EXTRA_LIBS = $(LIBNSPR) $(LIBNSJAVA)
|
||||
else
|
||||
EXTRA_LIBS = $(LIBNSPR) $(LIBNSJAVA) $(OBJDIR)/libjs.lib
|
||||
endif
|
||||
endif
|
||||
|
||||
MODULE = js
|
||||
|
||||
CSRCS = jsapi.c \
|
||||
jsarray.c \
|
||||
jsatom.c \
|
||||
jsbool.c \
|
||||
jscntxt.c \
|
||||
jsdate.c \
|
||||
jsdbgapi.c \
|
||||
jsemit.c \
|
||||
jsfun.c \
|
||||
jsgc.c \
|
||||
jsinterp.c \
|
||||
jsmath.c \
|
||||
jsnum.c \
|
||||
jsobj.c \
|
||||
jsopcode.c \
|
||||
jsparse.c \
|
||||
jsregexp.c \
|
||||
jsscan.c \
|
||||
jsscope.c \
|
||||
jsscript.c \
|
||||
jsstr.c \
|
||||
jslock.c \
|
||||
jsxdrapi.c \
|
||||
prmjtime.c \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = jsapi.h \
|
||||
jsarray.h \
|
||||
jsatom.h \
|
||||
jsbool.h \
|
||||
jscntxt.h \
|
||||
jscompat.h \
|
||||
jsconfig.h \
|
||||
jsdate.h \
|
||||
jsdbgapi.h \
|
||||
jsemit.h \
|
||||
jsfun.h \
|
||||
jsgc.h \
|
||||
jsinterp.h \
|
||||
jslock.h \
|
||||
jsmath.h \
|
||||
jsnum.h \
|
||||
jsobj.h \
|
||||
jsopcode.def \
|
||||
jsopcode.h \
|
||||
jsparse.h \
|
||||
jsprvtd.h \
|
||||
jspubtd.h \
|
||||
jsregexp.h \
|
||||
jsscan.h \
|
||||
jsscope.h \
|
||||
jsscript.h \
|
||||
jsstr.h \
|
||||
jsxdrapi.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
# when using gcc the assembly is inlined in the C-file (see jslock.c)
|
||||
ifdef NS_USE_NATIVE
|
||||
ASFILES = $(wildcard $(srcdir)/*_$(OS_ARCH).s)
|
||||
endif
|
||||
|
||||
JS_SAFE_ARENA = 1
|
||||
|
||||
ifdef JS_SAFE_ARENA
|
||||
DEFINES += -DJS_USE_SAFE_ARENA
|
||||
CSRCS += prarena.c
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifndef BUILD_OPT
|
||||
MOCHAFILE = 1
|
||||
endif
|
||||
|
||||
ifdef JSFILE
|
||||
DEFINES += -DJSFILE
|
||||
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
|
||||
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
|
||||
ifndef JS_NO_ULTRA
|
||||
ULTRA_OPTIONS := -xarch=v8plus,-DULTRA_SPARC
|
||||
ULTRA_OPTIONSCC := -DULTRA_SPARC
|
||||
else
|
||||
ULTRA_OPTIONS := -xarch=v8
|
||||
ULTRA_OPTIONSCC :=
|
||||
endif
|
||||
|
||||
ifeq ($(shell uname -m),sun4u)
|
||||
ASFLAGS += -Wa,$(ULTRA_OPTIONS),-P,-L,-D_ASM,-D__STDC__=0 $(ULTRA_OPTIONSCC)
|
||||
else
|
||||
ASFLAGS += -Wa,-xarch=v8,-P,-L,-D_ASM,-D__STDC__=0
|
||||
endif
|
||||
|
||||
endif # sparc
|
||||
|
||||
INCLUDES += -I$(srcdir)
|
||||
|
||||
ifdef NSPR20
|
||||
INCLUDES += -I$(DIST)/include/nspr20/pr
|
||||
else
|
||||
INCLUDES += -I$(XPDIST)/public/nspr
|
||||
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)
|
||||
|
||||
# LIBNSPR includes unneeded libmsgc21.a, but abstracts nspr version,
|
||||
# etc. nicely.
|
||||
LDFLAGS = $(LIBNSPR) -lm
|
||||
|
||||
ifeq ($(OS_ARCH), OSF1)
|
||||
LDFLAGS += -lc_r
|
||||
endif
|
||||
ifeq ($(OS_ARCH), SunOS)
|
||||
LDFLAGS += -lposix4 -ldl -lnsl -lsocket
|
||||
endif
|
||||
ifeq ($(OS_ARCH), Linux)
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
# this requires clobbering and recompiling with XCFLAGS=-DJSFILE
|
||||
js:
|
||||
$(MAKE) clobber
|
||||
$(MAKE) XCFLAGS=-DJSFILE $(OBJDIR)/js$(BIN_SUFFIX)
|
||||
|
||||
.PHONY: js$(BIN_SUFFIX)
|
||||
|
||||
ifneq ($(OS_ARCH),OS2)
|
||||
$(OBJDIR)/js$(BIN_SUFFIX): $(OBJDIR)/js.o $(LIBRARY)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -o $@ $(OBJDIR)/js.o $(LIBRARY) $(LDFLAGS)
|
||||
else
|
||||
OS_CFLAGS += -tm-
|
||||
$(OBJDIR)/js$(BIN_SUFFIX): $(OBJDIR)/js.o $(LIBRARY)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(LINK_EXE) -OUT:$@ $(OBJDIR)/js.o $(LIBRARIES) $(EXTRA_LIBS)
|
||||
endif
|
||||
|
||||
# hardwire dependencies on jsopcode.def
|
||||
jsopcode.h jsopcode.c: jsopcode.def
|
||||
|
||||
# this section was put in the merged by danda into the
|
||||
# JAVA_*_MERGE section and normally would have
|
||||
# been removed. However it looks like it shouldn't have
|
||||
# been put there in the first place, so we're leaving it
|
||||
# here until danda can confirm (we don't have OS/2 machines
|
||||
# to build on) - hshaw/sudu
|
||||
#
|
||||
ifeq ($(OS_ARCH),OS2)
|
||||
$(OBJDIR)/js.o: js.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $(JSJAVA_CFLAGS) js.c
|
||||
endif
|
||||
|
||||
|
||||
refdiff:
|
||||
@for f in `cat commfiles`; do \
|
||||
t=/tmp/refdiff.$$$$; \
|
||||
trap 'rm -f $$t' 0 1 2 15; \
|
||||
sed -f prconv.sed ../ref/$$f > $$t; \
|
||||
cmp -s $$t $$f; \
|
||||
if test $$? -ne 0; then \
|
||||
echo "=== $$f"; \
|
||||
diff $$f $$t; \
|
||||
fi; \
|
||||
rm -f $$t; \
|
||||
done
|
||||
|
||||
refconv:
|
||||
@for f in `cat commfiles`; do \
|
||||
echo "=== $$f"; \
|
||||
sed -f prconv.sed ../ref/$$f > $$f; \
|
||||
done
|
||||
|
||||
.PHONY: refdiff refconv
|
||||
316
mozilla/js/src/Makefile.ref
Normal file
316
mozilla/js/src/Makefile.ref
Normal file
@@ -0,0 +1,316 @@
|
||||
#
|
||||
# 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.
|
||||
|
||||
#
|
||||
# JSRef GNUmake makefile.
|
||||
#
|
||||
|
||||
# Set os+release dependent make variables
|
||||
OS_ARCH := $(subst /,_,$(shell uname -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
|
||||
|
||||
# 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
|
||||
OS_CONFIG := $(OS_ARCH)$(OS_OBJTYPE)$(OS_RELEASE)
|
||||
endif
|
||||
endif
|
||||
|
||||
ASFLAGS =
|
||||
DEFINES =
|
||||
|
||||
#NS_USE_NATIVE = 1
|
||||
|
||||
include config/$(OS_CONFIG).mk
|
||||
|
||||
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
|
||||
|
||||
#DEFINES += -DJS_THREADSAFE
|
||||
|
||||
ifdef JS_NO_THIN_LOCKS
|
||||
DEFINES += -DJS_USE_ONLY_NSPR_LOCKS
|
||||
endif
|
||||
|
||||
# Name of the binary code directories
|
||||
OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).OBJ
|
||||
VPATH = $(OBJDIR)
|
||||
|
||||
# Automatic make dependencies file
|
||||
DEPENDENCIES = $(OBJDIR)/.md
|
||||
|
||||
define MAKE_OBJDIR
|
||||
if test ! -d $(@D); then rm -rf $(@D); mkdir $(@D); fi
|
||||
endef
|
||||
|
||||
# Look in OBJDIR to find prcpucfg.h
|
||||
INCLUDES = -I$(OBJDIR)
|
||||
|
||||
#
|
||||
# XCFLAGS may be set in the environment or on the gmake command line
|
||||
#
|
||||
CFLAGS = $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \
|
||||
-DJSFILE $(XCFLAGS)
|
||||
LDFLAGS = -lm $(XLDFLAGS)
|
||||
|
||||
#
|
||||
# Ask perl what flags it was built with, so we can build js with similar flags
|
||||
# and link properly. Viva gmake.
|
||||
#
|
||||
ifdef PERLCONNECT
|
||||
DEFINES += -DPERLCONNECT
|
||||
|
||||
PERLCFLAGS := $(shell perl -MExtUtils::Embed -e ccopts)
|
||||
PERLLDFLAGS := $(shell perl -MExtUtils::Embed -e ldopts)
|
||||
|
||||
CFLAGS += $(PERLCFLAGS)
|
||||
LDFLAGS += $(PERLLDFLAGS)
|
||||
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 \
|
||||
jslock.h \
|
||||
jsmath.h \
|
||||
jsnum.h \
|
||||
jsobj.h \
|
||||
jsopcode.h \
|
||||
jsparse.h \
|
||||
jsarena.h \
|
||||
jsclist.h \
|
||||
jsdtoa.h \
|
||||
jshash.h \
|
||||
jslong.h \
|
||||
jsmacos.h \
|
||||
jsosdep.h \
|
||||
jspcos.h \
|
||||
jsprintf.h \
|
||||
jstime.h \
|
||||
jstypes.h \
|
||||
jsprvtd.h \
|
||||
jspubtd.h \
|
||||
jsregexp.h \
|
||||
jsscan.h \
|
||||
jsscope.h \
|
||||
jsscript.h \
|
||||
jsstr.h \
|
||||
jsxdrapi.h \
|
||||
$(NULL)
|
||||
|
||||
API_HFILES = \
|
||||
jsapi.h \
|
||||
jsdbgapi.h \
|
||||
$(NULL)
|
||||
|
||||
HFILES = $(JS_HFILES) $(API_HFILES)
|
||||
|
||||
JS_CFILES = \
|
||||
jsapi.c \
|
||||
jsarray.c \
|
||||
jsatom.c \
|
||||
jsbool.c \
|
||||
jscntxt.c \
|
||||
jsdate.c \
|
||||
jsdbgapi.c \
|
||||
jsemit.c \
|
||||
jsexn.c \
|
||||
jsfun.c \
|
||||
jsgc.c \
|
||||
jsinterp.c \
|
||||
jslock.c \
|
||||
jsmath.c \
|
||||
jsnum.c \
|
||||
jsobj.c \
|
||||
jsopcode.c \
|
||||
jsparse.c \
|
||||
jsarena.c \
|
||||
jsdtoa.c \
|
||||
jshash.c \
|
||||
jslog2.c \
|
||||
jslong.c \
|
||||
jsprf.c \
|
||||
jsregexp.c \
|
||||
jsscan.c \
|
||||
jsscope.c \
|
||||
jsscript.c \
|
||||
jsstr.c \
|
||||
jsutil.c \
|
||||
jsxdrapi.c \
|
||||
prmjtime.c \
|
||||
$(NULL)
|
||||
|
||||
ifdef PERLCONNECT
|
||||
JS_CFILES += jsperl.c
|
||||
endif
|
||||
|
||||
LIB_CFILES = $(JS_CFILES)
|
||||
LIB_ASFILES := $(wildcard *_$(OS_ARCH).s)
|
||||
PROG_CFILES = js.c
|
||||
|
||||
ifdef USE_MSVC
|
||||
LIB_OBJS = $(addprefix $(OBJDIR)/, $(LIB_CFILES:.c=.obj))
|
||||
PROG_OBJS = $(addprefix $(OBJDIR)/, $(PROG_CFILES:.c=.obj))
|
||||
else
|
||||
LIB_OBJS = $(addprefix $(OBJDIR)/, $(LIB_CFILES:.c=.o))
|
||||
LIB_OBJS += $(addprefix $(OBJDIR)/, $(LIB_ASFILES:.s=.o))
|
||||
PROG_OBJS = $(addprefix $(OBJDIR)/, $(PROG_CFILES:.c=.o))
|
||||
endif
|
||||
|
||||
CFILES = $(LIB_CFILES) $(PROG_CFILES)
|
||||
OBJS = $(LIB_OBJS) $(PROG_OBJS)
|
||||
|
||||
ifdef USE_MSVC
|
||||
LIBRARY = $(OBJDIR)/js32.dll
|
||||
PROGRAM = $(OBJDIR)/js
|
||||
else
|
||||
LIBRARY = $(OBJDIR)/libjs.a
|
||||
PROGRAM = $(OBJDIR)/js
|
||||
endif
|
||||
|
||||
ifdef USE_MSVC
|
||||
TARGETS = $(LIBRARY) # $(PROGRAM) not supported for MSVC yet
|
||||
else
|
||||
TARGETS = $(LIBRARY) $(PROGRAM)
|
||||
endif
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJS)
|
||||
|
||||
clobber:
|
||||
rm -rf $(OBJS) $(TARGETS) $(DEPENDENCIES)
|
||||
|
||||
depend:
|
||||
gcc -MM $(CFLAGS) $(JS_CFILES)
|
||||
|
||||
$(OBJDIR)/%: %.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -o $@ $(CFLAGS) $*.c $(LDFLAGS)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -o $@ -c $(CFLAGS) $*.c
|
||||
|
||||
$(OBJDIR)/%.o: %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(AS) -o $@ $(ASFLAGS) $*.s
|
||||
|
||||
# windows only
|
||||
$(OBJDIR)/%.obj: %.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -Fo$(OBJDIR)/ -c $(CFLAGS) $*.c
|
||||
|
||||
ifeq ($(OS_ARCH),OS2)
|
||||
$(LIBRARY): $(LIB_OBJS)
|
||||
$(AR) $@ $? $(AR_OS2_SUFFIX)
|
||||
$(RANLIB) $@
|
||||
else
|
||||
ifdef USE_MSVC
|
||||
$(LIBRARY): $(LIB_OBJS)
|
||||
link.exe $(LIB_LINK_FLAGS) /base:0x61000000 \
|
||||
/out:"$@" /pdb:"$(OBJDIR)/js32.pdb" /implib:"$(OBJDIR)/js32.lib" $?
|
||||
else
|
||||
$(LIBRARY): $(LIB_OBJS)
|
||||
$(AR) rv $@ $?
|
||||
$(RANLIB) $@
|
||||
endif
|
||||
endif
|
||||
|
||||
#NSPR_LIBRARY = ../../dist/$(OBJDIR)/lib/libnspr21.so
|
||||
NSPR_LIBRARY =
|
||||
|
||||
$(PROGRAM): $(PROG_OBJS) $(LIBRARY)
|
||||
$(CC) -o $@ $(CFLAGS) $(PROG_OBJS) $(LIBRARY) $(NSPR_LIBRARY) $(LDFLAGS)
|
||||
|
||||
$(PROGRAM).pure: $(PROG_OBJS) $(LIBRARY)
|
||||
purify $(PUREFLAGS) \
|
||||
$(CC) -o $@ $(PURE_OS_CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS)
|
||||
|
||||
$(HFILES) $(CFILES): $(OBJDIR)/jscpucfg.h
|
||||
|
||||
ifdef PREBUILT_CPUCFG
|
||||
$(OBJDIR)/jscpucfg.h: jscpucfg.h
|
||||
cp jscpucfg.h $(OBJDIR)
|
||||
else
|
||||
$(OBJDIR)/jscpucfg.h: $(OBJDIR)/jscpucfg
|
||||
rm -f $@
|
||||
$(OBJDIR)/jscpucfg > $@
|
||||
|
||||
$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o
|
||||
$(CC) -o $@ $(OBJDIR)/jscpucfg.o
|
||||
endif
|
||||
|
||||
#
|
||||
# Hardwire dependencies on jsopcode.tbl
|
||||
#
|
||||
jsopcode.h jsopcode.c: jsopcode.tbl
|
||||
|
||||
-include $(DEPENDENCIES)
|
||||
|
||||
TARNAME = jsref.tar
|
||||
TARFILES = files `cat files`
|
||||
|
||||
tar:
|
||||
tar cvf $(TARNAME) $(TARFILES)
|
||||
gzip $(TARNAME)
|
||||
|
||||
SUFFIXES: .i
|
||||
%.i: %.c
|
||||
$(CC) -C -E $(CFLAGS) $< > $*.i
|
||||
17
mozilla/js/src/README
Normal file
17
mozilla/js/src/README
Normal file
@@ -0,0 +1,17 @@
|
||||
The js/ref directory contains standalone ANSI-C source for the Netscape
|
||||
JavaScript Reference implementation, JSRef, which was licensed to over 180
|
||||
companies as part of Netscape ONE, starting in fall 1996. Now, JSRef is
|
||||
available under NPL from http://www.mozilla.org.
|
||||
|
||||
The js/src directory contains source files listed in the file "commfiles",
|
||||
that are derived via prconv.sed from counterparts in the js/ref directory.
|
||||
It also contains files such as jscompat.h that are not needed in js/ref.
|
||||
The Makefile in js/src has refconv and refdiff targets to help keep js/ref
|
||||
and js/src in synch.
|
||||
|
||||
If you think you need to change a file listed in commfiles here, please
|
||||
make the change in js/ref first and then use prconv.sed or gmake refconv to
|
||||
get it into js/src. If you have trouble, please let us know by mailing the
|
||||
JS owner and peers listed in http://www.mozilla.org/owners.html#JavaScript.
|
||||
|
||||
Brendan Eich (brendan@mozilla.org), 15-May-98
|
||||
100
mozilla/js/src/actra.mk
Normal file
100
mozilla/js/src/actra.mk
Normal file
@@ -0,0 +1,100 @@
|
||||
#! gmake
|
||||
|
||||
#
|
||||
# Since everyone seems to need to have their own build configuration
|
||||
# system these days, this is yet another makefile to build JavaScript.
|
||||
# This makefile conforms to the NSPR20 build rules. If you have built
|
||||
# NSPR20 this will build JS and stick the lib and bin files over in
|
||||
# the dist area created by NSPR (which is different from the dist
|
||||
# expected by the client and also the dist expected by LiveWire, but
|
||||
# don't get me started).
|
||||
#
|
||||
# I don't currently know enough about what sort of JS-engine the Actra
|
||||
# projects are going to expect so I don't know if we need to add
|
||||
# to CFLAGS for -DJS_THREADSAFE or -DJSFILE
|
||||
#
|
||||
|
||||
MOD_DEPTH = ../../nspr20
|
||||
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
INCLUDES = -I$(DIST)/include
|
||||
CFLAGS += -DNSPR20
|
||||
|
||||
CSRCS = prmjtime.c \
|
||||
jsapi.c \
|
||||
jsarray.c \
|
||||
jsatom.c \
|
||||
jsbool.c \
|
||||
jscntxt.c \
|
||||
jsdate.c \
|
||||
jsdbgapi.c \
|
||||
jsemit.c \
|
||||
jsfun.c \
|
||||
jsgc.c \
|
||||
jsinterp.c \
|
||||
jsmath.c \
|
||||
jsnum.c \
|
||||
jsobj.c \
|
||||
jsopcode.c \
|
||||
jsparse.c \
|
||||
jsregexp.c \
|
||||
jsscan.c \
|
||||
jsscope.c \
|
||||
jsscript.c \
|
||||
jsstr.c \
|
||||
jslock.c \
|
||||
$(NULL)
|
||||
|
||||
HEADERS = jsapi.h \
|
||||
jsarray.h \
|
||||
jsatom.h \
|
||||
jsbool.h \
|
||||
jscntxt.h \
|
||||
jscompat.h \
|
||||
jsconfig.h \
|
||||
jsdate.h \
|
||||
jsdbgapi.h \
|
||||
jsemit.h \
|
||||
jsfun.h \
|
||||
jsgc.h \
|
||||
jsinterp.h \
|
||||
jslock.h \
|
||||
jsmath.h \
|
||||
jsnum.h \
|
||||
jsobj.h \
|
||||
jsopcode.def \
|
||||
jsopcode.h \
|
||||
jsparse.h \
|
||||
jsprvtd.h \
|
||||
jspubtd.h \
|
||||
jsregexp.h \
|
||||
jsscan.h \
|
||||
jsscope.h \
|
||||
jsscript.h \
|
||||
jsstr.h \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
EXTRA_LIBS += $(DIST)/lib/libnspr$(MOD_VERSION).lib
|
||||
EXTRA_LIBS += $(DIST)/lib/libplds$(MOD_VERSION).lib
|
||||
else
|
||||
EXTRA_LIBS += -L$(DIST)/lib -lnspr$(MOD_VERSION) -lnplds$(MOD_VERSION)
|
||||
endif
|
||||
|
||||
LIBRARY_NAME = js
|
||||
LIBRARY_VERSION = $(MOD_VERSION)
|
||||
|
||||
RELEASE_HEADERS = $(HEADERS)
|
||||
RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
|
||||
RELEASE_LIBS = $(TARGETS)
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
$(INSTALL) -m 444 $(HEADERS) $(MOD_DEPTH)/../dist/public/$(LIBRARY_NAME)
|
||||
$(INSTALL) -m 444 $(TARGETS) $(DIST)/lib
|
||||
$(INSTALL) -m 444 $(SHARED_LIBRARY) $(DIST)/bin
|
||||
|
||||
install:: export
|
||||
|
||||
51
mozilla/js/src/commfiles
Normal file
51
mozilla/js/src/commfiles
Normal file
@@ -0,0 +1,51 @@
|
||||
js.c
|
||||
jsapi.c
|
||||
jsapi.h
|
||||
jsarray.c
|
||||
jsarray.h
|
||||
jsatom.c
|
||||
jsatom.h
|
||||
jsbool.c
|
||||
jsbool.h
|
||||
jscntxt.c
|
||||
jscntxt.h
|
||||
jsconfig.h
|
||||
jsdate.c
|
||||
jsdate.h
|
||||
jsdbgapi.c
|
||||
jsdbgapi.h
|
||||
jsemit.c
|
||||
jsemit.h
|
||||
jsfun.c
|
||||
jsfun.h
|
||||
jsgc.c
|
||||
jsgc.h
|
||||
jsinterp.c
|
||||
jsinterp.h
|
||||
jslock.h
|
||||
jslock.c
|
||||
jsmath.c
|
||||
jsmath.h
|
||||
jsnum.c
|
||||
jsnum.h
|
||||
jsobj.c
|
||||
jsobj.h
|
||||
jsopcode.c
|
||||
jsopcode.def
|
||||
jsopcode.h
|
||||
jsparse.c
|
||||
jsparse.h
|
||||
jsprvtd.h
|
||||
jspubtd.h
|
||||
jsregexp.c
|
||||
jsregexp.h
|
||||
jsscan.c
|
||||
jsscan.h
|
||||
jsscope.c
|
||||
jsscope.h
|
||||
jsscript.c
|
||||
jsscript.h
|
||||
jsstr.c
|
||||
jsstr.h
|
||||
jsxdrapi.h
|
||||
jsxdrapi.c
|
||||
37
mozilla/js/src/config/AIX4.1.mk
Normal file
37
mozilla/js/src/config/AIX4.1.mk
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# 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
|
||||
OS_LIBS = -lbsd -lsvld -lm
|
||||
#-lpthreads -lc_r
|
||||
|
||||
37
mozilla/js/src/config/AIX4.2.mk
Normal file
37
mozilla/js/src/config/AIX4.2.mk
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# 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
|
||||
OS_LIBS = -lbsd -lsvld -lm
|
||||
#-lpthreads -lc_r
|
||||
|
||||
48
mozilla/js/src/config/HP-UXB.10.10.mk
Normal file
48
mozilla/js/src/config/HP-UXB.10.10.mk
Normal file
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for HPUX
|
||||
#
|
||||
|
||||
CC = gcc -Wall -Wno-format
|
||||
CCC = g++ -Wall -Wno-format
|
||||
|
||||
RANLIB = echo
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = hppa
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -D_SVID_GETTOD
|
||||
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
|
||||
48
mozilla/js/src/config/HP-UXB.11.00.mk
Normal file
48
mozilla/js/src/config/HP-UXB.11.00.mk
Normal file
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for HPUX
|
||||
#
|
||||
|
||||
CC = gcc -Wall -Wno-format
|
||||
CCC = g++ -Wall -Wno-format
|
||||
|
||||
RANLIB = echo
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = hppa
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -D_SVID_GETTOD
|
||||
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
|
||||
58
mozilla/js/src/config/IRIX.mk
Normal file
58
mozilla/js/src/config/IRIX.mk
Normal file
@@ -0,0 +1,58 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for IRIX
|
||||
#
|
||||
|
||||
CPU_ARCH = mips
|
||||
GFX_ARCH = x
|
||||
|
||||
RANLIB = /bin/true
|
||||
|
||||
#NS_USE_GCC = 1
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
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 -32 -DIRIX6_2
|
||||
endif
|
||||
ifeq ($(OS_RELEASE),6.3)
|
||||
CC = cc -32 -DIRIX6_3
|
||||
endif
|
||||
CCC = 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
|
||||
|
||||
OS_CFLAGS = $(PURE_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
|
||||
|
||||
BSDECHO = echo
|
||||
MKSHLIB = $(LD) -shared
|
||||
22
mozilla/js/src/config/IRIX5.3.mk
Normal file
22
mozilla/js/src/config/IRIX5.3.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for IRIX5.3
|
||||
#
|
||||
|
||||
include config/IRIX.mk
|
||||
22
mozilla/js/src/config/IRIX6.1.mk
Normal file
22
mozilla/js/src/config/IRIX6.1.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for IRIX6.3
|
||||
#
|
||||
|
||||
include config/IRIX.mk
|
||||
22
mozilla/js/src/config/IRIX6.2.mk
Normal file
22
mozilla/js/src/config/IRIX6.2.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for IRIX6.2
|
||||
#
|
||||
|
||||
include config/IRIX.mk
|
||||
22
mozilla/js/src/config/IRIX6.3.mk
Normal file
22
mozilla/js/src/config/IRIX6.3.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for IRIX6.3
|
||||
#
|
||||
|
||||
include config/IRIX.mk
|
||||
47
mozilla/js/src/config/Linux_All.mk
Normal file
47
mozilla/js/src/config/Linux_All.mk
Normal file
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config for all versions of Linux
|
||||
#
|
||||
|
||||
CC = gcc -Wall -Wno-format
|
||||
CCC = g++ -Wall -Wno-format
|
||||
|
||||
RANLIB = echo
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = $(shell uname -m)
|
||||
ifeq (86,$(findstring 86,$(CPU_ARCH)))
|
||||
CPU_ARCH = x86
|
||||
endif
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DLINUX
|
||||
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
|
||||
79
mozilla/js/src/config/SunOS4.1.4.mk
Normal file
79
mozilla/js/src/config/SunOS4.1.4.mk
Normal file
@@ -0,0 +1,79 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SunOS4.1
|
||||
#
|
||||
|
||||
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 =
|
||||
66
mozilla/js/src/config/SunOS5.3.mk
Normal file
66
mozilla/js/src/config/SunOS5.3.mk
Normal file
@@ -0,0 +1,66 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SunOS5.3
|
||||
#
|
||||
|
||||
CC = gcc -Wall -Wno-format
|
||||
CCC = g++ -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
|
||||
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
|
||||
67
mozilla/js/src/config/SunOS5.4.mk
Normal file
67
mozilla/js/src/config/SunOS5.4.mk
Normal file
@@ -0,0 +1,67 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SunOS5.4
|
||||
#
|
||||
|
||||
ifdef NS_USE_NATIVE
|
||||
CC = cc
|
||||
CCC = CC
|
||||
else
|
||||
CC = gcc -Wall -Wno-format
|
||||
CCC = g++ -Wall -Wno-format
|
||||
endif
|
||||
|
||||
RANLIB = echo
|
||||
|
||||
CPU_ARCH = sparc
|
||||
GFX_ARCH = x
|
||||
|
||||
OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D__svr4 -DSOLARIS
|
||||
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
|
||||
71
mozilla/js/src/config/SunOS5.5.1.mk
Normal file
71
mozilla/js/src/config/SunOS5.5.1.mk
Normal file
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SunOS5.5
|
||||
#
|
||||
|
||||
AS = as
|
||||
ifndef NS_USE_NATIVE
|
||||
CC = gcc -Wall -Wno-format
|
||||
CCC = g++ -Wall
|
||||
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 -D_SVID_GETTOD
|
||||
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
|
||||
62
mozilla/js/src/config/SunOS5.5.mk
Normal file
62
mozilla/js/src/config/SunOS5.5.mk
Normal file
@@ -0,0 +1,62 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for SunOS5.5
|
||||
#
|
||||
|
||||
AS = as
|
||||
CC = gcc -Wall -Wno-format
|
||||
CCC = g++ -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 -D_SVID_GETTOD
|
||||
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 -DULTRA_SPARC
|
||||
else
|
||||
ULTRA_OPTIONS := -xarch=v8
|
||||
endif
|
||||
|
||||
ifeq ($(OS_CPUARCH),sun4u)
|
||||
ASFLAGS += $(ULTRA_OPTIONS)
|
||||
ifeq ($(findstring gcc,$(CC)),gcc)
|
||||
DEFINES += -Wa,$(ULTRA_OPTIONS)
|
||||
endif
|
||||
else
|
||||
ifeq ($(OS_CPUARCH),sun4m)
|
||||
ASFLAGS += -xarch=v8
|
||||
ifeq ($(findstring gcc,$(CC)),gcc)
|
||||
DEFINES += -Wa,-xarch=v8
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
46
mozilla/js/src/config/WINNT4.0.mk
Normal file
46
mozilla/js/src/config/WINNT4.0.mk
Normal file
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
#
|
||||
# Config for Windows NT using MS Visual C++ (version?)
|
||||
#
|
||||
|
||||
CC = cl
|
||||
|
||||
RANLIB = echo
|
||||
|
||||
#.c.o:
|
||||
# $(CC) -c -MD $*.d $(CFLAGS) $<
|
||||
|
||||
CPU_ARCH = x86 # XXX fixme
|
||||
GFX_ARCH = win32
|
||||
|
||||
OS_CFLAGS = -DXP_PC -DWIN32 -D_WINDOWS -D_WIN32
|
||||
OS_LIBS = -lm -lc
|
||||
|
||||
PREBUILT_CPUCFG = 1
|
||||
USE_MSVC = 1
|
||||
|
||||
LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
|
||||
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib /nologo\
|
||||
/subsystem:windows /dll /incremental:yes /debug\
|
||||
/machine:I386
|
||||
|
||||
CAFEDIR = t:/cafe
|
||||
JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
|
||||
JAVAC = $(CAFEDIR)/Bin/sj.exe
|
||||
JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
|
||||
JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
|
||||
42
mozilla/js/src/config/dgux.mk
Normal file
42
mozilla/js/src/config/dgux.mk
Normal file
@@ -0,0 +1,42 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Config stuff for Data General DG/UX
|
||||
#
|
||||
|
||||
#
|
||||
# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com)
|
||||
#
|
||||
|
||||
AS = as
|
||||
CC = gcc
|
||||
CCC = g++
|
||||
|
||||
RANLIB = echo
|
||||
|
||||
#
|
||||
# _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
|
||||
OS_LIBS = -lsocket -lnsl
|
||||
|
||||
NOSUCHFILE = /no-such-file
|
||||
30
mozilla/js/src/export.mac
Normal file
30
mozilla/js/src/export.mac
Normal file
@@ -0,0 +1,30 @@
|
||||
# This is a list of local files which get copied to the mozilla:dist directory
|
||||
#
|
||||
|
||||
jsapi.h
|
||||
jsarray.h
|
||||
jsatom.h
|
||||
jsbool.h
|
||||
jscntxt.h
|
||||
jscompat.h
|
||||
jsconfig.h
|
||||
jsdate.h
|
||||
jsdbgapi.h
|
||||
jsemit.h
|
||||
jsfun.h
|
||||
jsgc.h
|
||||
jsinterp.h
|
||||
jslock.h
|
||||
jsmath.h
|
||||
jsnum.h
|
||||
jsobj.h
|
||||
jsopcode.def
|
||||
jsopcode.h
|
||||
jsparse.h
|
||||
jsprvtd.h
|
||||
jspubtd.h
|
||||
jsregexp.h
|
||||
jsscan.h
|
||||
jsscope.h
|
||||
jsscript.h
|
||||
jsstr.h
|
||||
1545
mozilla/js/src/js.c
Normal file
1545
mozilla/js/src/js.c
Normal file
File diff suppressed because it is too large
Load Diff
184
mozilla/js/src/js.dsp
Normal file
184
mozilla/js/src/js.dsp
Normal file
@@ -0,0 +1,184 @@
|
||||
# Microsoft Developer Studio Project File - Name="jsshell" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=jsshell - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "js.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "js.mak" CFG="jsshell - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "jsshell - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "jsshell - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "jsshell - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\jsshell_"
|
||||
# PROP BASE Intermediate_Dir ".\jsshell_"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir ".\Release"
|
||||
# PROP Intermediate_Dir ".\Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "mininspr" /D "NDEBUG" /D "_CONSOLE" /D "_WIN32" /D "WIN32" /D "XP_PC" /D "_WINDOWS" /D "JSFILE" /D "MINI_NSPR" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:".\Release\jsshell.exe"
|
||||
|
||||
!ELSEIF "$(CFG)" == "jsshell - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\jsshell0"
|
||||
# PROP BASE Intermediate_Dir ".\jsshell0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir ".\Debug"
|
||||
# PROP Intermediate_Dir ".\Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "mininspr" /D "_DEBUG" /D "DEBUG" /D "_CONSOLE" /D "_WIN32" /D "WIN32" /D "XP_PC" /D "_WINDOWS" /D "JSFILE" /D "MINI_NSPR" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:".\Debug\jsshell.exe"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "jsshell - Win32 Release"
|
||||
# Name "jsshell - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\js.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsapi.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsatom.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jscntxt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsdbgapi.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsemit.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsfun.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsgc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsinterp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jslock.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsobj.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsopcode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsparse.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsprvtd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jspubtd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsregexp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsscan.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsscope.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsscript.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsstddef.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsstr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\prarena.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
56
mozilla/js/src/js.dsw
Normal file
56
mozilla/js/src/js.dsw
Normal file
@@ -0,0 +1,56 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 5.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "js32"=.\js32.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "jsshell"=.\js.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name js32
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "miniNSPR"=.\miniNSPR.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
3756
mozilla/js/src/js.mak
Normal file
3756
mozilla/js/src/js.mak
Normal file
File diff suppressed because it is too large
Load Diff
BIN
mozilla/js/src/js.mdp
Normal file
BIN
mozilla/js/src/js.mdp
Normal file
Binary file not shown.
194
mozilla/js/src/js.msg
Normal file
194
mozilla/js/src/js.msg
Normal file
@@ -0,0 +1,194 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
This is the JavaScript error message file.
|
||||
|
||||
The format for each JS error message is:
|
||||
|
||||
MSG_DEF(<SYMBOLIC_NAME>, <ERROR_NUMBER>, <ARGUMENT_COUNT>, <EXCEPTION_NAME>,
|
||||
<FORMAT_STRING>)
|
||||
|
||||
where ;
|
||||
<SYMBOLIC_NAME> is a legal C identifer that will be used in the
|
||||
JS engine source.
|
||||
|
||||
<ERROR_NUMBER> is an unique integral value identifying this error.
|
||||
|
||||
<ARGUMENT_COUNT> is an integer literal specifying the total number of
|
||||
replaceable arguments in the following format string.
|
||||
|
||||
<EXCEPTION_NAME> is an exception index from the enum in jsexn.c;
|
||||
JSEXN_NONE for none. The given exception index will be raised by the
|
||||
engine when the corresponding error occurs.
|
||||
|
||||
<FORMAT_STRING> is a string literal, optionally containing sequences
|
||||
{X} where X is an integer representing the argument number that will
|
||||
be replaced with a string value when the error is reported.
|
||||
|
||||
e.g.
|
||||
|
||||
MSG_DEF(JSMSG_NOT_A_SUBSPECIES, 73, JSEXN_NONE, 2,
|
||||
"{0} is not a member of the {1} family")
|
||||
|
||||
can be used :
|
||||
|
||||
JS_ReportErrorNumber(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey");
|
||||
|
||||
to report :
|
||||
|
||||
"Rhino is not a member of the Monkey family"
|
||||
|
||||
*/
|
||||
|
||||
MSG_DEF(JSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
|
||||
MSG_DEF(JSMSG_NOT_DEFINED, 1, 1, JSEXN_REFERENCEERR, "{0} is not defined")
|
||||
MSG_DEF(JSMSG_NO_REG_EXPS, 2, 1, JSEXN_INTERNALERR, "sorry, regular expression are not supported")
|
||||
MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, 3, JSEXN_NONE, "{0} requires more than {1} argument{2}")
|
||||
MSG_DEF(JSMSG_BAD_CHAR, 4, 1, JSEXN_NONE, "invalid format character {0}")
|
||||
MSG_DEF(JSMSG_BAD_TYPE, 5, 1, JSEXN_NONE, "unknown type {0}")
|
||||
MSG_DEF(JSMSG_CANT_LOCK, 6, 0, JSEXN_NONE, "can't lock memory")
|
||||
MSG_DEF(JSMSG_CANT_UNLOCK, 7, 0, JSEXN_NONE, "can't unlock memory")
|
||||
MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 8, 3, JSEXN_TARGETERR, "{0}.prototype.{1} called on incompatible {2}")
|
||||
MSG_DEF(JSMSG_NO_CONSTRUCTOR, 9, 1, JSEXN_NONE, "{0} has no constructor")
|
||||
MSG_DEF(JSMSG_CANT_ALIAS, 10, 3, JSEXN_NONE, "can't alias {0} to {1} in class {2}")
|
||||
MSG_DEF(JSMSG_NO_PROTO, 11, 1, JSEXN_INTERNALERR, "sorry, Array.prototype.{0} is not yet implemented")
|
||||
MSG_DEF(JSMSG_BAD_SORT_ARG, 12, 0, JSEXN_ARRAYERR, "invalid Array.prototype.sort argument")
|
||||
MSG_DEF(JSMSG_BAD_ATOMIC_NUMBER, 13, 1, JSEXN_INTERNALERR, "internal error: no index for atom {0}")
|
||||
MSG_DEF(JSMSG_TOO_MANY_LITERALS, 14, 0, JSEXN_INTERNALERR, "too many literals")
|
||||
MSG_DEF(JSMSG_CANT_WATCH, 15, 1, JSEXN_NONE, "can't watch non-native objects of class {0}")
|
||||
MSG_DEF(JSMSG_STACK_UNDERFLOW, 16, 2, JSEXN_INTERNALERR, "internal error compiling {0}: stack underflow at pc {1}")
|
||||
MSG_DEF(JSMSG_NEED_DIET, 17, 1, JSEXN_SYNTAXERR, "{0} too large")
|
||||
MSG_DEF(JSMSG_BAD_CASE, 18, 2, JSEXN_SYNTAXERR, "{0}, line {1}: invalid case expression")
|
||||
MSG_DEF(JSMSG_READ_ONLY, 19, 1, JSEXN_ERR, "{0} is read-only")
|
||||
MSG_DEF(JSMSG_BAD_FORMAL, 20, 0, JSEXN_SYNTAXERR, "malformed formal parameter")
|
||||
MSG_DEF(JSMSG_SAME_FORMAL, 21, 1, JSEXN_NONE, "duplicate formal argument {0}")
|
||||
MSG_DEF(JSMSG_NOT_FUNCTION, 22, 1, JSEXN_CALLERR, "{0} is not a function")
|
||||
MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 23, 1, JSEXN_CONSTRUCTORERR, "{0} is not a constructor")
|
||||
MSG_DEF(JSMSG_STACK_OVERFLOW, 24, 1, JSEXN_NONE, "stack overflow in {0}")
|
||||
MSG_DEF(JSMSG_NOT_EXPORTED, 25, 1, JSEXN_NONE, "{0} is not exported")
|
||||
MSG_DEF(JSMSG_OVER_RECURSED, 26, 0, JSEXN_NONE, "too much recursion")
|
||||
MSG_DEF(JSMSG_IN_NOT_OBJECT, 27, 0, JSEXN_ERR, "target of 'in' operator must be an object")
|
||||
MSG_DEF(JSMSG_BAD_NEW_RESULT, 28, 1, JSEXN_NONE, "invalid new expression result {0}")
|
||||
MSG_DEF(JSMSG_BAD_SHARP_DEF, 29, 1, JSEXN_ERR, "invalid sharp variable definition #{0}=")
|
||||
MSG_DEF(JSMSG_BAD_SHARP_USE, 30, 1, JSEXN_ERR, "invalid sharp variable use #{0}#")
|
||||
MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 31, 1, JSEXN_ERR, "invalid instanceof operand {0}")
|
||||
MSG_DEF(JSMSG_BAD_BYTECODE, 32, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
|
||||
MSG_DEF(JSMSG_BAD_RADIX, 33, 1, JSEXN_ERR, "illegal radix {0}")
|
||||
MSG_DEF(JSMSG_NAN, 34, 1, JSEXN_ERR, "{0} is not a number")
|
||||
MSG_DEF(JSMSG_CANT_CONVERT, 35, 1, JSEXN_TOPRIMITIVEERR, "can't convert {0} to an integer")
|
||||
MSG_DEF(JSMSG_CYCLIC_VALUE, 36, 1, JSEXN_ERR, "cyclic {0} value")
|
||||
MSG_DEF(JSMSG_PERMANENT, 37, 1, JSEXN_ERR, "{0} is permanent")
|
||||
MSG_DEF(JSMSG_CANT_CONVERT_TO, 38, 2, JSEXN_DEFAULTVALUEERR, "can't convert {0} to {1}")
|
||||
MSG_DEF(JSMSG_NO_PROPERTIES, 39, 1, JSEXN_TOOBJECTERR, "{0} has no properties")
|
||||
MSG_DEF(JSMSG_CANT_FIND_CLASS, 40, 1, JSEXN_NONE, "can't find class id {0}")
|
||||
MSG_DEF(JSMSG_CANT_XDR_CLASS, 41, 1, JSEXN_NONE, "can't XDR class {0}")
|
||||
MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 42, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
|
||||
MSG_DEF(JSMSG_UNKNOWN_FORMAT, 43, 1, JSEXN_INTERNALERR, "unknown bytecode format {0}")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CON_ARGS, 44, 0, JSEXN_SYNTAXERR, "too many constructor arguments")
|
||||
MSG_DEF(JSMSG_TOO_MANY_FUN_ARGS, 45, 0, JSEXN_SYNTAXERR, "too many function arguments")
|
||||
MSG_DEF(JSMSG_BAD_QUANTIFIER, 46, 1, JSEXN_SYNTAXERR, "invalid quantifier {0}")
|
||||
MSG_DEF(JSMSG_MIN_TOO_BIG, 47, 1, JSEXN_SYNTAXERR, "overlarge minimum {0}")
|
||||
MSG_DEF(JSMSG_MAX_TOO_BIG, 48, 1, JSEXN_SYNTAXERR, "overlarge maximum {0}")
|
||||
MSG_DEF(JSMSG_OUT_OF_ORDER, 49, 1, JSEXN_SYNTAXERR, "maximum {0} less than minimum")
|
||||
MSG_DEF(JSMSG_ZERO_QUANTIFIER, 50, 1, JSEXN_SYNTAXERR, "zero quantifier {0}")
|
||||
MSG_DEF(JSMSG_UNTERM_QUANTIFIER, 51, 1, JSEXN_SYNTAXERR, "unterminated quantifier {0}")
|
||||
MSG_DEF(JSMSG_EMPTY_BEFORE_STAR, 52, 0, JSEXN_SYNTAXERR, "regular expression before * could be empty")
|
||||
MSG_DEF(JSMSG_EMPTY_BEFORE_PLUS, 53, 0, JSEXN_SYNTAXERR, "regular expression before + could be empty")
|
||||
MSG_DEF(JSMSG_MISSING_PAREN, 54, 1, JSEXN_SYNTAXERR, "unterminated parenthetical {0}")
|
||||
MSG_DEF(JSMSG_UNTERM_CLASS, 55, 1, JSEXN_SYNTAXERR, "unterminated character class {0}")
|
||||
MSG_DEF(JSMSG_TRAILING_SLASH, 56, 0, JSEXN_SYNTAXERR, "trailing \\ in regular expression")
|
||||
MSG_DEF(JSMSG_BAD_CLASS_RANGE, 57, 0, JSEXN_SYNTAXERR, "invalid range in character class")
|
||||
MSG_DEF(JSMSG_BAD_FLAG, 58, 1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}")
|
||||
MSG_DEF(JSMSG_NO_INPUT, 59, 3, JSEXN_SYNTAXERR, "no input for /{0}/{1}{2}")
|
||||
MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_NONE, "can't open {0}: {1}")
|
||||
MSG_DEF(JSMSG_BAD_STRING_MASK, 61, 1, JSEXN_ERR, "invalid string escape mask {0}")
|
||||
MSG_DEF(JSMSG_NO_STRING_PROTO, 62, 1, JSEXN_INTERNALERR, "sorry, String.prototype.{0} is not yet implemented")
|
||||
MSG_DEF(JSMSG_END_OF_DATA, 63, 0, JSEXN_NONE, "unexpected end of data")
|
||||
MSG_DEF(JSMSG_SEEK_BEYOND_START, 64, 0, JSEXN_NONE, "illegal seek beyond start")
|
||||
MSG_DEF(JSMSG_SEEK_BEYOND_END, 65, 0, JSEXN_NONE, "illegal seek beyond end")
|
||||
MSG_DEF(JSMSG_END_SEEK, 66, 0, JSEXN_NONE, "illegal end-based seek")
|
||||
MSG_DEF(JSMSG_WHITHER_WHENCE, 67, 1, JSEXN_NONE, "unknown seek whence: {0}")
|
||||
MSG_DEF(JSMSG_BAD_JVAL_TYPE, 68, 1, JSEXN_NONE, "unknown jsval type {0} for XDR")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")
|
||||
MSG_DEF(JSMSG_MISSING_FORMAL, 70, 0, JSEXN_SYNTAXERR, "missing formal parameter")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 71, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 72, 0, JSEXN_SYNTAXERR, "missing { before function body")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_BODY, 73, 0, JSEXN_SYNTAXERR, "missing } after function body")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_COND, 74, 0, JSEXN_SYNTAXERR, "missing ( before condition")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_COND, 75, 0, JSEXN_SYNTAXERR, "missing ) after condition")
|
||||
MSG_DEF(JSMSG_NO_IMPORT_NAME, 76, 0, JSEXN_SYNTAXERR, "missing name in import statement")
|
||||
MSG_DEF(JSMSG_NAME_AFTER_DOT, 77, 0, JSEXN_SYNTAXERR, "missing name after . operator")
|
||||
MSG_DEF(JSMSG_BRACKET_IN_INDEX, 78, 0, JSEXN_SYNTAXERR, "missing ] in index expression")
|
||||
MSG_DEF(JSMSG_NO_EXPORT_NAME, 79, 0, JSEXN_SYNTAXERR, "missing name in export statement")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 80, 0, JSEXN_SYNTAXERR, "missing ( before switch expression")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 81, 0, JSEXN_SYNTAXERR, "missing ) after switch expression")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 82, 0, JSEXN_SYNTAXERR, "missing { before switch body")
|
||||
MSG_DEF(JSMSG_COLON_AFTER_CASE, 83, 0, JSEXN_SYNTAXERR, "missing : after case label")
|
||||
MSG_DEF(JSMSG_WHILE_AFTER_DO, 84, 0, JSEXN_SYNTAXERR, "missing while after do-loop body")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_FOR, 85, 0, JSEXN_SYNTAXERR, "missing ( after for")
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 86, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 87, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 88, 0, JSEXN_SYNTAXERR, "missing ) after for-loop control")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 89, 0, JSEXN_SYNTAXERR, "missing { before try block")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_TRY, 90, 0, JSEXN_SYNTAXERR, "missing } after try block")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 91, 0, JSEXN_SYNTAXERR, "missing ( before catch")
|
||||
MSG_DEF(JSMSG_CATCH_IDENTIFIER, 92, 0, JSEXN_SYNTAXERR, "missing identifier in catch")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 93, 0, JSEXN_SYNTAXERR, "missing ) after catch")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 94, 0, JSEXN_SYNTAXERR, "missing { before catch block")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 95, 0, JSEXN_SYNTAXERR, "missing } after catch block")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 96, 0, JSEXN_SYNTAXERR, "missing { before finally block")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 97, 0, JSEXN_SYNTAXERR, "missing } after finally block")
|
||||
MSG_DEF(JSMSG_CATCH_OR_FINALLY, 98, 0, JSEXN_SYNTAXERR, "missing catch or finally after try")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 99, 0, JSEXN_SYNTAXERR, "missing ( before with-statement object")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_WITH, 100, 0, JSEXN_SYNTAXERR, "missing ) after with-statement object")
|
||||
MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 101, 0, JSEXN_SYNTAXERR, "missing } in compound statement")
|
||||
MSG_DEF(JSMSG_NO_VARIABLE_NAME, 102, 0, JSEXN_SYNTAXERR, "missing variable name")
|
||||
MSG_DEF(JSMSG_COLON_IN_COND, 103, 0, JSEXN_SYNTAXERR, "missing : in conditional expression")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 104, 0, JSEXN_SYNTAXERR, "missing ) after argument list")
|
||||
MSG_DEF(JSMSG_BRACKET_AFTER_LIST, 105, 0, JSEXN_SYNTAXERR, "missing ] after element list")
|
||||
MSG_DEF(JSMSG_COLON_AFTER_ID, 106, 0, JSEXN_SYNTAXERR, "missing : after property id")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_LIST, 107, 0, JSEXN_SYNTAXERR, "missing } after property list")
|
||||
MSG_DEF(JSMSG_PAREN_IN_PAREN, 108, 0, JSEXN_SYNTAXERR, "missing ) in parenthetical")
|
||||
MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 109, 0, JSEXN_SYNTAXERR, "missing ; before statement")
|
||||
MSG_DEF(JSMSG_NO_RETURN_VALUE, 110, 0, JSEXN_NONE, "function does not always return a value")
|
||||
MSG_DEF(JSMSG_DUPLICATE_FORMAL, 111, 1, JSEXN_NONE, "duplicate formal argument {0}")
|
||||
MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 112, 1, JSEXN_NONE, "test for equality (==) mistyped as assignment (=)?{0}")
|
||||
MSG_DEF(JSMSG_BAD_IMPORT, 113, 0, JSEXN_SYNTAXERR, "invalid import expression")
|
||||
MSG_DEF(JSMSG_TOO_MANY_DEFAULTS, 114, 0, JSEXN_SYNTAXERR, "more than one switch default")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CASES, 115, 0, JSEXN_INTERNALERR, "too many switch cases")
|
||||
MSG_DEF(JSMSG_BAD_SWITCH, 116, 0, JSEXN_SYNTAXERR, "invalid switch statement")
|
||||
MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 117, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side")
|
||||
MSG_DEF(JSMSG_CATCH_AFTER_GENERAL, 118, 0, JSEXN_NONE, "catch clause after general catch")
|
||||
MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 119, 0, JSEXN_SYNTAXERR, "catch without try")
|
||||
MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 120, 0, JSEXN_SYNTAXERR, "finally without try")
|
||||
MSG_DEF(JSMSG_LABEL_NOT_FOUND, 121, 0, JSEXN_SYNTAXERR, "label not found")
|
||||
MSG_DEF(JSMSG_TOUGH_BREAK, 122, 0, JSEXN_SYNTAXERR, "invalid break")
|
||||
MSG_DEF(JSMSG_BAD_CONTINUE, 123, 0, JSEXN_SYNTAXERR, "invalid continue")
|
||||
MSG_DEF(JSMSG_BAD_RETURN, 124, 0, JSEXN_SYNTAXERR, "invalid return")
|
||||
MSG_DEF(JSMSG_BAD_LABEL, 125, 0, JSEXN_SYNTAXERR, "invalid label")
|
||||
MSG_DEF(JSMSG_DUPLICATE_LABEL, 126, 0, JSEXN_SYNTAXERR, "duplicate label")
|
||||
MSG_DEF(JSMSG_VAR_HIDES_ARG, 127, 1, JSEXN_NONE, "variable {0} hides argument")
|
||||
MSG_DEF(JSMSG_BAD_VAR_INIT, 128, 0, JSEXN_SYNTAXERR, "invalid variable initialization")
|
||||
MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 129, 0, JSEXN_SYNTAXERR, "invalid assignment left-hand side")
|
||||
MSG_DEF(JSMSG_BAD_OPERAND, 130, 1, JSEXN_SYNTAXERR, "invalid {0} operand")
|
||||
MSG_DEF(JSMSG_BAD_PROP_ID, 131, 0, JSEXN_SYNTAXERR, "invalid property id")
|
||||
MSG_DEF(JSMSG_RESERVED_ID, 132, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier")
|
||||
MSG_DEF(JSMSG_SYNTAX_ERROR, 133, 0, JSEXN_SYNTAXERR, "syntax error")
|
||||
MSG_DEF(JSMSG_BAD_SHARP_VAR_DEF, 134, 0, JSEXN_SYNTAXERR, "invalid sharp variable definition")
|
||||
MSG_DEF(JSMSG_BAD_PROTOTYPE, 135, 1, JSEXN_ERR, "'prototype' property of {0} is not an object")
|
||||
130
mozilla/js/src/js11640.def
Normal file
130
mozilla/js/src/js11640.def
Normal file
@@ -0,0 +1,130 @@
|
||||
; 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.
|
||||
LIBRARY JS1640.DLL
|
||||
EXETYPE WINDOWS
|
||||
PROTMODE
|
||||
|
||||
DESCRIPTION 'Netscape 16-bit JavaScript Library'
|
||||
|
||||
CODE LOADONCALL MOVEABLE DISCARDABLE
|
||||
DATA PRELOAD MOVEABLE SINGLE
|
||||
|
||||
HEAPSIZE 8192
|
||||
|
||||
EXPORTS
|
||||
WEP @1 RESIDENTNAME NONAME
|
||||
_JS_Init = _JS_Init @2
|
||||
_JS_Finish = _JS_Finish @3
|
||||
_JS_GetNaNValue
|
||||
_JS_GetNegativeInfinityValue
|
||||
_JS_GetPositiveInfinityValue
|
||||
_JS_GetEmptyStringValue
|
||||
_JS_ConvertValue
|
||||
_JS_ValueToObject
|
||||
_JS_ValueToFunction
|
||||
_JS_ValueToString
|
||||
_JS_ValueToNumber
|
||||
_JS_ValueToBoolean
|
||||
_JS_TypeOfValue
|
||||
_JS_GetTypeName
|
||||
_JS_Lock
|
||||
_JS_Unlock
|
||||
_JS_NewContext
|
||||
_JS_DestroyContext
|
||||
_JS_ContextIterator
|
||||
_JS_GetGlobalObject
|
||||
_JS_SetGlobalObject
|
||||
_JS_InitStandardClasses
|
||||
; _JS_GetStaticLink
|
||||
_JS_malloc
|
||||
_JS_realloc
|
||||
_JS_free
|
||||
_JS_strdup
|
||||
_JS_NewDouble
|
||||
_JS_NewDoubleValue
|
||||
_JS_AddRoot
|
||||
_JS_RemoveRoot
|
||||
_JS_LockGCThing
|
||||
_JS_UnlockGCThing
|
||||
_JS_GC
|
||||
_JS_PropertyStub
|
||||
_JS_EnumerateStub
|
||||
_JS_ResolveStub
|
||||
_JS_ConvertStub
|
||||
_JS_FinalizeStub
|
||||
_JS_InitClass
|
||||
_JS_GetClass
|
||||
_JS_InstanceOf
|
||||
_JS_GetPrivate
|
||||
_JS_SetPrivate
|
||||
_JS_GetInstancePrivate
|
||||
_JS_GetPrototype
|
||||
_JS_GetParent
|
||||
_JS_SetParent
|
||||
_JS_GetConstructor
|
||||
_JS_NewObject
|
||||
_JS_DefineObject
|
||||
_JS_DefineConstDoubles
|
||||
_JS_DefineProperties
|
||||
_JS_DefineProperty
|
||||
_JS_DefinePropertyWithTinyId
|
||||
_JS_AliasProperty
|
||||
_JS_LookupProperty
|
||||
_JS_GetProperty
|
||||
_JS_SetProperty
|
||||
_JS_DeleteProperty
|
||||
_JS_NewArrayObject
|
||||
_JS_DefineElement
|
||||
_JS_AliasElement
|
||||
_JS_LookupElement
|
||||
_JS_GetElement
|
||||
_JS_SetElement
|
||||
_JS_DeleteElement
|
||||
_JS_ClearScope
|
||||
_JS_NewFunction
|
||||
_JS_GetFunctionObject
|
||||
_JS_GetFunctionName
|
||||
_JS_DefineFunctions
|
||||
_JS_DefineFunction
|
||||
_JS_CompileScript
|
||||
_JS_DestroyScript
|
||||
_JS_CompileFunction
|
||||
_JS_DecompileScript
|
||||
_JS_DecompileFunction
|
||||
_JS_DecompileFunctionBody
|
||||
_JS_ExecuteScript
|
||||
_JS_EvaluateScript
|
||||
_JS_CallFunction
|
||||
_JS_CallFunctionName
|
||||
_JS_CallFunctionValue
|
||||
_JS_SetBranchCallback
|
||||
_JS_IsRunning
|
||||
_JS_NewString
|
||||
_JS_NewStringCopyN
|
||||
_JS_NewStringCopyZ
|
||||
_JS_InternString
|
||||
_JS_GetStringBytes
|
||||
_JS_GetStringLength
|
||||
_JS_CompareStrings
|
||||
_JS_ReportError
|
||||
_JS_ReportOutOfMemory
|
||||
_JS_SetErrorReporter
|
||||
_JS_NewRegExpObject
|
||||
_JS_SetRegExpInput
|
||||
_JS_ClearRegExpStatics
|
||||
|
||||
IMPORTS
|
||||
_printf = nspr21.11
|
||||
_strftime = nspr21.13
|
||||
137
mozilla/js/src/js1640.def
Normal file
137
mozilla/js/src/js1640.def
Normal file
@@ -0,0 +1,137 @@
|
||||
LIBRARY JS1640.DLL
|
||||
EXETYPE WINDOWS
|
||||
PROTMODE
|
||||
|
||||
DESCRIPTION 'Netscape 16-bit JavaScript Library'
|
||||
|
||||
CODE LOADONCALL MOVEABLE DISCARDABLE
|
||||
DATA PRELOAD MOVEABLE SINGLE
|
||||
|
||||
HEAPSIZE 8192
|
||||
|
||||
EXPORTS
|
||||
WEP @1 RESIDENTNAME NONAME
|
||||
_JS_Init = _JS_Init @2
|
||||
_JS_Finish = _JS_Finish @3
|
||||
_JS_GetNaNValue
|
||||
_JS_GetNegativeInfinityValue
|
||||
_JS_GetPositiveInfinityValue
|
||||
_JS_GetEmptyStringValue
|
||||
_JS_ConvertValue
|
||||
_JS_ValueToObject
|
||||
_JS_ValueToFunction
|
||||
_JS_ValueToString
|
||||
_JS_ValueToNumber
|
||||
_JS_ValueToBoolean
|
||||
_JS_TypeOfValue
|
||||
_JS_GetTypeName
|
||||
_JS_Lock
|
||||
_JS_Unlock
|
||||
_JS_NewContext
|
||||
_JS_DestroyContext
|
||||
_JS_ContextIterator
|
||||
_JS_GetGlobalObject
|
||||
_JS_SetGlobalObject
|
||||
_JS_InitStandardClasses
|
||||
; _JS_GetStaticLink
|
||||
_JS_malloc
|
||||
_JS_realloc
|
||||
_JS_free
|
||||
_JS_strdup
|
||||
_JS_NewDouble
|
||||
_JS_NewDoubleValue
|
||||
_JS_AddRoot
|
||||
_JS_RemoveRoot
|
||||
_JS_LockGCThing
|
||||
_JS_UnlockGCThing
|
||||
_JS_GC
|
||||
_JS_PropertyStub
|
||||
_JS_EnumerateStub
|
||||
_JS_ResolveStub
|
||||
_JS_ConvertStub
|
||||
_JS_FinalizeStub
|
||||
_JS_InitClass
|
||||
_JS_GetClass
|
||||
_JS_InstanceOf
|
||||
_JS_GetPrivate
|
||||
_JS_SetPrivate
|
||||
_JS_GetInstancePrivate
|
||||
_JS_GetPrototype
|
||||
_JS_GetParent
|
||||
_JS_SetParent
|
||||
_JS_GetConstructor
|
||||
_JS_NewObject
|
||||
_JS_DefineObject
|
||||
_JS_DefineConstDoubles
|
||||
_JS_DefineProperties
|
||||
_JS_DefineProperty
|
||||
_JS_DefinePropertyWithTinyId
|
||||
_JS_AliasProperty
|
||||
_JS_LookupProperty
|
||||
_JS_GetProperty
|
||||
_JS_SetProperty
|
||||
_JS_DeleteProperty
|
||||
_JS_NewArrayObject
|
||||
_JS_DefineElement
|
||||
_JS_AliasElement
|
||||
_JS_LookupElement
|
||||
_JS_GetElement
|
||||
_JS_SetElement
|
||||
_JS_DeleteElement
|
||||
_JS_ClearScope
|
||||
_JS_NewFunction
|
||||
_JS_GetFunctionObject
|
||||
_JS_GetFunctionName
|
||||
_JS_DefineFunctions
|
||||
_JS_DefineFunction
|
||||
_JS_CompileScript
|
||||
_JS_DestroyScript
|
||||
_JS_CompileFunction
|
||||
_JS_DecompileScript
|
||||
_JS_DecompileFunction
|
||||
_JS_DecompileFunctionBody
|
||||
_JS_ExecuteScript
|
||||
_JS_EvaluateScript
|
||||
_JS_CallFunction
|
||||
_JS_CallFunctionName
|
||||
_JS_CallFunctionValue
|
||||
_JS_SetBranchCallback
|
||||
_JS_IsRunning
|
||||
_JS_NewString
|
||||
_JS_NewStringCopyN
|
||||
_JS_NewStringCopyZ
|
||||
_JS_InternString
|
||||
_JS_GetStringBytes
|
||||
_JS_GetStringLength
|
||||
_JS_CompareStrings
|
||||
_JS_ReportError
|
||||
_JS_ReportOutOfMemory
|
||||
_JS_SetErrorReporter
|
||||
_JS_NewRegExpObject
|
||||
_JS_SetRegExpInput
|
||||
_JS_ClearRegExpStatics
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
60
mozilla/js/src/js1640.rc
Normal file
60
mozilla/js/src/js1640.rc
Normal file
@@ -0,0 +1,60 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 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 Module\0"
|
||||
|
||||
VALUE "FileVersion", "4.0\0"
|
||||
|
||||
VALUE "InternalName", "JS1640\0"
|
||||
|
||||
VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
|
||||
|
||||
VALUE "LegalTrademarks", "Netscape, Mozilla\0"
|
||||
|
||||
VALUE "OriginalFilename","JS1640.DLL\0"
|
||||
|
||||
VALUE "ProductName", "NETSCAPE\0"
|
||||
|
||||
VALUE "ProductVersion", "4.0\0"
|
||||
|
||||
END
|
||||
|
||||
END
|
||||
|
||||
END
|
||||
|
||||
318
mozilla/js/src/js32.dsp
Normal file
318
mozilla/js/src/js32.dsp
Normal file
@@ -0,0 +1,318 @@
|
||||
# Microsoft Developer Studio Project File - Name="js32" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=js32 - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "js32.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "js32.mak" CFG="js32 - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "js32 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "js32 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "js32 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\js32\Release"
|
||||
# PROP BASE Intermediate_Dir ".\js32\Release"
|
||||
# PROP BASE Target_Dir ".\js32"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir ".\Release"
|
||||
# PROP Intermediate_Dir ".\Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ".\js32"
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "mininspr" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "WIN32" /D "XP_PC" /D "JSFILE" /D "EXPORT_JS_API" /D "MINI_NSPR" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
# ADD LINK32 H:\ns\dist\WINNT4.0_OPT.OBJ\lib\libnspr21_s.lib H:\ns\dist\WINNT4.0_OPT.OBJ\lib\libplds21_s.lib winmm.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "js32 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\js32\Debug"
|
||||
# PROP BASE Intermediate_Dir ".\js32\Debug"
|
||||
# PROP BASE Target_Dir ".\js32"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir ".\Debug"
|
||||
# PROP Intermediate_Dir ".\Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ".\js32"
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "mininspr" /D "_DEBUG" /D "DEBUG" /D "_WINDOWS" /D "_WIN32" /D "WIN32" /D "XP_PC" /D "JSFILE" /D "EXPORT_JS_API" /D "MINI_NSPR" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
|
||||
# ADD LINK32 H:\ns\dist\WINNT4.0_DBG.OBJ\lib\libnspr21_s.lib H:\ns\dist\WINNT4.0_DBG.OBJ\lib\libplds21_s.lib winmm.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "js32 - Win32 Release"
|
||||
# Name "js32 - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsapi.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsarray.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsatom.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsbool.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jscntxt.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsdate.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsdbgapi.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsemit.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsfun.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsgc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsinterp.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jslock.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsmath.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsnum.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsobj.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsopcode.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsparse.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsregexp.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsscan.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsscope.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsscript.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsstr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsxdrapi.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\prarena.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\prmjtime.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsapi.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsarray.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsatom.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsbool.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jscntxt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsconfig.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsdate.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsdbgapi.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsemit.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsfun.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsgc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsinterp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jslock.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsmath.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsnum.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsobj.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsopcode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsparse.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsprvtd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jspubtd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsregexp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsscan.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsscope.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsscript.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsstddef.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsstr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\jsxdrapi.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\prarena.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\prdtoa.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
79
mozilla/js/src/js3240.rc
Normal file
79
mozilla/js/src/js3240.rc
Normal file
@@ -0,0 +1,79 @@
|
||||
//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 Module\0"
|
||||
VALUE "FileVersion", "4.0\0"
|
||||
VALUE "InternalName", "JS3240\0"
|
||||
VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
|
||||
VALUE "LegalTrademarks", "Netscape, Mozilla\0"
|
||||
VALUE "OriginalFilename", "js3240.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
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
623
mozilla/js/src/jsOS240.def
Normal file
623
mozilla/js/src/jsOS240.def
Normal file
@@ -0,0 +1,623 @@
|
||||
; 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.
|
||||
|
||||
LIBRARY JS3240 INITINSTANCE TERMINSTANCE
|
||||
PROTMODE
|
||||
|
||||
DESCRIPTION 'Netscape OS/2 JavaScript Library'
|
||||
|
||||
|
||||
CODE LOADONCALL MOVEABLE DISCARDABLE
|
||||
DATA PRELOAD MOVEABLE MULTIPLE NONSHARED
|
||||
|
||||
|
||||
EXPORTS
|
||||
;====================== win16 exports these at least... ===========
|
||||
; JS_Init = JS_Init @2
|
||||
; JS_Finish = JS_Finish @3
|
||||
; JS_GetNaNValue
|
||||
; JS_GetNegativeInfinityValue
|
||||
; JS_GetPositiveInfinityValue
|
||||
; JS_GetEmptyStringValue
|
||||
; JS_ConvertValue
|
||||
; JS_ValueToObject
|
||||
; JS_ValueToFunction
|
||||
; JS_ValueToString
|
||||
; JS_ValueToNumber
|
||||
; JS_ValueToBoolean
|
||||
; JS_TypeOfValue
|
||||
; JS_GetTypeName
|
||||
; JS_Lock
|
||||
; JS_Unlock
|
||||
; JS_NewContext
|
||||
; JS_DestroyContext
|
||||
; JS_ContextIterator
|
||||
; JS_GetGlobalObject
|
||||
; JS_SetGlobalObject
|
||||
; JS_InitStandardClasses
|
||||
;; JS_GetStaticLink
|
||||
; JS_malloc
|
||||
; JS_realloc
|
||||
; JS_free
|
||||
; JS_strdup
|
||||
; JS_NewDouble
|
||||
; JS_NewDoubleValue
|
||||
; JS_AddRoot
|
||||
; JS_RemoveRoot
|
||||
; JS_LockGCThing
|
||||
; JS_UnlockGCThing
|
||||
; JS_GC
|
||||
; JS_PropertyStub
|
||||
; JS_EnumerateStub
|
||||
; JS_ResolveStub
|
||||
; JS_ConvertStub
|
||||
; JS_FinalizeStub
|
||||
; JS_InitClass
|
||||
; JS_GetClass
|
||||
; JS_InstanceOf
|
||||
; JS_GetPrivate
|
||||
; JS_SetPrivate
|
||||
; JS_GetInstancePrivate
|
||||
; JS_GetPrototype
|
||||
; JS_GetParent
|
||||
; JS_SetParent
|
||||
; JS_GetConstructor
|
||||
; JS_NewObject
|
||||
; JS_DefineObject
|
||||
; JS_DefineConstDoubles
|
||||
; JS_DefineProperties
|
||||
; JS_DefineProperty
|
||||
; JS_DefinePropertyWithTinyId
|
||||
; JS_AliasProperty
|
||||
; JS_LookupProperty
|
||||
; JS_GetProperty
|
||||
; JS_SetProperty
|
||||
; JS_DeleteProperty
|
||||
; JS_NewArrayObject
|
||||
; JS_DefineElement
|
||||
; JS_AliasElement
|
||||
; JS_LookupElement
|
||||
; JS_GetElement
|
||||
; JS_SetElement
|
||||
; JS_DeleteElement
|
||||
; JS_ClearScope
|
||||
; JS_NewFunction
|
||||
; JS_GetFunctionObject
|
||||
; JS_GetFunctionName
|
||||
; JS_DefineFunctions
|
||||
; JS_DefineFunction
|
||||
; JS_CompileScript
|
||||
; JS_DestroyScript
|
||||
; JS_CompileFunction
|
||||
; JS_DecompileScript
|
||||
; JS_DecompileFunction
|
||||
; JS_DecompileFunctionBody
|
||||
; JS_ExecuteScript
|
||||
; JS_EvaluateScript
|
||||
; JS_CallFunction
|
||||
; JS_CallFunctionName
|
||||
; JS_CallFunctionValue
|
||||
; JS_SetBranchCallback
|
||||
; JS_IsRunning
|
||||
; JS_NewString
|
||||
; JS_NewStringCopyN
|
||||
; JS_NewStringCopyZ
|
||||
; JS_InternString
|
||||
; JS_GetStringBytes
|
||||
; JS_GetStringLength
|
||||
; JS_CompareStrings
|
||||
; JS_ReportError
|
||||
; JS_ReportOutOfMemory
|
||||
; JS_SetErrorReporter
|
||||
; JS_NewRegExpObject
|
||||
; JS_SetRegExpInput
|
||||
; JS_ClearRegExpStatics
|
||||
;=================================================
|
||||
|
||||
|
||||
;00001:jsstr (OFFSET:0x00002e17, SIZE:0x0000ae17):
|
||||
; - Public Definitions:
|
||||
; js_EmptySubString
|
||||
; js_CompareStrings
|
||||
; js_HashString
|
||||
; js_ValueToString
|
||||
; js_StringToObject
|
||||
; js_FinalizeString
|
||||
; js_NewStringCopyZ
|
||||
; js_NewString
|
||||
; js_InitStringClass
|
||||
; js_NewStringCopyN
|
||||
; js_BoyerMooreHorspool
|
||||
;
|
||||
;
|
||||
;00002:jsscript (OFFSET:0x0000dc2e, SIZE:0x00003abb):
|
||||
; - Public Definitions:
|
||||
; js_LineNumberToPC
|
||||
; js_PCToLineNumber
|
||||
; js_GetSrcNote
|
||||
; js_DestroyScript
|
||||
; js_NewScript
|
||||
;
|
||||
;
|
||||
;00003:jsscope (OFFSET:0x000116e9, SIZE:0x00004f82):
|
||||
; - Public Definitions:
|
||||
; js_hash_scope_ops
|
||||
; js_list_scope_ops
|
||||
; js_DestroyProperty
|
||||
; js_NewProperty
|
||||
; js_IdToValue
|
||||
; js_HashValue
|
||||
; js_DestroyScope
|
||||
; js_MutateScope
|
||||
; js_DropScope
|
||||
; js_HoldScope
|
||||
; js_NewScope
|
||||
; js_GetMutableScope
|
||||
; js_HoldProperty
|
||||
; js_DropProperty
|
||||
;
|
||||
;
|
||||
;00004:jsscan (OFFSET:0x0001666b, SIZE:0x00008890):
|
||||
; - Public Definitions:
|
||||
; js_MatchToken
|
||||
; js_FlushNewlines
|
||||
; js_PeekTokenSameLine
|
||||
; js_UngetToken
|
||||
; js_GetToken
|
||||
; js_PeekToken
|
||||
; js_ReportCompileError
|
||||
js_CloseTokenStream
|
||||
js_NewBufferTokenStream
|
||||
; js_NewTokenStream
|
||||
; js_InitScanner
|
||||
;
|
||||
;
|
||||
;00005:jsregexp (OFFSET:0x0001eefb, SIZE:0x0000eee4):
|
||||
; - Public Definitions:
|
||||
; js_RegExpClass
|
||||
; reopsize
|
||||
; js_NewRegExpObject
|
||||
; js_InitRegExpClass
|
||||
; js_FreeRegExpStatics
|
||||
; js_InitRegExpStatics
|
||||
; js_ExecuteRegExp
|
||||
; js_NewRegExpOpt
|
||||
; js_DestroyRegExp
|
||||
; js_NewRegExp
|
||||
;
|
||||
;
|
||||
;00006:jsparse (OFFSET:0x0002dddf, SIZE:0x00010b71):
|
||||
; - Public Definitions:
|
||||
; js_ParseFunctionBody
|
||||
js_Parse
|
||||
;
|
||||
;
|
||||
;00007:jsopcode (OFFSET:0x0003e950, SIZE:0x0000d362):
|
||||
; - Public Definitions:
|
||||
; js_EscapeMap
|
||||
; js_NumCodeSpecs
|
||||
; js_CodeSpec
|
||||
; js_incop_str
|
||||
; js_true_str
|
||||
; js_false_str
|
||||
; js_this_str
|
||||
; js_null_str
|
||||
; js_void_str
|
||||
; js_typeof_str
|
||||
; js_delete_str
|
||||
; js_new_str
|
||||
; js_ValueToSource
|
||||
; js_DecompileScript
|
||||
; js_DecompileCode
|
||||
; js_DecompileFunction
|
||||
; js_puts
|
||||
; js_printf
|
||||
; js_GetPrinterOutput
|
||||
; js_DestroyPrinter
|
||||
; js_NewPrinter
|
||||
; js_EscapeString
|
||||
; js_Disassemble1
|
||||
; js_Disassemble
|
||||
;
|
||||
;00008:jsobj (OFFSET:0x0004bcb2, SIZE:0x000090a4):
|
||||
; - Public Definitions:
|
||||
; js_WithClass
|
||||
; js_ObjectClass
|
||||
; js_TryValueOf
|
||||
; js_ValueToNonNullObject
|
||||
; js_TryMethod
|
||||
; js_ObjectToString
|
||||
; js_SetClassPrototype
|
||||
; js_DeleteProperty2
|
||||
; js_DeleteProperty
|
||||
; js_SetProperty
|
||||
; js_GetProperty
|
||||
; js_FindVariableScope
|
||||
; js_FindVariable
|
||||
; js_FindProperty
|
||||
; js_LookupProperty
|
||||
; js_DefineProperty
|
||||
; js_FreeSlot
|
||||
; js_AllocSlot
|
||||
; js_FinalizeObject
|
||||
; js_GetClassPrototype
|
||||
; js_NewObject
|
||||
; js_InitObjectClass
|
||||
; js_ValueToObject
|
||||
; js_obj_toString
|
||||
; js_SetSlot
|
||||
; js_GetSlot
|
||||
;
|
||||
;
|
||||
;00009:jsnum (OFFSET:0x00054d56, SIZE:0x00004f29):
|
||||
; - Public Definitions:
|
||||
; js_ValueToInt32
|
||||
; js_NumberToObject
|
||||
; js_FinalizeDouble
|
||||
; js_InitNumberClass
|
||||
; js_NumberToString
|
||||
; js_NewDoubleValue
|
||||
; js_NewDouble
|
||||
; js_ValueToNumber
|
||||
;
|
||||
;
|
||||
;00010:jsmath (OFFSET:0x00059c7f, SIZE:0x000054b6):
|
||||
; - Public Definitions:
|
||||
; js_InitMathClass
|
||||
;
|
||||
;
|
||||
;00011:jsjava (OFFSET:0x0005f135, SIZE:0x00022aad):
|
||||
; - Public Definitions:
|
||||
; js_Hooks
|
||||
; MojaSrcLog
|
||||
; finalizeTask
|
||||
JSJ_FindCurrentJSContext
|
||||
; JSJ_GetPrincipals
|
||||
JSJ_IsSafeMethod
|
||||
JSJ_InitContext
|
||||
JSJ_Init
|
||||
js_JSErrorToJException
|
||||
js_JavaErrorReporter
|
||||
js_RemoveReflection
|
||||
js_ReflectJObjectToJSObject
|
||||
js_convertJObjectToJSValue
|
||||
js_convertJSValueToJObject
|
||||
js_ReflectJSObjectToJObject
|
||||
; js_ReflectJClassToJSObject
|
||||
JSJ_ExitJS
|
||||
JSJ_EnterJS
|
||||
JSJ_CurrentContext
|
||||
JSJ_IsEnabled
|
||||
;added in GA code - DSR70297
|
||||
JSJ_Finish
|
||||
JSJ_IsCalledFromJava
|
||||
js_GetJSPrincipalsFromJavaCaller
|
||||
|
||||
;
|
||||
;
|
||||
;00012:jsinterp (OFFSET:0x00081be2, SIZE:0x00012274):
|
||||
; - Public Definitions:
|
||||
; js_Call
|
||||
; js_Interpret
|
||||
; js_SetLocalVariable
|
||||
; js_GetLocalVariable
|
||||
; js_SetArgument
|
||||
; js_GetArgument
|
||||
; js_FlushPropertyCacheByProp
|
||||
; js_FlushPropertyCache
|
||||
;
|
||||
;
|
||||
;00013:jsgc (OFFSET:0x00093e56, SIZE:0x00004f8d):
|
||||
; - Public Definitions:
|
||||
; js_ForceGC
|
||||
; js_UnlockGCThing
|
||||
; js_LockGCThing
|
||||
; js_GC
|
||||
; js_AllocGCThing
|
||||
; js_RemoveRoot
|
||||
; js_AddRoot
|
||||
; js_FinishGC
|
||||
; js_InitGC
|
||||
;
|
||||
;
|
||||
;00014:jsfun (OFFSET:0x00098de3, SIZE:0x0000977c):
|
||||
; - Public Definitions:
|
||||
; js_FunctionClass
|
||||
; js_ClosureClass
|
||||
; js_CallClass
|
||||
; js_DefineFunction
|
||||
; js_NewFunction
|
||||
; js_InitCallAndClosureClasses
|
||||
; js_InitFunctionClass
|
||||
; js_ValueToFunction
|
||||
; js_SetCallVariable
|
||||
; js_GetCallVariable
|
||||
; js_PutCallObject
|
||||
; js_GetCallObject
|
||||
;
|
||||
;
|
||||
;00015:jsemit (OFFSET:0x000a255f, SIZE:0x000077be):
|
||||
; - Public Definitions:
|
||||
; js_SrcNoteName
|
||||
; js_SrcNoteArity
|
||||
js_FinishTakingSrcNotes
|
||||
; js_MoveSrcNotes
|
||||
; js_GetSrcNoteOffset
|
||||
; js_BumpSrcNoteDelta
|
||||
; js_NewSrcNote3
|
||||
; js_NewSrcNote2
|
||||
; js_PopStatement
|
||||
; js_EmitContinue
|
||||
; js_EmitBreak
|
||||
; js_SetSrcNoteOffset
|
||||
; js_NewSrcNote
|
||||
; js_PushStatement
|
||||
; js_MoveCode
|
||||
; js_SetJumpOffset
|
||||
; js_Emit3
|
||||
; js_Emit2
|
||||
; js_Emit1
|
||||
; js_UpdateDepth
|
||||
; js_SrcNoteLength
|
||||
; js_CancelLastOpcode
|
||||
js_InitCodeGenerator
|
||||
;
|
||||
;
|
||||
;00016:jsdbgapi (OFFSET:0x000a9d1d, SIZE:0x000057db):
|
||||
; - Public Definitions:
|
||||
; js_watchpoint_list
|
||||
; js_trap_list
|
||||
; JS_SetAnnotationInFrame
|
||||
; JS_GetAnnotationFromFrame
|
||||
; JS_GetJSPrincipalArrayFromFrame
|
||||
; JS_NextJSFrame
|
||||
; JS_InitJSFrameIterator
|
||||
JS_LineNumberToPC
|
||||
JS_PCToLineNumber
|
||||
JS_ClearAllWatchPoints
|
||||
JS_ClearWatchPoint
|
||||
JS_SetWatchPoint
|
||||
JS_HandleTrap
|
||||
JS_ClearAllTraps
|
||||
JS_ClearScriptTraps
|
||||
JS_ClearTrap
|
||||
JS_GetTrapOpcode
|
||||
JS_SetTrap
|
||||
;DSR070297 - added in GA code
|
||||
JS_FrameIterator
|
||||
JS_GetFrameAnnotation
|
||||
JS_GetFramePrincipalArray
|
||||
JS_GetFrameScript
|
||||
JS_GetScriptFilename
|
||||
JS_SetFrameAnnotation
|
||||
JS_GetFramePC
|
||||
JS_GetFunctionScript
|
||||
|
||||
;
|
||||
;
|
||||
;00017:jsdate (OFFSET:0x000af4f8, SIZE:0x00009a8e):
|
||||
; - Public Definitions:
|
||||
js_DateGetSeconds
|
||||
js_DateGetMinutes
|
||||
js_DateGetHours
|
||||
js_DateGetDate
|
||||
js_DateGetMonth
|
||||
js_DateGetYear
|
||||
js_NewDateObject
|
||||
; js_InitDateClass
|
||||
;
|
||||
;
|
||||
;00018:jscntxt (OFFSET:0x000b8f86, SIZE:0x00003732):
|
||||
; - Public Definitions:
|
||||
; js_InterpreterHooks
|
||||
; js_ReportIsNotDefined
|
||||
; js_ReportErrorAgain
|
||||
; js_ReportErrorVA
|
||||
; js_ContextIterator
|
||||
; js_DestroyContext
|
||||
; js_NewContext
|
||||
; js_SetInterpreterHooks
|
||||
;
|
||||
;
|
||||
;00019:jsbool (OFFSET:0x000bc6b8, SIZE:0x00003375):
|
||||
; - Public Definitions:
|
||||
; js_BooleanToString
|
||||
; js_BooleanToObject
|
||||
; js_InitBooleanClass
|
||||
; js_ValueToBoolean
|
||||
;
|
||||
;
|
||||
;00020:jsatom (OFFSET:0x000bfa2d, SIZE:0x000058d0):
|
||||
; - Public Definitions:
|
||||
; js_valueOf_str
|
||||
; js_toString_str
|
||||
; js_length_str
|
||||
; js_eval_str
|
||||
; js_constructor_str
|
||||
; js_class_prototype_str
|
||||
; js_assign_str
|
||||
; js_anonymous_str
|
||||
; js_Object_str
|
||||
; js_Array_str
|
||||
; js_type_str
|
||||
; js_DropUnmappedAtoms
|
||||
js_FreeAtomMap
|
||||
js_InitAtomMap
|
||||
; js_GetAtom
|
||||
; js_DropAtom
|
||||
; js_IndexAtom
|
||||
; js_ValueToStringAtom
|
||||
; js_AtomizeString
|
||||
; js_AtomizeDouble
|
||||
; js_AtomizeInt
|
||||
; js_AtomizeBoolean
|
||||
; js_AtomizeObject
|
||||
; js_HoldAtom
|
||||
; js_MarkAtomState
|
||||
; js_FreeAtomState
|
||||
; js_Atomize
|
||||
; js_InitAtomState
|
||||
;
|
||||
;
|
||||
;00021:jsarray (OFFSET:0x000c52fd, SIZE:0x00007c86):
|
||||
; - Public Definitions:
|
||||
; js_ArrayClass
|
||||
; js_SetArrayLength
|
||||
; js_GetArrayLength
|
||||
; js_InitArrayClass
|
||||
; js_NewArrayObject
|
||||
; PR_qsort
|
||||
;
|
||||
;
|
||||
;00022:jsapi (OFFSET:0x000ccf83, SIZE:0x0000de8c):
|
||||
; - Public Definitions:
|
||||
JS_ClearRegExpStatics
|
||||
JS_SetRegExpInput
|
||||
JS_NewRegExpObject
|
||||
JS_SetErrorReporter
|
||||
JS_CompareStrings
|
||||
JS_GetStringLength
|
||||
JS_GetStringBytes
|
||||
JS_InternString
|
||||
JS_NewStringCopyZ
|
||||
JS_NewStringCopyN
|
||||
JS_NewString
|
||||
JS_IsRunning
|
||||
JS_SetBranchCallback
|
||||
JS_CallFunctionValue
|
||||
JS_CallFunctionName
|
||||
JS_CallFunction
|
||||
JS_EvaluateScriptForPrincipals
|
||||
JS_EvaluateScript
|
||||
JS_ExecuteScript
|
||||
JS_DecompileFunctionBody
|
||||
JS_DecompileFunction
|
||||
JS_DecompileScript
|
||||
JS_CompileFunctionForPrincipals
|
||||
JS_CompileFunction
|
||||
JS_DestroyScript
|
||||
JS_CompileScriptForPrincipals
|
||||
JS_CompileScript
|
||||
JS_DefineFunction
|
||||
JS_GetFunctionName
|
||||
JS_GetFunctionObject
|
||||
JS_NewFunction
|
||||
JS_ClearScope
|
||||
JS_DeleteElement
|
||||
JS_SetElement
|
||||
JS_GetElement
|
||||
JS_LookupElement
|
||||
JS_AliasElement
|
||||
JS_DefineElement
|
||||
JS_SetArrayLength
|
||||
JS_GetArrayLength
|
||||
JS_NewArrayObject
|
||||
JS_DeleteProperty
|
||||
JS_SetProperty
|
||||
JS_GetProperty
|
||||
JS_LookupProperty
|
||||
JS_AliasProperty
|
||||
JS_DefinePropertyWithTinyId
|
||||
JS_DefineProperty
|
||||
JS_DefineConstDoubles
|
||||
JS_DefineObject
|
||||
JS_NewObject
|
||||
JS_GetConstructor
|
||||
JS_SetParent
|
||||
JS_GetParent
|
||||
JS_SetPrototype
|
||||
JS_GetPrototype
|
||||
JS_GetInstancePrivate
|
||||
JS_SetPrivate
|
||||
JS_GetPrivate
|
||||
JS_InstanceOf
|
||||
JS_GetClass
|
||||
JS_DefineFunctions
|
||||
JS_DefineProperties
|
||||
JS_InitClass
|
||||
JS_FinalizeStub
|
||||
JS_ConvertStub
|
||||
JS_ResolveStub
|
||||
JS_EnumerateStub
|
||||
JS_PropertyStub
|
||||
JS_GC
|
||||
JS_UnlockGCThing
|
||||
JS_LockGCThing
|
||||
JS_RemoveRoot
|
||||
JS_AddRoot
|
||||
JS_NewDoubleValue
|
||||
JS_NewDouble
|
||||
JS_strdup
|
||||
JS_free
|
||||
JS_realloc
|
||||
JS_ReportOutOfMemory
|
||||
JS_malloc
|
||||
JS_GetScopeChain
|
||||
JS_InitStandardClasses
|
||||
JS_SetGlobalObject
|
||||
JS_GetGlobalObject
|
||||
JS_SetVersion
|
||||
JS_GetVersion
|
||||
JS_ContextIterator
|
||||
JS_GetTaskState
|
||||
JS_DestroyContext
|
||||
JS_NewContext
|
||||
JS_Unlock
|
||||
JS_Lock
|
||||
JS_Finish
|
||||
JS_Init
|
||||
JS_GetTypeName
|
||||
JS_TypeOfValue
|
||||
JS_ValueToBoolean
|
||||
JS_ValueToInt32
|
||||
JS_ValueToNumber
|
||||
JS_ValueToString
|
||||
JS_ValueToFunction
|
||||
JS_ValueToObject
|
||||
JS_ReportError
|
||||
JS_ConvertValue
|
||||
JS_GetEmptyStringValue
|
||||
JS_GetPositiveInfinityValue
|
||||
JS_GetNegativeInfinityValue
|
||||
JS_GetNaNValue
|
||||
;DSR062897 - added for GA code
|
||||
JS_MaybeGC
|
||||
JS_GetScriptPrincipals
|
||||
JS_IsAssigning
|
||||
JS_SetCharSetInfo
|
||||
;
|
||||
;
|
||||
;00023:prmjtime (OFFSET:0x000dae0f, SIZE:0x00008986):
|
||||
; - Public Definitions:
|
||||
PRMJ_FormatTimeUSEnglish
|
||||
PRMJ_gmtime
|
||||
PRMJ_FormatTime
|
||||
PRMJ_mktime
|
||||
PRMJ_ComputeTime
|
||||
PRMJ_localtime
|
||||
PRMJ_ExplodeTime
|
||||
PRMJ_ToLocal
|
||||
PRMJ_ToGMT
|
||||
PRMJ_NowLocal
|
||||
PRMJ_DSTOffset
|
||||
PRMJ_NowS
|
||||
PRMJ_NowMS
|
||||
PRMJ_Now
|
||||
PRMJ_ToExtendedTime
|
||||
PRMJ_ToBaseTime
|
||||
PRMJ_setDST
|
||||
PRMJ_LocalGMTDifference
|
||||
|
||||
|
||||
42
mozilla/js/src/jsaddr.c
Normal file
42
mozilla/js/src/jsaddr.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright © 1996 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsinterp.h"
|
||||
|
||||
/* These functions are needed to get the addresses of certain functions
|
||||
* in the JS module. On WIN32 especially, these symbols have a different
|
||||
* address from the actual address of these functions in the JS module.
|
||||
* This is because on WIN32, import function address fixups are done only
|
||||
* at load time and function calls are made by indirection - that is by
|
||||
* using a couple extra instructions to lookup the actual function address
|
||||
* in the importing module's import address table.
|
||||
*/
|
||||
|
||||
IMPLEMENT(JSPropertyOp)
|
||||
js_GetArgumentAddress()
|
||||
{
|
||||
return ((void *)js_GetArgument);
|
||||
}
|
||||
|
||||
IMPLEMENT(JSPropertyOp)
|
||||
js_SetArgumentAddress()
|
||||
{
|
||||
return ((void *)js_SetArgument);
|
||||
}
|
||||
|
||||
IMPLEMENT(JSPropertyOp)
|
||||
js_GetLocalVariableAddress()
|
||||
{
|
||||
return ((void *)js_GetLocalVariable);
|
||||
}
|
||||
|
||||
IMPLEMENT(JSPropertyOp)
|
||||
js_SetLocalVariableAddress()
|
||||
{
|
||||
return ((void *)js_SetLocalVariable);
|
||||
}
|
||||
20
mozilla/js/src/jsaddr.h
Normal file
20
mozilla/js/src/jsaddr.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright © 1996 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsaddr_h___
|
||||
#define jsaddr_h___
|
||||
|
||||
EXTERN(JSPropertyOp)
|
||||
js_GetArgumentAddress();
|
||||
|
||||
EXTERN(JSPropertyOp)
|
||||
js_SetArgumentAddress();
|
||||
|
||||
EXTERN(JSPropertyOp)
|
||||
js_GetLocalVariableAddress();
|
||||
|
||||
EXTERN(JSPropertyOp)
|
||||
js_SetLocalVariableAddress();
|
||||
|
||||
#endif /* jsaddr_h___ */
|
||||
2756
mozilla/js/src/jsapi.c
Normal file
2756
mozilla/js/src/jsapi.c
Normal file
File diff suppressed because it is too large
Load Diff
1058
mozilla/js/src/jsapi.h
Normal file
1058
mozilla/js/src/jsapi.h
Normal file
File diff suppressed because it is too large
Load Diff
343
mozilla/js/src/jsarena.c
Normal file
343
mozilla/js/src/jsarena.c
Normal file
@@ -0,0 +1,343 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsbit.h"
|
||||
#ifndef NSPR20
|
||||
#include "jsarena.h"
|
||||
#else
|
||||
/* Removed by JSIFY: #include "plarena.h"
|
||||
*/
|
||||
#include "jsarena.h" /* Added by JSIFY */
|
||||
#endif
|
||||
/* Removed by JSIFY: #include "prlog.h" */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
extern js_CompareAndSwap(jsword *, jsword, jsword);
|
||||
#endif
|
||||
|
||||
static JSArena *arena_freelist;
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
static JSArenaStats *arena_stats_list;
|
||||
|
||||
#define COUNT(pool,what) (pool)->stats.what++
|
||||
#else
|
||||
#define COUNT(pool,what) /* nothing */
|
||||
#endif
|
||||
|
||||
#define JS_ARENA_DEFAULT_ALIGN sizeof(double)
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_InitArenaPool(JSArenaPool *pool, const char *name, JSUint32 size, JSUint32 align)
|
||||
{
|
||||
if (align == 0)
|
||||
align = JS_ARENA_DEFAULT_ALIGN;
|
||||
pool->mask = JS_BITMASK(JS_CeilingLog2(align));
|
||||
pool->first.next = NULL;
|
||||
pool->first.base = pool->first.avail = pool->first.limit =
|
||||
(jsuword)JS_ARENA_ALIGN(pool, &pool->first + 1);
|
||||
pool->current = &pool->first;
|
||||
pool->arenasize = size;
|
||||
#ifdef JS_ARENAMETER
|
||||
memset(&pool->stats, 0, sizeof pool->stats);
|
||||
pool->stats.name = strdup(name);
|
||||
pool->stats.next = arena_stats_list;
|
||||
arena_stats_list = &pool->stats;
|
||||
#endif
|
||||
}
|
||||
|
||||
IMPLEMENT(void *)
|
||||
JS_ArenaAllocate(JSArenaPool *pool, JSUint32 nb)
|
||||
{
|
||||
JSArena **ap, *a, *b;
|
||||
#ifdef JS_THREADSAFE
|
||||
JSArena *c;
|
||||
#endif
|
||||
JSUint32 sz;
|
||||
void *p;
|
||||
|
||||
JS_ASSERT((nb & pool->mask) == 0);
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
if (nb >= 60000U)
|
||||
return 0;
|
||||
#endif /* WIN16 */
|
||||
ap = &arena_freelist;
|
||||
for (a = pool->current; a->avail + nb > a->limit; pool->current = a) {
|
||||
if (a->next) { /* move to next arena */
|
||||
a = a->next;
|
||||
continue;
|
||||
}
|
||||
while ((b = *ap) != NULL) { /* reclaim a free arena */
|
||||
if (b->limit - b->base == pool->arenasize) {
|
||||
#ifdef JS_THREADSAFE
|
||||
do {
|
||||
b = *ap;
|
||||
c = b->next;
|
||||
} while (!js_CompareAndSwap((jsword *)ap,(jsword)b,(jsword)c));
|
||||
#else
|
||||
*ap = b->next;
|
||||
#endif
|
||||
b->next = NULL;
|
||||
a = a->next = b;
|
||||
COUNT(pool, nreclaims);
|
||||
goto claim;
|
||||
}
|
||||
ap = &b->next;
|
||||
}
|
||||
sz = JS_MAX(pool->arenasize, nb); /* allocate a new arena */
|
||||
sz += sizeof *a + pool->mask; /* header and alignment slop */
|
||||
b = malloc(sz);
|
||||
if (!b)
|
||||
return 0;
|
||||
a = a->next = b;
|
||||
a->next = NULL;
|
||||
a->limit = (jsuword)a + sz;
|
||||
JS_COUNT_ARENA(pool,++);
|
||||
COUNT(pool, nmallocs);
|
||||
claim:
|
||||
a->base = a->avail = (jsuword)JS_ARENA_ALIGN(pool, a + 1);
|
||||
}
|
||||
p = (void *)a->avail;
|
||||
a->avail += nb;
|
||||
return p;
|
||||
}
|
||||
|
||||
IMPLEMENT(void *)
|
||||
JS_ArenaGrow(JSArenaPool *pool, void *p, JSUint32 size, JSUint32 incr)
|
||||
{
|
||||
void *newp;
|
||||
|
||||
JS_ARENA_ALLOCATE(newp, pool, size + incr);
|
||||
memcpy(newp, p, size);
|
||||
return newp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free tail arenas linked after head, which may not be the true list head.
|
||||
* Reset pool->current to point to head in case it pointed at a tail arena.
|
||||
*/
|
||||
static void
|
||||
FreeArenaList(JSArenaPool *pool, JSArena *head, JSBool reallyFree)
|
||||
{
|
||||
JSArena **ap, *a;
|
||||
#ifdef JS_THREADSAFE
|
||||
JSArena *b;
|
||||
#endif
|
||||
|
||||
ap = &head->next;
|
||||
a = *ap;
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
|
||||
a->avail = a->base;
|
||||
JS_CLEAR_UNUSED(a);
|
||||
} while ((a = a->next) != NULL);
|
||||
a = *ap;
|
||||
#endif
|
||||
|
||||
if (reallyFree) {
|
||||
do {
|
||||
*ap = a->next;
|
||||
JS_CLEAR_ARENA(a);
|
||||
JS_COUNT_ARENA(pool,--);
|
||||
free(a);
|
||||
} while ((a = *ap) != NULL);
|
||||
} else {
|
||||
/* Insert the whole arena chain at the front of the freelist. */
|
||||
do {
|
||||
ap = &(*ap)->next;
|
||||
} while (*ap);
|
||||
#ifdef JS_THREADSAFE
|
||||
do {
|
||||
*ap = b = arena_freelist;
|
||||
} while (!js_CompareAndSwap((jsword*)&arena_freelist,(jsword)b,(jsword)a));
|
||||
#else
|
||||
*ap = arena_freelist;
|
||||
arena_freelist = a;
|
||||
#endif
|
||||
head->next = NULL;
|
||||
}
|
||||
|
||||
pool->current = head;
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_ArenaRelease(JSArenaPool *pool, char *mark)
|
||||
{
|
||||
JSArena *a;
|
||||
|
||||
for (a = pool->first.next; a; a = a->next) {
|
||||
if (JS_UPTRDIFF(mark, a) < JS_UPTRDIFF(a->avail, a)) {
|
||||
a->avail = (jsuword)JS_ARENA_ALIGN(pool, mark);
|
||||
FreeArenaList(pool, a, JS_TRUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_FreeArenaPool(JSArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first, JS_FALSE);
|
||||
COUNT(pool, ndeallocs);
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_FinishArenaPool(JSArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first, JS_TRUE);
|
||||
#ifdef JS_ARENAMETER
|
||||
{
|
||||
JSArenaStats *stats, **statsp;
|
||||
|
||||
if (pool->stats.name)
|
||||
free(pool->stats.name);
|
||||
for (statsp = &arena_stats_list; (stats = *statsp) != 0;
|
||||
statsp = &stats->next) {
|
||||
if (stats == &pool->stats) {
|
||||
*statsp = stats->next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_CompactArenaPool(JSArenaPool *pool)
|
||||
{
|
||||
#if 0 /* XP_MAC */
|
||||
JSArena *a = pool->first.next;
|
||||
|
||||
while (a) {
|
||||
reallocSmaller(a, a->avail - (jsuword)a);
|
||||
a->limit = a->avail;
|
||||
a = a->next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_ArenaFinish()
|
||||
{
|
||||
JSArena *a, *next;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
while (arena_freelist) {
|
||||
a = arena_freelist;
|
||||
next = a->next;
|
||||
if (js_CompareAndSwap((jsword*)&arena_freelist,(jsword)a,(jsword)next))
|
||||
free(a);
|
||||
}
|
||||
#else
|
||||
for (a = arena_freelist; a; a = next) {
|
||||
next = a->next;
|
||||
free(a);
|
||||
}
|
||||
arena_freelist = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
IMPLEMENT(void)
|
||||
JS_ArenaCountAllocation(JSArenaPool *pool, JSUint32 nb)
|
||||
{
|
||||
pool->stats.nallocs++;
|
||||
pool->stats.nbytes += nb;
|
||||
if (nb > pool->stats.maxalloc)
|
||||
pool->stats.maxalloc = nb;
|
||||
pool->stats.variance += nb * nb;
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_ArenaCountInplaceGrowth(JSArenaPool *pool, JSUint32 size, JSUint32 incr)
|
||||
{
|
||||
pool->stats.ninplace++;
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_ArenaCountGrowth(JSArenaPool *pool, JSUint32 size, JSUint32 incr)
|
||||
{
|
||||
pool->stats.ngrows++;
|
||||
pool->stats.nbytes += incr;
|
||||
pool->stats.variance -= size * size;
|
||||
size += incr;
|
||||
if (size > pool->stats.maxalloc)
|
||||
pool->stats.maxalloc = size;
|
||||
pool->stats.variance += size * size;
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_ArenaCountRelease(JSArenaPool *pool, char *mark)
|
||||
{
|
||||
pool->stats.nreleases++;
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_ArenaCountRetract(JSArenaPool *pool, char *mark)
|
||||
{
|
||||
pool->stats.nfastrels++;
|
||||
}
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_DumpArenaStats(FILE *fp)
|
||||
{
|
||||
JSArenaStats *stats;
|
||||
double mean, variance;
|
||||
|
||||
for (stats = arena_stats_list; stats; stats = stats->next) {
|
||||
if (stats->nallocs != 0) {
|
||||
mean = (double)stats->nbytes / stats->nallocs;
|
||||
variance = fabs(stats->variance / stats->nallocs - mean * mean);
|
||||
} else {
|
||||
mean = variance = 0;
|
||||
}
|
||||
|
||||
fprintf(fp, "\n%s allocation statistics:\n", stats->name);
|
||||
fprintf(fp, " number of arenas: %u\n", stats->narenas);
|
||||
fprintf(fp, " number of allocations: %u\n", stats->nallocs);
|
||||
fprintf(fp, " number of free arena reclaims: %u\n", stats->nreclaims);
|
||||
fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs);
|
||||
fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs);
|
||||
fprintf(fp, " number of allocation growths: %u\n", stats->ngrows);
|
||||
fprintf(fp, " number of in-place growths: %u\n", stats->ninplace);
|
||||
fprintf(fp, "number of released allocations: %u\n", stats->nreleases);
|
||||
fprintf(fp, " number of fast releases: %u\n", stats->nfastrels);
|
||||
fprintf(fp, " total bytes allocated: %u\n", stats->nbytes);
|
||||
fprintf(fp, " mean allocation size: %g\n", mean);
|
||||
fprintf(fp, " standard deviation: %g\n", sqrt(variance));
|
||||
fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc);
|
||||
}
|
||||
}
|
||||
#endif /* JS_ARENAMETER */
|
||||
246
mozilla/js/src/jsarena.h
Normal file
246
mozilla/js/src/jsarena.h
Normal file
@@ -0,0 +1,246 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jsarena_h___
|
||||
#define jsarena_h___
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*
|
||||
* Also supports LIFO allocation (JS_ARENA_MARK/JS_ARENA_RELEASE).
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jscompat.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct JSArena JSArena;
|
||||
typedef struct JSArenaPool JSArenaPool;
|
||||
|
||||
struct JSArena {
|
||||
JSArena *next; /* next arena for this lifetime */
|
||||
jsuword base; /* aligned base address, follows this header */
|
||||
jsuword limit; /* one beyond last byte in arena */
|
||||
jsuword avail; /* points to next available byte */
|
||||
};
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
typedef struct JSArenaStats JSArenaStats;
|
||||
|
||||
struct JSArenaStats {
|
||||
JSArenaStats *next; /* next in arenaStats list */
|
||||
char *name; /* name for debugging */
|
||||
uint32 narenas; /* number of arenas in pool */
|
||||
uint32 nallocs; /* number of JS_ARENA_ALLOCATE() calls */
|
||||
uint32 nreclaims; /* number of reclaims from freeArenas */
|
||||
uint32 nmallocs; /* number of malloc() calls */
|
||||
uint32 ndeallocs; /* number of lifetime deallocations */
|
||||
uint32 ngrows; /* number of JS_ARENA_GROW() calls */
|
||||
uint32 ninplace; /* number of in-place growths */
|
||||
uint32 nreleases; /* number of JS_ARENA_RELEASE() calls */
|
||||
uint32 nfastrels; /* number of "fast path" releases */
|
||||
size_t nbytes; /* total bytes allocated */
|
||||
size_t maxalloc; /* maximum allocation size in bytes */
|
||||
double variance; /* size variance accumulator */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct JSArenaPool {
|
||||
JSArena first; /* first arena in pool list */
|
||||
JSArena *current; /* arena from which to allocate space */
|
||||
size_t arenasize; /* net exact size of a new arena */
|
||||
jsuword mask; /* alignment mask (power-of-2 - 1) */
|
||||
#ifdef JS_ARENAMETER
|
||||
JSArenaStats stats;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* If the including .c file uses only one power-of-2 alignment, it may define
|
||||
* JS_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions
|
||||
* per ALLOCATE and GROW.
|
||||
*/
|
||||
#ifdef JS_ARENA_CONST_ALIGN_MASK
|
||||
#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + JS_ARENA_CONST_ALIGN_MASK) \
|
||||
& ~JS_ARENA_CONST_ALIGN_MASK)
|
||||
|
||||
#define JS_INIT_ARENA_POOL(pool, name, size) \
|
||||
JS_InitArenaPool(pool, name, size, JS_ARENA_CONST_ALIGN_MASK + 1)
|
||||
#else
|
||||
#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + (pool)->mask) & ~(pool)->mask)
|
||||
#endif
|
||||
|
||||
#define JS_ARENA_ALLOCATE(p, pool, nb) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSArena *_a = (pool)->current; \
|
||||
size_t _nb = JS_ARENA_ALIGN(pool, nb); \
|
||||
jsuword _p = _a->avail; \
|
||||
jsuword _q = _p + _nb; \
|
||||
if (_q > _a->limit) \
|
||||
_p = (jsuword)JS_ArenaAllocate(pool, _nb); \
|
||||
else \
|
||||
_a->avail = _q; \
|
||||
p = (void *)_p; \
|
||||
JS_ArenaCountAllocation(pool, nb); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_ARENA_GROW(p, pool, size, incr) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSArena *_a = (pool)->current; \
|
||||
size_t _incr = JS_ARENA_ALIGN(pool, incr); \
|
||||
jsuword _p = _a->avail; \
|
||||
jsuword _q = _p + _incr; \
|
||||
if (_p == (jsuword)(p) + JS_ARENA_ALIGN(pool, size) && \
|
||||
_q <= _a->limit) { \
|
||||
_a->avail = _q; \
|
||||
JS_ArenaCountInplaceGrowth(pool, size, incr); \
|
||||
} else { \
|
||||
p = JS_ArenaGrow(pool, p, size, incr); \
|
||||
} \
|
||||
JS_ArenaCountGrowth(pool, size, incr); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_ARENA_MARK(pool) ((void *) (pool)->current->avail)
|
||||
#define JS_UPTRDIFF(p,q) ((jsuword)(p) - (jsuword)(q))
|
||||
|
||||
#ifdef DEBUG
|
||||
#define free_PATTERN 0xDA
|
||||
#define JS_CLEAR_UNUSED(a) (JS_ASSERT((a)->avail <= (a)->limit), \
|
||||
memset((void*)(a)->avail, free_PATTERN, \
|
||||
(a)->limit - (a)->avail))
|
||||
#define JS_CLEAR_ARENA(a) memset((void*)(a), free_PATTERN, \
|
||||
(a)->limit - (jsuword)(a))
|
||||
#else
|
||||
#define JS_CLEAR_UNUSED(a) /* nothing */
|
||||
#define JS_CLEAR_ARENA(a) /* nothing */
|
||||
#endif
|
||||
|
||||
#define JS_ARENA_RELEASE(pool, mark) \
|
||||
JS_BEGIN_MACRO \
|
||||
char *_m = (char *)(mark); \
|
||||
JSArena *_a = (pool)->current; \
|
||||
if (JS_UPTRDIFF(_m, _a) <= JS_UPTRDIFF(_a->avail, _a)) { \
|
||||
_a->avail = (jsuword)JS_ARENA_ALIGN(pool, _m); \
|
||||
JS_CLEAR_UNUSED(_a); \
|
||||
JS_ArenaCountRetract(pool, _m); \
|
||||
} else { \
|
||||
JS_ArenaRelease(pool, _m); \
|
||||
} \
|
||||
JS_ArenaCountRelease(pool, _m); \
|
||||
JS_END_MACRO
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
#define JS_COUNT_ARENA(pool,op) ((pool)->stats.narenas op)
|
||||
#else
|
||||
#define JS_COUNT_ARENA(pool,op)
|
||||
#endif
|
||||
|
||||
#define JS_ARENA_DESTROY(pool, a, pnext) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_COUNT_ARENA(pool,--); \
|
||||
if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
|
||||
*(pnext) = (a)->next; \
|
||||
JS_CLEAR_ARENA(a); \
|
||||
free(a); \
|
||||
(a) = NULL; \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
* Initialize an arena pool with the given name for debugging and metering,
|
||||
* with a minimum size per arena of size bytes.
|
||||
*/
|
||||
EXTERN(void)
|
||||
JS_InitArenaPool(JSArenaPool *pool, const char *name, JSUint32 size,
|
||||
JSUint32 align);
|
||||
|
||||
/*
|
||||
* Free the arenas in pool. The user may continue to allocate from pool
|
||||
* after calling this function. There is no need to call JS_InitArenaPool()
|
||||
* again unless JS_FinishArenaPool(pool) has been called.
|
||||
*/
|
||||
EXTERN(void)
|
||||
JS_FreeArenaPool(JSArenaPool *pool);
|
||||
|
||||
/*
|
||||
* Free the arenas in pool and finish using it altogether.
|
||||
*/
|
||||
EXTERN(void)
|
||||
JS_FinishArenaPool(JSArenaPool *pool);
|
||||
|
||||
/*
|
||||
* Compact all of the arenas in a pool so that no space is wasted.
|
||||
*/
|
||||
EXTERN(void)
|
||||
JS_CompactArenaPool(JSArenaPool *pool);
|
||||
|
||||
/*
|
||||
* Finish using arenas, freeing all memory associated with them.
|
||||
*/
|
||||
EXTERN(void)
|
||||
JS_ArenaFinish(void);
|
||||
|
||||
/*
|
||||
* Friend functions used by the JS_ARENA_*() macros.
|
||||
*/
|
||||
EXTERN(void *)
|
||||
JS_ArenaAllocate(JSArenaPool *pool, JSUint32 nb);
|
||||
|
||||
EXTERN(void *)
|
||||
JS_ArenaGrow(JSArenaPool *pool, void *p, JSUint32 size, JSUint32 incr);
|
||||
|
||||
EXTERN(void)
|
||||
JS_ArenaRelease(JSArenaPool *pool, char *mark);
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
EXTERN(void)
|
||||
JS_ArenaCountAllocation(JSArenaPool *pool, JSUint32 nb);
|
||||
|
||||
EXTERN(void)
|
||||
JS_ArenaCountInplaceGrowth(JSArenaPool *pool, JSUint32 size, JSUint32 incr);
|
||||
|
||||
EXTERN(void)
|
||||
JS_ArenaCountGrowth(JSArenaPool *pool, JSUint32 size, JSUint32incr);
|
||||
|
||||
EXTERN(void)
|
||||
JS_ArenaCountRelease(JSArenaPool *pool, char *mark);
|
||||
|
||||
EXTERN(void)
|
||||
JS_ArenaCountRetract(JSArenaPool *pool, char *mark);
|
||||
|
||||
EXTERN(void)
|
||||
JS_DumpArenaStats(FILE *fp);
|
||||
|
||||
#else /* !JS_ARENAMETER */
|
||||
|
||||
#define JS_ArenaCountAllocation(ap, nb) /* nothing */
|
||||
#define JS_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */
|
||||
#define JS_ArenaCountGrowth(ap, size, incr) /* nothing */
|
||||
#define JS_ArenaCountRelease(ap, mark) /* nothing */
|
||||
#define JS_ArenaCountRetract(ap, mark) /* nothing */
|
||||
|
||||
#endif /* !JS_ARENAMETER */
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsarena_h___ */
|
||||
1300
mozilla/js/src/jsarray.c
Normal file
1300
mozilla/js/src/jsarray.c
Normal file
File diff suppressed because it is too large
Load Diff
56
mozilla/js/src/jsarray.h
Normal file
56
mozilla/js/src/jsarray.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jsarray_h___
|
||||
#define jsarray_h___
|
||||
/*
|
||||
* JS Array interface.
|
||||
*/
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JSClass js_ArrayClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitArrayClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSObject *
|
||||
js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector);
|
||||
|
||||
extern JSBool
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
||||
|
||||
extern JSBool
|
||||
js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length);
|
||||
|
||||
extern JSBool
|
||||
js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
||||
|
||||
/*
|
||||
* JS-specific qsort function.
|
||||
*/
|
||||
typedef int (*JSComparator)(const void *a, const void *b, void *arg);
|
||||
|
||||
extern JSBool
|
||||
js_qsort(void *vec, size_t nel, size_t elsize, JSComparator cmp, void *arg);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsarray_h___ */
|
||||
672
mozilla/js/src/jsatom.c
Normal file
672
mozilla/js/src/jsatom.c
Normal file
@@ -0,0 +1,672 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS atom table.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
/* Removed by JSIFY: #include "prlog.h" */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#ifndef NSPR20
|
||||
#include "jshash.h"
|
||||
#else
|
||||
/* Removed by JSIFY: #include "JShash.h"
|
||||
*/
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
#endif
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsgc.h"
|
||||
#include "jslock.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
/*
|
||||
* Keep this in sync with jspubtd.h -- an assertion below will insist that
|
||||
* its length match the JSType enum's JSTYPE_LIMIT limit value.
|
||||
*/
|
||||
char *js_type_str[] = {
|
||||
"undefined",
|
||||
"object",
|
||||
"function",
|
||||
"string",
|
||||
"number",
|
||||
"boolean",
|
||||
};
|
||||
|
||||
char *js_boolean_str[] = {
|
||||
js_false_str,
|
||||
js_true_str
|
||||
};
|
||||
|
||||
char js_Array_str[] = "Array";
|
||||
char js_Math_str[] = "Math";
|
||||
char js_Object_str[] = "Object";
|
||||
char js_anonymous_str[] = "anonymous";
|
||||
char js_arguments_str[] = "arguments";
|
||||
char js_arity_str[] = "arity";
|
||||
char js_assign_str[] = "assign";
|
||||
char js_callee_str[] = "callee";
|
||||
char js_caller_str[] = "caller";
|
||||
char js_class_prototype_str[] = "prototype";
|
||||
char js_constructor_str[] = "constructor";
|
||||
char js_count_str[] = "__count__";
|
||||
char js_eval_str[] = "eval";
|
||||
char js_index_str[] = "index";
|
||||
char js_input_str[] = "input";
|
||||
char js_length_str[] = "length";
|
||||
char js_name_str[] = "name";
|
||||
char js_parent_str[] = "__parent__";
|
||||
char js_proto_str[] = "__proto__";
|
||||
char js_toSource_str[] = "toSource";
|
||||
char js_toString_str[] = "toString";
|
||||
char js_valueOf_str[] = "valueOf";
|
||||
|
||||
#define HASH_OBJECT(o) ((JSHashNumber)(o) >> JSVAL_TAGBITS)
|
||||
#define HASH_INT(i) ((JSHashNumber)(i))
|
||||
#define HASH_DOUBLE(dp) ((JSHashNumber)(((uint32*)(dp))[0] ^ ((uint32*)(dp))[1]))
|
||||
#define HASH_BOOLEAN(b) ((JSHashNumber)(b))
|
||||
|
||||
STATIC_DLL_CALLBACK(JSHashNumber)
|
||||
js_hash_atom_key(const void *key)
|
||||
{
|
||||
jsval v;
|
||||
jsdouble *dp;
|
||||
|
||||
/* Order JSVAL_IS_* tests by likelihood of success. */
|
||||
v = (jsval)key;
|
||||
if (JSVAL_IS_STRING(v))
|
||||
return js_HashString(JSVAL_TO_STRING(v));
|
||||
if (JSVAL_IS_INT(v))
|
||||
return HASH_INT(JSVAL_TO_INT(v));
|
||||
if (JSVAL_IS_DOUBLE(v)) {
|
||||
dp = JSVAL_TO_DOUBLE(v);
|
||||
return HASH_DOUBLE(dp);
|
||||
}
|
||||
if (JSVAL_IS_OBJECT(v))
|
||||
return HASH_OBJECT(JSVAL_TO_OBJECT(v));
|
||||
if (JSVAL_IS_BOOLEAN(v))
|
||||
return HASH_BOOLEAN(JSVAL_TO_BOOLEAN(v));
|
||||
return (JSHashNumber)v;
|
||||
}
|
||||
|
||||
STATIC_DLL_CALLBACK(intN)
|
||||
js_compare_atom_keys(const void *k1, const void *k2)
|
||||
{
|
||||
jsval v1, v2;
|
||||
|
||||
v1 = (jsval)k1, v2 = (jsval)k2;
|
||||
if (JSVAL_IS_STRING(v1) && JSVAL_IS_STRING(v2))
|
||||
return !js_CompareStrings(JSVAL_TO_STRING(v1), JSVAL_TO_STRING(v2));
|
||||
if (JSVAL_IS_DOUBLE(v1) && JSVAL_IS_DOUBLE(v2)) {
|
||||
double d1 = *JSVAL_TO_DOUBLE(v1);
|
||||
double d2 = *JSVAL_TO_DOUBLE(v2);
|
||||
if (JSDOUBLE_IS_NaN(d1))
|
||||
return JSDOUBLE_IS_NaN(d2);
|
||||
#ifdef XP_PC
|
||||
/* XXX MSVC miscompiles such that (NaN == 0) */
|
||||
if (JSDOUBLE_IS_NaN(d2))
|
||||
return JS_FALSE;
|
||||
#endif
|
||||
return d1 == d2;
|
||||
}
|
||||
return v1 == v2;
|
||||
}
|
||||
|
||||
STATIC_DLL_CALLBACK(int)
|
||||
js_compare_stub(const void *v1, const void *v2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
STATIC_DLL_CALLBACK(void *)
|
||||
js_alloc_atom_space(void *priv, size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
STATIC_DLL_CALLBACK(void)
|
||||
js_free_atom_space(void *priv, void *item)
|
||||
{
|
||||
free(item);
|
||||
}
|
||||
|
||||
STATIC_DLL_CALLBACK(JSHashEntry *)
|
||||
js_alloc_atom(void *priv, const void *key)
|
||||
{
|
||||
JSAtomState *state = priv;
|
||||
JSAtom *atom;
|
||||
|
||||
atom = malloc(sizeof(JSAtom));
|
||||
if (!atom)
|
||||
return NULL;
|
||||
#ifdef JS_THREADSAFE
|
||||
state->tablegen++;
|
||||
#endif
|
||||
atom->entry.key = key;
|
||||
atom->entry.value = NULL;
|
||||
atom->flags = 0;
|
||||
atom->kwindex = -1;
|
||||
atom->number = state->number++;
|
||||
return &atom->entry;
|
||||
}
|
||||
|
||||
STATIC_DLL_CALLBACK(void)
|
||||
js_free_atom(void *priv, JSHashEntry *he, uintN flag)
|
||||
{
|
||||
if (flag != HT_FREE_ENTRY)
|
||||
return;
|
||||
#ifdef JS_THREADSAFE
|
||||
((JSAtomState *)priv)->tablegen++;
|
||||
#endif
|
||||
free(he);
|
||||
}
|
||||
|
||||
static JSHashAllocOps atom_alloc_ops = {
|
||||
js_alloc_atom_space, js_free_atom_space,
|
||||
js_alloc_atom, js_free_atom
|
||||
};
|
||||
|
||||
#define JS_ATOM_HASH_SIZE 1024
|
||||
|
||||
JSBool
|
||||
js_InitAtomState(JSContext *cx, JSAtomState *state)
|
||||
{
|
||||
uintN i;
|
||||
|
||||
state->runtime = cx->runtime;
|
||||
state->number = 0;
|
||||
state->table = JS_NewHashTable(JS_ATOM_HASH_SIZE, js_hash_atom_key,
|
||||
js_compare_atom_keys, js_compare_stub,
|
||||
&atom_alloc_ops, state);
|
||||
if (!state->table) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
#ifdef JS_THREADSAFE
|
||||
js_NewLock(&state->lock);
|
||||
state->tablegen = 0;
|
||||
#endif
|
||||
|
||||
#define FROB(lval,str) { \
|
||||
if (!(state->lval = js_Atomize(cx, str, strlen(str), ATOM_PINNED))) { \
|
||||
js_FreeAtomState(cx, state); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
}
|
||||
|
||||
JS_ASSERT(sizeof js_type_str / sizeof js_type_str[0] == JSTYPE_LIMIT);
|
||||
for (i = 0; i < JSTYPE_LIMIT; i++)
|
||||
FROB(typeAtoms[i], js_type_str[i]);
|
||||
|
||||
FROB(booleanAtoms[0], js_false_str);
|
||||
FROB(booleanAtoms[1], js_true_str);
|
||||
FROB(nullAtom, js_null_str);
|
||||
|
||||
FROB(ArrayAtom, js_Array_str);
|
||||
FROB(MathAtom, js_Math_str);
|
||||
FROB(ObjectAtom, js_Object_str);
|
||||
FROB(anonymousAtom, js_anonymous_str);
|
||||
FROB(argumentsAtom, js_arguments_str);
|
||||
FROB(arityAtom, js_arity_str);
|
||||
FROB(assignAtom, js_assign_str);
|
||||
FROB(calleeAtom, js_callee_str);
|
||||
FROB(callerAtom, js_caller_str);
|
||||
FROB(classPrototypeAtom, js_class_prototype_str);
|
||||
FROB(constructorAtom, js_constructor_str);
|
||||
FROB(countAtom, js_count_str);
|
||||
FROB(indexAtom, js_index_str);
|
||||
FROB(inputAtom, js_input_str);
|
||||
FROB(lengthAtom, js_length_str);
|
||||
FROB(nameAtom, js_name_str);
|
||||
FROB(parentAtom, js_parent_str);
|
||||
FROB(protoAtom, js_proto_str);
|
||||
FROB(toSourceAtom, js_toSource_str);
|
||||
FROB(toStringAtom, js_toString_str);
|
||||
FROB(valueOfAtom, js_valueOf_str);
|
||||
|
||||
#undef FROB
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
js_FreeAtomState(JSContext *cx, JSAtomState *state)
|
||||
{
|
||||
state->runtime = NULL;
|
||||
JS_HashTableDestroy(state->table);
|
||||
state->table = NULL;
|
||||
state->number = 0;
|
||||
#ifdef JS_THREADSAFE
|
||||
js_DestroyLock(&state->lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct MarkArgs {
|
||||
JSRuntime *runtime;
|
||||
JSGCThingMarker mark;
|
||||
} MarkArgs;
|
||||
|
||||
STATIC_DLL_CALLBACK(intN)
|
||||
js_atom_marker(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
JSAtom *atom;
|
||||
jsval key;
|
||||
MarkArgs *args;
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
if (atom->flags & ATOM_PINNED) {
|
||||
atom->flags |= ATOM_MARK;
|
||||
key = ATOM_KEY(atom);
|
||||
if (JSVAL_IS_GCTHING(key)) {
|
||||
args = arg;
|
||||
args->mark(args->runtime, JSVAL_TO_GCTHING(key));
|
||||
}
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
js_MarkAtomState(JSAtomState *state, JSGCThingMarker mark)
|
||||
{
|
||||
MarkArgs args;
|
||||
|
||||
args.runtime = state->runtime;
|
||||
args.mark = mark;
|
||||
JS_HashTableEnumerateEntries(state->table, js_atom_marker, &args);
|
||||
}
|
||||
|
||||
STATIC_DLL_CALLBACK(intN)
|
||||
js_atom_sweeper(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
JSAtom *atom;
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
if (atom->flags & ATOM_MARK) {
|
||||
atom->flags &= ~ATOM_MARK;
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
JS_ASSERT((atom->flags & ATOM_PINNED) == 0);
|
||||
atom->entry.key = NULL;
|
||||
atom->flags = 0;
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
js_SweepAtomState(JSAtomState *state)
|
||||
{
|
||||
JS_HashTableEnumerateEntries(state->table, js_atom_sweeper, NULL);
|
||||
}
|
||||
|
||||
STATIC_DLL_CALLBACK(intN)
|
||||
js_atom_unpinner(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
JSAtom *atom;
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags &= ~ATOM_PINNED;
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
js_UnpinPinnedAtoms(JSAtomState *state)
|
||||
{
|
||||
JS_HashTableEnumerateEntries(state->table, js_atom_unpinner, NULL);
|
||||
}
|
||||
|
||||
static JSAtom *
|
||||
js_AtomizeHashedKey(JSContext *cx, jsval key, JSHashNumber keyHash, uintN flags)
|
||||
{
|
||||
JSAtomState *state;
|
||||
JSHashTable *table;
|
||||
JSHashEntry *he, **hep;
|
||||
JSAtom *atom;
|
||||
|
||||
state = &cx->runtime->atomState;
|
||||
JS_LOCK(&state->lock,cx);
|
||||
table = state->table;
|
||||
hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
|
||||
if ((he = *hep) == NULL) {
|
||||
he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
|
||||
if (!he) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
atom = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags |= flags;
|
||||
out:
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeObject(JSContext *cx, JSObject *obj, uintN flags)
|
||||
{
|
||||
jsval key;
|
||||
JSHashNumber keyHash;
|
||||
|
||||
/* XXX must be set in the following order or MSVC1.52 will crash */
|
||||
keyHash = HASH_OBJECT(obj);
|
||||
key = OBJECT_TO_JSVAL(obj);
|
||||
return js_AtomizeHashedKey(cx, key, keyHash, flags);
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags)
|
||||
{
|
||||
jsval key;
|
||||
JSHashNumber keyHash;
|
||||
|
||||
key = BOOLEAN_TO_JSVAL(b);
|
||||
keyHash = HASH_BOOLEAN(b);
|
||||
return js_AtomizeHashedKey(cx, key, keyHash, flags);
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeInt(JSContext *cx, jsint i, uintN flags)
|
||||
{
|
||||
jsval key;
|
||||
JSHashNumber keyHash;
|
||||
|
||||
key = INT_TO_JSVAL(i);
|
||||
keyHash = HASH_INT(i);
|
||||
return js_AtomizeHashedKey(cx, key, keyHash, flags);
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags)
|
||||
{
|
||||
jsdouble *dp;
|
||||
JSHashNumber keyHash;
|
||||
jsval key;
|
||||
JSAtomState *state;
|
||||
JSHashTable *table;
|
||||
JSHashEntry *he, **hep;
|
||||
JSAtom *atom;
|
||||
|
||||
#if JS_ALIGN_OF_DOUBLE == 8
|
||||
dp = &d;
|
||||
#else
|
||||
char alignbuf[16];
|
||||
|
||||
dp = (jsdouble *)&alignbuf[8 - ((jsuword)&alignbuf & 7)];
|
||||
*dp = d;
|
||||
#endif
|
||||
|
||||
keyHash = HASH_DOUBLE(dp);
|
||||
key = DOUBLE_TO_JSVAL(dp);
|
||||
state = &cx->runtime->atomState;
|
||||
JS_LOCK(&state->lock,cx);
|
||||
table = state->table;
|
||||
hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
|
||||
if ((he = *hep) == NULL) {
|
||||
#ifdef JS_THREADSAFE
|
||||
uint32 gen = state->tablegen;
|
||||
#endif
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
if (!js_NewDoubleValue(cx, d, &key))
|
||||
return NULL;
|
||||
JS_LOCK(&state->lock,cx);
|
||||
#ifdef JS_THREADSAFE
|
||||
if (state->tablegen != gen) {
|
||||
hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
|
||||
if ((he = *hep) != NULL) {
|
||||
atom = (JSAtom *)he;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
|
||||
if (!he) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
atom = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags |= flags;
|
||||
out:
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
jsval key;
|
||||
JSAtomState *state;
|
||||
JSHashTable *table;
|
||||
JSHashEntry *he, **hep;
|
||||
JSAtom *atom;
|
||||
|
||||
keyHash = js_HashString(str);
|
||||
key = STRING_TO_JSVAL(str);
|
||||
state = &cx->runtime->atomState;
|
||||
JS_LOCK(&state->lock,cx);
|
||||
table = state->table;
|
||||
hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
|
||||
if ((he = *hep) == NULL) {
|
||||
if (flags & ATOM_TMPSTR) {
|
||||
#ifdef JS_THREADSAFE
|
||||
uint32 gen = state->tablegen;
|
||||
#endif
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
flags &= ~ATOM_TMPSTR;
|
||||
if (flags & ATOM_NOCOPY) {
|
||||
flags &= ~ATOM_NOCOPY;
|
||||
str = js_NewString(cx, str->chars, str->length, 0);
|
||||
} else {
|
||||
str = js_NewStringCopyN(cx, str->chars, str->length, 0);
|
||||
}
|
||||
if (!str)
|
||||
return NULL;
|
||||
key = STRING_TO_JSVAL(str);
|
||||
JS_LOCK(&state->lock,cx);
|
||||
#ifdef JS_THREADSAFE
|
||||
if (state->tablegen != gen) {
|
||||
hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
|
||||
if ((he = *hep) != NULL) {
|
||||
atom = (JSAtom *)he;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
|
||||
if (!he) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
atom = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags |= flags;
|
||||
out:
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSAtom *)
|
||||
js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags)
|
||||
{
|
||||
jschar *chars;
|
||||
JSString *str;
|
||||
JSAtom *atom;
|
||||
#if JS_ALIGN_OF_DOUBLE == 8
|
||||
union { jsdouble d; JSString s; } u;
|
||||
|
||||
str = &u.s;
|
||||
#else
|
||||
char alignbuf[16];
|
||||
|
||||
str = (JSString *)&alignbuf[8 - ((jsuword)&alignbuf & 7)];
|
||||
#endif
|
||||
|
||||
chars = js_InflateString(cx, bytes, length);
|
||||
if (!chars)
|
||||
return NULL;
|
||||
str->chars = chars;
|
||||
str->length = length;
|
||||
atom = js_AtomizeString(cx, str, ATOM_TMPSTR | ATOM_NOCOPY | flags);
|
||||
if (!atom || ATOM_TO_STRING(atom)->chars != chars)
|
||||
JS_free(cx, chars);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSAtom *)
|
||||
js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags)
|
||||
{
|
||||
JSString *str;
|
||||
#if JS_ALIGN_OF_DOUBLE == 8
|
||||
union { jsdouble d; JSString s; } u;
|
||||
|
||||
str = &u.s;
|
||||
#else
|
||||
char alignbuf[16];
|
||||
|
||||
str = (JSString *)&alignbuf[8 - ((jsuword)&alignbuf & 7)];
|
||||
#endif
|
||||
|
||||
str->chars = (jschar *)chars;
|
||||
str->length = length;
|
||||
return js_AtomizeString(cx, str, ATOM_TMPSTR | flags);
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeValue(JSContext *cx, jsval value, uintN flags)
|
||||
{
|
||||
if (JSVAL_IS_STRING(value))
|
||||
return js_AtomizeString(cx, JSVAL_TO_STRING(value), flags);
|
||||
if (JSVAL_IS_INT(value))
|
||||
return js_AtomizeInt(cx, JSVAL_TO_INT(value), flags);
|
||||
if (JSVAL_IS_DOUBLE(value))
|
||||
return js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(value), flags);
|
||||
if (JSVAL_IS_OBJECT(value))
|
||||
return js_AtomizeObject(cx, JSVAL_TO_OBJECT(value), flags);
|
||||
if (JSVAL_IS_BOOLEAN(value))
|
||||
return js_AtomizeBoolean(cx, JSVAL_TO_BOOLEAN(value), flags);
|
||||
return js_AtomizeHashedKey(cx, value, (JSHashNumber)value, flags);
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_ValueToStringAtom(JSContext *cx, jsval v)
|
||||
{
|
||||
JSString *str;
|
||||
|
||||
str = js_ValueToString(cx, v);
|
||||
if (!str)
|
||||
return NULL;
|
||||
return js_AtomizeString(cx, str, 0);
|
||||
}
|
||||
|
||||
JSAtomListElement *
|
||||
js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al)
|
||||
{
|
||||
JSAtomListElement *ale;
|
||||
|
||||
ATOM_LIST_SEARCH(ale, al, atom);
|
||||
if (!ale) {
|
||||
JS_ARENA_ALLOCATE(ale, &cx->tempPool, sizeof(JSAtomListElement));
|
||||
if (!ale) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
ale->atom = atom;
|
||||
ale->index = (jsatomid) al->count++;
|
||||
ale->next = al->list;
|
||||
al->list = ale;
|
||||
}
|
||||
return ale;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSAtom *)
|
||||
js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i)
|
||||
{
|
||||
JSAtom *atom;
|
||||
|
||||
JS_ASSERT(map->vector && i < map->length);
|
||||
if (!map->vector || i >= map->length) {
|
||||
char numBuf[12];
|
||||
JS_snprintf(numBuf, sizeof numBuf, "%lu", (unsigned long)i);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_ATOMIC_NUMBER, numBuf);
|
||||
return NULL;
|
||||
}
|
||||
atom = map->vector[i];
|
||||
JS_ASSERT(atom);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al)
|
||||
{
|
||||
JSAtom **vector;
|
||||
JSAtomListElement *ale, *next;
|
||||
uint32 count;
|
||||
|
||||
ale = al->list;
|
||||
if (!ale) {
|
||||
map->vector = NULL;
|
||||
map->length = 0;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
count = al->count;
|
||||
if (count >= ATOM_INDEX_LIMIT) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_TOO_MANY_LITERALS);
|
||||
return JS_FALSE;
|
||||
}
|
||||
vector = JS_malloc(cx, (size_t) count * sizeof *vector);
|
||||
if (!vector)
|
||||
return JS_FALSE;
|
||||
|
||||
do {
|
||||
vector[ale->index] = ale->atom;
|
||||
next = ale->next;
|
||||
ale->next = NULL;
|
||||
} while ((ale = next) != NULL);
|
||||
al->list = NULL;
|
||||
al->count = 0;
|
||||
|
||||
map->vector = vector;
|
||||
map->length = (jsatomid)count;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_FreeAtomMap(JSContext *cx, JSAtomMap *map)
|
||||
{
|
||||
if (map->vector) {
|
||||
free(map->vector);
|
||||
map->vector = NULL;
|
||||
}
|
||||
map->length = 0;
|
||||
}
|
||||
278
mozilla/js/src/jsatom.h
Normal file
278
mozilla/js/src/jsatom.h
Normal file
@@ -0,0 +1,278 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jsatom_h___
|
||||
#define jsatom_h___
|
||||
/*
|
||||
* JS atom table.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "jstypes.h"
|
||||
#ifndef NSPR20
|
||||
#include "jshash.h"
|
||||
#else
|
||||
/* Removed by JSIFY: #include "JShash.h"
|
||||
*/
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
#endif
|
||||
#include "jsapi.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
#include "jslock.h"
|
||||
#endif
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#define ATOM_NOCOPY 0x01 /* don't copy atom string bytes */
|
||||
#define ATOM_TMPSTR 0x02 /* internal, to avoid extra string */
|
||||
#define ATOM_MARK 0x04 /* atom is reachable via GC */
|
||||
#define ATOM_PINNED 0x08 /* atom is pinned against GC */
|
||||
|
||||
struct JSAtom {
|
||||
JSHashEntry entry; /* key is jsval, value keyword info */
|
||||
uint8 flags; /* flags, PINNED and/or MARK for now */
|
||||
int8 kwindex; /* keyword index, -1 if not keyword */
|
||||
jsatomid number; /* atom serial number and hash code */
|
||||
};
|
||||
|
||||
#define ATOM_KEY(atom) ((jsval)(atom)->entry.key)
|
||||
#define ATOM_IS_OBJECT(atom) JSVAL_IS_OBJECT(ATOM_KEY(atom))
|
||||
#define ATOM_TO_OBJECT(atom) JSVAL_TO_OBJECT(ATOM_KEY(atom))
|
||||
#define ATOM_IS_INT(atom) JSVAL_IS_INT(ATOM_KEY(atom))
|
||||
#define ATOM_TO_INT(atom) JSVAL_TO_INT(ATOM_KEY(atom))
|
||||
#define ATOM_IS_DOUBLE(atom) JSVAL_IS_DOUBLE(ATOM_KEY(atom))
|
||||
#define ATOM_TO_DOUBLE(atom) JSVAL_TO_DOUBLE(ATOM_KEY(atom))
|
||||
#define ATOM_IS_STRING(atom) JSVAL_IS_STRING(ATOM_KEY(atom))
|
||||
#define ATOM_TO_STRING(atom) JSVAL_TO_STRING(ATOM_KEY(atom))
|
||||
#define ATOM_IS_BOOLEAN(atom) JSVAL_IS_BOOLEAN(ATOM_KEY(atom))
|
||||
#define ATOM_TO_BOOLEAN(atom) JSVAL_TO_BOOLEAN(ATOM_KEY(atom))
|
||||
#define ATOM_BYTES(atom) JS_GetStringBytes(ATOM_TO_STRING(atom))
|
||||
|
||||
struct JSAtomListElement {
|
||||
JSAtomListElement *next;
|
||||
jsatomid index; /* index in script-specific atom map */
|
||||
JSAtom *atom;
|
||||
};
|
||||
|
||||
struct JSAtomList {
|
||||
JSAtomListElement *list; /* literals indexed for mapping */
|
||||
jsuint count; /* count of indexed literals */
|
||||
};
|
||||
|
||||
#define ATOM_LIST_INIT(al) ((al)->list = NULL, (al)->count = 0)
|
||||
|
||||
#define ATOM_LIST_SEARCH(_ale,_al,_atom) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSAtomListElement **_alep = &(_al)->list; \
|
||||
while ((_ale = *_alep) != NULL) { \
|
||||
if (_ale->atom == (_atom)) { \
|
||||
/* Hit, move atom's element to the front of the list. */ \
|
||||
*_alep = _ale->next; \
|
||||
_ale->next = (_al)->list; \
|
||||
(_al)->list = _ale; \
|
||||
break; \
|
||||
} \
|
||||
_alep = &_ale->next; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
struct JSAtomMap {
|
||||
JSAtom **vector; /* array of ptrs to indexed atoms */
|
||||
jsatomid length; /* count of (to-be-)indexed atoms */
|
||||
};
|
||||
|
||||
struct JSAtomState {
|
||||
JSRuntime *runtime; /* runtime that owns us */
|
||||
JSHashTable *table; /* hash table containing all atoms */
|
||||
jsatomid number; /* one beyond greatest atom number */
|
||||
|
||||
/* Type names and value literals. */
|
||||
JSAtom *typeAtoms[JSTYPE_LIMIT];
|
||||
JSAtom *booleanAtoms[2];
|
||||
JSAtom *nullAtom;
|
||||
|
||||
/* Various built-in or commonly-used atoms. */
|
||||
JSAtom *ArrayAtom;
|
||||
JSAtom *MathAtom;
|
||||
JSAtom *ObjectAtom;
|
||||
JSAtom *anonymousAtom;
|
||||
JSAtom *argumentsAtom;
|
||||
JSAtom *arityAtom;
|
||||
JSAtom *assignAtom;
|
||||
JSAtom *calleeAtom;
|
||||
JSAtom *callerAtom;
|
||||
JSAtom *classPrototypeAtom;
|
||||
JSAtom *constructorAtom;
|
||||
JSAtom *countAtom;
|
||||
JSAtom *indexAtom;
|
||||
JSAtom *inputAtom;
|
||||
JSAtom *lengthAtom;
|
||||
JSAtom *nameAtom;
|
||||
JSAtom *parentAtom;
|
||||
JSAtom *protoAtom;
|
||||
JSAtom *toSourceAtom;
|
||||
JSAtom *toStringAtom;
|
||||
JSAtom *valueOfAtom;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
JSThinLock lock;
|
||||
volatile uint32 tablegen;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Well-known predefined strings and their atoms. */
|
||||
extern char *js_type_str[];
|
||||
extern char *js_boolean_str[];
|
||||
|
||||
extern char js_Array_str[];
|
||||
extern char js_Math_str[];
|
||||
extern char js_Object_str[];
|
||||
extern char js_anonymous_str[];
|
||||
extern char js_arguments_str[];
|
||||
extern char js_arity_str[];
|
||||
extern char js_assign_str[];
|
||||
extern char js_callee_str[];
|
||||
extern char js_caller_str[];
|
||||
extern char js_class_prototype_str[];
|
||||
extern char js_constructor_str[];
|
||||
extern char js_count_str[];
|
||||
extern char js_eval_str[];
|
||||
extern char js_index_str[];
|
||||
extern char js_input_str[];
|
||||
extern char js_length_str[];
|
||||
extern char js_name_str[];
|
||||
extern char js_parent_str[];
|
||||
extern char js_proto_str[];
|
||||
extern char js_toSource_str[];
|
||||
extern char js_toString_str[];
|
||||
extern char js_valueOf_str[];
|
||||
|
||||
/*
|
||||
* Initialize atom state. Return true on success, false with an out of
|
||||
* memory error report on failure.
|
||||
*/
|
||||
extern JSBool
|
||||
js_InitAtomState(JSContext *cx, JSAtomState *state);
|
||||
|
||||
/*
|
||||
* Free and clear atom state.
|
||||
*/
|
||||
extern void
|
||||
js_FreeAtomState(JSContext *cx, JSAtomState *state);
|
||||
|
||||
/*
|
||||
* Atom garbage collection hooks.
|
||||
*/
|
||||
typedef void
|
||||
(*JSGCThingMarker)(JSRuntime *rt, void *thing);
|
||||
|
||||
extern void
|
||||
js_MarkAtomState(JSAtomState *state, JSGCThingMarker mark);
|
||||
|
||||
extern void
|
||||
js_SweepAtomState(JSAtomState *state);
|
||||
|
||||
extern void
|
||||
js_UnpinPinnedAtoms(JSAtomState *state);
|
||||
|
||||
/*
|
||||
* Find or create the atom for an object. If we create a new atom, give it the
|
||||
* type indicated in flags. Return 0 on failure to allocate memory.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeObject(JSContext *cx, JSObject *obj, uintN flags);
|
||||
|
||||
/*
|
||||
* Find or create the atom for a Boolean value. If we create a new atom, give
|
||||
* it the type indicated in flags. Return 0 on failure to allocate memory.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags);
|
||||
|
||||
/*
|
||||
* Find or create the atom for an integer value. If we create a new atom, give
|
||||
* it the type indicated in flags. Return 0 on failure to allocate memory.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeInt(JSContext *cx, jsint i, uintN flags);
|
||||
|
||||
/*
|
||||
* Find or create the atom for a double value. If we create a new atom, give
|
||||
* it the type indicated in flags. Return 0 on failure to allocate memory.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags);
|
||||
|
||||
/*
|
||||
* Find or create the atom for a string. If we create a new atom, give it the
|
||||
* type indicated in flags. Return 0 on failure to allocate memory.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeString(JSContext *cx, JSString *str, uintN flags);
|
||||
|
||||
extern JS_FRIEND_API(JSAtom *)
|
||||
js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags);
|
||||
|
||||
extern JS_FRIEND_API(JSAtom *)
|
||||
js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags);
|
||||
|
||||
/*
|
||||
* This variant handles all value tag types.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeValue(JSContext *cx, jsval value, uintN flags);
|
||||
|
||||
/*
|
||||
* Convert v to an atomized string.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_ValueToStringAtom(JSContext *cx, jsval v);
|
||||
|
||||
/*
|
||||
* Assign atom an index and insert it on al.
|
||||
*/
|
||||
extern JSAtomListElement *
|
||||
js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al);
|
||||
|
||||
/*
|
||||
* Get the atom with index i from map.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSAtom *)
|
||||
js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i);
|
||||
|
||||
/*
|
||||
* For all unmapped atoms recorded in al, add a mapping from the atom's index
|
||||
* to its address. The GC must not run until all indexed atoms in atomLists
|
||||
* have been mapped by scripts connected to live objects (Function and Script
|
||||
* class objects have scripts as/in their private data -- the GC knows about
|
||||
* these two classes).
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al);
|
||||
|
||||
/*
|
||||
* Free map->vector and clear map.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
js_FreeAtomMap(JSContext *cx, JSAtomMap *map);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsatom_h___ */
|
||||
92
mozilla/js/src/jsbit.h
Normal file
92
mozilla/js/src/jsbit.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsbit_h___
|
||||
#define jsbit_h___
|
||||
|
||||
#include "jstypes.h"
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
** A jsbitmap_t is a long integer that can be used for bitmaps
|
||||
*/
|
||||
typedef unsigned long jsbitmap_t;
|
||||
|
||||
#define JS_TEST_BIT(_map,_bit) \
|
||||
((_map)[(_bit)>>JS_BITS_PER_LONG_LOG2] & (1L << ((_bit) & (JS_BITS_PER_LONG-1))))
|
||||
#define JS_SET_BIT(_map,_bit) \
|
||||
((_map)[(_bit)>>JS_BITS_PER_LONG_LOG2] |= (1L << ((_bit) & (JS_BITS_PER_LONG-1))))
|
||||
#define JS_CLEAR_BIT(_map,_bit) \
|
||||
((_map)[(_bit)>>JS_BITS_PER_LONG_LOG2] &= ~(1L << ((_bit) & (JS_BITS_PER_LONG-1))))
|
||||
|
||||
/*
|
||||
** Compute the log of the least power of 2 greater than or equal to n
|
||||
*/
|
||||
EXTERN(JSIntn) JS_CeilingLog2(JSUint32 i);
|
||||
|
||||
/*
|
||||
** Compute the log of the greatest power of 2 less than or equal to n
|
||||
*/
|
||||
EXTERN(JSIntn) JS_FloorLog2(JSUint32 i);
|
||||
|
||||
/*
|
||||
** Macro version of JS_CeilingLog2: Compute the log of the least power of
|
||||
** 2 greater than or equal to _n. The result is returned in _log2.
|
||||
*/
|
||||
#define JS_CEILING_LOG2(_log2,_n) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSUint32 j_ = (JSUint32)(_n); \
|
||||
(_log2) = 0; \
|
||||
if ((j_) & ((j_)-1)) \
|
||||
(_log2) += 1; \
|
||||
if ((j_) >> 16) \
|
||||
(_log2) += 16, (j_) >>= 16; \
|
||||
if ((j_) >> 8) \
|
||||
(_log2) += 8, (j_) >>= 8; \
|
||||
if ((j_) >> 4) \
|
||||
(_log2) += 4, (j_) >>= 4; \
|
||||
if ((j_) >> 2) \
|
||||
(_log2) += 2, (j_) >>= 2; \
|
||||
if ((j_) >> 1) \
|
||||
(_log2) += 1; \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Macro version of JS_FloorLog2: Compute the log of the greatest power of
|
||||
** 2 less than or equal to _n. The result is returned in _log2.
|
||||
**
|
||||
** This is equivalent to finding the highest set bit in the word.
|
||||
*/
|
||||
#define JS_FLOOR_LOG2(_log2,_n) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSUint32 j_ = (JSUint32)(_n); \
|
||||
(_log2) = 0; \
|
||||
if ((j_) >> 16) \
|
||||
(_log2) += 16, (j_) >>= 16; \
|
||||
if ((j_) >> 8) \
|
||||
(_log2) += 8, (j_) >>= 8; \
|
||||
if ((j_) >> 4) \
|
||||
(_log2) += 4, (j_) >>= 4; \
|
||||
if ((j_) >> 2) \
|
||||
(_log2) += 2, (j_) >>= 2; \
|
||||
if ((j_) >> 1) \
|
||||
(_log2) += 1; \
|
||||
JS_END_MACRO
|
||||
|
||||
JS_END_EXTERN_C
|
||||
#endif /* jsbit_h___ */
|
||||
211
mozilla/js/src/jsbool.c
Normal file
211
mozilla/js/src/jsbool.c
Normal file
@@ -0,0 +1,211 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS boolean implementation.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include "jstypes.h"
|
||||
/* Removed by JSIFY: #include "prlog.h" */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsbool.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jslock.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
static JSClass boolean_class = {
|
||||
"Boolean",
|
||||
JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
#include "jsprf.h"
|
||||
|
||||
static JSBool
|
||||
bool_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
jsval v;
|
||||
char buf[32];
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &boolean_class, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
if (!JSVAL_IS_BOOLEAN(v))
|
||||
return js_obj_toSource(cx, obj, argc, argv, rval);
|
||||
JS_snprintf(buf, sizeof buf, "(new %s(%s))",
|
||||
boolean_class.name,
|
||||
js_boolean_str[JSVAL_TO_BOOLEAN(v) ? 1 : 0]);
|
||||
str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
bool_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
jsval v;
|
||||
JSAtom *atom;
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &boolean_class, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
if (!JSVAL_IS_BOOLEAN(v))
|
||||
return js_obj_toString(cx, obj, argc, argv, rval);
|
||||
atom = cx->runtime->atomState.booleanAtoms[JSVAL_TO_BOOLEAN(v) ? 1 : 0];
|
||||
str = ATOM_TO_STRING(atom);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
bool_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
if (!JS_InstanceOf(cx, obj, &boolean_class, argv))
|
||||
return JS_FALSE;
|
||||
*rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec boolean_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, bool_toSource, 0},
|
||||
#endif
|
||||
{js_toString_str, bool_toString, 0},
|
||||
{js_valueOf_str, bool_valueOf, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
#ifdef XP_MAC
|
||||
#undef Boolean
|
||||
#define Boolean js_Boolean
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
Boolean(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSBool b;
|
||||
jsval bval;
|
||||
|
||||
if (argc != 0) {
|
||||
if (!js_ValueToBoolean(cx, argv[0], &b))
|
||||
return JS_FALSE;
|
||||
bval = BOOLEAN_TO_JSVAL(b);
|
||||
} else {
|
||||
bval = JSVAL_FALSE;
|
||||
}
|
||||
if (!cx->fp->constructing) {
|
||||
*rval = bval;
|
||||
return JS_TRUE;
|
||||
}
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, bval);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_InitBooleanClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *proto;
|
||||
|
||||
proto = JS_InitClass(cx, obj, NULL, &boolean_class, Boolean, 1,
|
||||
NULL, boolean_methods, NULL, NULL);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE, JSVAL_FALSE);
|
||||
return proto;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_BooleanToObject(JSContext *cx, JSBool b)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = js_NewObject(cx, &boolean_class, NULL, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, BOOLEAN_TO_JSVAL(b));
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSString *
|
||||
js_BooleanToString(JSContext *cx, JSBool b)
|
||||
{
|
||||
return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[b ? 1 : 0]);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
|
||||
{
|
||||
JSBool b;
|
||||
jsdouble d;
|
||||
|
||||
#if defined XP_PC && defined _MSC_VER &&_MSC_VER <= 800
|
||||
/* MSVC1.5 coredumps */
|
||||
if (!bp)
|
||||
return JS_TRUE;
|
||||
#endif
|
||||
|
||||
/* XXX this should be an if-else chain, but MSVC1.5 crashes if it is. */
|
||||
if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
|
||||
/* Must return early to avoid falling thru to JSVAL_IS_OBJECT case. */
|
||||
*bp = JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (JSVAL_IS_OBJECT(v)) {
|
||||
if (!JSVERSION_IS_ECMA(cx->version)) {
|
||||
if (!OBJ_DEFAULT_VALUE(cx, JSVAL_TO_OBJECT(v), JSTYPE_BOOLEAN, &v))
|
||||
return JS_FALSE;
|
||||
if (!JSVAL_IS_BOOLEAN(v))
|
||||
v = JSVAL_TRUE; /* non-null object is true */
|
||||
b = JSVAL_TO_BOOLEAN(v);
|
||||
} else {
|
||||
b = JS_TRUE;
|
||||
}
|
||||
}
|
||||
if (JSVAL_IS_STRING(v)) {
|
||||
b = JSVAL_TO_STRING(v)->length ? JS_TRUE : JS_FALSE;
|
||||
}
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
b = JSVAL_TO_INT(v) ? JS_TRUE : JS_FALSE;
|
||||
}
|
||||
if (JSVAL_IS_DOUBLE(v)) {
|
||||
d = *JSVAL_TO_DOUBLE(v);
|
||||
b = (!JSDOUBLE_IS_NaN(d) && d != 0) ? JS_TRUE : JS_FALSE;
|
||||
}
|
||||
if (JSVAL_IS_BOOLEAN(v)) {
|
||||
b = JSVAL_TO_BOOLEAN(v);
|
||||
}
|
||||
*bp = b;
|
||||
return JS_TRUE;
|
||||
}
|
||||
41
mozilla/js/src/jsbool.h
Normal file
41
mozilla/js/src/jsbool.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jsbool_h___
|
||||
#define jsbool_h___
|
||||
/*
|
||||
* JS boolean interface.
|
||||
*/
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JSObject *
|
||||
js_InitBooleanClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSObject *
|
||||
js_BooleanToObject(JSContext *cx, JSBool b);
|
||||
|
||||
extern JSString *
|
||||
js_BooleanToString(JSContext *cx, JSBool b);
|
||||
|
||||
extern JSBool
|
||||
js_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsbool_h___ */
|
||||
121
mozilla/js/src/jsclist.h
Normal file
121
mozilla/js/src/jsclist.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsclist_h___
|
||||
#define jsclist_h___
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
typedef struct JSCListStr JSCList;
|
||||
|
||||
/*
|
||||
** Circular linked list
|
||||
*/
|
||||
struct JSCListStr {
|
||||
JSCList *next;
|
||||
JSCList *prev;
|
||||
};
|
||||
|
||||
/*
|
||||
** Insert element "_e" into the list, before "_l".
|
||||
*/
|
||||
#define JS_INSERT_BEFORE(_e,_l) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->next = (_l); \
|
||||
(_e)->prev = (_l)->prev; \
|
||||
(_l)->prev->next = (_e); \
|
||||
(_l)->prev = (_e); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Insert element "_e" into the list, after "_l".
|
||||
*/
|
||||
#define JS_INSERT_AFTER(_e,_l) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->next = (_l)->next; \
|
||||
(_e)->prev = (_l); \
|
||||
(_l)->next->prev = (_e); \
|
||||
(_l)->next = (_e); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Return the element following element "_e"
|
||||
*/
|
||||
#define JS_NEXT_LINK(_e) \
|
||||
((_e)->next)
|
||||
/*
|
||||
** Return the element preceding element "_e"
|
||||
*/
|
||||
#define JS_PREV_LINK(_e) \
|
||||
((_e)->prev)
|
||||
|
||||
/*
|
||||
** Append an element "_e" to the end of the list "_l"
|
||||
*/
|
||||
#define JS_APPEND_LINK(_e,_l) JS_INSERT_BEFORE(_e,_l)
|
||||
|
||||
/*
|
||||
** Insert an element "_e" at the head of the list "_l"
|
||||
*/
|
||||
#define JS_INSERT_LINK(_e,_l) JS_INSERT_AFTER(_e,_l)
|
||||
|
||||
/* Return the head/tail of the list */
|
||||
#define JS_LIST_HEAD(_l) (_l)->next
|
||||
#define JS_LIST_TAIL(_l) (_l)->prev
|
||||
|
||||
/*
|
||||
** Remove the element "_e" from it's circular list.
|
||||
*/
|
||||
#define JS_REMOVE_LINK(_e) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->prev->next = (_e)->next; \
|
||||
(_e)->next->prev = (_e)->prev; \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Remove the element "_e" from it's circular list. Also initializes the
|
||||
** linkage.
|
||||
*/
|
||||
#define JS_REMOVE_AND_INIT_LINK(_e) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->prev->next = (_e)->next; \
|
||||
(_e)->next->prev = (_e)->prev; \
|
||||
(_e)->next = (_e); \
|
||||
(_e)->prev = (_e); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Return non-zero if the given circular list "_l" is empty, zero if the
|
||||
** circular list is not empty
|
||||
*/
|
||||
#define JS_CLIST_IS_EMPTY(_l) \
|
||||
((_l)->next == (_l))
|
||||
|
||||
/*
|
||||
** Initialize a circular list
|
||||
*/
|
||||
#define JS_INIT_CLIST(_l) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_l)->next = (_l); \
|
||||
(_l)->prev = (_l); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_INIT_STATIC_CLIST(_l) \
|
||||
{(_l), (_l)}
|
||||
|
||||
#endif /* jsclist_h___ */
|
||||
400
mozilla/js/src/jscntxt.c
Normal file
400
mozilla/js/src/jscntxt.c
Normal file
@@ -0,0 +1,400 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS execution context.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#ifndef NSPR20
|
||||
#include "jsarena.h"
|
||||
#else
|
||||
/* Removed by JSIFY: #include "plarena.h"
|
||||
*/
|
||||
#include "jsarena.h" /* Added by JSIFY */
|
||||
#endif
|
||||
/* Removed by JSIFY: #include "prlog.h" */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsclist.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsexn.h"
|
||||
#include "jsgc.h"
|
||||
#include "jslock.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsscan.h"
|
||||
#include "jsscript.h"
|
||||
|
||||
JSContext *
|
||||
js_NewContext(JSRuntime *rt, size_t stacksize)
|
||||
{
|
||||
JSContext *cx;
|
||||
|
||||
cx = malloc(sizeof *cx);
|
||||
if (!cx)
|
||||
return NULL;
|
||||
memset(cx, 0, sizeof *cx);
|
||||
|
||||
cx->runtime = rt;
|
||||
#ifdef JS_THREADSAFE
|
||||
js_InitContextForLocking(cx);
|
||||
#endif
|
||||
if (rt->contextList.next == (JSCList *)&rt->contextList) {
|
||||
/* First context on this runtime: initialize atoms and keywords. */
|
||||
if (!js_InitAtomState(cx, &rt->atomState) ||
|
||||
!js_InitScanner(cx)) {
|
||||
free(cx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* Atomicly append cx to rt's context list. */
|
||||
JS_LOCK_RUNTIME_VOID(rt, JS_APPEND_LINK(&cx->links, &rt->contextList));
|
||||
|
||||
cx->version = JSVERSION_DEFAULT;
|
||||
cx->jsop_eq = JSOP_EQ;
|
||||
cx->jsop_ne = JSOP_NE;
|
||||
JS_InitArenaPool(&cx->stackPool, "stack", stacksize, sizeof(jsval));
|
||||
JS_InitArenaPool(&cx->codePool, "code", 1024, sizeof(jsbytecode));
|
||||
JS_InitArenaPool(&cx->tempPool, "temp", 1024, sizeof(jsdouble));
|
||||
|
||||
#if JS_HAS_REGEXPS
|
||||
if (!js_InitRegExpStatics(cx, &cx->regExpStatics)) {
|
||||
js_DestroyContext(cx);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
js_DestroyContext(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSBool rtempty;
|
||||
|
||||
rt = cx->runtime;
|
||||
|
||||
/* Remove cx from context list first. */
|
||||
JS_LOCK_RUNTIME(rt);
|
||||
JS_REMOVE_LINK(&cx->links);
|
||||
rtempty = (rt->contextList.next == (JSCList *)&rt->contextList);
|
||||
JS_UNLOCK_RUNTIME(rt);
|
||||
|
||||
if (rtempty) {
|
||||
/* Unpin all pinned atoms before final GC. */
|
||||
js_UnpinPinnedAtoms(&rt->atomState);
|
||||
|
||||
/* Unlock GC things held by runtime pointers. */
|
||||
js_UnlockGCThing(cx, rt->jsNaN);
|
||||
js_UnlockGCThing(cx, rt->jsNegativeInfinity);
|
||||
js_UnlockGCThing(cx, rt->jsPositiveInfinity);
|
||||
js_UnlockGCThing(cx, rt->emptyString);
|
||||
|
||||
/*
|
||||
* Clear these so they get recreated if the standard classes are
|
||||
* initialized again.
|
||||
*/
|
||||
rt->jsNaN = NULL;
|
||||
rt->jsNegativeInfinity = NULL;
|
||||
rt->jsPositiveInfinity = NULL;
|
||||
rt->emptyString = NULL;
|
||||
|
||||
/* Clear debugging state to remove GC roots. */
|
||||
JS_ClearAllTraps(cx);
|
||||
JS_ClearAllWatchPoints(cx);
|
||||
}
|
||||
|
||||
/* Remove more GC roots in regExpStatics, then collect garbage. */
|
||||
#if JS_HAS_REGEXPS
|
||||
js_FreeRegExpStatics(cx, &cx->regExpStatics);
|
||||
#endif
|
||||
js_ForceGC(cx);
|
||||
|
||||
if (rtempty) {
|
||||
/* Free atom state now that we've run the GC. */
|
||||
js_FreeAtomState(cx, &rt->atomState);
|
||||
}
|
||||
|
||||
/* Free the stuff hanging off of cx. */
|
||||
JS_FinishArenaPool(&cx->stackPool);
|
||||
JS_FinishArenaPool(&cx->codePool);
|
||||
JS_FinishArenaPool(&cx->tempPool);
|
||||
if (cx->lastMessage)
|
||||
free(cx->lastMessage);
|
||||
free(cx);
|
||||
}
|
||||
|
||||
JSContext *
|
||||
js_ContextIterator(JSRuntime *rt, JSContext **iterp)
|
||||
{
|
||||
JSContext *cx = *iterp;
|
||||
|
||||
JS_LOCK_RUNTIME(rt);
|
||||
if (!cx)
|
||||
cx = (JSContext *)rt->contextList.next;
|
||||
if ((void *)cx == &rt->contextList)
|
||||
cx = NULL;
|
||||
else
|
||||
*iterp = (JSContext *)cx->links.next;
|
||||
JS_UNLOCK_RUNTIME(rt);
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
|
||||
{
|
||||
JSStackFrame *fp;
|
||||
JSErrorReport report, *reportp;
|
||||
char *last;
|
||||
|
||||
fp = cx->fp;
|
||||
if (fp && fp->script && fp->pc) {
|
||||
report.filename = fp->script->filename;
|
||||
report.lineno = js_PCToLineNumber(fp->script, fp->pc);
|
||||
/* XXX should fetch line somehow */
|
||||
report.linebuf = NULL;
|
||||
report.tokenptr = NULL;
|
||||
report.flags = flags;
|
||||
reportp = &report;
|
||||
} else {
|
||||
/* XXXshaver still fill out report here for flags? */
|
||||
reportp = NULL;
|
||||
}
|
||||
last = JS_vsmprintf(format, ap);
|
||||
if (!last)
|
||||
return;
|
||||
|
||||
js_ReportErrorAgain(cx, last, reportp);
|
||||
free(last);
|
||||
}
|
||||
|
||||
/*
|
||||
* The arguments from ap need to be packaged up into an array and stored
|
||||
* into the report struct.
|
||||
*
|
||||
* The format string addressed by the error number may contain operands
|
||||
* identified by the format {N}, where N is a decimal digit. Each of these
|
||||
* is to be replaced by the Nth argument from the va_list. The complete
|
||||
* message is placed into reportp->ucmessage converted to a JSString.
|
||||
*
|
||||
* returns true/false if the expansion succeeds (can fail for memory errors)
|
||||
*/
|
||||
JSBool
|
||||
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
|
||||
void *userRef, const uintN errorNumber,
|
||||
char **messagep, JSErrorReport *reportp, va_list ap)
|
||||
{
|
||||
const JSErrorFormatString *fmtData;
|
||||
int i;
|
||||
int argCount;
|
||||
|
||||
*messagep = NULL;
|
||||
if (callback) {
|
||||
fmtData = (*callback)(userRef, "Mountain View", errorNumber);
|
||||
if (fmtData != NULL) {
|
||||
argCount = fmtData->argCount;
|
||||
if (argCount > 0) {
|
||||
/*
|
||||
* Gather the arguments into a char * array, the
|
||||
* messageArgs field is supposed to be an array of
|
||||
* JSString's and we'll convert them later.
|
||||
*/
|
||||
reportp->messageArgs = malloc(sizeof(char *) * argCount);
|
||||
if (!reportp->messageArgs)
|
||||
return JS_FALSE;
|
||||
for (i = 0; i < argCount; i++)
|
||||
reportp->messageArgs[i] = (JSString *) va_arg(ap, char *);
|
||||
}
|
||||
/*
|
||||
* Parse the error format, substituting the argument X
|
||||
* for {X} in the format.
|
||||
*/
|
||||
if (argCount > 0) {
|
||||
if (fmtData->format) {
|
||||
const char *fmt, *arg;
|
||||
char *out;
|
||||
int expandedArgs = 0;
|
||||
int expandedLength
|
||||
= strlen(fmtData->format)
|
||||
- (3 * argCount); /* exclude the {n} */
|
||||
|
||||
for (i = 0; i < argCount; i++) {
|
||||
expandedLength
|
||||
+= strlen((char *)reportp->messageArgs[i]);
|
||||
}
|
||||
*messagep = out = malloc(expandedLength + 1);
|
||||
if (!out) {
|
||||
if (reportp->messageArgs) {
|
||||
free(reportp->messageArgs);
|
||||
reportp->messageArgs = NULL;
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
fmt = fmtData->format;
|
||||
while (*fmt) {
|
||||
if (*fmt == '{') { /* balance} */
|
||||
if (isdigit(fmt[1])) {
|
||||
int d = JS7_UNDEC(fmt[1]);
|
||||
JS_ASSERT(expandedArgs < argCount);
|
||||
arg = (char *)reportp->messageArgs[d];
|
||||
strcpy(out, arg);
|
||||
out += strlen(arg);
|
||||
fmt += 3;
|
||||
expandedArgs++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*out++ = *fmt++;
|
||||
}
|
||||
JS_ASSERT(expandedArgs == argCount);
|
||||
*out = '\0';
|
||||
}
|
||||
/*
|
||||
* Now convert all the arguments to JSStrings.
|
||||
*/
|
||||
for (i = 0; i < argCount; i++) {
|
||||
reportp->messageArgs[i] =
|
||||
JS_NewStringCopyZ(cx, (char *)reportp->messageArgs[i]);
|
||||
}
|
||||
} else {
|
||||
*messagep = JS_strdup(cx, fmtData->format);
|
||||
}
|
||||
/*
|
||||
* And finally convert the message.
|
||||
*/
|
||||
reportp->ucmessage = JS_NewStringCopyZ(cx, *messagep);
|
||||
}
|
||||
}
|
||||
if (*messagep == NULL) {
|
||||
/* where's the right place for this ??? */
|
||||
const char *defaultErrorMessage
|
||||
= "No error message available for error number %d";
|
||||
size_t nbytes = strlen(defaultErrorMessage) + 16;
|
||||
*messagep = (char *)malloc(nbytes);
|
||||
JS_snprintf(*messagep, nbytes, defaultErrorMessage, errorNumber);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
|
||||
void *userRef, const uintN errorNumber, va_list ap)
|
||||
{
|
||||
JSStackFrame *fp;
|
||||
JSErrorReport report;
|
||||
char *message;
|
||||
|
||||
report.messageArgs = NULL;
|
||||
report.ucmessage = NULL;
|
||||
message = NULL;
|
||||
|
||||
fp = cx->fp;
|
||||
if (fp && fp->script && fp->pc) {
|
||||
report.filename = fp->script->filename;
|
||||
report.lineno = js_PCToLineNumber(fp->script, fp->pc);
|
||||
} else {
|
||||
report.filename = NULL;
|
||||
report.lineno = 0;
|
||||
}
|
||||
|
||||
/* XXX should fetch line somehow */
|
||||
report.linebuf = NULL;
|
||||
report.tokenptr = NULL;
|
||||
report.flags = flags;
|
||||
report.errorNumber = errorNumber;
|
||||
|
||||
if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
|
||||
&message, &report, ap))
|
||||
return;
|
||||
|
||||
#if JS_HAS_ERROR_EXCEPTIONS
|
||||
/*
|
||||
* Check the error report, and set a JavaScript-catchable exception
|
||||
* if the error is defined to have an associated exception. If an
|
||||
* exception is thrown, then the JSREPORT_EXCEPTION flag will be set
|
||||
* on the error report, and exception-aware hosts should ignore it.
|
||||
*/
|
||||
js_ErrorToException(cx, &report, message);
|
||||
#endif
|
||||
|
||||
js_ReportErrorAgain(cx, message, &report);
|
||||
|
||||
if (message)
|
||||
free(message);
|
||||
if (report.messageArgs)
|
||||
free(report.messageArgs);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
|
||||
{
|
||||
JSErrorReporter onError;
|
||||
|
||||
if (!message)
|
||||
return;
|
||||
if (cx->lastMessage)
|
||||
free(cx->lastMessage);
|
||||
cx->lastMessage = JS_strdup(cx, message);
|
||||
if (!cx->lastMessage)
|
||||
return;
|
||||
onError = cx->errorReporter;
|
||||
if (onError)
|
||||
(*onError)(cx, cx->lastMessage, reportp);
|
||||
}
|
||||
|
||||
void
|
||||
js_ReportIsNotDefined(JSContext *cx, const char *name)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_DEFINED, name);
|
||||
}
|
||||
|
||||
#if defined DEBUG && defined XP_UNIX
|
||||
/* For gdb usage. */
|
||||
void js_traceon(JSContext *cx) { cx->tracefp = stderr; }
|
||||
void js_traceoff(JSContext *cx) { cx->tracefp = NULL; }
|
||||
#endif
|
||||
|
||||
|
||||
JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
|
||||
#if JS_HAS_DFLT_MSG_STRINGS
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
{ format, count } ,
|
||||
#else
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
{ NULL, count } ,
|
||||
#endif
|
||||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
};
|
||||
|
||||
const JSErrorFormatString *
|
||||
js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
|
||||
{
|
||||
if ((errorNumber > 0) && (errorNumber < JSErr_Limit))
|
||||
return &js_ErrorFormatString[errorNumber];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
230
mozilla/js/src/jscntxt.h
Normal file
230
mozilla/js/src/jscntxt.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jscntxt_h___
|
||||
#define jscntxt_h___
|
||||
/*
|
||||
* JS execution context.
|
||||
*/
|
||||
#ifndef NSPR20
|
||||
#include "jsarena.h"
|
||||
#else
|
||||
/* Removed by JSIFY: #include "plarena.h"
|
||||
*/
|
||||
#include "jsarena.h" /* Added by JSIFY */
|
||||
#endif
|
||||
#include "jsclist.h"
|
||||
#include "jslong.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsregexp.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
struct JSRuntime {
|
||||
/* Garbage collector state, used by jsgc.c. */
|
||||
JSArenaPool gcArenaPool;
|
||||
JSArenaPool gcFlagsPool;
|
||||
JSHashTable *gcRootsHash;
|
||||
JSGCThing *gcFreeList;
|
||||
uint32 gcBytes;
|
||||
uint32 gcLastBytes;
|
||||
uint32 gcMaxBytes;
|
||||
uint32 gcLevel;
|
||||
uint32 gcNumber;
|
||||
JSBool gcPoke;
|
||||
JSGCCallback gcCallback;
|
||||
#ifdef JS_GCMETER
|
||||
JSGCStats gcStats;
|
||||
#endif
|
||||
|
||||
/* Literal table maintained by jsatom.c functions. */
|
||||
JSAtomState atomState;
|
||||
|
||||
/* Random number generator state, used by jsmath.c. */
|
||||
JSBool rngInitialized;
|
||||
int64 rngMultiplier;
|
||||
int64 rngAddend;
|
||||
int64 rngMask;
|
||||
int64 rngSeed;
|
||||
jsdouble rngDscale;
|
||||
|
||||
/* Well-known numbers held for use by this runtime's contexts. */
|
||||
jsdouble *jsNaN;
|
||||
jsdouble *jsNegativeInfinity;
|
||||
jsdouble *jsPositiveInfinity;
|
||||
|
||||
/* Empty string held for use by this runtime's contexts. */
|
||||
JSString *emptyString;
|
||||
|
||||
/* List of active contexts sharing this runtime. */
|
||||
JSCList contextList;
|
||||
|
||||
/* These are used for debugging -- see jsprvtd.h and jsdbgapi.h. */
|
||||
JSTrapHandler interruptHandler;
|
||||
void *interruptHandlerData;
|
||||
JSNewScriptHook newScriptHook;
|
||||
void *newScriptHookData;
|
||||
JSDestroyScriptHook destroyScriptHook;
|
||||
void *destroyScriptHookData;
|
||||
JSTrapHandler debuggerHandler;
|
||||
void *debuggerHandlerData;
|
||||
JSSourceHandler sourceHandler;
|
||||
void *sourceHandlerData;
|
||||
JSInterpreterHook executeHook;
|
||||
void *executeHookData;
|
||||
JSInterpreterHook callHook;
|
||||
void *callHookData;
|
||||
|
||||
/* More debugging state, see jsdbgapi.c. */
|
||||
JSCList trapList;
|
||||
JSCList watchPointList;
|
||||
|
||||
/* Weak links to properties, indexed by quickened get/set opcodes. */
|
||||
/* XXX must come after JSCLists or MSVC alignment bug bites empty lists */
|
||||
JSPropertyCache propertyCache;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/* These combine to interlock the GC and new requests. */
|
||||
PRLock *gcLock;
|
||||
PRCondVar *gcDone;
|
||||
PRCondVar *requestDone;
|
||||
uint32 requestCount;
|
||||
|
||||
/* Lock and owning thread pointer for JS_LOCK_RUNTIME. */
|
||||
JSThinLock rtLock;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct JSContext {
|
||||
JSCList links;
|
||||
|
||||
/* Interpreter activation count. */
|
||||
uintN interpLevel;
|
||||
|
||||
/* Runtime version control identifier and equality operators. */
|
||||
JSVersion version;
|
||||
jsbytecode jsop_eq;
|
||||
jsbytecode jsop_ne;
|
||||
|
||||
/* Data shared by threads in an address space. */
|
||||
JSRuntime *runtime;
|
||||
|
||||
/* Stack arena pool and frame pointer register. */
|
||||
JSArenaPool stackPool;
|
||||
JSStackFrame *fp;
|
||||
|
||||
/* Temporary arena pools used while compiling and decompiling. */
|
||||
JSArenaPool codePool;
|
||||
JSArenaPool tempPool;
|
||||
|
||||
/* Top-level object and pointer to top stack frame's scope chain. */
|
||||
JSObject *globalObject;
|
||||
|
||||
/* Most recently created things by type, members of the GC's root set. */
|
||||
JSGCThing *newborn[GCX_NTYPES];
|
||||
|
||||
/* Regular expression class statics (XXX not shared globally). */
|
||||
JSRegExpStatics regExpStatics;
|
||||
|
||||
/* State for object and array toSource conversion. */
|
||||
JSSharpObjectMap sharpObjectMap;
|
||||
|
||||
/* Last message string and trace file for debugging. */
|
||||
char *lastMessage;
|
||||
#ifdef DEBUG
|
||||
void *tracefp;
|
||||
#endif
|
||||
|
||||
/* Per-context optional user callbacks. */
|
||||
JSBranchCallback branchCallback;
|
||||
JSErrorReporter errorReporter;
|
||||
|
||||
/* Client opaque pointer */
|
||||
void *data;
|
||||
|
||||
/* GC and thread-safe state. */
|
||||
JSStackFrame *dormantFrameChain; /* dormant stack frame to scan */
|
||||
uint32 gcDisabled; /* XXX for pre-ECMAv2 switch */
|
||||
#ifdef JS_THREADSAFE
|
||||
jsword thread;
|
||||
jsrefcount requestDepth;
|
||||
JSPackedBool gcActive;
|
||||
#endif
|
||||
|
||||
/* Exception state (NB: throwing is packed with gcActive above). */
|
||||
JSPackedBool throwing; /* is there a pending exception? */
|
||||
jsval exception; /* most-recently-thrown exceptin */
|
||||
};
|
||||
|
||||
extern JSContext *
|
||||
js_NewContext(JSRuntime *rt, size_t stacksize);
|
||||
|
||||
extern void
|
||||
js_DestroyContext(JSContext *cx);
|
||||
|
||||
extern JSContext *
|
||||
js_ContextIterator(JSRuntime *rt, JSContext **iterp);
|
||||
|
||||
/*
|
||||
* Report an exception, which is currently realized as a printf-style format
|
||||
* string and its arguments.
|
||||
*/
|
||||
typedef enum JSErrNum {
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
name = number,
|
||||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
JSErr_Limit
|
||||
} JSErrNum;
|
||||
|
||||
extern const JSErrorFormatString *
|
||||
js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
|
||||
|
||||
#ifdef va_start
|
||||
extern void
|
||||
js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap);
|
||||
extern void
|
||||
js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
|
||||
void *userRef, const uintN errorNumber, va_list ap);
|
||||
|
||||
extern JSBool
|
||||
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
|
||||
void *userRef, const uintN errorNumber,
|
||||
char **message, JSErrorReport *reportp,
|
||||
va_list ap);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Report an exception using a previously composed JSErrorReport.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
|
||||
|
||||
extern void
|
||||
js_ReportIsNotDefined(JSContext *cx, const char *name);
|
||||
|
||||
extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jscntxt_h___ */
|
||||
20
mozilla/js/src/jscompat.h
Normal file
20
mozilla/js/src/jscompat.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright © 1996 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
#ifndef jscompat_h___
|
||||
#define jscompat_h___
|
||||
/*
|
||||
* Compatibility glue for various NSPR versions. We must always define int8,
|
||||
* int16, jsword, and so on to minimize differences with js/ref, no matter what
|
||||
* the NSPR typedef names may be.
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include "jslong.h"
|
||||
|
||||
typedef JSIntn intN;
|
||||
typedef JSUintn uintN;
|
||||
typedef JSUword jsuword;
|
||||
typedef JSWord jsword;
|
||||
typedef float float32;
|
||||
#define allocPriv allocPool
|
||||
#endif /* jscompat_h___ */
|
||||
267
mozilla/js/src/jsconfig.h
Normal file
267
mozilla/js/src/jsconfig.h
Normal file
@@ -0,0 +1,267 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS configuration macros.
|
||||
*/
|
||||
#ifndef JS_VERSION
|
||||
#define JS_VERSION 140
|
||||
#endif
|
||||
|
||||
#if JS_VERSION == 100
|
||||
|
||||
#define JS_BUG_AUTO_INDEX_PROPS 1 /* new object o: o.p = v sets o[0] */
|
||||
#define JS_BUG_NULL_INDEX_PROPS 1 /* o[0] defaults to null, not void */
|
||||
#define JS_BUG_EMPTY_INDEX_ZERO 1 /* o[""] is equivalent to o[0] */
|
||||
#define JS_BUG_SHORT_CIRCUIT 1 /* 1 && 1 => true, 1 && 0 => 0 bug */
|
||||
#define JS_BUG_EAGER_TOSTRING 1 /* o.toString() trumps o.valueOf() */
|
||||
#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */
|
||||
#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */
|
||||
#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */
|
||||
#define JS_BUG_FALLIBLE_EQOPS 1 /* fallible/intransitive equality ops */
|
||||
#define JS_BUG_FALLIBLE_TONUM 1 /* fallible ValueToNumber primitive */
|
||||
#define JS_BUG_WITH_CLOSURE 0 /* with(o)function f(){} sets o.f */
|
||||
#define JS_BUG_SET_ENUMERATE 1 /* o.p=q flags o.p JSPROP_ENUMERATE */
|
||||
|
||||
#define JS_HAS_PROP_DELETE 0 /* delete o.p removes p from o */
|
||||
#define JS_HAS_CALL_OBJECT 0 /* fun.caller is stack frame obj */
|
||||
#define JS_HAS_LABEL_STATEMENT 0 /* has break/continue to label: */
|
||||
#define JS_HAS_DO_WHILE_LOOP 0 /* has do {...} while (b) */
|
||||
#define JS_HAS_SWITCH_STATEMENT 0 /* has switch (v) {case c: ...} */
|
||||
#define JS_HAS_SOME_PERL_FUN 0 /* has array.join/reverse/sort */
|
||||
#define JS_HAS_MORE_PERL_FUN 0 /* has array.push, str.substr, etc */
|
||||
#define JS_HAS_VALUEOF_HINT 0 /* valueOf(hint) where hint is typeof */
|
||||
#define JS_HAS_LEXICAL_CLOSURE 0 /* nested functions, lexically closed */
|
||||
#define JS_HAS_APPLY_FUNCTION 0 /* has fun.apply(obj, argArray) */
|
||||
#define JS_HAS_CALL_FUNCTION 0 /* has fun.call(obj, arg1, ... argN) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_REGEXPS 0 /* has perl r.e.s via RegExp, /pat/ */
|
||||
#define JS_HAS_SEQUENCE_OPS 0 /* has array.slice, string.concat */
|
||||
#define JS_HAS_INITIALIZERS 0 /* has var o = {'foo': 42, 'bar':3} */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_EXPORT_IMPORT 0 /* has export fun; import obj.fun */
|
||||
#define JS_HAS_EVAL_THIS_SCOPE 0 /* Math.eval is same as with (Math) */
|
||||
#define JS_HAS_TRIPLE_EQOPS 0 /* has === and !== identity eqops */
|
||||
#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_REPLACE_LAMBDA 0 /* has string.replace(re, lambda) */
|
||||
#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
|
||||
#define JS_HAS_XDR 0 /* has XDR API and object methods */
|
||||
#define JS_HAS_EXCEPTIONS 0 /* has exception handling */
|
||||
#define JS_HAS_UNDEFINED 0 /* has global "undefined" property */
|
||||
#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
|
||||
#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */
|
||||
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
|
||||
#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */
|
||||
#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
|
||||
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
|
||||
|
||||
#elif JS_VERSION == 110
|
||||
|
||||
#define JS_BUG_AUTO_INDEX_PROPS 0 /* new object o: o.p = v sets o[0] */
|
||||
#define JS_BUG_NULL_INDEX_PROPS 1 /* o[0] defaults to null, not void */
|
||||
#define JS_BUG_EMPTY_INDEX_ZERO 1 /* o[""] is equivalent to o[0] */
|
||||
#define JS_BUG_SHORT_CIRCUIT 1 /* 1 && 1 => true, 1 && 0 => 0 bug */
|
||||
#define JS_BUG_EAGER_TOSTRING 1 /* o.toString() trumps o.valueOf() */
|
||||
#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */
|
||||
#define JS_BUG_EVAL_THIS_FUN 1 /* eval('this') in function f is f */
|
||||
#define JS_BUG_EVAL_THIS_SCOPE 1 /* Math.eval('sin(x)') vs. local x */
|
||||
#define JS_BUG_FALLIBLE_EQOPS 1 /* fallible/intransitive equality ops */
|
||||
#define JS_BUG_FALLIBLE_TONUM 1 /* fallible ValueToNumber primitive */
|
||||
#define JS_BUG_WITH_CLOSURE 0 /* with(o)function f(){} sets o.f */
|
||||
#define JS_BUG_SET_ENUMERATE 1 /* o.p=q flags o.p JSPROP_ENUMERATE */
|
||||
|
||||
#define JS_HAS_PROP_DELETE 0 /* delete o.p removes p from o */
|
||||
#define JS_HAS_CALL_OBJECT 0 /* fun.caller is stack frame obj */
|
||||
#define JS_HAS_LABEL_STATEMENT 0 /* has break/continue to label: */
|
||||
#define JS_HAS_DO_WHILE_LOOP 0 /* has do {...} while (b) */
|
||||
#define JS_HAS_SWITCH_STATEMENT 0 /* has switch (v) {case c: ...} */
|
||||
#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */
|
||||
#define JS_HAS_MORE_PERL_FUN 0 /* has array.push, str.substr, etc */
|
||||
#define JS_HAS_VALUEOF_HINT 0 /* valueOf(hint) where hint is typeof */
|
||||
#define JS_HAS_LEXICAL_CLOSURE 0 /* nested functions, lexically closed */
|
||||
#define JS_HAS_APPLY_FUNCTION 0 /* has apply(fun, arg1, ... argN) */
|
||||
#define JS_HAS_CALL_FUNCTION 0 /* has fun.call(obj, arg1, ... argN) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_REGEXPS 0 /* has perl r.e.s via RegExp, /pat/ */
|
||||
#define JS_HAS_SEQUENCE_OPS 0 /* has array.slice, string.concat */
|
||||
#define JS_HAS_INITIALIZERS 0 /* has var o = {'foo': 42, 'bar':3} */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_EXPORT_IMPORT 0 /* has export fun; import obj.fun */
|
||||
#define JS_HAS_EVAL_THIS_SCOPE 0 /* Math.eval is same as with (Math) */
|
||||
#define JS_HAS_TRIPLE_EQOPS 0 /* has === and !== identity eqops */
|
||||
#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_REPLACE_LAMBDA 0 /* has string.replace(re, lambda) */
|
||||
#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
|
||||
#define JS_HAS_XDR 0 /* has XDR API and object methods */
|
||||
#define JS_HAS_EXCEPTIONS 0 /* has exception handling */
|
||||
#define JS_HAS_UNDEFINED 0 /* has global "undefined" property */
|
||||
#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
|
||||
#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */
|
||||
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
|
||||
#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */
|
||||
#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
|
||||
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
|
||||
|
||||
#elif JS_VERSION == 120
|
||||
|
||||
#define JS_BUG_AUTO_INDEX_PROPS 0 /* new object o: o.p = v sets o[0] */
|
||||
#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */
|
||||
#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */
|
||||
#define JS_BUG_SHORT_CIRCUIT 0 /* 1 && 1 => true, 1 && 0 => 0 bug */
|
||||
#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */
|
||||
#define JS_BUG_VOID_TOSTRING 1 /* void 0 + 0 == "undefined0" */
|
||||
#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */
|
||||
#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */
|
||||
#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */
|
||||
#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */
|
||||
#define JS_BUG_WITH_CLOSURE 1 /* with(o)function f(){} sets o.f */
|
||||
#define JS_BUG_SET_ENUMERATE 1 /* o.p=q flags o.p JSPROP_ENUMERATE */
|
||||
|
||||
#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */
|
||||
#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */
|
||||
#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */
|
||||
#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */
|
||||
#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */
|
||||
#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */
|
||||
#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */
|
||||
#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */
|
||||
#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */
|
||||
#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */
|
||||
#define JS_HAS_CALL_FUNCTION 0 /* has fun.call(obj, arg1, ... argN) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */
|
||||
#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */
|
||||
#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */
|
||||
#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
|
||||
#define JS_HAS_TRIPLE_EQOPS 0 /* has === and !== identity eqops */
|
||||
#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_REPLACE_LAMBDA 0 /* has string.replace(re, lambda) */
|
||||
#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
|
||||
#define JS_HAS_XDR 0 /* has XDR API and object methods */
|
||||
#define JS_HAS_EXCEPTIONS 0 /* has exception handling */
|
||||
#define JS_HAS_UNDEFINED 0 /* has global "undefined" property */
|
||||
#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
|
||||
#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */
|
||||
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
|
||||
#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */
|
||||
#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
|
||||
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
|
||||
|
||||
#elif JS_VERSION == 130
|
||||
|
||||
#define JS_BUG_AUTO_INDEX_PROPS 0 /* new object o: o.p = v sets o[0] */
|
||||
#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */
|
||||
#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */
|
||||
#define JS_BUG_SHORT_CIRCUIT 0 /* 1 && 1 => true, 1 && 0 => 0 bug */
|
||||
#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */
|
||||
#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */
|
||||
#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */
|
||||
#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */
|
||||
#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */
|
||||
#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */
|
||||
#define JS_BUG_WITH_CLOSURE 1 /* with(o)function f(){} sets o.f */
|
||||
#define JS_BUG_SET_ENUMERATE 0 /* o.p=q flags o.p JSPROP_ENUMERATE */
|
||||
|
||||
#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */
|
||||
#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */
|
||||
#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */
|
||||
#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */
|
||||
#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */
|
||||
#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */
|
||||
#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */
|
||||
#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */
|
||||
#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */
|
||||
#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */
|
||||
#define JS_HAS_CALL_FUNCTION 1 /* has fun.call(obj, arg1, ... argN) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */
|
||||
#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */
|
||||
#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */
|
||||
#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
|
||||
#define JS_HAS_TRIPLE_EQOPS 1 /* has === and !== identity eqops */
|
||||
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_REPLACE_LAMBDA 1 /* has string.replace(re, lambda) */
|
||||
#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */
|
||||
#define JS_HAS_XDR 1 /* has XDR API and object methods */
|
||||
#define JS_HAS_EXCEPTIONS 0 /* has exception handling */
|
||||
#define JS_HAS_UNDEFINED 1 /* has global "undefined" property */
|
||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||
#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */
|
||||
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
|
||||
#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */
|
||||
#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
|
||||
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
|
||||
|
||||
#elif JS_VERSION == 140
|
||||
|
||||
#define JS_BUG_AUTO_INDEX_PROPS 0 /* new object o: o.p = v sets o[0] */
|
||||
#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */
|
||||
#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */
|
||||
#define JS_BUG_SHORT_CIRCUIT 0 /* 1 && 1 => true, 1 && 0 => 0 bug */
|
||||
#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */
|
||||
#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */
|
||||
#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */
|
||||
#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */
|
||||
#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */
|
||||
#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */
|
||||
#define JS_BUG_WITH_CLOSURE 1 /* with(o)function f(){} sets o.f */
|
||||
#define JS_BUG_SET_ENUMERATE 0 /* o.p=q flags o.p JSPROP_ENUMERATE */
|
||||
|
||||
#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */
|
||||
#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */
|
||||
#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */
|
||||
#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */
|
||||
#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */
|
||||
#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */
|
||||
#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */
|
||||
#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */
|
||||
#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */
|
||||
#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */
|
||||
#define JS_HAS_CALL_FUNCTION 1 /* has fun.call(obj, arg1, ... argN) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */
|
||||
#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */
|
||||
#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */
|
||||
#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
|
||||
#define JS_HAS_TRIPLE_EQOPS 1 /* has === and !== identity eqops */
|
||||
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_REPLACE_LAMBDA 1 /* has string.replace(re, lambda) */
|
||||
#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */
|
||||
#define JS_HAS_XDR 1 /* has XDR API and object methods */
|
||||
#define JS_HAS_EXCEPTIONS 1 /* has exception handling */
|
||||
#define JS_HAS_UNDEFINED 1 /* has global "undefined" property */
|
||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||
#define JS_HAS_IN_OPERATOR 1 /* has in operator ('p' in {p:1}) */
|
||||
#define JS_HAS_INSTANCEOF 1 /* has {p:1} instanceof Object */
|
||||
#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */
|
||||
#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
|
||||
#define JS_HAS_ERROR_EXCEPTIONS 1 /* rt errors reflected as exceptions */
|
||||
|
||||
#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */
|
||||
|
||||
#else
|
||||
|
||||
#error "unknown JS_VERSION"
|
||||
|
||||
#endif
|
||||
288
mozilla/js/src/jscpucfg.c
Normal file
288
mozilla/js/src/jscpucfg.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generate CPU-specific bit-size and similar #defines.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(sgi)
|
||||
#ifndef IRIX
|
||||
# error "IRIX is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__sun)
|
||||
#if defined(__svr4) || defined(__svr4__)
|
||||
#ifndef SOLARIS
|
||||
# error "SOLARIS is not defined"
|
||||
#endif
|
||||
#else
|
||||
#ifndef SUNOS4
|
||||
# error "SUNOS4 is not defined"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__hpux)
|
||||
#ifndef HPUX
|
||||
# error "HPUX is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__osf__)
|
||||
#ifndef OSF1
|
||||
# error "OSF1 is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_IBMR2)
|
||||
#ifndef AIX
|
||||
# error "AIX is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(linux)
|
||||
#ifndef LINUX
|
||||
# error "LINUX is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(bsdi)
|
||||
#ifndef BSDI
|
||||
# error "BSDI is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(M_UNIX)
|
||||
#ifndef SCO
|
||||
# error "SCO is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(M_UNIX) && defined(_USLC_)
|
||||
#ifndef UNIXWARE
|
||||
# error "UNIXWARE is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __MWERKS__
|
||||
#define XP_MAC 1
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* Generate cpucfg.h */
|
||||
#ifdef XP_MAC
|
||||
#include <Types.h>
|
||||
#define INT64 UnsignedWide
|
||||
#else
|
||||
#ifdef XP_PC
|
||||
#ifdef WIN32
|
||||
#define INT64 _int64
|
||||
#else
|
||||
#define INT64 long
|
||||
#endif
|
||||
#else
|
||||
#if defined(HPUX) || defined(SCO) || defined(UNIXWARE)
|
||||
#define INT64 long
|
||||
#else
|
||||
#define INT64 long long
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef void *prword;
|
||||
|
||||
struct align_short {
|
||||
char c;
|
||||
short a;
|
||||
};
|
||||
struct align_int {
|
||||
char c;
|
||||
int a;
|
||||
};
|
||||
struct align_long {
|
||||
char c;
|
||||
long a;
|
||||
};
|
||||
struct align_int64 {
|
||||
char c;
|
||||
INT64 a;
|
||||
};
|
||||
struct align_fakelonglong {
|
||||
char c;
|
||||
struct {
|
||||
long hi, lo;
|
||||
} a;
|
||||
};
|
||||
struct align_float {
|
||||
char c;
|
||||
float a;
|
||||
};
|
||||
struct align_double {
|
||||
char c;
|
||||
double a;
|
||||
};
|
||||
struct align_pointer {
|
||||
char c;
|
||||
void *a;
|
||||
};
|
||||
struct align_prword {
|
||||
char c;
|
||||
prword a;
|
||||
};
|
||||
|
||||
#define ALIGN_OF(type) \
|
||||
(((char*)&(((struct align_##type *)0)->a)) - ((char*)0))
|
||||
|
||||
int bpb;
|
||||
|
||||
static int Log2(int n)
|
||||
{
|
||||
int log2 = 0;
|
||||
|
||||
if (n & (n-1))
|
||||
log2++;
|
||||
if (n >> 16)
|
||||
log2 += 16, n >>= 16;
|
||||
if (n >> 8)
|
||||
log2 += 8, n >>= 8;
|
||||
if (n >> 4)
|
||||
log2 += 4, n >>= 4;
|
||||
if (n >> 2)
|
||||
log2 += 2, n >>= 2;
|
||||
if (n >> 1)
|
||||
log2++;
|
||||
return log2;
|
||||
}
|
||||
|
||||
/* We assume that int's are 32 bits */
|
||||
static void do64(void)
|
||||
{
|
||||
union {
|
||||
long i;
|
||||
char c[4];
|
||||
} u;
|
||||
|
||||
u.i = 0x01020304;
|
||||
if (u.c[0] == 0x01) {
|
||||
printf("#undef IS_LITTLE_ENDIAN\n");
|
||||
printf("#define IS_BIG_ENDIAN 1\n\n");
|
||||
} else {
|
||||
printf("#define IS_LITTLE_ENDIAN 1\n");
|
||||
printf("#undef IS_BIG_ENDIAN\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void do32(void)
|
||||
{
|
||||
union {
|
||||
long i;
|
||||
char c[4];
|
||||
} u;
|
||||
|
||||
u.i = 0x01020304;
|
||||
if (u.c[0] == 0x01) {
|
||||
printf("#undef IS_LITTLE_ENDIAN\n");
|
||||
printf("#define IS_BIG_ENDIAN 1\n\n");
|
||||
} else {
|
||||
printf("#define IS_LITTLE_ENDIAN 1\n");
|
||||
printf("#undef IS_BIG_ENDIAN\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Conceivably this could actually be used, but there is lots of code out
|
||||
* there with ands and shifts in it that assumes a byte is exactly 8 bits,
|
||||
* so forget about porting THIS code to all those non 8 bit byte machines.
|
||||
*/
|
||||
static void BitsPerByte(void)
|
||||
{
|
||||
bpb = 8;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BitsPerByte();
|
||||
|
||||
printf("#ifndef js_cpucfg___\n");
|
||||
printf("#define js_cpucfg___\n\n");
|
||||
|
||||
printf("/* AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n");
|
||||
|
||||
if (sizeof(long) == 8) {
|
||||
do64();
|
||||
} else {
|
||||
do32();
|
||||
}
|
||||
printf("#define JS_BYTES_PER_BYTE %dL\n", sizeof(char));
|
||||
printf("#define JS_BYTES_PER_SHORT %dL\n", sizeof(short));
|
||||
printf("#define JS_BYTES_PER_INT %dL\n", sizeof(int));
|
||||
printf("#define JS_BYTES_PER_INT64 %dL\n", 8);
|
||||
printf("#define JS_BYTES_PER_LONG %dL\n", sizeof(long));
|
||||
printf("#define JS_BYTES_PER_FLOAT %dL\n", sizeof(float));
|
||||
printf("#define JS_BYTES_PER_DOUBLE %dL\n", sizeof(double));
|
||||
printf("#define JS_BYTES_PER_WORD %dL\n", sizeof(prword));
|
||||
printf("#define JS_BYTES_PER_DWORD %dL\n", 8);
|
||||
printf("\n");
|
||||
|
||||
printf("#define JS_BITS_PER_BYTE %dL\n", bpb);
|
||||
printf("#define JS_BITS_PER_SHORT %dL\n", bpb * sizeof(short));
|
||||
printf("#define JS_BITS_PER_INT %dL\n", bpb * sizeof(int));
|
||||
printf("#define JS_BITS_PER_INT64 %dL\n", bpb * 8);
|
||||
printf("#define JS_BITS_PER_LONG %dL\n", bpb * sizeof(long));
|
||||
printf("#define JS_BITS_PER_FLOAT %dL\n", bpb * sizeof(float));
|
||||
printf("#define JS_BITS_PER_DOUBLE %dL\n", bpb * sizeof(double));
|
||||
printf("#define JS_BITS_PER_WORD %dL\n", bpb * sizeof(prword));
|
||||
printf("\n");
|
||||
|
||||
printf("#define JS_BITS_PER_BYTE_LOG2 %dL\n", Log2(bpb));
|
||||
printf("#define JS_BITS_PER_SHORT_LOG2 %dL\n", Log2(bpb * sizeof(short)));
|
||||
printf("#define JS_BITS_PER_INT_LOG2 %dL\n", Log2(bpb * sizeof(int)));
|
||||
printf("#define JS_BITS_PER_INT64_LOG2 %dL\n", 6);
|
||||
printf("#define JS_BITS_PER_LONG_LOG2 %dL\n", Log2(bpb * sizeof(long)));
|
||||
printf("#define JS_BITS_PER_FLOAT_LOG2 %dL\n", Log2(bpb * sizeof(float)));
|
||||
printf("#define JS_BITS_PER_DOUBLE_LOG2 %dL\n", Log2(bpb * sizeof(double)));
|
||||
printf("#define JS_BITS_PER_WORD_LOG2 %dL\n", Log2(bpb * sizeof(prword)));
|
||||
printf("\n");
|
||||
|
||||
printf("#define JS_ALIGN_OF_SHORT %dL\n", ALIGN_OF(short));
|
||||
printf("#define JS_ALIGN_OF_INT %dL\n", ALIGN_OF(int));
|
||||
printf("#define JS_ALIGN_OF_LONG %dL\n", ALIGN_OF(long));
|
||||
if (sizeof(INT64) < 8) {
|
||||
/* this machine doesn't actually support int64's */
|
||||
printf("#define JS_ALIGN_OF_INT64 %dL\n", ALIGN_OF(fakelonglong));
|
||||
} else {
|
||||
printf("#define JS_ALIGN_OF_INT64 %dL\n", ALIGN_OF(int64));
|
||||
}
|
||||
printf("#define JS_ALIGN_OF_FLOAT %dL\n", ALIGN_OF(float));
|
||||
printf("#define JS_ALIGN_OF_DOUBLE %dL\n", ALIGN_OF(double));
|
||||
printf("#define JS_ALIGN_OF_POINTER %dL\n", ALIGN_OF(pointer));
|
||||
printf("#define JS_ALIGN_OF_WORD %dL\n", ALIGN_OF(prword));
|
||||
printf("\n");
|
||||
|
||||
printf("#define JS_BYTES_PER_WORD_LOG2 %dL\n", Log2(sizeof(prword)));
|
||||
printf("#define JS_BYTES_PER_DWORD_LOG2 %dL\n", Log2(8));
|
||||
printf("#define JS_WORDS_PER_DWORD_LOG2 %dL\n", Log2(8/sizeof(prword)));
|
||||
printf("\n");
|
||||
|
||||
printf("#endif /* js_cpucfg___ */\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
702
mozilla/js/src/jscpucfg.h
Normal file
702
mozilla/js/src/jscpucfg.h
Normal file
@@ -0,0 +1,702 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 js_cpucfg___
|
||||
#define js_cpucfg___
|
||||
|
||||
#include "jsosdep.h"
|
||||
|
||||
#ifdef XP_MAC
|
||||
#include "jsmacos.h"
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 2L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 4L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
#endif /* XP_MAC */
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 8L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 4L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if defined(_WINDOWS) && !defined(_WIN32) /* WIN16 */
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 2L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 16L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 4L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 2L
|
||||
#define JS_ALIGN_OF_LONG 2L
|
||||
#define JS_ALIGN_OF_INT64 2L
|
||||
#define JS_ALIGN_OF_FLOAT 2L
|
||||
#define JS_ALIGN_OF_DOUBLE 2L
|
||||
#define JS_ALIGN_OF_POINTER 2L
|
||||
#define JS_ALIGN_OF_WORD 2L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
#endif /* defined(_WINDOWS) && !defined(_WIN32) */
|
||||
|
||||
#ifdef XP_UNIX
|
||||
|
||||
#ifdef AIXV3
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 8L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 4L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
|
||||
#elif defined(BSDI)
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 4L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 4L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
|
||||
#elif defined(HPUX)
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 4L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 8L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
|
||||
#elif defined(IRIX)
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 8L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 8L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
|
||||
#elif defined(LINUX)
|
||||
|
||||
#ifdef __powerpc__
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#elif __i386__
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
#else
|
||||
#error "linux cpu architecture not supported by jscpucfg.h"
|
||||
#endif
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 4L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 4L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
|
||||
#elif defined(OSF1)
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 8L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 8L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 64L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 64L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 6L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 6L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 8L
|
||||
#define JS_ALIGN_OF_INT64 8L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 8L
|
||||
#define JS_ALIGN_OF_POINTER 8L
|
||||
#define JS_ALIGN_OF_WORD 8L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 3L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 0L
|
||||
|
||||
|
||||
#elif defined(SOLARIS)
|
||||
|
||||
#ifdef i386
|
||||
/* PC-based */
|
||||
#undef IS_BIG_ENDIAN
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#else
|
||||
/* Sparc-based */
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 8L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 8L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#ifdef i386
|
||||
#undef JS_ALIGN_OF_INT64
|
||||
#undef JS_ALIGN_OF_DOUBLE
|
||||
#define JS_ALIGN_OF_INT64 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 4L
|
||||
#endif
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
|
||||
#elif defined(SUNOS4)
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 8L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 8L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
|
||||
#elif defined(SNI)
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 8L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 8L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
|
||||
#elif defined(SONY)
|
||||
/* Don't have it */
|
||||
|
||||
#elif defined(NECSVR4)
|
||||
/* Don't have it */
|
||||
|
||||
#elif defined(SCO)
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 4L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 4L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
|
||||
#elif defined(UNIXWARE)
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 4L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 4L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
#endif
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
#endif /* js_cpucfg___ */
|
||||
2023
mozilla/js/src/jsdate.c
Normal file
2023
mozilla/js/src/jsdate.c
Normal file
File diff suppressed because it is too large
Load Diff
76
mozilla/js/src/jsdate.h
Normal file
76
mozilla/js/src/jsdate.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jsdate_h___
|
||||
#define jsdate_h___
|
||||
/*
|
||||
* JS Date class interface.
|
||||
*/
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JSObject *
|
||||
js_InitDateClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* These functions provide a C interface to the date/time object
|
||||
*/
|
||||
extern JS_FRIEND_API(JSObject*)
|
||||
js_NewDateObject(JSContext* cx, int year, int mon, int mday,
|
||||
int hour, int min, int sec);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetYear(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetMonth(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetDate(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetHours(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetMinutes(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetSeconds(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetYear(JSContext *cx, JSObject *obj, int year);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetMonth(JSContext *cx, JSObject *obj, int year);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetDate(JSContext *cx, JSObject *obj, int date);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetHours(JSContext *cx, JSObject *obj, int hours);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds);
|
||||
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsdate_h___ */
|
||||
859
mozilla/js/src/jsdbgapi.c
Normal file
859
mozilla/js/src/jsdbgapi.c
Normal file
@@ -0,0 +1,859 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS debugging API.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
/* Removed by JSIFY: #include "prlog.h" */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsclist.h"
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jslock.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsscript.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
typedef struct JSTrap {
|
||||
JSCList links;
|
||||
JSScript *script;
|
||||
jsbytecode *pc;
|
||||
JSOp op;
|
||||
JSTrapHandler handler;
|
||||
void *closure;
|
||||
} JSTrap;
|
||||
|
||||
static JSTrap *
|
||||
FindTrap(JSRuntime *rt, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
JSTrap *trap;
|
||||
|
||||
for (trap = (JSTrap *)rt->trapList.next;
|
||||
trap != (JSTrap *)&rt->trapList;
|
||||
trap = (JSTrap *)trap->links.next) {
|
||||
if (trap->script == script && trap->pc == pc)
|
||||
return trap;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
js_PatchOpcode(JSContext *cx, JSScript *script, jsbytecode *pc, JSOp op)
|
||||
{
|
||||
JSTrap *trap;
|
||||
|
||||
trap = FindTrap(cx->runtime, script, pc);
|
||||
if (trap)
|
||||
trap->op = op;
|
||||
else
|
||||
*pc = (jsbytecode)op;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler handler, void *closure)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSTrap *trap;
|
||||
|
||||
rt = cx->runtime;
|
||||
trap = FindTrap(rt, script, pc);
|
||||
if (trap) {
|
||||
/* Restore opcode at pc so it can be saved again. */
|
||||
*pc = (jsbytecode)trap->op;
|
||||
} else {
|
||||
trap = JS_malloc(cx, sizeof *trap);
|
||||
if (!trap || !js_AddRoot(cx, &trap->closure, "trap->closure")) {
|
||||
if (trap)
|
||||
JS_free(cx, trap);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
JS_APPEND_LINK(&trap->links, &rt->trapList);
|
||||
trap->script = script;
|
||||
trap->pc = pc;
|
||||
trap->op = (JSOp)*pc;
|
||||
trap->handler = handler;
|
||||
trap->closure = closure;
|
||||
*pc = JSOP_TRAP;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSOp)
|
||||
JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
JSTrap *trap;
|
||||
|
||||
trap = FindTrap(cx->runtime, script, pc);
|
||||
if (!trap) {
|
||||
JS_ASSERT(0); /* XXX can't happen */
|
||||
return JSOP_LIMIT;
|
||||
}
|
||||
return trap->op;
|
||||
}
|
||||
|
||||
static void
|
||||
DestroyTrap(JSContext *cx, JSTrap *trap)
|
||||
{
|
||||
JS_REMOVE_LINK(&trap->links);
|
||||
*trap->pc = (jsbytecode)trap->op;
|
||||
js_RemoveRoot(cx, &trap->closure);
|
||||
JS_free(cx, trap);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler *handlerp, void **closurep)
|
||||
{
|
||||
JSTrap *trap;
|
||||
|
||||
trap = FindTrap(cx->runtime, script, pc);
|
||||
if (handlerp)
|
||||
*handlerp = trap ? trap->handler : NULL;
|
||||
if (closurep)
|
||||
*closurep = trap ? trap->closure : NULL;
|
||||
if (trap)
|
||||
DestroyTrap(cx, trap);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearScriptTraps(JSContext *cx, JSScript *script)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSTrap *trap, *next;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (trap = (JSTrap *)rt->trapList.next;
|
||||
trap != (JSTrap *)&rt->trapList;
|
||||
trap = next) {
|
||||
next = (JSTrap *)trap->links.next;
|
||||
if (trap->script == script)
|
||||
DestroyTrap(cx, trap);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearAllTraps(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSTrap *trap, *next;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (trap = (JSTrap *)rt->trapList.next;
|
||||
trap != (JSTrap *)&rt->trapList;
|
||||
trap = next) {
|
||||
next = (JSTrap *)trap->links.next;
|
||||
DestroyTrap(cx, trap);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSTrapStatus)
|
||||
JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval)
|
||||
{
|
||||
JSTrap *trap;
|
||||
JSTrapStatus status;
|
||||
jsint op;
|
||||
|
||||
trap = FindTrap(cx->runtime, script, pc);
|
||||
if (!trap) {
|
||||
JS_ASSERT(0); /* XXX can't happen */
|
||||
return JSTRAP_ERROR;
|
||||
}
|
||||
/*
|
||||
* It's important that we not use 'trap->' after calling the callback --
|
||||
* the callback might remove the trap!
|
||||
*/
|
||||
op = (jsint)trap->op;
|
||||
status = trap->handler(cx, script, pc, rval, trap->closure);
|
||||
if (status == JSTRAP_CONTINUE) {
|
||||
/* By convention, return the true op to the interpreter in rval. */
|
||||
*rval = INT_TO_JSVAL(op);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure)
|
||||
{
|
||||
rt->interruptHandler = handler;
|
||||
rt->interruptHandlerData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep)
|
||||
{
|
||||
if (handlerp)
|
||||
*handlerp = (JSTrapHandler)rt->interruptHandler;
|
||||
if (closurep)
|
||||
*closurep = rt->interruptHandlerData;
|
||||
rt->interruptHandler = 0;
|
||||
rt->interruptHandlerData = 0;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
typedef struct JSWatchPoint {
|
||||
JSCList links;
|
||||
JSObject *object; /* weak link, see js_FinalizeObject */
|
||||
jsval userid;
|
||||
JSScopeProperty *sprop;
|
||||
JSPropertyOp setter;
|
||||
JSWatchPointHandler handler;
|
||||
void *closure;
|
||||
jsrefcount nrefs;
|
||||
} JSWatchPoint;
|
||||
|
||||
#define HoldWatchPoint(wp) ((wp)->nrefs++)
|
||||
|
||||
static void
|
||||
DropWatchPoint(JSContext *cx, JSWatchPoint *wp)
|
||||
{
|
||||
if (--wp->nrefs != 0)
|
||||
return;
|
||||
wp->sprop->setter = wp->setter;
|
||||
JS_LOCK_OBJ_VOID(cx, wp->object,
|
||||
js_DropScopeProperty(cx, (JSScope *)wp->object->map,
|
||||
wp->sprop));
|
||||
JS_REMOVE_LINK(&wp->links);
|
||||
js_RemoveRoot(cx, &wp->closure);
|
||||
JS_free(cx, wp);
|
||||
}
|
||||
|
||||
static JSWatchPoint *
|
||||
FindWatchPoint(JSRuntime *rt, JSObject *obj, jsval userid)
|
||||
{
|
||||
JSWatchPoint *wp;
|
||||
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
wp != (JSWatchPoint *)&rt->watchPointList;
|
||||
wp = (JSWatchPoint *)wp->links.next) {
|
||||
if (wp->object == obj && wp->userid == userid)
|
||||
return wp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSScopeProperty *
|
||||
js_FindWatchPoint(JSRuntime *rt, JSObject *obj, jsval userid)
|
||||
{
|
||||
JSWatchPoint *wp;
|
||||
|
||||
wp = FindWatchPoint(rt, obj, userid);
|
||||
if (!wp)
|
||||
return NULL;
|
||||
return wp->sprop;
|
||||
}
|
||||
|
||||
JSBool DLL_CALLBACK
|
||||
js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSWatchPoint *wp;
|
||||
JSScopeProperty *sprop;
|
||||
JSSymbol *sym;
|
||||
jsval userid, value;
|
||||
jsid symid;
|
||||
JSScope *scope;
|
||||
JSAtom *atom;
|
||||
JSBool ok;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
wp != (JSWatchPoint *)&rt->watchPointList;
|
||||
wp = (JSWatchPoint *)wp->links.next) {
|
||||
sprop = wp->sprop;
|
||||
if (wp->object == obj && sprop->id == id) {
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
sym = sprop->symbols;
|
||||
if (!sym) {
|
||||
userid = wp->userid;
|
||||
atom = NULL;
|
||||
if (JSVAL_IS_INT(userid)) {
|
||||
symid = (jsid)userid;
|
||||
} else {
|
||||
atom = js_ValueToStringAtom(cx, userid);
|
||||
if (!atom) {
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return JS_FALSE;
|
||||
}
|
||||
symid = (jsid)atom;
|
||||
}
|
||||
scope = (JSScope *) obj->map;
|
||||
JS_ASSERT(scope->props);
|
||||
ok = LOCKED_OBJ_GET_CLASS(obj)->addProperty(cx, obj, sprop->id,
|
||||
&value);
|
||||
if (!ok) {
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return JS_FALSE;
|
||||
}
|
||||
ok = (scope->ops->add(cx, scope, symid, sprop) != NULL);
|
||||
if (!ok) {
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return JS_FALSE;
|
||||
}
|
||||
sym = sprop->symbols;
|
||||
}
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
HoldWatchPoint(wp);
|
||||
ok = wp->handler(cx, obj, js_IdToValue(sym_id(sym)),
|
||||
OBJ_GET_SLOT(cx, obj, wp->sprop->slot), vp,
|
||||
wp->closure);
|
||||
if (ok)
|
||||
ok = wp->setter(cx, obj, id, vp);
|
||||
DropWatchPoint(cx, wp);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(0); /* XXX can't happen */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JSWatchPointHandler handler, void *closure)
|
||||
{
|
||||
JSAtom *atom;
|
||||
jsid symid;
|
||||
JSObject *pobj;
|
||||
JSScopeProperty *sprop;
|
||||
JSRuntime *rt;
|
||||
JSWatchPoint *wp;
|
||||
|
||||
if (!OBJ_IS_NATIVE(obj)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH,
|
||||
OBJ_GET_CLASS(cx, obj)->name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_INT(id)) {
|
||||
symid = (jsid)id;
|
||||
atom = NULL;
|
||||
} else {
|
||||
atom = js_ValueToStringAtom(cx, id);
|
||||
if (!atom)
|
||||
return JS_FALSE;
|
||||
symid = (jsid)atom;
|
||||
}
|
||||
|
||||
if (!js_LookupProperty(cx, obj, symid, &pobj, (JSProperty **)&sprop))
|
||||
return JS_FALSE;
|
||||
rt = cx->runtime;
|
||||
if (!sprop) {
|
||||
/* Check for a deleted symbol watchpoint, which holds its property. */
|
||||
sprop = js_FindWatchPoint(rt, obj, id);
|
||||
if (sprop) {
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Emulate js_LookupProperty if thread-safe. */
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
sprop->nrefs++;
|
||||
#endif
|
||||
} else {
|
||||
/* Make a new property in obj so we can watch for the first set. */
|
||||
if (!js_DefineProperty(cx, obj, symid, JSVAL_VOID, NULL, NULL, 0,
|
||||
(JSProperty **)&sprop)) {
|
||||
sprop = NULL;
|
||||
}
|
||||
}
|
||||
} else if (pobj != obj) {
|
||||
/* Clone the prototype property so we can watch the right object. */
|
||||
jsval value;
|
||||
JSPropertyOp getter, setter;
|
||||
uintN attrs;
|
||||
|
||||
if (OBJ_IS_NATIVE(pobj)) {
|
||||
value = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
|
||||
} else {
|
||||
if (!OBJ_GET_PROPERTY(cx, pobj, id, &value)) {
|
||||
OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
getter = sprop->getter;
|
||||
setter = sprop->setter;
|
||||
attrs = sprop->attrs;
|
||||
OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
|
||||
|
||||
if (!js_DefineProperty(cx, obj, symid, value, getter, setter, attrs,
|
||||
(JSProperty **)&sprop)) {
|
||||
sprop = NULL;
|
||||
}
|
||||
}
|
||||
if (!sprop)
|
||||
return JS_FALSE;
|
||||
|
||||
wp = FindWatchPoint(rt, obj, id);
|
||||
if (!wp) {
|
||||
wp = JS_malloc(cx, sizeof *wp);
|
||||
if (!wp)
|
||||
return JS_FALSE;
|
||||
if (!js_AddRoot(cx, &wp->closure, "wp->closure")) {
|
||||
JS_free(cx, wp);
|
||||
return JS_FALSE;
|
||||
}
|
||||
JS_APPEND_LINK(&wp->links, &rt->watchPointList);
|
||||
wp->object = obj;
|
||||
wp->userid = id;
|
||||
wp->sprop = js_HoldScopeProperty(cx, (JSScope *)obj->map, sprop);
|
||||
wp->setter = sprop->setter;
|
||||
sprop->setter = js_watch_set;
|
||||
wp->nrefs = 1;
|
||||
}
|
||||
wp->handler = handler;
|
||||
wp->closure = closure;
|
||||
OBJ_DROP_PROPERTY(cx, obj, (JSProperty *)sprop);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JSWatchPointHandler *handlerp, void **closurep)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSWatchPoint *wp;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
wp != (JSWatchPoint *)&rt->watchPointList;
|
||||
wp = (JSWatchPoint *)wp->links.next) {
|
||||
if (wp->object == obj && wp->userid == id) {
|
||||
if (handlerp)
|
||||
*handlerp = wp->handler;
|
||||
if (closurep)
|
||||
*closurep = wp->closure;
|
||||
DropWatchPoint(cx, wp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (handlerp)
|
||||
*handlerp = NULL;
|
||||
if (closurep)
|
||||
*closurep = NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSWatchPoint *wp, *next;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
wp != (JSWatchPoint *)&rt->watchPointList;
|
||||
wp = next) {
|
||||
next = (JSWatchPoint *)wp->links.next;
|
||||
if (wp->object == obj)
|
||||
DropWatchPoint(cx, wp);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearAllWatchPoints(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSWatchPoint *wp, *next;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
wp != (JSWatchPoint *)&rt->watchPointList;
|
||||
wp = next) {
|
||||
next = (JSWatchPoint *)wp->links.next;
|
||||
DropWatchPoint(cx, wp);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uintN)
|
||||
JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
return js_PCToLineNumber(script, pc);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(jsbytecode *)
|
||||
JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
|
||||
{
|
||||
return js_LineNumberToPC(script, lineno);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return fun->script;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_GetScriptPrincipals(JSContext *cx, JSScript *script)
|
||||
{
|
||||
return script->principals;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Stack Frame Iterator
|
||||
*/
|
||||
JS_PUBLIC_API(JSStackFrame *)
|
||||
JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp)
|
||||
{
|
||||
*iteratorp = (*iteratorp == NULL) ? cx->fp : (*iteratorp)->down;
|
||||
return *iteratorp;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFrameScript(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->script;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(jsbytecode *)
|
||||
JS_GetFramePC(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->pc;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
if (fp->annotation) {
|
||||
JSPrincipals *principals = fp->script
|
||||
? fp->script->principals
|
||||
: NULL;
|
||||
|
||||
if (principals == NULL)
|
||||
return NULL;
|
||||
|
||||
if (principals->globalPrivilegesEnabled(cx, principals)) {
|
||||
/*
|
||||
* Only give out an annotation if privileges have not
|
||||
* been revoked globally.
|
||||
*/
|
||||
return fp->annotation;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation)
|
||||
{
|
||||
fp->annotation = annotation;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
JSPrincipals *principals = fp->script
|
||||
? fp->script->principals
|
||||
: NULL;
|
||||
|
||||
return principals
|
||||
? principals->getPrincipalArray(cx, principals)
|
||||
: NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->fun && fp->fun->call;
|
||||
}
|
||||
|
||||
/* this is deprecated, use JS_GetFrameScopeChain instead */
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameObject(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->scopeChain;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
/* Force creation of argument and call objects if not yet created */
|
||||
JS_GetFrameCallObject(cx, fp);
|
||||
return fp->scopeChain;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
if (! fp->fun)
|
||||
return NULL;
|
||||
/* Force creation of argument object if not yet created */
|
||||
js_GetArgsObject(cx, fp);
|
||||
#if JS_HAS_CALL_OBJECT
|
||||
return js_GetCallObject(cx, fp, NULL, NULL);
|
||||
#else
|
||||
return NULL;
|
||||
#endif /* JS_HAS_CALL_OBJECT */
|
||||
}
|
||||
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->thisp;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->fun;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsContructorFrame(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->constructing;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->debugging;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(jsval)
|
||||
JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->rval;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval)
|
||||
{
|
||||
fp->rval = rval;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(const char *)
|
||||
JS_GetScriptFilename(JSContext *cx, JSScript *script)
|
||||
{
|
||||
return script->filename;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uintN)
|
||||
JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script)
|
||||
{
|
||||
return script->lineno;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uintN)
|
||||
JS_GetScriptLineExtent(JSContext *cx, JSScript *script)
|
||||
{
|
||||
return js_GetScriptLineExtent(script);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata)
|
||||
{
|
||||
rt->newScriptHook = hook;
|
||||
rt->newScriptHookData = callerdata;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
|
||||
void *callerdata)
|
||||
{
|
||||
rt->destroyScriptHook = hook;
|
||||
rt->destroyScriptHookData = callerdata;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
const char *bytes, uintN length,
|
||||
const char *filename, uintN lineno,
|
||||
jsval *rval)
|
||||
{
|
||||
JSScript *script;
|
||||
JSBool ok;
|
||||
|
||||
script = JS_CompileScriptForPrincipals(cx, fp->scopeChain,
|
||||
fp->script ? fp->script->principals
|
||||
: NULL,
|
||||
bytes, length, filename, lineno);
|
||||
if (!script)
|
||||
return JS_FALSE;
|
||||
ok = js_Execute(cx, fp->scopeChain, script, fp->fun, fp, JS_TRUE, rval);
|
||||
js_DestroyScript(cx, script);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(JSScopeProperty *)
|
||||
JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
|
||||
{
|
||||
JSScopeProperty *sprop;
|
||||
JSScope *scope;
|
||||
|
||||
sprop = *iteratorp;
|
||||
scope = (JSScope *) obj->map;
|
||||
sprop = (sprop == NULL) ? scope->props : sprop->next;
|
||||
*iteratorp = sprop;
|
||||
return sprop;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
||||
JSPropertyDesc *pd)
|
||||
{
|
||||
JSSymbol *sym;
|
||||
|
||||
sym = sprop->symbols;
|
||||
pd->id = sym ? js_IdToValue(sym_id(sym)) : JSVAL_VOID;
|
||||
if (!sym || !js_GetProperty(cx, obj, sym_id(sym), &pd->value))
|
||||
pd->value = OBJ_GET_SLOT(cx, obj, sprop->slot);
|
||||
pd->flags = ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0)
|
||||
| ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0)
|
||||
| ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0)
|
||||
#if JS_HAS_CALL_OBJECT
|
||||
| ((sprop->getter == js_GetCallVariable) ? JSPD_VARIABLE : 0)
|
||||
#endif /* JS_HAS_CALL_OBJECT */
|
||||
| ((sprop->getter == js_GetArgument) ? JSPD_ARGUMENT : 0)
|
||||
| ((sprop->getter == js_GetLocalVariable) ? JSPD_VARIABLE : 0);
|
||||
#if JS_HAS_CALL_OBJECT
|
||||
/* for Call Object 'real' getter isn't passed in to us */
|
||||
if (OBJ_GET_CLASS(cx, obj) == &js_CallClass &&
|
||||
OBJ_GET_CLASS(cx, obj)->getProperty == sprop->getter)
|
||||
pd->flags |= JSPD_ARGUMENT;
|
||||
#endif /* JS_HAS_CALL_OBJECT */
|
||||
pd->spare = 0;
|
||||
pd->slot = (pd->flags & (JSPD_ARGUMENT | JSPD_VARIABLE))
|
||||
? JSVAL_TO_INT(sprop->id)
|
||||
: 0;
|
||||
if (!sym || !sym->next || (pd->flags & (JSPD_ARGUMENT | JSPD_VARIABLE))) {
|
||||
pd->alias = JSVAL_VOID;
|
||||
} else {
|
||||
pd->alias = js_IdToValue(sym_id(sym->next));
|
||||
pd->flags |= JSPD_ALIAS;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
|
||||
{
|
||||
JSScope *scope;
|
||||
uint32 i, n;
|
||||
JSPropertyDesc *pd;
|
||||
JSScopeProperty *sprop;
|
||||
jsval state;
|
||||
jsid num_prop;
|
||||
|
||||
if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, &num_prop))
|
||||
return JS_FALSE;
|
||||
scope = (JSScope *)obj->map;
|
||||
/* have no props, or object's scope has not mutated from that of proto */
|
||||
if (!scope->props ||
|
||||
(OBJ_GET_PROTO(cx,obj) &&
|
||||
scope == (JSScope *)(OBJ_GET_PROTO(cx,obj)->map))) {
|
||||
pda->length = 0;
|
||||
pda->array = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
n = scope->map.freeslot;
|
||||
pd = JS_malloc(cx, (size_t)n * sizeof(JSPropertyDesc));
|
||||
if (!pd)
|
||||
return JS_FALSE;
|
||||
i = 0;
|
||||
for (sprop = scope->props; sprop; sprop = sprop->next) {
|
||||
if (!js_AddRoot(cx, &pd[i].id, NULL))
|
||||
goto bad;
|
||||
if (!js_AddRoot(cx, &pd[i].value, NULL))
|
||||
goto bad;
|
||||
JS_GetPropertyDesc(cx, obj, sprop, &pd[i]);
|
||||
if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
|
||||
goto bad;
|
||||
if (++i == n)
|
||||
break;
|
||||
}
|
||||
pda->length = i;
|
||||
pda->array = pd;
|
||||
return JS_TRUE;
|
||||
|
||||
bad:
|
||||
pda->length = i + 1;
|
||||
pda->array = pd;
|
||||
JS_PutPropertyDescArray(cx, pda);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
|
||||
{
|
||||
JSPropertyDesc *pd;
|
||||
uint32 i;
|
||||
|
||||
pd = pda->array;
|
||||
for (i = 0; i < pda->length; i++) {
|
||||
js_RemoveRoot(cx, &pd[i].id);
|
||||
js_RemoveRoot(cx, &pd[i].value);
|
||||
if (pd[i].flags & JSPD_ALIAS)
|
||||
js_RemoveRoot(cx, &pd[i].alias);
|
||||
}
|
||||
JS_free(cx, pd);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure)
|
||||
{
|
||||
rt->debuggerHandler = handler;
|
||||
rt->debuggerHandlerData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure)
|
||||
{
|
||||
rt->sourceHandler = handler;
|
||||
rt->sourceHandlerData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
|
||||
{
|
||||
rt->executeHook = hook;
|
||||
rt->executeHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
|
||||
{
|
||||
rt->callHook = hook;
|
||||
rt->callHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
245
mozilla/js/src/jsdbgapi.h
Normal file
245
mozilla/js/src/jsdbgapi.h
Normal file
@@ -0,0 +1,245 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jsdbgapi_h___
|
||||
#define jsdbgapi_h___
|
||||
/*
|
||||
* JS debugger API.
|
||||
*/
|
||||
#include "jsapi.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsprvtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern void
|
||||
js_PatchOpcode(JSContext *cx, JSScript *script, jsbytecode *pc, JSOp op);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSOp)
|
||||
JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler *handlerp, void **closurep);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearScriptTraps(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearAllTraps(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(JSTrapStatus)
|
||||
JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JSWatchPointHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JSWatchPointHandler *handlerp, void **closurep);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearAllWatchPoints(JSContext *cx);
|
||||
|
||||
#ifdef JS_HAS_OBJ_WATCHPOINT
|
||||
/*
|
||||
* Hide these non-API function prototypes by testing whether the internal
|
||||
* header file "jsconfig.h" has been included.
|
||||
*/
|
||||
extern JSScopeProperty *
|
||||
js_FindWatchPoint(JSRuntime *rt, JSObject *obj, jsval userid);
|
||||
|
||||
extern JSBool DLL_CALLBACK
|
||||
js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(uintN)
|
||||
JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
|
||||
extern JS_PUBLIC_API(jsbytecode *)
|
||||
JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_GetScriptPrincipals(JSContext *cx, JSScript *script);
|
||||
|
||||
/*
|
||||
* Stack Frame Iterator
|
||||
*
|
||||
* Used to iterate through the JS stack frames to extract
|
||||
* information from the frames.
|
||||
*/
|
||||
|
||||
extern JS_PUBLIC_API(JSStackFrame *)
|
||||
JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFrameScript(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(jsbytecode *)
|
||||
JS_GetFramePC(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
/* this is deprecated, use JS_GetFrameScopeChain instead */
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSFunction *)
|
||||
JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsContructorFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(jsval)
|
||||
JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(const char *)
|
||||
JS_GetScriptFilename(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(uintN)
|
||||
JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(uintN)
|
||||
JS_GetScriptLineExtent(JSContext *cx, JSScript *script);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
* Hook setters for script creation and destruction, see jsprvtd.h for the
|
||||
* typedefs. These macros provide binary compatibility and newer, shorter
|
||||
* synonyms.
|
||||
*/
|
||||
#define JS_SetNewScriptHook JS_SetNewScriptHookProc
|
||||
#define JS_SetDestroyScriptHook JS_SetDestroyScriptHookProc
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
|
||||
void *callerdata);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
const char *bytes, uintN length,
|
||||
const char *filename, uintN lineno,
|
||||
jsval *rval);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
typedef struct JSPropertyDesc {
|
||||
jsval id; /* primary id, a string or int */
|
||||
jsval value; /* property value */
|
||||
uint8 flags; /* flags, see below */
|
||||
uint8 spare; /* unused */
|
||||
uint16 slot; /* argument/variable slot */
|
||||
jsval alias; /* alias id if JSPD_ALIAS flag */
|
||||
} JSPropertyDesc;
|
||||
|
||||
#define JSPD_ENUMERATE 0x01 /* visible to for/in loop */
|
||||
#define JSPD_READONLY 0x02 /* assignment is error */
|
||||
#define JSPD_PERMANENT 0x04 /* property cannot be deleted */
|
||||
#define JSPD_ALIAS 0x08 /* property has an alias id */
|
||||
#define JSPD_ARGUMENT 0x10 /* argument to function */
|
||||
#define JSPD_VARIABLE 0x20 /* local variable in function */
|
||||
|
||||
typedef struct JSPropertyDescArray {
|
||||
uint32 length; /* number of elements in array */
|
||||
JSPropertyDesc *array; /* alloc'd by Get, freed by Put */
|
||||
} JSPropertyDescArray;
|
||||
|
||||
extern JS_PUBLIC_API(JSScopeProperty *)
|
||||
JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
||||
JSPropertyDesc *pd);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsdbgapi_h___ */
|
||||
2607
mozilla/js/src/jsdtoa.c
Normal file
2607
mozilla/js/src/jsdtoa.c
Normal file
File diff suppressed because it is too large
Load Diff
54
mozilla/js/src/jsdtoa.h
Normal file
54
mozilla/js/src/jsdtoa.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jsdtoa_h___
|
||||
#define jsdtoa_h___
|
||||
/*
|
||||
* Public interface to portable double-precision floating point to string
|
||||
* and back conversion package.
|
||||
*/
|
||||
|
||||
#include "jscompat.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* PR_strtod() returns as a double-precision floating-point number
|
||||
* the value represented by the character string pointed to by
|
||||
* s00. The string is scanned up to the first unrecognized
|
||||
* character.
|
||||
* If the value of se is not (char **)NULL, a pointer to
|
||||
* the character terminating the scan is returned in the location pointed
|
||||
* to by se. If no number can be formed, se is set to s00r, and
|
||||
* zero is returned.
|
||||
*/
|
||||
extern PUBLIC_API(double)
|
||||
PR_strtod(const char *s00, char **se);
|
||||
|
||||
/*
|
||||
* PR_cnvtf()
|
||||
* conversion routines for floating point
|
||||
* prcsn - number of digits of precision to generate floating
|
||||
* point value.
|
||||
*/
|
||||
extern PUBLIC_API(void)
|
||||
PR_cnvtf(char *buf, intN bufsz, intN prcsn, double dval);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsdtoa_h___ */
|
||||
2508
mozilla/js/src/jsemit.c
Normal file
2508
mozilla/js/src/jsemit.c
Normal file
File diff suppressed because it is too large
Load Diff
366
mozilla/js/src/jsemit.h
Normal file
366
mozilla/js/src/jsemit.h
Normal file
@@ -0,0 +1,366 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jsemit_h___
|
||||
#define jsemit_h___
|
||||
/*
|
||||
* JS bytecode generation.
|
||||
*/
|
||||
|
||||
#include "jsstddef.h"
|
||||
#include "jstypes.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef enum JSStmtType {
|
||||
STMT_BLOCK = 0, /* compound statement: { s1[;... sN] } */
|
||||
STMT_LABEL = 1, /* labeled statement: l: s */
|
||||
STMT_IF = 2, /* if (then) statement */
|
||||
STMT_ELSE = 3, /* else statement */
|
||||
STMT_SWITCH = 4, /* switch statement */
|
||||
STMT_WITH = 5, /* with statement */
|
||||
STMT_TRY = 6, /* try statement */
|
||||
STMT_CATCH = 7, /* catch block */
|
||||
STMT_FINALLY = 8, /* finally statement */
|
||||
STMT_DO_LOOP = 9, /* do/while loop statement */
|
||||
STMT_FOR_LOOP = 10, /* for loop statement */
|
||||
STMT_FOR_IN_LOOP = 11, /* for/in loop statement */
|
||||
STMT_WHILE_LOOP = 12 /* while loop statement */
|
||||
} JSStmtType;
|
||||
|
||||
#define STMT_IS_LOOP(stmt) ((stmt)->type >= STMT_DO_LOOP)
|
||||
|
||||
typedef struct JSStmtInfo JSStmtInfo;
|
||||
|
||||
struct JSStmtInfo {
|
||||
JSStmtType type; /* statement type */
|
||||
ptrdiff_t top; /* offset of loop top from cg base */
|
||||
ptrdiff_t update; /* loop update offset (top if none) */
|
||||
ptrdiff_t breaks; /* offset of last break in loop */
|
||||
ptrdiff_t continues; /* offset of last continue in loop */
|
||||
JSAtom *label; /* label name if type is STMT_LABEL */
|
||||
JSStmtInfo *down; /* info for enclosing statement */
|
||||
};
|
||||
|
||||
#define SET_STATEMENT_TOP(stmt, top) \
|
||||
((stmt)->top = (stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
|
||||
|
||||
struct JSTreeContext { /* tree context for semantic checks */
|
||||
uint32 flags; /* statement state flags, see below */
|
||||
uint32 tryCount; /* total count of try statements parsed */
|
||||
JSStmtInfo *topStmt; /* top of statement info stack */
|
||||
};
|
||||
|
||||
#define TCF_IN_FUNCTION 0x01 /* parsing inside function body */
|
||||
#define TCF_RETURN_EXPR 0x02 /* function has 'return expr;' */
|
||||
#define TCF_RETURN_VOID 0x04 /* function has 'return;' */
|
||||
#define TCF_IN_FOR_INIT 0x08 /* parsing init expr of for; exclude 'in' */
|
||||
|
||||
#define TREE_CONTEXT_INIT(tc) \
|
||||
((tc)->flags = 0, (tc)->tryCount = 0, (tc)->topStmt = NULL)
|
||||
|
||||
struct JSCodeGenerator {
|
||||
void *codeMark; /* low watermark in cx->codePool */
|
||||
void *tempMark; /* low watermark in cx->tempPool */
|
||||
jsbytecode *base; /* base of JS bytecode vector */
|
||||
jsbytecode *limit; /* one byte beyond end of bytecode */
|
||||
jsbytecode *next; /* pointer to next free bytecode */
|
||||
const char *filename; /* null or weak link to source filename */
|
||||
uintN firstLine; /* first line, for js_NewScriptFromCG */
|
||||
uintN currentLine; /* line number for tree-based srcnote gen */
|
||||
JSPrincipals *principals; /* principals for constant folding eval */
|
||||
JSTreeContext treeContext; /* for break/continue code generation */
|
||||
JSAtomList atomList; /* literals indexed for mapping */
|
||||
intN stackDepth; /* current stack depth in basic block */
|
||||
uintN maxStackDepth; /* maximum stack depth so far */
|
||||
jssrcnote *notes; /* source notes, see below */
|
||||
uintN noteCount; /* number of source notes so far */
|
||||
ptrdiff_t lastNoteOffset; /* code offset for last source note */
|
||||
JSTryNote *tryBase; /* first exception handling note */
|
||||
JSTryNote *tryNext; /* next available note */
|
||||
size_t tryNoteSpace; /* # of bytes allocated at tryBase */
|
||||
};
|
||||
|
||||
#define CG_CODE(cg,offset) ((cg)->base + (offset))
|
||||
#define CG_OFFSET(cg) PTRDIFF((cg)->next, (cg)->base, jsbytecode)
|
||||
|
||||
/*
|
||||
* Initialize cg to allocate bytecode space from cx->codePool, and srcnote
|
||||
* space from cx->tempPool. Return true on success. Report an error and
|
||||
* return false if the initial code segment can't be allocated.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg,
|
||||
const char *filename, uintN lineno,
|
||||
JSPrincipals *principals);
|
||||
|
||||
/*
|
||||
* Release cx->codePool and cx->tempPool to marks set by js_InitCodeGenerator.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
js_ResetCodeGenerator(JSContext *cx, JSCodeGenerator *cg);
|
||||
|
||||
/*
|
||||
* Emit one bytecode.
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op);
|
||||
|
||||
/*
|
||||
* Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1).
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1);
|
||||
|
||||
/*
|
||||
* Emit three bytecodes, an opcode with two bytes of immediate operands.
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
|
||||
jsbytecode op2);
|
||||
|
||||
/*
|
||||
* Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra);
|
||||
|
||||
/*
|
||||
* Unsafe macro to call js_SetJumpOffset and return false if it does.
|
||||
*/
|
||||
#define CHECK_AND_SET_JUMP_OFFSET(cx,cg,pc,off) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!js_SetJumpOffset(cx, cg, pc, off)) \
|
||||
return JS_FALSE; \
|
||||
JS_END_MACRO
|
||||
|
||||
#define CHECK_AND_SET_JUMP_OFFSET_AT(cx,cg,off) \
|
||||
CHECK_AND_SET_JUMP_OFFSET(cx, cg, CG_CODE(cg,off), CG_OFFSET(cg) - (off))
|
||||
|
||||
extern JSBool
|
||||
js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
|
||||
ptrdiff_t off);
|
||||
|
||||
/*
|
||||
* Push the C-stack-allocated struct at stmt onto the stmtInfo stack.
|
||||
*/
|
||||
extern void
|
||||
js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
|
||||
ptrdiff_t top);
|
||||
|
||||
/*
|
||||
* Emit a break instruction, recording it for backpatching.
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_EmitBreak(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *stmt,
|
||||
JSAtomListElement *label);
|
||||
|
||||
/*
|
||||
* Emit a continue instruction, recording it for backpatching.
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_EmitContinue(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *stmt,
|
||||
JSAtomListElement *label);
|
||||
|
||||
/*
|
||||
* Pop tc->topStmt. If the top JSStmtInfo struct is not stack-allocated, it
|
||||
* is up to the caller to free it.
|
||||
*/
|
||||
extern void
|
||||
js_PopStatement(JSTreeContext *tc);
|
||||
|
||||
/*
|
||||
* Like js_PopStatement(&cg->treeContext), also patch breaks and continues.
|
||||
* May fail if a jump offset overflows.
|
||||
*/
|
||||
extern JSBool
|
||||
js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg);
|
||||
|
||||
/*
|
||||
* Emit code into cg for the tree rooted at pn.
|
||||
*/
|
||||
extern JSBool
|
||||
js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn);
|
||||
|
||||
/*
|
||||
* Emit code into cg for the tree rooted at body, then create a persistent
|
||||
* script for fun from cg.
|
||||
*/
|
||||
extern JSBool
|
||||
js_EmitFunctionBody(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body,
|
||||
JSFunction *fun);
|
||||
|
||||
/*
|
||||
* Source notes generated along with bytecode for decompiling and debugging.
|
||||
* A source note is a uint8 with 5 bits of type and 3 of offset from the pc of
|
||||
* the previous note. If 3 bits of offset aren't enough, extended delta notes
|
||||
* (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits
|
||||
* are emitted before the next note. Some notes have operand offsets encoded
|
||||
* immediately after them, in note bytes or byte-triples.
|
||||
*
|
||||
* At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE,
|
||||
* SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode.
|
||||
*
|
||||
* NB: the js_SrcNoteName and js_SrcNoteArity arrays in jsemit.c are indexed
|
||||
* by this enum, so their initializers need to match the order here.
|
||||
*/
|
||||
typedef enum JSSrcNoteType {
|
||||
SRC_NULL = 0, /* terminates a note vector */
|
||||
SRC_IF = 1, /* JSOP_IFEQ bytecode is from an if-then */
|
||||
SRC_IF_ELSE = 2, /* JSOP_IFEQ bytecode is from an if-then-else */
|
||||
SRC_WHILE = 3, /* JSOP_IFEQ is from a while loop */
|
||||
SRC_FOR = 4, /* JSOP_NOP or JSOP_POP in for loop head */
|
||||
SRC_CONTINUE = 5, /* JSOP_GOTO is a continue, not a break;
|
||||
also used on JSOP_ENDINIT if extra comma
|
||||
at end of array literal: [1,2,,] */
|
||||
SRC_VAR = 6, /* JSOP_NAME/FORNAME with a var declaration */
|
||||
SRC_PCDELTA = 7, /* offset from comma-operator to next POP,
|
||||
or from CONDSWITCH to first CASE opcode */
|
||||
SRC_ASSIGNOP = 8, /* += or another assign-op follows */
|
||||
SRC_COND = 9, /* JSOP_IFEQ is from conditional ?: operator */
|
||||
SRC_PAREN = 10, /* JSOP_NOP generated to mark user parens */
|
||||
SRC_HIDDEN = 11, /* opcode shouldn't be decompiled */
|
||||
SRC_PCBASE = 12, /* offset of first obj.prop.subprop bytecode */
|
||||
SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */
|
||||
SRC_LABELBRACE = 14, /* JSOP_NOP for label: {...} begin brace */
|
||||
SRC_ENDBRACE = 15, /* JSOP_NOP for label: {...} end brace */
|
||||
SRC_BREAK2LABEL = 16, /* JSOP_GOTO for 'break label' with atomid */
|
||||
SRC_CONT2LABEL = 17, /* JSOP_GOTO for 'continue label' with atomid */
|
||||
SRC_SWITCH = 18, /* JSOP_*SWITCH with offset to end of switch,
|
||||
2nd off to first JSOP_CASE if condswitch */
|
||||
SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */
|
||||
SRC_TRYFIN = 20, /* JSOP_NOP for try or finally section */
|
||||
SRC_CATCH = 21, /* catch block has guard */
|
||||
SRC_NEWLINE = 22, /* bytecode follows a source newline */
|
||||
SRC_SETLINE = 23, /* a file-absolute source line number note */
|
||||
SRC_XDELTA = 24 /* 24-31 are for extended delta notes */
|
||||
} JSSrcNoteType;
|
||||
|
||||
#define SN_TYPE_BITS 5
|
||||
#define SN_DELTA_BITS 3
|
||||
#define SN_XDELTA_BITS 6
|
||||
#define SN_TYPE_MASK (JS_BITMASK(SN_TYPE_BITS) << SN_DELTA_BITS)
|
||||
#define SN_DELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_DELTA_BITS))
|
||||
#define SN_XDELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_XDELTA_BITS))
|
||||
|
||||
#define SN_MAKE_NOTE(sn,t,d) (*(sn) = (jssrcnote) \
|
||||
(((t) << SN_DELTA_BITS) \
|
||||
| ((d) & SN_DELTA_MASK)))
|
||||
#define SN_MAKE_XDELTA(sn,d) (*(sn) = (jssrcnote) \
|
||||
((SRC_XDELTA << SN_DELTA_BITS) \
|
||||
| ((d) & SN_XDELTA_MASK)))
|
||||
|
||||
#define SN_IS_XDELTA(sn) ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA)
|
||||
#define SN_TYPE(sn) (SN_IS_XDELTA(sn) ? SRC_XDELTA \
|
||||
: *(sn) >> SN_DELTA_BITS)
|
||||
#define SN_SET_TYPE(sn,type) SN_MAKE_NOTE(sn, type, SN_DELTA(sn))
|
||||
#define SN_IS_GETTABLE(sn) (SN_TYPE(sn) < SRC_NEWLINE)
|
||||
|
||||
#define SN_DELTA(sn) ((ptrdiff_t)(SN_IS_XDELTA(sn) \
|
||||
? *(sn) & SN_XDELTA_MASK \
|
||||
: *(sn) & SN_DELTA_MASK))
|
||||
#define SN_SET_DELTA(sn,delta) (SN_IS_XDELTA(sn) \
|
||||
? SN_MAKE_XDELTA(sn, delta) \
|
||||
: SN_MAKE_NOTE(sn, SN_TYPE(sn), delta))
|
||||
|
||||
#define SN_DELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_DELTA_BITS))
|
||||
#define SN_XDELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_XDELTA_BITS))
|
||||
|
||||
/*
|
||||
* Offset fields follow certain notes and are frequency-encoded: an offset in
|
||||
* [0,0x7f] consumes one byte, an offset in [0x80,0x7fffff] takes three, and
|
||||
* the high bit of the first byte is set.
|
||||
*/
|
||||
#define SN_3BYTE_OFFSET_FLAG 0x80
|
||||
#define SN_3BYTE_OFFSET_MASK 0x7f
|
||||
|
||||
extern JS_FRIEND_DATA(const char *) js_SrcNoteName[];
|
||||
extern JS_FRIEND_DATA(uint8) js_SrcNoteArity[];
|
||||
extern JS_FRIEND_DATA(uintN) js_SrcNoteLength(jssrcnote *sn);
|
||||
|
||||
#define SN_LENGTH(sn) ((js_SrcNoteArity[SN_TYPE(sn)] == 0) ? 1 \
|
||||
: js_SrcNoteLength(sn))
|
||||
#define SN_NEXT(sn) ((sn) + SN_LENGTH(sn))
|
||||
|
||||
/* A source note array is terminated by an all-zero element. */
|
||||
#define SN_MAKE_TERMINATOR(sn) (*(sn) = SRC_NULL)
|
||||
#define SN_IS_TERMINATOR(sn) (*(sn) == SRC_NULL)
|
||||
|
||||
/*
|
||||
* Append a new source note of the given type (and therefore size) to cg's
|
||||
* notes dynamic array, updating cg->noteCount. Return the new note's index
|
||||
* within the array pointed at by cg->notes. Return -1 if out of memory.
|
||||
*/
|
||||
extern intN
|
||||
js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type);
|
||||
|
||||
extern intN
|
||||
js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
|
||||
ptrdiff_t offset);
|
||||
|
||||
extern intN
|
||||
js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
|
||||
ptrdiff_t offset1, ptrdiff_t offset2);
|
||||
|
||||
/*
|
||||
* Get and set the offset operand identified by which (0 for the first, etc.).
|
||||
*/
|
||||
extern JS_FRIEND_API(ptrdiff_t)
|
||||
js_GetSrcNoteOffset(jssrcnote *sn, uintN which);
|
||||
|
||||
extern JSBool
|
||||
js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index,
|
||||
uintN which, ptrdiff_t offset);
|
||||
|
||||
/*
|
||||
* Finish taking source notes in cx's tempPool by copying them to new
|
||||
* stable store allocated via JS_malloc. Return null on malloc failure,
|
||||
* which means this function reported an error.
|
||||
*/
|
||||
extern jssrcnote *
|
||||
js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg);
|
||||
|
||||
/*
|
||||
* Allocate cg->treeContext.tryCount notes (plus one for the end sentinel)
|
||||
* from cx->tempPool and set up cg->tryBase/tryNext for exactly tryCount
|
||||
* js_NewTryNote calls. The storage is freed by js_ResetCodeGenerator.
|
||||
*/
|
||||
extern JSBool
|
||||
js_AllocTryNotes(JSContext *cx, JSCodeGenerator *cg);
|
||||
|
||||
/*
|
||||
* Grab the next trynote slot in cg, filling it in appropriately.
|
||||
*/
|
||||
extern JSTryNote *
|
||||
js_NewTryNote(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t start,
|
||||
ptrdiff_t end, ptrdiff_t catchStart);
|
||||
|
||||
/*
|
||||
* Finish generating exception information, and copy it to JS_malloc
|
||||
* storage.
|
||||
*/
|
||||
extern JSBool
|
||||
js_FinishTakingTryNotes(JSContext *cx, JSCodeGenerator *cg, JSTryNote **tryp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsemit_h___ */
|
||||
477
mozilla/js/src/jsexn.c
Normal file
477
mozilla/js/src/jsexn.c
Normal file
@@ -0,0 +1,477 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS standard exception implementation.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This is currently very messy, and in flux. Don't anybody think
|
||||
* I'm going to leave it like this. No no.
|
||||
*/
|
||||
|
||||
|
||||
#include "jsstddef.h"
|
||||
#include "jstypes.h"
|
||||
/* Removed by JSIFY: #include "prlog.h" */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsexn.h"
|
||||
|
||||
#if JS_HAS_ERROR_EXCEPTIONS
|
||||
#if !JS_HAS_EXCEPTIONS
|
||||
# error "JS_HAS_EXCEPTIONS must be defined to use JS_HAS_ERROR_EXCEPTIONS"
|
||||
#endif
|
||||
|
||||
JSObject *tlobj;
|
||||
|
||||
/*
|
||||
* This could end up just being the error report, but I
|
||||
* want to learn how to support random garbage here.
|
||||
*
|
||||
* If I go with it, a rambling comment mentioning GC, memory management etc. is
|
||||
* needed.
|
||||
*
|
||||
* I'd rather have the errorReport inline, to avoid the extra malloc'd object
|
||||
* dangle. But I'll figure that out later, if I still need it.
|
||||
*/
|
||||
typedef struct JSExnPrivate {
|
||||
JSErrorReport *errorReport;
|
||||
const char *message;
|
||||
} JSExnPrivate;
|
||||
|
||||
|
||||
/*
|
||||
* Copy everything interesting about an error into allocated memory.
|
||||
*/
|
||||
static JSExnPrivate *
|
||||
exn_initPrivate(JSContext *cx, JSErrorReport *report, const char *message)
|
||||
{
|
||||
JSExnPrivate *newPrivate;
|
||||
JSErrorReport * newReport;
|
||||
char *newMessage;
|
||||
|
||||
newPrivate = (JSExnPrivate *)JS_malloc(cx, sizeof (JSExnPrivate));
|
||||
|
||||
JS_ASSERT(message);
|
||||
newMessage = (char *)JS_malloc(cx, strlen(message)+1);
|
||||
strcpy(newMessage, message);
|
||||
newPrivate->message = newMessage;
|
||||
|
||||
/* Copy the error report */
|
||||
newReport = (JSErrorReport *)JS_malloc(cx, sizeof (JSErrorReport));
|
||||
|
||||
if (report->filename) {
|
||||
newReport->filename =
|
||||
(const char *)JS_malloc(cx, strlen(report->filename)+1);
|
||||
/* Ack. Const! */
|
||||
strcpy((char *)newReport->filename, report->filename);
|
||||
} else {
|
||||
newReport->filename = NULL;
|
||||
}
|
||||
|
||||
newReport->lineno = report->lineno;
|
||||
|
||||
/*
|
||||
* We don't need to copy linebuf and tokenptr, because they
|
||||
* point into the deflated string cache. (currently?)
|
||||
*/
|
||||
newReport->linebuf = report->linebuf;
|
||||
newReport->tokenptr = report->tokenptr;
|
||||
|
||||
/*
|
||||
* But we do need to copy uclinebuf, uctokenptr, because they're
|
||||
* pointers into internal tokenstream structs, and may go away.
|
||||
* But only if they're non-null...
|
||||
*
|
||||
* NOTE nothing uses this and I'm not really maintaining it until
|
||||
* I know it's the desired API.
|
||||
*
|
||||
* Temporarily disabled, because uclinebuf is 0x10 when I evaluate 'Math()'!
|
||||
*/
|
||||
|
||||
#if 0
|
||||
if (report->uclinebuf) {
|
||||
size_t len = js_strlen(report->uclinebuf)+1;
|
||||
newReport->uclinebuf =
|
||||
(const jschar *)JS_malloc(cx, len);
|
||||
js_strncpy(newReport->uclinebuf, report->uclinebuf, len);
|
||||
newReport->uctokenptr = newReport->uclinebuf + (report->uctokenptr -
|
||||
report->uclinebuf);
|
||||
} else
|
||||
#endif
|
||||
newReport->uclinebuf = newReport->uctokenptr = NULL;
|
||||
|
||||
/* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
|
||||
newReport->flags = report->flags;
|
||||
|
||||
/* Skipping *ucmessage, **messageArgs for now. My guess is that it'll just
|
||||
* mean copying the pointers, and adding another GC root. Then de-rooting
|
||||
* them in the finalizer. Dunno if they're rooted in the first place -
|
||||
* maybe it's only relevant for an exception that goes where it pleases,
|
||||
* and not for the formerly stack-bound use of the error report.
|
||||
*/
|
||||
|
||||
newPrivate->errorReport = newReport;
|
||||
|
||||
return newPrivate;
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo all the damage done by exn_initPrivate.
|
||||
*/
|
||||
static void
|
||||
exn_destroyPrivate(JSContext *cx, JSExnPrivate *privateData)
|
||||
{
|
||||
JS_ASSERT(privateData->message);
|
||||
/* ! what does const do? */
|
||||
JS_free(cx, (void *)privateData->message);
|
||||
|
||||
JS_ASSERT(privateData->errorReport);
|
||||
if (privateData->errorReport->uclinebuf)
|
||||
JS_free(cx, (void *)privateData->errorReport->uclinebuf);
|
||||
|
||||
if (privateData->errorReport->filename)
|
||||
JS_free(cx, (void *)privateData->errorReport->filename);
|
||||
|
||||
JS_free(cx, privateData->errorReport);
|
||||
|
||||
JS_free(cx, privateData);
|
||||
}
|
||||
|
||||
/* Destroy associated data... */
|
||||
static void
|
||||
exn_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSExnPrivate *privateData;
|
||||
|
||||
privateData = (JSExnPrivate *)
|
||||
JSVAL_TO_PRIVATE(OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE));
|
||||
|
||||
if (privateData) {
|
||||
exn_destroyPrivate(cx, privateData);
|
||||
}
|
||||
}
|
||||
|
||||
/* This must be kept in synch with the exceptions array below. */
|
||||
typedef enum JSExnType {
|
||||
JSEXN_NONE = -1,
|
||||
JSEXN_EXCEPTION,
|
||||
JSEXN_ERR,
|
||||
JSEXN_INTERNALERR,
|
||||
JSEXN_SYNTAXERR,
|
||||
JSEXN_REFERENCEERR,
|
||||
JSEXN_CALLERR,
|
||||
JSEXN_TARGETERR,
|
||||
JSEXN_CONSTRUCTORERR,
|
||||
JSEXN_CONVERSIONERR,
|
||||
JSEXN_TOOBJECTERR,
|
||||
JSEXN_TOPRIMITIVEERR,
|
||||
JSEXN_DEFAULTVALUEERR,
|
||||
JSEXN_ARRAYERR,
|
||||
JSEXN_LIMIT
|
||||
} JSExnType;
|
||||
|
||||
#define FLAGS JSCLASS_HAS_PRIVATE
|
||||
|
||||
/* Maybe #define RANDOM_CLASS(name, prototype) 4 here? */
|
||||
struct JSExnSpec {
|
||||
int protoIndex;
|
||||
JSClass theclass;
|
||||
};
|
||||
|
||||
/*
|
||||
* I want to replace all of these with just one class. All we really care
|
||||
* about is the prototypes, and the constructor names.
|
||||
*/
|
||||
static struct JSExnSpec exceptions[] = {
|
||||
{ JSEXN_NONE, /* No proto? */ {
|
||||
"Exception", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_EXCEPTION, {
|
||||
"Error", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_ERR, {
|
||||
"InternalError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_ERR, {
|
||||
"SyntaxError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_ERR, {
|
||||
"ReferenceError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_ERR, {
|
||||
"CallError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_CALLERR, {
|
||||
"TargetError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_ERR, {
|
||||
"ConstructorError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_ERR, {
|
||||
"ConversionError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_CONVERSIONERR, {
|
||||
"ToObjectError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_CONVERSIONERR, {
|
||||
"ToPrimitiveError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_CONVERSIONERR, {
|
||||
"DefaultValueError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{ JSEXN_ERR, {
|
||||
"ArrayError", FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize
|
||||
} },
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSBool
|
||||
Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
if (!cx->fp->constructing) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* gotta null out that private data */
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, JSVAL_NULL);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert to string. Much of this is taken from js.c.
|
||||
*
|
||||
* I should rewrite this to use message, line, file etc. from
|
||||
* javascript-modifiable properties (which might be lazily created
|
||||
* from the encapsulated error report.)
|
||||
*/
|
||||
static JSBool
|
||||
exn_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSString *str;
|
||||
JSExnPrivate *privateData;
|
||||
JSErrorReport *report;
|
||||
jsval v;
|
||||
char *name;
|
||||
JSClass *theclass;
|
||||
|
||||
/* Check needed against incompatible target... */
|
||||
|
||||
/* Try to include the exception name in the error message. */
|
||||
theclass = OBJ_GET_CLASS(cx, obj);
|
||||
name = theclass->name;
|
||||
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
|
||||
if (!JSVAL_IS_NULL(v)) {
|
||||
char *msgbuf, *tmp;
|
||||
|
||||
privateData = JSVAL_TO_PRIVATE(v);
|
||||
report = privateData->errorReport;
|
||||
|
||||
msgbuf = JS_smprintf("%s:", name);
|
||||
|
||||
if (report->filename) {
|
||||
tmp = msgbuf;
|
||||
msgbuf = JS_smprintf("%s%s:", tmp, report->filename);
|
||||
JS_free(cx, tmp);
|
||||
}
|
||||
if (report->lineno) {
|
||||
tmp = msgbuf;
|
||||
msgbuf = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
|
||||
if (tmp)
|
||||
JS_free(cx, tmp);
|
||||
}
|
||||
JS_ASSERT(privateData->message);
|
||||
tmp = msgbuf;
|
||||
msgbuf = JS_smprintf("%s%s", tmp ? tmp : "", privateData->message);
|
||||
if(tmp)
|
||||
JS_free(cx, tmp);
|
||||
|
||||
str = JS_NewStringCopyZ(cx, msgbuf);
|
||||
} else {
|
||||
str = JS_NewStringCopyZ(cx, "some non-engine-thrown exception");
|
||||
}
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec exception_methods[] = {
|
||||
{js_toString_str, exn_toString, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
JSObject *
|
||||
js_InitExceptionClasses(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
|
||||
JSObject *protos[JSEXN_LIMIT];
|
||||
int i;
|
||||
|
||||
for (i = 0; exceptions[i].theclass.name != 0; i++) {
|
||||
int protoidx = exceptions[i].protoIndex;
|
||||
protos[i] = JS_InitClass(cx, obj,
|
||||
((protoidx >= 0) ? protos[protoidx] : NULL),
|
||||
&(exceptions[i].theclass),
|
||||
Exception, 1,
|
||||
NULL,
|
||||
exception_methods,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* So finalize knows whether to. */
|
||||
OBJ_SET_SLOT(cx, protos[i], JSSLOT_PRIVATE, JSVAL_NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* JS_InitClass magically replaces a null prototype with Object.prototype,
|
||||
* so we need to explicitly assign to the proto slot to get null.
|
||||
*
|
||||
* Temporarily disabled until I do toString for Exception.
|
||||
*/
|
||||
|
||||
/* protos[0]->slots[JSSLOT_PROTO] = JSVAL_NULL; */
|
||||
|
||||
return protos[0];
|
||||
}
|
||||
|
||||
static JSErrorReport *
|
||||
js_GetErrorFromException(JSContext *cx, JSObject *errobj)
|
||||
{
|
||||
JSExnPrivate *privateData;
|
||||
#if 0
|
||||
{
|
||||
JSClass *errobjclass;
|
||||
/* Assert that we have an Exception object */
|
||||
/* This assert does the right thing, but we can't use it yet, because
|
||||
* we're throwing lots of different exception classes. */
|
||||
errobjclass = OBJ_GET_CLASS(cx, errobj);
|
||||
JS_ASSERT(errobjclass == &(exceptions[JSEXN_CALLERR].theclass));
|
||||
}
|
||||
#endif
|
||||
privateData = JSVAL_TO_PRIVATE(OBJ_GET_SLOT(cx, errobj, JSSLOT_PRIVATE));
|
||||
|
||||
/* Still OK to return NULL, tho. */
|
||||
return privateData->errorReport;
|
||||
}
|
||||
|
||||
static JSExnType errorToException[] = {
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
exception,
|
||||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
};
|
||||
|
||||
#if defined ( DEBUG_mccabe ) && defined ( PRINTNAMES )
|
||||
/* For use below... get character strings for error name and exception name */
|
||||
static struct exnname { char *name; char *exception; } errortoexnname[] = {
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
{#name, #exception},
|
||||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
};
|
||||
#endif /* DEBUG */
|
||||
|
||||
JSBool
|
||||
js_ErrorToException(JSContext *cx, JSErrorReport *reportp, const char *message)
|
||||
{
|
||||
JSErrNum errorNumber;
|
||||
JSObject *errobj;
|
||||
JSExnType exn;
|
||||
JSExnPrivate *privateData;
|
||||
|
||||
JS_ASSERT(reportp);
|
||||
errorNumber = reportp->errorNumber;
|
||||
exn = errorToException[errorNumber];
|
||||
JS_ASSERT(exn < JSEXN_LIMIT);
|
||||
|
||||
#if defined( DEBUG_mccabe ) && defined ( PRINTNAMES )
|
||||
/* Print the error name and the associated exception name to stderr */
|
||||
fprintf(stderr, "%s\t%s\n",
|
||||
errortoexnname[errorNumber].name,
|
||||
errortoexnname[errorNumber].exception);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return false (no exception raised) if no exception is associated
|
||||
* with the given error number.
|
||||
*/
|
||||
if (exn == JSEXN_NONE)
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* Should (?) be js_ConstructObject... switching to NewObject
|
||||
* in the speculation that it won't require a frame. DefaultValue trouble.
|
||||
* And it seems to work???? For the record, the trouble was that
|
||||
* cx->fp was null when trying to construct the object...
|
||||
*/
|
||||
errobj = js_NewObject(cx,
|
||||
&(exceptions[exn].theclass),
|
||||
NULL, NULL);
|
||||
|
||||
/*
|
||||
* Construct a new copy of the error report, and store it in the
|
||||
* exception objects' private data. We can't use the error report
|
||||
* handed in, because it's stack-allocated, and may point to transient
|
||||
* data in the JSTokenStream.
|
||||
*/
|
||||
|
||||
/* XXX report failure? */
|
||||
privateData = exn_initPrivate(cx, reportp, message);
|
||||
OBJ_SET_SLOT(cx, errobj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(privateData));
|
||||
|
||||
JS_SetPendingException(cx, OBJECT_TO_JSVAL(errobj));
|
||||
reportp->flags |= JSREPORT_EXCEPTION;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#endif /* JS_HAS_ERROR_EXCEPTIONS */
|
||||
|
||||
47
mozilla/js/src/jsexn.h
Normal file
47
mozilla/js/src/jsexn.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS runtime exception classes.
|
||||
*/
|
||||
|
||||
#ifndef jsexn_h___
|
||||
#define jsexn_h___
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* Initialize exception object hierarchy.
|
||||
*/
|
||||
extern JSObject *
|
||||
js_InitExceptionClasses(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Given a JSErrorReport, check to see if there is an exception associated
|
||||
* with the error number. If there is, then create an appropriate exception
|
||||
* object, set it as the pending exception, and set the JSREPORT_EXCEPTION
|
||||
* flag on the error report. Exception-aware host error reporters will
|
||||
* know to ignore error reports so flagged. Returns JS_TRUE if an associated
|
||||
* exception is found, JS_FALSE if none.
|
||||
*/
|
||||
extern JSBool
|
||||
js_ErrorToException(JSContext *cx, JSErrorReport *reportp, const char *message);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsexn_h___ */
|
||||
1771
mozilla/js/src/jsfun.c
Normal file
1771
mozilla/js/src/jsfun.c
Normal file
File diff suppressed because it is too large
Load Diff
106
mozilla/js/src/jsfun.h
Normal file
106
mozilla/js/src/jsfun.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jsfun_h___
|
||||
#define jsfun_h___
|
||||
/*
|
||||
* JS function definitions.
|
||||
*/
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
struct JSFunction {
|
||||
jsrefcount nrefs; /* number of referencing objects */
|
||||
JSObject *object; /* back-pointer to GC'ed object header */
|
||||
JSNative call; /* native method pointer or null */
|
||||
uint16 nargs; /* minimum number of actual arguments */
|
||||
uint16 extra; /* number of arg slots for local GC roots */
|
||||
uint16 nvars; /* number of local variables */
|
||||
uint8 flags; /* bound method and other flags, see jsapi.h */
|
||||
uint8 spare; /* reserved for future use */
|
||||
JSAtom *atom; /* name for diagnostics and decompiling */
|
||||
JSScript *script; /* interpreted bytecode descriptor or null */
|
||||
};
|
||||
|
||||
extern JSClass js_ArgumentsClass;
|
||||
extern JSClass js_CallClass;
|
||||
extern JSClass js_ClosureClass;
|
||||
/* JS_FRIEND_DATA so that JSVAL_IS_FUNCTION is callable from outside */
|
||||
extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
|
||||
|
||||
/*
|
||||
* NB: jsapi.h and jsobj.h must be included before any call to this macro.
|
||||
*/
|
||||
#define JSVAL_IS_FUNCTION(cx, v) \
|
||||
(JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) && \
|
||||
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass)
|
||||
|
||||
extern JSBool
|
||||
js_IsIdentifier(JSString *str);
|
||||
|
||||
extern JSObject *
|
||||
js_InitFunctionClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
js_InitArgsCallClosureClasses(JSContext *cx, JSObject *obj,
|
||||
JSObject *arrayProto);
|
||||
|
||||
extern JSFunction *
|
||||
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative call, uintN nargs,
|
||||
uintN flags, JSObject *parent, JSAtom *atom);
|
||||
|
||||
extern JSBool
|
||||
js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *object);
|
||||
|
||||
extern JSFunction *
|
||||
js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative call,
|
||||
uintN nargs, uintN flags);
|
||||
|
||||
extern JSFunction *
|
||||
js_ValueToFunction(JSContext *cx, jsval *vp, JSBool constructing);
|
||||
|
||||
extern void
|
||||
js_ReportIsNotFunction(JSContext *cx, jsval *vp, JSBool constructing);
|
||||
|
||||
extern JSObject *
|
||||
js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent,
|
||||
JSObject *withobj);
|
||||
|
||||
extern JSBool
|
||||
js_PutCallObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JSBool
|
||||
js_GetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_SetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
extern JSObject *
|
||||
js_GetArgsObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JSBool
|
||||
js_PutArgsObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JSBool
|
||||
js_XDRFunction(JSXDRState *xdr, JSObject **objp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsfun_h___ */
|
||||
925
mozilla/js/src/jsgc.c
Normal file
925
mozilla/js/src/jsgc.c
Normal file
@@ -0,0 +1,925 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS Mark-and-Sweep Garbage Collector.
|
||||
*
|
||||
* This GC allocates only fixed-sized things big enough to contain two words
|
||||
* (pointers) on any host architecture. It allocates from an arena pool (see
|
||||
* jsarena.h). It uses a parallel arena-pool array of flag bytes to hold the
|
||||
* mark bit, finalizer type index, etc.
|
||||
*
|
||||
* XXX swizzle page to freelist for better locality of reference
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <stdlib.h> /* for free, called by JS_ARENA_DESTROY */
|
||||
#include <string.h> /* for memset, called by jsarena.h macros if DEBUG */
|
||||
#include "jstypes.h"
|
||||
#ifndef NSPR20
|
||||
#include "jsarena.h"
|
||||
#else
|
||||
/* Removed by JSIFY: #include "plarena.h"
|
||||
*/
|
||||
#include "jsarena.h" /* Added by JSIFY */
|
||||
#endif
|
||||
/* Removed by JSIFY: #include "prlog.h" */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#ifndef NSPR20
|
||||
#include "jshash.h"
|
||||
#else
|
||||
/* Removed by JSIFY: #include "JShash.h"
|
||||
*/
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
#endif
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jslock.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsscript.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
/*
|
||||
* Arena sizes, the first must be a multiple of the second so the two arena
|
||||
* pools can be maintained (in particular, arenas may be destroyed from the
|
||||
* middle of each pool) in parallel.
|
||||
*/
|
||||
#define GC_ARENA_SIZE 8192 /* 1024 (512 on Alpha) objects */
|
||||
#define GC_FLAGS_SIZE (GC_ARENA_SIZE / sizeof(JSGCThing))
|
||||
#define GC_ROOTS_SIZE 256 /* SWAG, small enough to amortize */
|
||||
|
||||
static JSHashNumber gc_hash_root(const void *key);
|
||||
|
||||
struct JSGCThing {
|
||||
JSGCThing *next;
|
||||
uint8 *flagp;
|
||||
};
|
||||
|
||||
typedef void (*GCFinalizeOp)(JSContext *cx, JSGCThing *thing);
|
||||
|
||||
static GCFinalizeOp gc_finalizers[GCX_NTYPES];
|
||||
|
||||
#ifdef JS_GCMETER
|
||||
#define METER(x) x
|
||||
#else
|
||||
#define METER(x) /* nothing */
|
||||
#endif
|
||||
|
||||
JSBool
|
||||
js_InitGC(JSRuntime *rt, uint32 maxbytes)
|
||||
{
|
||||
if (!gc_finalizers[GCX_OBJECT]) {
|
||||
gc_finalizers[GCX_OBJECT] = (GCFinalizeOp)js_FinalizeObject;
|
||||
gc_finalizers[GCX_STRING] = (GCFinalizeOp)js_FinalizeString;
|
||||
gc_finalizers[GCX_DOUBLE] = (GCFinalizeOp)js_FinalizeDouble;
|
||||
}
|
||||
|
||||
JS_InitArenaPool(&rt->gcArenaPool, "gc-arena", GC_ARENA_SIZE,
|
||||
sizeof(JSGCThing));
|
||||
JS_InitArenaPool(&rt->gcFlagsPool, "gc-flags", GC_FLAGS_SIZE,
|
||||
sizeof(uint8));
|
||||
rt->gcRootsHash = JS_NewHashTable(GC_ROOTS_SIZE, gc_hash_root,
|
||||
JS_CompareValues, JS_CompareValues,
|
||||
NULL, NULL);
|
||||
if (!rt->gcRootsHash)
|
||||
return JS_FALSE;
|
||||
rt->gcMaxBytes = maxbytes;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_GCMETER
|
||||
void
|
||||
js_DumpGCStats(JSRuntime *rt, FILE *fp)
|
||||
{
|
||||
fprintf(fp, "\nGC allocation statistics:\n");
|
||||
fprintf(fp, " bytes currently allocated: %lu\n", rt->gcBytes);
|
||||
fprintf(fp, " alloc attempts: %lu\n", rt->gcStats.alloc);
|
||||
fprintf(fp, " GC freelist length: %lu\n", rt->gcStats.freelen);
|
||||
fprintf(fp, " recycles through GC freelist: %lu\n", rt->gcStats.recycle);
|
||||
fprintf(fp, "alloc retries after running GC: %lu\n", rt->gcStats.retry);
|
||||
fprintf(fp, " allocation failures: %lu\n", rt->gcStats.fail);
|
||||
fprintf(fp, " valid lock calls: %lu\n", rt->gcStats.lock);
|
||||
fprintf(fp, " valid unlock calls: %lu\n", rt->gcStats.unlock);
|
||||
fprintf(fp, " locks that hit stuck counts: %lu\n", rt->gcStats.stuck);
|
||||
fprintf(fp, " unlocks that saw stuck counts: %lu\n", rt->gcStats.unstuck);
|
||||
fprintf(fp, " mark recursion depth: %lu\n", rt->gcStats.depth);
|
||||
fprintf(fp, " maximum mark recursion depth: %lu\n", rt->gcStats.maxdepth);
|
||||
fprintf(fp, " maximum GC nesting level: %lu\n", rt->gcStats.maxlevel);
|
||||
fprintf(fp, " potentially useful GC calls: %lu\n", rt->gcStats.poke);
|
||||
fprintf(fp, " useless GC calls: %lu\n", rt->gcStats.nopoke);
|
||||
fprintf(fp, " thing arena corruption: %lu\n", rt->gcStats.badarena);
|
||||
fprintf(fp, " flags arena corruption: %lu\n", rt->gcStats.badflag);
|
||||
fprintf(fp, " thing arenas freed so far: %lu\n", rt->gcStats.afree);
|
||||
fprintf(fp, " flags arenas freed so far: %lu\n", rt->gcStats.fafree);
|
||||
#ifdef JS_ARENAMETER
|
||||
JS_DumpArenaStats(fp);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
js_FinishGC(JSRuntime *rt)
|
||||
{
|
||||
#ifdef JS_ARENAMETER
|
||||
JS_DumpArenaStats(stdout);
|
||||
#endif
|
||||
#ifdef JS_GCMETER
|
||||
js_DumpGCStats(rt, stdout);
|
||||
#endif
|
||||
JS_FinishArenaPool(&rt->gcArenaPool);
|
||||
JS_FinishArenaPool(&rt->gcFlagsPool);
|
||||
JS_ArenaFinish();
|
||||
JS_HashTableDestroy(rt->gcRootsHash);
|
||||
rt->gcRootsHash = NULL;
|
||||
rt->gcFreeList = NULL;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_AddRoot(JSContext *cx, void *rp, const char *name)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSBool ok;
|
||||
|
||||
rt = cx->runtime;
|
||||
JS_LOCK_GC_VOID(rt,
|
||||
ok = (JS_HashTableAdd(rt->gcRootsHash, rp, (void *)name) != NULL));
|
||||
if (!ok)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_RemoveRoot(JSContext *cx, void *rp)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
|
||||
rt = cx->runtime;
|
||||
JS_LOCK_GC_VOID(rt, JS_HashTableRemove(rt->gcRootsHash, rp));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
void *
|
||||
js_AllocGCThing(JSContext *cx, uintN flags)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSGCThing *thing;
|
||||
uint8 *flagp;
|
||||
#ifdef TOO_MUCH_GC
|
||||
JSBool tried_gc = JS_TRUE;
|
||||
js_GC(cx);
|
||||
#else
|
||||
JSBool tried_gc = JS_FALSE;
|
||||
#endif
|
||||
|
||||
rt = cx->runtime;
|
||||
JS_LOCK_GC(rt);
|
||||
METER(rt->gcStats.alloc++);
|
||||
retry:
|
||||
thing = rt->gcFreeList;
|
||||
if (thing) {
|
||||
rt->gcFreeList = thing->next;
|
||||
flagp = thing->flagp;
|
||||
METER(rt->gcStats.freelen--);
|
||||
METER(rt->gcStats.recycle++);
|
||||
} else {
|
||||
if (rt->gcBytes < rt->gcMaxBytes) {
|
||||
JS_ARENA_ALLOCATE(thing, &rt->gcArenaPool, sizeof(JSGCThing));
|
||||
JS_ARENA_ALLOCATE(flagp, &rt->gcFlagsPool, sizeof(uint8));
|
||||
}
|
||||
if (!thing || !flagp) {
|
||||
if (thing)
|
||||
JS_ARENA_RELEASE(&rt->gcArenaPool, thing);
|
||||
if (!tried_gc) {
|
||||
JS_UNLOCK_GC(rt);
|
||||
js_GC(cx);
|
||||
tried_gc = JS_TRUE;
|
||||
JS_LOCK_GC(rt);
|
||||
METER(rt->gcStats.retry++);
|
||||
goto retry;
|
||||
}
|
||||
METER(rt->gcStats.fail++);
|
||||
JS_UNLOCK_GC(rt);
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*flagp = (uint8)flags;
|
||||
rt->gcBytes += sizeof(JSGCThing) + sizeof(uint8);
|
||||
cx->newborn[flags & GCF_TYPEMASK] = thing;
|
||||
|
||||
/*
|
||||
* Clear thing before unlocking in case a GC run is about to scan it,
|
||||
* finding it via cx->newborn[].
|
||||
*/
|
||||
thing->next = NULL;
|
||||
thing->flagp = NULL;
|
||||
JS_UNLOCK_GC(rt);
|
||||
return thing;
|
||||
}
|
||||
|
||||
static uint8 *
|
||||
gc_find_flags(JSRuntime *rt, void *thing)
|
||||
{
|
||||
jsuword index, offset, length;
|
||||
JSArena *a, *fa;
|
||||
|
||||
index = 0;
|
||||
for (a = rt->gcArenaPool.first.next; a; a = a->next) {
|
||||
offset = JS_UPTRDIFF(thing, a->base);
|
||||
length = a->avail - a->base;
|
||||
if (offset < length) {
|
||||
index += offset / sizeof(JSGCThing);
|
||||
for (fa = rt->gcFlagsPool.first.next; fa; fa = fa->next) {
|
||||
offset = fa->avail - fa->base;
|
||||
if (index < offset)
|
||||
return (uint8 *)fa->base + index;
|
||||
index -= offset;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
index += length / sizeof(JSGCThing);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_LockGCThing(JSContext *cx, void *thing)
|
||||
{
|
||||
uint8 *flagp, flags;
|
||||
|
||||
if (!thing)
|
||||
return JS_TRUE;
|
||||
flagp = gc_find_flags(cx->runtime, thing);
|
||||
if (!flagp)
|
||||
return JS_FALSE;
|
||||
flags = *flagp;
|
||||
if ((flags & GCF_LOCKMASK) != GCF_LOCKMASK) {
|
||||
*flagp = (uint8)(flags + GCF_LOCK);
|
||||
} else {
|
||||
METER(cx->runtime->gcStats.stuck++);
|
||||
}
|
||||
METER(cx->runtime->gcStats.lock++);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_UnlockGCThing(JSContext *cx, void *thing)
|
||||
{
|
||||
uint8 *flagp, flags;
|
||||
|
||||
if (!thing)
|
||||
return JS_TRUE;
|
||||
flagp = gc_find_flags(cx->runtime, thing);
|
||||
if (!flagp)
|
||||
return JS_FALSE;
|
||||
flags = *flagp;
|
||||
if ((flags & GCF_LOCKMASK) != GCF_LOCKMASK) {
|
||||
*flagp = (uint8)(flags - GCF_LOCK);
|
||||
} else {
|
||||
METER(cx->runtime->gcStats.unstuck++);
|
||||
}
|
||||
METER(cx->runtime->gcStats.unlock++);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "jsprf.h"
|
||||
|
||||
JS_FRIEND_DATA(FILE *) js_DumpGCHeap;
|
||||
JS_FRIEND_DATA(void *) js_LiveThingToFind;
|
||||
|
||||
typedef struct GCMarkNode GCMarkNode;
|
||||
|
||||
struct GCMarkNode {
|
||||
void *thing;
|
||||
char *name;
|
||||
GCMarkNode *next;
|
||||
GCMarkNode *prev;
|
||||
};
|
||||
|
||||
static void
|
||||
gc_dump_thing(JSGCThing *thing, uint8 flags, GCMarkNode *prev, FILE *fp)
|
||||
{
|
||||
GCMarkNode *next = NULL;
|
||||
char *path = NULL;
|
||||
JSObject *obj;
|
||||
JSClass *clasp;
|
||||
|
||||
while (prev) {
|
||||
next = prev;
|
||||
prev = prev->prev;
|
||||
}
|
||||
while (next) {
|
||||
path = JS_sprintf_append(path, "%s.", next->name);
|
||||
next = next->next;
|
||||
}
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
fprintf(fp, "%08lx ", (long)thing);
|
||||
switch (flags & GCF_TYPEMASK) {
|
||||
case GCX_OBJECT:
|
||||
obj = (JSObject *)thing;
|
||||
clasp = JSVAL_TO_PRIVATE(obj->slots[JSSLOT_CLASS]);
|
||||
fprintf(fp, "object %s", clasp->name);
|
||||
break;
|
||||
case GCX_STRING:
|
||||
fprintf(fp, "string %s", JS_GetStringBytes((JSString *)thing));
|
||||
break;
|
||||
case GCX_DOUBLE:
|
||||
fprintf(fp, "double %g", *(jsdouble *)thing);
|
||||
break;
|
||||
case GCX_DECIMAL:
|
||||
break;
|
||||
}
|
||||
fprintf(fp, " via %s\n", path);
|
||||
free(path);
|
||||
}
|
||||
|
||||
static void
|
||||
gc_mark_node(JSRuntime *rt, void *thing, GCMarkNode *prev);
|
||||
|
||||
#define GC_MARK(_rt, _thing, _name, _prev) \
|
||||
JS_BEGIN_MACRO \
|
||||
GCMarkNode _node; \
|
||||
_node.thing = _thing; \
|
||||
_node.name = _name; \
|
||||
_node.next = NULL; \
|
||||
_node.prev = _prev; \
|
||||
if (_prev) ((GCMarkNode *)(_prev))->next = &_node; \
|
||||
gc_mark_node(_rt, _thing, &_node); \
|
||||
JS_END_MACRO
|
||||
|
||||
static void
|
||||
gc_mark(JSRuntime *rt, void *thing)
|
||||
{
|
||||
GC_MARK(rt, thing, "atom", NULL);
|
||||
}
|
||||
|
||||
#define GC_MARK_ATOM(rt, atom, prev) gc_mark_atom(rt, atom, prev)
|
||||
#define GC_MARK_SCRIPT(rt, script, prev) gc_mark_script(rt, script, prev)
|
||||
|
||||
#else /* !GC_MARK_DEBUG */
|
||||
|
||||
#define GC_MARK(rt, thing, name, prev) gc_mark(rt, thing)
|
||||
#define GC_MARK_ATOM(rt, atom, prev) gc_mark_atom(rt, atom)
|
||||
#define GC_MARK_SCRIPT(rt, script, prev) gc_mark_script(rt, script)
|
||||
|
||||
static void
|
||||
gc_mark(JSRuntime *rt, void *thing);
|
||||
|
||||
#endif /* !GC_MARK_DEBUG */
|
||||
|
||||
static void
|
||||
gc_mark_atom(JSRuntime *rt, JSAtom *atom
|
||||
#ifdef GC_MARK_DEBUG
|
||||
, GCMarkNode *prev
|
||||
#endif
|
||||
)
|
||||
{
|
||||
jsval key;
|
||||
|
||||
if (!atom || atom->flags & ATOM_MARK)
|
||||
return;
|
||||
atom->flags |= ATOM_MARK;
|
||||
key = ATOM_KEY(atom);
|
||||
if (JSVAL_IS_GCTHING(key)) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
char name[32];
|
||||
|
||||
if (JSVAL_IS_STRING(key)) {
|
||||
JS_snprintf(name, sizeof name, "'%s'",
|
||||
JS_GetStringBytes(JSVAL_TO_STRING(key)));
|
||||
} else {
|
||||
JS_snprintf(name, sizeof name, "<%x>", key);
|
||||
}
|
||||
#endif
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(key), name, prev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gc_mark_script(JSRuntime *rt, JSScript *script
|
||||
#ifdef GC_MARK_DEBUG
|
||||
, GCMarkNode *prev
|
||||
#endif
|
||||
)
|
||||
{
|
||||
JSAtomMap *map;
|
||||
uintN i, length;
|
||||
JSAtom **vector;
|
||||
|
||||
map = &script->atomMap;
|
||||
length = map->length;
|
||||
vector = map->vector;
|
||||
for (i = 0; i < length; i++)
|
||||
GC_MARK_ATOM(rt, vector[i], prev);
|
||||
}
|
||||
|
||||
static void
|
||||
#ifdef GC_MARK_DEBUG
|
||||
gc_mark_node(JSRuntime *rt, void *thing, GCMarkNode *prev)
|
||||
#else
|
||||
gc_mark(JSRuntime *rt, void *thing)
|
||||
#endif
|
||||
{
|
||||
uint8 flags, *flagp;
|
||||
JSObject *obj;
|
||||
jsval v, *vp, *end;
|
||||
JSScope *scope;
|
||||
JSClass *clasp;
|
||||
JSScript *script;
|
||||
JSFunction *fun;
|
||||
JSScopeProperty *sprop;
|
||||
JSSymbol *sym;
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
flagp = gc_find_flags(rt, thing);
|
||||
if (!flagp)
|
||||
return;
|
||||
|
||||
/* Check for something on the GC freelist to handle recycled stack. */
|
||||
flags = *flagp;
|
||||
if (flags == GCF_FINAL)
|
||||
return;
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
if (js_LiveThingToFind == thing)
|
||||
gc_dump_thing(thing, flags, prev, stderr);
|
||||
#endif
|
||||
|
||||
if (flags & GCF_MARK)
|
||||
return;
|
||||
*flagp |= GCF_MARK;
|
||||
METER(if (++rt->gcStats.depth > rt->gcStats.maxdepth)
|
||||
rt->gcStats.maxdepth = rt->gcStats.depth);
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
if (js_DumpGCHeap)
|
||||
gc_dump_thing(thing, flags, prev, js_DumpGCHeap);
|
||||
#endif
|
||||
|
||||
if ((flags & GCF_TYPEMASK) == GCX_OBJECT) {
|
||||
obj = thing;
|
||||
vp = obj->slots;
|
||||
if (vp) {
|
||||
scope = OBJ_IS_NATIVE(obj) ? (JSScope *) obj->map : NULL;
|
||||
if (scope) {
|
||||
clasp = JSVAL_TO_PRIVATE(obj->slots[JSSLOT_CLASS]);
|
||||
|
||||
if (clasp == &js_ScriptClass) {
|
||||
v = vp[JSSLOT_PRIVATE];
|
||||
if (!JSVAL_IS_VOID(v)) {
|
||||
script = JSVAL_TO_PRIVATE(v);
|
||||
if (script)
|
||||
GC_MARK_SCRIPT(rt, script, prev);
|
||||
}
|
||||
}
|
||||
|
||||
if (clasp == &js_FunctionClass) {
|
||||
v = vp[JSSLOT_PRIVATE];
|
||||
if (!JSVAL_IS_VOID(v)) {
|
||||
fun = JSVAL_TO_PRIVATE(v);
|
||||
if (fun) {
|
||||
if (fun->atom)
|
||||
GC_MARK_ATOM(rt, fun->atom, prev);
|
||||
if (fun->script)
|
||||
GC_MARK_SCRIPT(rt, fun->script, prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (sprop = scope->props; sprop; sprop = sprop->next) {
|
||||
for (sym = sprop->symbols; sym; sym = sym->next) {
|
||||
if (JSVAL_IS_INT(sym_id(sym)))
|
||||
continue;
|
||||
GC_MARK_ATOM(rt, sym_atom(sym), prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!scope || scope->object == obj)
|
||||
end = vp + obj->map->freeslot;
|
||||
else
|
||||
end = vp + JS_INITIAL_NSLOTS;
|
||||
for (; vp < end; vp++) {
|
||||
v = *vp;
|
||||
if (JSVAL_IS_GCTHING(v)) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
char name[32];
|
||||
|
||||
if (scope) {
|
||||
uint32 slot;
|
||||
jsval nval;
|
||||
|
||||
slot = vp - obj->slots;
|
||||
for (sprop = scope->props; ; sprop = sprop->next) {
|
||||
if (!sprop) {
|
||||
switch (slot) {
|
||||
case JSSLOT_PROTO:
|
||||
strcpy(name, "__proto__");
|
||||
break;
|
||||
case JSSLOT_PARENT:
|
||||
strcpy(name, "__parent__");
|
||||
break;
|
||||
case JSSLOT_PRIVATE:
|
||||
strcpy(name, "__private__");
|
||||
break;
|
||||
default:
|
||||
JS_snprintf(name, sizeof name,
|
||||
"**UNKNOWN SLOT %ld**",
|
||||
(long)slot);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (sprop->slot == slot) {
|
||||
nval = sprop->symbols
|
||||
? js_IdToValue(sym_id(sprop->symbols))
|
||||
: sprop->id;
|
||||
if (JSVAL_IS_INT(nval)) {
|
||||
JS_snprintf(name, sizeof name, "%ld",
|
||||
(long)JSVAL_TO_INT(nval));
|
||||
} else if (JSVAL_IS_STRING(nval)) {
|
||||
JS_snprintf(name, sizeof name, "%s",
|
||||
JS_GetStringBytes(JSVAL_TO_STRING(nval)));
|
||||
} else {
|
||||
strcpy(name, "**FINALIZED ATOM KEY**");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(v), name, prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
METER(rt->gcStats.depth--);
|
||||
}
|
||||
|
||||
static JSHashNumber
|
||||
gc_hash_root(const void *key)
|
||||
{
|
||||
JSHashNumber num = (JSHashNumber) key; /* help lame MSVC1.5 on Win16 */
|
||||
|
||||
return num >> 2;
|
||||
}
|
||||
|
||||
STATIC_DLL_CALLBACK(intN)
|
||||
gc_root_marker(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
void **rp = (void **)he->key;
|
||||
|
||||
if (*rp) {
|
||||
#ifdef DEBUG
|
||||
JSArena *a;
|
||||
JSRuntime *rt = (JSRuntime *)arg;
|
||||
|
||||
for (a = rt->gcArenaPool.first.next; a; a = a->next) {
|
||||
JS_ASSERT(!rp ||
|
||||
(*rp >= (void *)a->base && *rp <= (void *)a->avail));
|
||||
}
|
||||
#endif
|
||||
GC_MARK(arg, *rp, he->value ? he->value : "root", NULL);
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_ForceGC(JSContext *cx)
|
||||
{
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->newborn[GCX_STRING] = NULL;
|
||||
cx->newborn[GCX_DOUBLE] = NULL;
|
||||
cx->runtime->gcPoke = JS_TRUE;
|
||||
js_GC(cx);
|
||||
JS_ArenaFinish();
|
||||
}
|
||||
|
||||
void
|
||||
js_GC(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSContext *iter, *acx;
|
||||
JSArena *a, *ma, *fa, **ap, **fap;
|
||||
jsval v, *vp, *sp;
|
||||
jsuword begin, end;
|
||||
JSStackFrame *fp, *chain;
|
||||
void *mark;
|
||||
uint8 flags, *flagp;
|
||||
JSGCThing *thing, *final, **flp, **oflp;
|
||||
GCFinalizeOp finalizer;
|
||||
JSBool a_all_clear, f_all_clear;
|
||||
|
||||
/*
|
||||
* XXX kludge for pre-ECMAv2 compile-time switch case expr eval, see
|
||||
* jsemit.c:js_EmitTree, under case TOK_SWITCH: (look for XXX).
|
||||
*/
|
||||
if (cx->gcDisabled)
|
||||
return;
|
||||
|
||||
rt = cx->runtime;
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Avoid deadlock. */
|
||||
JS_ASSERT(!JS_IS_RUNTIME_LOCKED(rt));
|
||||
#endif
|
||||
|
||||
/* Let the API user decide to defer a GC if it wants to. */
|
||||
if (rt->gcCallback && !rt->gcCallback(cx, JSGC_BEGIN))
|
||||
return;
|
||||
|
||||
/* Lock out other GC allocator and collector invocations. */
|
||||
JS_LOCK_GC(rt);
|
||||
|
||||
/* Do nothing if no assignment has executed since the last GC. */
|
||||
if (!rt->gcPoke) {
|
||||
METER(rt->gcStats.nopoke++);
|
||||
JS_UNLOCK_GC(rt);
|
||||
return;
|
||||
}
|
||||
rt->gcPoke = JS_FALSE;
|
||||
METER(rt->gcStats.poke++);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Bump gcLevel and return rather than nest on this context. */
|
||||
if (cx->gcActive) {
|
||||
rt->gcLevel++;
|
||||
METER(if (rt->gcLevel > rt->gcStats.maxlevel)
|
||||
rt->gcStats.maxlevel = rt->gcLevel);
|
||||
if (rt->gcLevel > 1) {
|
||||
JS_UNLOCK_GC(rt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're in a request, indicate, temporarily, that we're inactive. */
|
||||
if (cx->requestDepth) {
|
||||
rt->requestCount--;
|
||||
JS_NOTIFY_REQUEST_DONE(rt);
|
||||
}
|
||||
|
||||
/* If another thread is already in GC, don't attempt GC; wait instead. */
|
||||
if (rt->gcLevel > 0) {
|
||||
while (rt->gcLevel > 0)
|
||||
JS_AWAIT_GC_DONE(rt);
|
||||
if (cx->requestDepth)
|
||||
rt->requestCount++;
|
||||
JS_UNLOCK_GC(rt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* No other thread is in GC, so indicate that we're now in GC. */
|
||||
rt->gcLevel = 1;
|
||||
|
||||
/* Also indicate that GC is active on this context. */
|
||||
cx->gcActive = JS_TRUE;
|
||||
|
||||
/* Wait for all other requests to finish. */
|
||||
while (rt->requestCount > 0)
|
||||
JS_AWAIT_REQUEST_DONE(rt);
|
||||
|
||||
#else /* !JS_THREADSAFE */
|
||||
|
||||
/* Bump gcLevel and return rather than nest; the outer gc will restart. */
|
||||
rt->gcLevel++;
|
||||
METER(if (rt->gcLevel > rt->gcStats.maxlevel)
|
||||
rt->gcStats.maxlevel = rt->gcLevel);
|
||||
if (rt->gcLevel > 1)
|
||||
return;
|
||||
|
||||
#endif /* !JS_THREADSAFE */
|
||||
|
||||
/* Drop atoms held by the property cache, and clear property weak links. */
|
||||
js_FlushPropertyCache(cx);
|
||||
restart:
|
||||
rt->gcNumber++;
|
||||
|
||||
/* Mark phase. */
|
||||
JS_HashTableEnumerateEntries(rt->gcRootsHash, gc_root_marker, rt);
|
||||
js_MarkAtomState(&rt->atomState, gc_mark);
|
||||
iter = NULL;
|
||||
while ((acx = js_ContextIterator(rt, &iter)) != NULL) {
|
||||
/*
|
||||
* Iterate frame chain and dormant chains. Temporarily tack current
|
||||
* frame onto the head of the dormant list to ease iteration.
|
||||
*
|
||||
* (NOTE: see comment on this whole 'dormant' thing in js_Execute)
|
||||
*/
|
||||
chain = acx->fp;
|
||||
if (chain) {
|
||||
JS_ASSERT(!chain->dormantNext);
|
||||
chain->dormantNext = acx->dormantFrameChain;
|
||||
} else {
|
||||
chain = acx->dormantFrameChain;
|
||||
}
|
||||
for (fp=chain; fp; fp = chain = chain->dormantNext) {
|
||||
sp = fp->sp;
|
||||
if (sp) {
|
||||
for (a = acx->stackPool.first.next; a; a = a->next) {
|
||||
begin = a->base;
|
||||
end = a->avail;
|
||||
if (JS_UPTRDIFF(sp, begin) < JS_UPTRDIFF(end, begin))
|
||||
end = (jsuword)sp;
|
||||
for (vp = (jsval *)begin; vp < (jsval *)end; vp++) {
|
||||
v = *vp;
|
||||
if (JSVAL_IS_GCTHING(v))
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(v), "stack", NULL);
|
||||
}
|
||||
if (end == (jsuword)sp)
|
||||
break;
|
||||
}
|
||||
}
|
||||
do {
|
||||
GC_MARK(rt, fp->scopeChain, "scope chain", NULL);
|
||||
GC_MARK(rt, fp->thisp, "this", NULL);
|
||||
if (JSVAL_IS_GCTHING(fp->rval))
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(fp->rval), "rval", NULL);
|
||||
if (fp->callobj)
|
||||
GC_MARK(rt, fp->callobj, "call object", NULL);
|
||||
if (fp->argsobj)
|
||||
GC_MARK(rt, fp->argsobj, "arguments object", NULL);
|
||||
if (fp->script)
|
||||
GC_MARK_SCRIPT(rt, fp->script, NULL);
|
||||
if (fp->sharpArray)
|
||||
GC_MARK(rt, fp->sharpArray, "sharp array", NULL);
|
||||
} while ((fp = fp->down) != NULL);
|
||||
}
|
||||
/* cleanup temporary link */
|
||||
if (acx->fp)
|
||||
acx->fp->dormantNext = NULL;
|
||||
GC_MARK(rt, acx->globalObject, "global object", NULL);
|
||||
GC_MARK(rt, acx->newborn[GCX_OBJECT], "newborn object", NULL);
|
||||
GC_MARK(rt, acx->newborn[GCX_STRING], "newborn string", NULL);
|
||||
GC_MARK(rt, acx->newborn[GCX_DOUBLE], "newborn double", NULL);
|
||||
#if JS_HAS_EXCEPTIONS
|
||||
if (acx->throwing)
|
||||
GC_MARK(rt, acx->exception, "exception", NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Sweep phase. Mark in tempPool for release at label out:. */
|
||||
ma = cx->tempPool.current;
|
||||
mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
js_SweepAtomState(&rt->atomState);
|
||||
fa = rt->gcFlagsPool.first.next;
|
||||
flagp = (uint8 *)fa->base;
|
||||
for (a = rt->gcArenaPool.first.next; a; a = a->next) {
|
||||
for (thing = (JSGCThing *)a->base; thing < (JSGCThing *)a->avail;
|
||||
thing++) {
|
||||
if (flagp >= (uint8 *)fa->avail) {
|
||||
fa = fa->next;
|
||||
JS_ASSERT(fa);
|
||||
if (!fa) {
|
||||
METER(rt->gcStats.badflag++);
|
||||
goto out;
|
||||
}
|
||||
flagp = (uint8 *)fa->base;
|
||||
}
|
||||
flags = *flagp;
|
||||
if (flags & GCF_MARK) {
|
||||
*flagp &= ~GCF_MARK;
|
||||
} else if (!(flags & (GCF_LOCKMASK | GCF_FINAL))) {
|
||||
JS_ARENA_ALLOCATE(final, &cx->tempPool, sizeof(JSGCThing));
|
||||
if (!final)
|
||||
goto out;
|
||||
final->next = thing;
|
||||
final->flagp = flagp;
|
||||
JS_ASSERT(rt->gcBytes >= sizeof(JSGCThing) + sizeof(uint8));
|
||||
rt->gcBytes -= sizeof(JSGCThing) + sizeof(uint8);
|
||||
}
|
||||
flagp++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finalize phase. Don't hold the GC lock while running finalizers! */
|
||||
JS_UNLOCK_GC(rt);
|
||||
for (final = mark; ; final++) {
|
||||
if ((jsuword)final >= ma->avail) {
|
||||
ma = ma->next;
|
||||
if (!ma)
|
||||
break;
|
||||
final = (JSGCThing *)ma->base;
|
||||
}
|
||||
thing = final->next;
|
||||
flagp = final->flagp;
|
||||
flags = *flagp;
|
||||
finalizer = gc_finalizers[flags & GCF_TYPEMASK];
|
||||
if (finalizer) {
|
||||
*flagp |= GCF_FINAL;
|
||||
finalizer(cx, thing);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set flags to GCF_FINAL, signifying that thing is free, but don't
|
||||
* thread thing onto rt->gcFreeList. We need the GC lock to rebuild
|
||||
* the freelist below while also looking for free-able arenas.
|
||||
*/
|
||||
*flagp = GCF_FINAL;
|
||||
}
|
||||
JS_LOCK_GC(rt);
|
||||
|
||||
/* Free unused arenas and rebuild the freelist. */
|
||||
ap = &rt->gcArenaPool.first.next;
|
||||
a = *ap;
|
||||
if (!a)
|
||||
goto out;
|
||||
thing = (JSGCThing *)a->base;
|
||||
a_all_clear = f_all_clear = JS_TRUE;
|
||||
flp = oflp = &rt->gcFreeList;
|
||||
*flp = NULL;
|
||||
METER(rt->gcStats.freelen = 0);
|
||||
|
||||
fap = &rt->gcFlagsPool.first.next;
|
||||
while ((fa = *fap) != NULL) {
|
||||
/* XXX optimize by unrolling to use word loads */
|
||||
for (flagp = (uint8 *)fa->base; ; flagp++) {
|
||||
JS_ASSERT(a);
|
||||
if (!a) {
|
||||
METER(rt->gcStats.badarena++);
|
||||
goto out;
|
||||
}
|
||||
if (thing >= (JSGCThing *)a->avail) {
|
||||
if (a_all_clear) {
|
||||
JS_ARENA_DESTROY(&rt->gcArenaPool, a, ap);
|
||||
flp = oflp;
|
||||
METER(rt->gcStats.afree++);
|
||||
} else {
|
||||
ap = &a->next;
|
||||
a_all_clear = JS_TRUE;
|
||||
oflp = flp;
|
||||
}
|
||||
a = *ap;
|
||||
if (!a)
|
||||
break;
|
||||
thing = (JSGCThing *)a->base;
|
||||
}
|
||||
if (flagp >= (uint8 *)fa->avail)
|
||||
break;
|
||||
if (*flagp != GCF_FINAL) {
|
||||
a_all_clear = f_all_clear = JS_FALSE;
|
||||
} else {
|
||||
thing->flagp = flagp;
|
||||
*flp = thing;
|
||||
flp = &thing->next;
|
||||
METER(rt->gcStats.freelen++);
|
||||
}
|
||||
thing++;
|
||||
}
|
||||
if (f_all_clear) {
|
||||
JS_ARENA_DESTROY(&rt->gcFlagsPool, fa, fap);
|
||||
METER(rt->gcStats.fafree++);
|
||||
} else {
|
||||
fap = &fa->next;
|
||||
f_all_clear = JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the new freelist. */
|
||||
*flp = NULL;
|
||||
|
||||
out:
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
if (rt->gcLevel > 1) {
|
||||
rt->gcLevel = 1;
|
||||
goto restart;
|
||||
}
|
||||
rt->gcLevel = 0;
|
||||
rt->gcLastBytes = rt->gcBytes;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/* If we were invoked during a request, undo the temporary decrement. */
|
||||
if (cx->requestDepth)
|
||||
rt->requestCount++;
|
||||
cx->gcActive = JS_FALSE;
|
||||
JS_NOTIFY_GC_DONE(rt);
|
||||
JS_UNLOCK_GC(rt);
|
||||
#endif
|
||||
if (rt->gcCallback)
|
||||
(void) rt->gcCallback(cx, JSGC_END);
|
||||
}
|
||||
110
mozilla/js/src/jsgc.h
Normal file
110
mozilla/js/src/jsgc.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 jsgc_h___
|
||||
#define jsgc_h___
|
||||
/*
|
||||
* JS Garbage Collector.
|
||||
*/
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/* GC thing type indexes. */
|
||||
#define GCX_OBJECT 0 /* JSObject */
|
||||
#define GCX_STRING 1 /* JSString */
|
||||
#define GCX_DOUBLE 2 /* jsdouble */
|
||||
#define GCX_DECIMAL 3 /* JSDecimal */
|
||||
#define GCX_NTYPES 4
|
||||
|
||||
/* GC flag definitions (type index goes in low bits). */
|
||||
#define GCF_TYPEMASK JS_BITMASK(2) /* use low bits for type */
|
||||
#define GCF_MARK JS_BIT(2) /* mark bit */
|
||||
#define GCF_FINAL JS_BIT(3) /* in finalization bit */
|
||||
#define GCF_LOCKBIT 4 /* lock bit shift and mask */
|
||||
#define GCF_LOCKMASK (JS_BITMASK(4) << GCF_LOCKBIT)
|
||||
#define GCF_LOCK JS_BIT(GCF_LOCKBIT) /* lock request bit in API */
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles
|
||||
* loading oldval. XXX remove implied force, poke in addroot/removeroot, &c
|
||||
*/
|
||||
#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JS_TRUE)
|
||||
#else
|
||||
#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval))
|
||||
#endif
|
||||
|
||||
extern JSBool
|
||||
js_InitGC(JSRuntime *rt, uint32 maxbytes);
|
||||
|
||||
extern void
|
||||
js_FinishGC(JSRuntime *rt);
|
||||
|
||||
extern JSBool
|
||||
js_AddRoot(JSContext *cx, void *rp, const char *name);
|
||||
|
||||
extern JSBool
|
||||
js_RemoveRoot(JSContext *cx, void *rp);
|
||||
|
||||
extern void *
|
||||
js_AllocGCThing(JSContext *cx, uintN flags);
|
||||
|
||||
extern JSBool
|
||||
js_LockGCThing(JSContext *cx, void *thing);
|
||||
|
||||
extern JSBool
|
||||
js_UnlockGCThing(JSContext *cx, void *thing);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_ForceGC(JSContext *cx);
|
||||
|
||||
extern void
|
||||
js_GC(JSContext *cx);
|
||||
|
||||
#ifdef JS_GCMETER
|
||||
|
||||
typedef struct JSGCStats {
|
||||
uint32 alloc; /* number of allocation attempts */
|
||||
uint32 freelen; /* gcFreeList length */
|
||||
uint32 recycle; /* number of things recycled through gcFreeList */
|
||||
uint32 retry; /* allocation attempt retries after running the GC */
|
||||
uint32 fail; /* allocation failures */
|
||||
uint32 lock; /* valid lock calls */
|
||||
uint32 unlock; /* valid unlock calls */
|
||||
uint32 stuck; /* stuck reference counts seen by lock calls */
|
||||
uint32 unstuck; /* unlock calls that saw a stuck lock count */
|
||||
uint32 depth; /* mark recursion depth */
|
||||
uint32 maxdepth; /* maximum mark recursion depth */
|
||||
uint32 maxlevel; /* maximum GC nesting (indirect recursion) level */
|
||||
uint32 poke; /* number of potentially useful GC calls */
|
||||
uint32 nopoke; /* useless GC calls where js_PokeGC was not set */
|
||||
uint32 badarena; /* thing arena corruption */
|
||||
uint32 badflag; /* flags arena corruption */
|
||||
uint32 afree; /* thing arenas freed so far */
|
||||
uint32 fafree; /* flags arenas freed so far */
|
||||
} JSGCStats;
|
||||
|
||||
extern void
|
||||
js_DumpGCStats(JSRuntime *rt, FILE *fp);
|
||||
|
||||
#endif /* JS_GCMETER */
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsgc_h___ */
|
||||
457
mozilla/js/src/jshash.c
Normal file
457
mozilla/js/src/jshash.c
Normal file
@@ -0,0 +1,457 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PR hash table package.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsbit.h"
|
||||
/* Removed by JSIFY: #include "prlog.h" */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#ifndef NSPR20
|
||||
#include "jshash.h"
|
||||
#else
|
||||
/* Removed by JSIFY: #include "JShash.h"
|
||||
*/
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
#endif
|
||||
|
||||
/* Compute the number of buckets in ht */
|
||||
#define NBUCKETS(ht) JS_BIT(PR_HASH_BITS - (ht)->shift)
|
||||
|
||||
/* The smallest table has 16 buckets */
|
||||
#define MINBUCKETSLOG2 4
|
||||
#define MINBUCKETS JS_BIT(MINBUCKETSLOG2)
|
||||
|
||||
/* Compute the maximum entries given n buckets that we will tolerate, ~90% */
|
||||
#define OVERLOADED(n) ((n) - ((n) >> 3))
|
||||
|
||||
/* Compute the number of entries below which we shrink the table by half */
|
||||
#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
|
||||
|
||||
/*
|
||||
** Stubs for default hash allocator ops.
|
||||
*/
|
||||
static void *
|
||||
DefaultAllocTable(void *pool, size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void
|
||||
DefaultFreeTable(void *pool, void *item)
|
||||
{
|
||||
free(item);
|
||||
}
|
||||
|
||||
static JSHashEntry *
|
||||
DefaultAllocEntry(void *pool, const void *key)
|
||||
{
|
||||
return malloc(sizeof(JSHashEntry));
|
||||
}
|
||||
|
||||
static void
|
||||
DefaultFreeEntry(void *pool, JSHashEntry *he, uintN flag)
|
||||
{
|
||||
if (flag == HT_FREE_ENTRY)
|
||||
free(he);
|
||||
}
|
||||
|
||||
static JSHashAllocOps defaultHashAllocOps = {
|
||||
DefaultAllocTable, DefaultFreeTable,
|
||||
DefaultAllocEntry, DefaultFreeEntry
|
||||
};
|
||||
|
||||
IMPLEMENT(JSHashTable *)
|
||||
JS_NewHashTable(uint32 n, JSHashFunction keyHash,
|
||||
JSHashComparator keyCompare, JSHashComparator valueCompare,
|
||||
JSHashAllocOps *allocOps, void *allocPriv)
|
||||
{
|
||||
JSHashTable *ht;
|
||||
size_t nb;
|
||||
|
||||
if (n <= MINBUCKETS) {
|
||||
n = MINBUCKETSLOG2;
|
||||
} else {
|
||||
n = JS_CeilingLog2(n);
|
||||
if ((int32)n < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!allocOps) allocOps = &defaultHashAllocOps;
|
||||
|
||||
ht = (*allocOps->allocTable)(allocPriv, sizeof *ht);
|
||||
if (!ht)
|
||||
return NULL;
|
||||
memset(ht, 0, sizeof *ht);
|
||||
ht->shift = PR_HASH_BITS - n;
|
||||
n = JS_BIT(n);
|
||||
#if defined(XP_PC) && defined _MSC_VER && _MSC_VER <= 800
|
||||
if (n > 16000) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* WIN16 */
|
||||
nb = n * sizeof(JSHashEntry *);
|
||||
ht->buckets = (*allocOps->allocTable)(allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return NULL;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
ht->keyHash = keyHash;
|
||||
ht->keyCompare = keyCompare;
|
||||
ht->valueCompare = valueCompare;
|
||||
ht->allocOps = allocOps;
|
||||
ht->allocPriv = allocPriv;
|
||||
return ht;
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_HashTableDestroy(JSHashTable *ht)
|
||||
{
|
||||
uint32 i, n;
|
||||
JSHashEntry *he, *next;
|
||||
JSHashAllocOps *allocOps = ht->allocOps;
|
||||
void *allocPriv = ht->allocPriv;
|
||||
|
||||
n = NBUCKETS(ht);
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = ht->buckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
(*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht->buckets);
|
||||
#ifdef DEBUG
|
||||
memset(ht, 0xDB, sizeof *ht);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
}
|
||||
|
||||
/*
|
||||
** Multiplicative hash, from Knuth 6.4.
|
||||
*/
|
||||
IMPLEMENT(JSHashEntry **)
|
||||
JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key)
|
||||
{
|
||||
JSHashEntry *he, **hep, **hep0;
|
||||
JSHashNumber h;
|
||||
|
||||
#ifdef HASHMETER
|
||||
ht->nlookups++;
|
||||
#endif
|
||||
h = keyHash * PR_GOLDEN_RATIO;
|
||||
h >>= ht->shift;
|
||||
hep = hep0 = &ht->buckets[h];
|
||||
while ((he = *hep) != NULL) {
|
||||
if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) {
|
||||
/* Move to front of chain if not already there */
|
||||
if (hep != hep0) {
|
||||
*hep = he->next;
|
||||
he->next = *hep0;
|
||||
*hep0 = he;
|
||||
}
|
||||
return hep0;
|
||||
}
|
||||
hep = &he->next;
|
||||
#ifdef HASHMETER
|
||||
ht->nsteps++;
|
||||
#endif
|
||||
}
|
||||
return hep;
|
||||
}
|
||||
|
||||
IMPLEMENT(JSHashEntry *)
|
||||
JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep,
|
||||
JSHashNumber keyHash, const void *key, void *value)
|
||||
{
|
||||
uint32 i, n;
|
||||
JSHashEntry *he, *next, **oldbuckets;
|
||||
size_t nb;
|
||||
|
||||
/* Grow the table if it is overloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (ht->nentries >= OVERLOADED(n)) {
|
||||
#ifdef HASHMETER
|
||||
ht->ngrows++;
|
||||
#endif
|
||||
ht->shift--;
|
||||
oldbuckets = ht->buckets;
|
||||
#if defined(XP_PC) && defined _MSC_VER && _MSC_VER <= 800
|
||||
if (2 * n > 16000)
|
||||
return NULL;
|
||||
#endif /* WIN16 */
|
||||
nb = 2 * n * sizeof(JSHashEntry *);
|
||||
ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return NULL;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = JS_HashTableRawLookup(ht, he->keyHash, he->key);
|
||||
JS_ASSERT(*hep == NULL);
|
||||
he->next = NULL;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
hep = JS_HashTableRawLookup(ht, keyHash, key);
|
||||
}
|
||||
|
||||
/* Make a new key value entry */
|
||||
he = (*ht->allocOps->allocEntry)(ht->allocPriv, key);
|
||||
if (!he)
|
||||
return NULL;
|
||||
he->keyHash = keyHash;
|
||||
he->key = key;
|
||||
he->value = value;
|
||||
he->next = *hep;
|
||||
*hep = he;
|
||||
ht->nentries++;
|
||||
return he;
|
||||
}
|
||||
|
||||
IMPLEMENT(JSHashEntry *)
|
||||
JS_HashTableAdd(JSHashTable *ht, const void *key, void *value)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
JSHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = JS_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) != NULL) {
|
||||
/* Hit; see if values match */
|
||||
if ((*ht->valueCompare)(he->value, value)) {
|
||||
/* key,value pair is already present in table */
|
||||
return he;
|
||||
}
|
||||
if (he->value)
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE);
|
||||
he->value = value;
|
||||
return he;
|
||||
}
|
||||
return JS_HashTableRawAdd(ht, hep, keyHash, key, value);
|
||||
}
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he)
|
||||
{
|
||||
uint32 i, n;
|
||||
JSHashEntry *next, **oldbuckets;
|
||||
size_t nb;
|
||||
|
||||
*hep = he->next;
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY);
|
||||
|
||||
/* Shrink table if it's underloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (--ht->nentries < UNDERLOADED(n)) {
|
||||
#ifdef HASHMETER
|
||||
ht->nshrinks++;
|
||||
#endif
|
||||
ht->shift++;
|
||||
oldbuckets = ht->buckets;
|
||||
nb = n * sizeof(JSHashEntry*) / 2;
|
||||
ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = JS_HashTableRawLookup(ht, he->keyHash, he->key);
|
||||
JS_ASSERT(*hep == NULL);
|
||||
he->next = NULL;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT(JSBool)
|
||||
JS_HashTableRemove(JSHashTable *ht, const void *key)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
JSHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = JS_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) == NULL)
|
||||
return JS_FALSE;
|
||||
|
||||
/* Hit; remove element */
|
||||
JS_HashTableRawRemove(ht, hep, he);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
IMPLEMENT(void *)
|
||||
JS_HashTableLookup(JSHashTable *ht, const void *key)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
JSHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = JS_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) != NULL) {
|
||||
return he->value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Iterate over the entries in the hash table calling func for each
|
||||
** entry found. Stop if "f" says to (return value & JS_ENUMERATE_STOP).
|
||||
** Return a count of the number of elements scanned.
|
||||
*/
|
||||
IMPLEMENT(int)
|
||||
JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg)
|
||||
{
|
||||
JSHashEntry *he, **hep;
|
||||
uint32 i, nbuckets;
|
||||
int rv, n = 0;
|
||||
JSHashEntry *todo = NULL;
|
||||
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
hep = &ht->buckets[i];
|
||||
while ((he = *hep) != NULL) {
|
||||
rv = (*f)(he, n, arg);
|
||||
n++;
|
||||
if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) {
|
||||
*hep = he->next;
|
||||
if (rv & HT_ENUMERATE_REMOVE) {
|
||||
he->next = todo;
|
||||
todo = he;
|
||||
}
|
||||
} else {
|
||||
hep = &he->next;
|
||||
}
|
||||
if (rv & HT_ENUMERATE_STOP) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
hep = &todo;
|
||||
while ((he = *hep) != NULL) {
|
||||
JS_HashTableRawRemove(ht, hep, he);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
#ifdef HASHMETER
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
IMPLEMENT(void)
|
||||
JS_HashTableDumpMeter(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
double mean, variance;
|
||||
uint32 nchains, nbuckets;
|
||||
uint32 i, n, maxChain, maxChainLen;
|
||||
JSHashEntry *he;
|
||||
|
||||
variance = 0;
|
||||
nchains = 0;
|
||||
maxChainLen = 0;
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
he = ht->buckets[i];
|
||||
if (!he)
|
||||
continue;
|
||||
nchains++;
|
||||
for (n = 0; he; he = he->next)
|
||||
n++;
|
||||
variance += n * n;
|
||||
if (n > maxChainLen) {
|
||||
maxChainLen = n;
|
||||
maxChain = i;
|
||||
}
|
||||
}
|
||||
mean = (double)ht->nentries / nchains;
|
||||
variance = fabs(variance / nchains - mean * mean);
|
||||
|
||||
fprintf(fp, "\nHash table statistics:\n");
|
||||
fprintf(fp, " number of lookups: %u\n", ht->nlookups);
|
||||
fprintf(fp, " number of entries: %u\n", ht->nentries);
|
||||
fprintf(fp, " number of grows: %u\n", ht->ngrows);
|
||||
fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
|
||||
fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
|
||||
/ ht->nlookups);
|
||||
fprintf(fp, "mean hash chain length: %g\n", mean);
|
||||
fprintf(fp, " standard deviation: %g\n", sqrt(variance));
|
||||
fprintf(fp, " max hash chain length: %u\n", maxChainLen);
|
||||
fprintf(fp, " max hash chain: [%u]\n", maxChain);
|
||||
|
||||
for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
|
||||
if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT)
|
||||
break;
|
||||
}
|
||||
#endif /* HASHMETER */
|
||||
|
||||
IMPLEMENT(int)
|
||||
JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = JS_HashTableEnumerateEntries(ht, dump, fp);
|
||||
#ifdef HASHMETER
|
||||
JS_HashTableDumpMeter(ht, dump, fp);
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
IMPLEMENT(JSHashNumber)
|
||||
JS_HashString(const void *key)
|
||||
{
|
||||
JSHashNumber h;
|
||||
const unsigned char *s;
|
||||
|
||||
h = 0;
|
||||
for (s = key; *s; s++)
|
||||
h = (h >> 28) ^ (h << 4) ^ *s;
|
||||
return h;
|
||||
}
|
||||
|
||||
IMPLEMENT(int)
|
||||
JS_CompareValues(const void *v1, const void *v2)
|
||||
{
|
||||
return v1 == v2;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user