Bugs 20724, 23715. Add a fixed-size allocator for nsXULAttribute objects. Always atomize 'id' attributes so nsXULElement::GetID() can be fast. r=hyatt

This commit is contained in:
waterson%netscape.com 2000-01-13 02:22:16 +00:00
Родитель c4b022703a
Коммит c592a32ef5
6 изменённых файлов: 290 добавлений и 24 удалений

Просмотреть файл

@ -137,6 +137,70 @@ nsClassList::ParseClasses(nsClassList** aList, const nsString& aClassString)
// nsXULAttribute
//
PRInt32 nsXULAttribute::gRefCnt;
nsIAtom* nsXULAttribute::kIdAtom;
const PRInt32 nsXULAttribute::kBlockSize = 512;
nsXULAttribute* nsXULAttribute::gFreeList;
void*
nsXULAttribute::operator new(size_t aSize)
{
// Simple fixed size allocator for nsXULAttribute objects. Look
// for an object on the |gFreeList|, if there isn't one, create a
// new block of 'em.
if (aSize != sizeof(nsXULAttribute))
return ::operator new(aSize);
nsXULAttribute* result = gFreeList;
if (result) {
gFreeList = gFreeList->mNext;
}
else {
// Create a chunk o' memory for the freelist.
nsXULAttribute* block =
NS_STATIC_CAST(nsXULAttribute*, ::operator new(kBlockSize * sizeof(nsXULAttribute)));
if (! block)
return nsnull;
// Thread it.
for (PRInt32 i = 1; i < kBlockSize - 1; ++i)
block[i].mNext = &block[i + 1];
block[kBlockSize - 1].mNext = nsnull;
result = block;
gFreeList = &block[1];
}
return result;
}
void
nsXULAttribute::operator delete(void* aObject, size_t aSize)
{
// Return |aObject| to |gFreeList|, if we can.
if (! aObject)
return;
if (aSize != sizeof(nsXULAttribute)) {
::operator delete(aObject);
return;
}
#ifdef DEBUG
nsCRT::memset(aObject, 0xdd, aSize);
#endif
nsXULAttribute* doomed = NS_STATIC_CAST(nsXULAttribute*, aObject);
doomed->mNext = gFreeList;
gFreeList = doomed;
}
nsXULAttribute::nsXULAttribute(nsIContent* aContent,
PRInt32 aNameSpaceID,
@ -149,6 +213,11 @@ nsXULAttribute::nsXULAttribute(nsIContent* aContent,
mValue(nsnull)
{
NS_INIT_REFCNT();
if (gRefCnt++ == 0) {
kIdAtom = NS_NewAtom("id");
}
NS_IF_ADDREF(aName);
SetValueInternal(aValue);
}
@ -157,6 +226,10 @@ nsXULAttribute::~nsXULAttribute()
{
NS_IF_RELEASE(mName);
ReleaseValue();
if (--gRefCnt == 0) {
NS_IF_RELEASE(kIdAtom);
}
}
nsresult
@ -444,7 +517,13 @@ nsresult
nsXULAttribute::SetValueInternal(const nsString& aValue)
{
nsCOMPtr<nsIAtom> newAtom;
if (aValue.Length() <= kMaxAtomValueLength) {
// Atomize the value if it is short, or if it is the 'id'
// attribute. We atomize the 'id' attribute to "prime" the global
// atom table: the style system frequently asks for it, and if the
// table is "unprimed" we see quite a bit of thrashing as the 'id'
// value is repeatedly added and then removed from the atom table.
if ((aValue.Length() <= kMaxAtomValueLength) || (mName == kIdAtom)) {
newAtom = getter_AddRefs( NS_NewAtom(aValue.GetUnicode()) );
}
@ -472,6 +551,22 @@ nsXULAttribute::SetValueInternal(const nsString& aValue)
return NS_OK;
}
nsresult
nsXULAttribute::GetValueAsAtom(nsIAtom** aResult)
{
if (! mValue) {
*aResult = nsnull;
}
else if (IsStringValue()) {
*aResult = NS_NewAtom((const PRUnichar*) mValue);
}
else {
*aResult = (nsIAtom*)(PRWord(mValue) & ~PRWord(kTypeMask));
NS_ADDREF(*aResult);
}
return NS_OK;
}
//----------------------------------------------------------------------
//

Просмотреть файл

@ -97,6 +97,20 @@ class nsXULAttribute : public nsIDOMAttr,
public nsIScriptObjectOwner
{
protected:
static PRInt32 gRefCnt;
static nsIAtom* kIdAtom;
// A global fixed-size allocator for nsXULAttribute
// objects. |kBlockSize| is the number of nsXULAttribute objects
// the live together in a contiguous block of memory.
static const PRInt32 kBlockSize;
// The head of the free list for free nsXULAttribute objects.
static nsXULAttribute* gFreeList;
static void* operator new(size_t aSize);
static void operator delete(void* aObject, size_t aSize);
nsXULAttribute(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
@ -131,9 +145,14 @@ public:
PRInt32 GetNameSpaceID() const { return mNameSpaceID; }
nsIAtom* GetName() const { return mName; }
nsresult SetValueInternal(const nsString& aValue);
nsresult GetValueAsAtom(nsIAtom** aResult);
protected:
nsIContent* mContent; // The content object that owns the attribute
union {
nsIContent* mContent; // The content object that owns the attribute
nsXULAttribute* mNext; // For objects on the freelist
};
void* mScriptObject; // The attribute's script object, if reified
PRInt32 mNameSpaceID; // The attribute namespace
nsIAtom* mName; // The attribute name

Просмотреть файл

@ -3327,17 +3327,36 @@ nsXULElement::GetElementsByAttribute(nsIDOMNode* aNode,
NS_IMETHODIMP
nsXULElement::GetID(nsIAtom*& aResult) const
{
nsAutoString value;
GetAttribute(kNameSpaceID_None, kIdAtom, value);
aResult = nsnull;
if (value.Length() > 0)
aResult = NS_NewAtom(value); // The NewAtom call does the AddRef.
else
{
aResult = kNullAtom;
NS_ADDREF(kNullAtom);
}
return NS_OK;
if (mSlots && mSlots->mAttributes) {
// Take advantage of the fact that the 'id' attribute will
// already be atomized.
PRInt32 count = mSlots->mAttributes->Count();
for (PRInt32 i = 0; i < count; ++i) {
nsXULAttribute* attr =
NS_REINTERPRET_CAST(nsXULAttribute*, mSlots->mAttributes->ElementAt(i));
if ((attr->GetNameSpaceID() == kNameSpaceID_None) && (attr->GetName() == kIdAtom)) {
nsIAtom* result;
attr->GetValueAsAtom(&result);
aResult = result; // transfer refcnt
break;
}
}
}
else if (mPrototype) {
PRInt32 count = mPrototype->mNumAttributes;
for (PRInt32 i = 0; i < count; i++) {
nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]);
if ((attr->mNameSpaceID == kNameSpaceID_None) && (attr->mName.get() == kIdAtom)) {
aResult = NS_NewAtom(attr->mValue);
break;
}
}
}
return NS_OK;
}
NS_IMETHODIMP

Просмотреть файл

@ -137,6 +137,70 @@ nsClassList::ParseClasses(nsClassList** aList, const nsString& aClassString)
// nsXULAttribute
//
PRInt32 nsXULAttribute::gRefCnt;
nsIAtom* nsXULAttribute::kIdAtom;
const PRInt32 nsXULAttribute::kBlockSize = 512;
nsXULAttribute* nsXULAttribute::gFreeList;
void*
nsXULAttribute::operator new(size_t aSize)
{
// Simple fixed size allocator for nsXULAttribute objects. Look
// for an object on the |gFreeList|, if there isn't one, create a
// new block of 'em.
if (aSize != sizeof(nsXULAttribute))
return ::operator new(aSize);
nsXULAttribute* result = gFreeList;
if (result) {
gFreeList = gFreeList->mNext;
}
else {
// Create a chunk o' memory for the freelist.
nsXULAttribute* block =
NS_STATIC_CAST(nsXULAttribute*, ::operator new(kBlockSize * sizeof(nsXULAttribute)));
if (! block)
return nsnull;
// Thread it.
for (PRInt32 i = 1; i < kBlockSize - 1; ++i)
block[i].mNext = &block[i + 1];
block[kBlockSize - 1].mNext = nsnull;
result = block;
gFreeList = &block[1];
}
return result;
}
void
nsXULAttribute::operator delete(void* aObject, size_t aSize)
{
// Return |aObject| to |gFreeList|, if we can.
if (! aObject)
return;
if (aSize != sizeof(nsXULAttribute)) {
::operator delete(aObject);
return;
}
#ifdef DEBUG
nsCRT::memset(aObject, 0xdd, aSize);
#endif
nsXULAttribute* doomed = NS_STATIC_CAST(nsXULAttribute*, aObject);
doomed->mNext = gFreeList;
gFreeList = doomed;
}
nsXULAttribute::nsXULAttribute(nsIContent* aContent,
PRInt32 aNameSpaceID,
@ -149,6 +213,11 @@ nsXULAttribute::nsXULAttribute(nsIContent* aContent,
mValue(nsnull)
{
NS_INIT_REFCNT();
if (gRefCnt++ == 0) {
kIdAtom = NS_NewAtom("id");
}
NS_IF_ADDREF(aName);
SetValueInternal(aValue);
}
@ -157,6 +226,10 @@ nsXULAttribute::~nsXULAttribute()
{
NS_IF_RELEASE(mName);
ReleaseValue();
if (--gRefCnt == 0) {
NS_IF_RELEASE(kIdAtom);
}
}
nsresult
@ -444,7 +517,13 @@ nsresult
nsXULAttribute::SetValueInternal(const nsString& aValue)
{
nsCOMPtr<nsIAtom> newAtom;
if (aValue.Length() <= kMaxAtomValueLength) {
// Atomize the value if it is short, or if it is the 'id'
// attribute. We atomize the 'id' attribute to "prime" the global
// atom table: the style system frequently asks for it, and if the
// table is "unprimed" we see quite a bit of thrashing as the 'id'
// value is repeatedly added and then removed from the atom table.
if ((aValue.Length() <= kMaxAtomValueLength) || (mName == kIdAtom)) {
newAtom = getter_AddRefs( NS_NewAtom(aValue.GetUnicode()) );
}
@ -472,6 +551,22 @@ nsXULAttribute::SetValueInternal(const nsString& aValue)
return NS_OK;
}
nsresult
nsXULAttribute::GetValueAsAtom(nsIAtom** aResult)
{
if (! mValue) {
*aResult = nsnull;
}
else if (IsStringValue()) {
*aResult = NS_NewAtom((const PRUnichar*) mValue);
}
else {
*aResult = (nsIAtom*)(PRWord(mValue) & ~PRWord(kTypeMask));
NS_ADDREF(*aResult);
}
return NS_OK;
}
//----------------------------------------------------------------------
//

Просмотреть файл

@ -97,6 +97,20 @@ class nsXULAttribute : public nsIDOMAttr,
public nsIScriptObjectOwner
{
protected:
static PRInt32 gRefCnt;
static nsIAtom* kIdAtom;
// A global fixed-size allocator for nsXULAttribute
// objects. |kBlockSize| is the number of nsXULAttribute objects
// the live together in a contiguous block of memory.
static const PRInt32 kBlockSize;
// The head of the free list for free nsXULAttribute objects.
static nsXULAttribute* gFreeList;
static void* operator new(size_t aSize);
static void operator delete(void* aObject, size_t aSize);
nsXULAttribute(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aName,
@ -131,9 +145,14 @@ public:
PRInt32 GetNameSpaceID() const { return mNameSpaceID; }
nsIAtom* GetName() const { return mName; }
nsresult SetValueInternal(const nsString& aValue);
nsresult GetValueAsAtom(nsIAtom** aResult);
protected:
nsIContent* mContent; // The content object that owns the attribute
union {
nsIContent* mContent; // The content object that owns the attribute
nsXULAttribute* mNext; // For objects on the freelist
};
void* mScriptObject; // The attribute's script object, if reified
PRInt32 mNameSpaceID; // The attribute namespace
nsIAtom* mName; // The attribute name

Просмотреть файл

@ -3327,17 +3327,36 @@ nsXULElement::GetElementsByAttribute(nsIDOMNode* aNode,
NS_IMETHODIMP
nsXULElement::GetID(nsIAtom*& aResult) const
{
nsAutoString value;
GetAttribute(kNameSpaceID_None, kIdAtom, value);
aResult = nsnull;
if (value.Length() > 0)
aResult = NS_NewAtom(value); // The NewAtom call does the AddRef.
else
{
aResult = kNullAtom;
NS_ADDREF(kNullAtom);
}
return NS_OK;
if (mSlots && mSlots->mAttributes) {
// Take advantage of the fact that the 'id' attribute will
// already be atomized.
PRInt32 count = mSlots->mAttributes->Count();
for (PRInt32 i = 0; i < count; ++i) {
nsXULAttribute* attr =
NS_REINTERPRET_CAST(nsXULAttribute*, mSlots->mAttributes->ElementAt(i));
if ((attr->GetNameSpaceID() == kNameSpaceID_None) && (attr->GetName() == kIdAtom)) {
nsIAtom* result;
attr->GetValueAsAtom(&result);
aResult = result; // transfer refcnt
break;
}
}
}
else if (mPrototype) {
PRInt32 count = mPrototype->mNumAttributes;
for (PRInt32 i = 0; i < count; i++) {
nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]);
if ((attr->mNameSpaceID == kNameSpaceID_None) && (attr->mName.get() == kIdAtom)) {
aResult = NS_NewAtom(attr->mValue);
break;
}
}
}
return NS_OK;
}
NS_IMETHODIMP