Commit cece7568 authored by ggaren@apple.com's avatar ggaren@apple.com

A bit of Collector refatoring.

        
Patch by Geoffrey Garen <ggaren@apple.com> on 2009-08-26
Reviewed by Oliver Hunt.

SunSpider says no change. v8 says 1.003x faster (1.02x faster on splay).

* JavaScriptCore.exp:

* runtime/JSCell.cpp:
(JSC::JSCell::toPrimitive):
(JSC::JSCell::getPrimitiveNumber):
(JSC::JSCell::toBoolean):
(JSC::JSCell::toNumber):
(JSC::JSCell::toString):
(JSC::JSCell::toObject): Removed pure virtual functions from
JSCell, so the collector can construct one. This allowed
me to remove a bunch of ASSERT_NOT_REACHED throughout the
code, too.

* runtime/JSCell.h:
(JSC::JSCell::JSCell): ditto
(JSC::Heap::heap): Inlined this function because it's trivial.

* JavaScriptCore.exp:

* runtime/Collector.cpp:
(JSC::Heap::destroy):
(JSC::Heap::allocateBlock):
(JSC::Heap::freeBlock):
(JSC::Heap::freeBlocks): Renamed freeHeap to freeBlocks, since
it doesn't actually free the Heap object.
(JSC::Heap::heapAllocate):
(JSC::Heap::sweep):
* runtime/Collector.h: Refactored block allocation and destruction
into helper functions.
        
* runtime/GetterSetter.cpp:
* runtime/JSAPIValueWrapper.cpp:
* runtime/JSPropertyNameIterator.cpp: Removed dummy implementations
of pure virtual functions. (See above.)



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@47799 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 47c1de1d
2009-08-26 Geoffrey Garen <ggaren@apple.com>
Reviewed by Oliver Hunt.
A bit of Collector refatoring.
SunSpider says no change. v8 says 1.003x faster (1.02x faster on splay).
* JavaScriptCore.exp:
* runtime/JSCell.cpp:
(JSC::JSCell::toPrimitive):
(JSC::JSCell::getPrimitiveNumber):
(JSC::JSCell::toBoolean):
(JSC::JSCell::toNumber):
(JSC::JSCell::toString):
(JSC::JSCell::toObject): Removed pure virtual functions from
JSCell, so the collector can construct one. This allowed
me to remove a bunch of ASSERT_NOT_REACHED throughout the
code, too.
* runtime/JSCell.h:
(JSC::JSCell::JSCell): ditto
(JSC::Heap::heap): Inlined this function because it's trivial.
* JavaScriptCore.exp:
* runtime/Collector.cpp:
(JSC::Heap::destroy):
(JSC::Heap::allocateBlock):
(JSC::Heap::freeBlock):
(JSC::Heap::freeBlocks): Renamed freeHeap to freeBlocks, since
it doesn't actually free the Heap object.
(JSC::Heap::heapAllocate):
(JSC::Heap::sweep):
* runtime/Collector.h: Refactored block allocation and destruction
into helper functions.
* runtime/GetterSetter.cpp:
* runtime/JSAPIValueWrapper.cpp:
* runtime/JSPropertyNameIterator.cpp: Removed dummy implementations
of pure virtual functions. (See above.)
=== End re-roll-in of r47738:47740 with Windows crash fixed ===
2009-08-26 Geoffrey Garen <ggaren@apple.com>
......
......@@ -178,7 +178,6 @@ __ZN3JSC4Heap20protectedObjectCountEv
__ZN3JSC4Heap24setGCProtectNeedsLockingEv
__ZN3JSC4Heap25protectedObjectTypeCountsEv
__ZN3JSC4Heap26protectedGlobalObjectCountEv
__ZN3JSC4Heap4heapENS_7JSValueE
__ZN3JSC4Heap6isBusyEv
__ZN3JSC4Heap7collectEv
__ZN3JSC4Heap7destroyEv
......@@ -195,6 +194,7 @@ __ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE
__ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
__ZN3JSC6JSCell18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC6JSCell3putEPNS_9ExecStateEjNS_7JSValueE
__ZN3JSC6JSCell9getObjectEv
......@@ -287,7 +287,6 @@ __ZN3JSCgtERKNS_7UStringES2_
__ZN3JSCltERKNS_7UStringES2_
__ZN3WTF10fastCallocEmm
__ZN3WTF10fastMallocEm
__ZN3WTF13tryFastMallocEm
__ZN3WTF11currentTimeEv
__ZN3WTF11fastReallocEPvm
__ZN3WTF12createThreadEPFPvS0_ES0_
......@@ -297,6 +296,7 @@ __ZN3WTF12isMainThreadEv
__ZN3WTF12randomNumberEv
__ZN3WTF13currentThreadEv
__ZN3WTF13tryFastCallocEmm
__ZN3WTF13tryFastMallocEm
__ZN3WTF15ThreadCondition4waitERNS_5MutexE
__ZN3WTF15ThreadCondition6signalEv
__ZN3WTF15ThreadCondition9broadcastEv
......@@ -348,13 +348,18 @@ __ZNK3JSC17DebuggerCallFrame4typeEv
__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_7JSValueE
__ZNK3JSC18PropertyDescriptor12hasAccessorsEv
__ZNK3JSC4Heap10statisticsEv
__ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
__ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
__ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
__ZNK3JSC6JSCell14isGetterSetterEv
__ZNK3JSC6JSCell8toNumberEPNS_9ExecStateE
__ZNK3JSC6JSCell8toObjectEPNS_9ExecStateE
__ZNK3JSC6JSCell8toStringEPNS_9ExecStateE
__ZNK3JSC6JSCell9classInfoEv
__ZNK3JSC6JSCell9getStringERNS_7UStringE
__ZNK3JSC6JSCell9getStringEv
__ZNK3JSC6JSCell9getUInt32ERj
__ZNK3JSC6JSCell9toBooleanEPNS_9ExecStateE
__ZNK3JSC7ArgList8getSliceEiRS0_
__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateE
__ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
......@@ -385,7 +390,6 @@ __ZTVN3JSC14JSGlobalObjectE
__ZTVN3JSC15JSWrapperObjectE
__ZTVN3JSC16InternalFunctionE
__ZTVN3JSC16JSVariableObjectE
__ZTVN3JSC17JSAPIValueWrapperE
__ZTVN3JSC8DebuggerE
__ZTVN3JSC8JSObjectE
__ZTVN3JSC8JSStringE
......
......@@ -93,7 +93,6 @@
#endif
#define DEBUG_COLLECTOR 0
#define COLLECT_ON_EVERY_ALLOCATION 0
using std::max;
......@@ -114,8 +113,6 @@ const size_t MAX_NUM_BLOCKS = 256; // Max size of collector heap set to 16 MB
static RHeap* userChunk = 0;
#endif
static void freeHeap(CollectorHeap*);
#if ENABLE(JSC_MULTIPLE_THREADS)
#if PLATFORM(DARWIN)
......@@ -204,8 +201,8 @@ void Heap::destroy()
ASSERT(!primaryHeap.numLiveObjects);
freeHeap(&primaryHeap);
freeHeap(&numberHeap);
freeBlocks(&primaryHeap);
freeBlocks(&numberHeap);
#if ENABLE(JSC_MULTIPLE_THREADS)
if (m_currentThreadRegistrar) {
......@@ -225,7 +222,7 @@ void Heap::destroy()
}
template <HeapType heapType>
static NEVER_INLINE CollectorBlock* allocateBlock()
NEVER_INLINE CollectorBlock* Heap::allocateBlock()
{
#if PLATFORM(DARWIN)
vm_address_t address = 0;
......@@ -272,11 +269,45 @@ static NEVER_INLINE CollectorBlock* allocateBlock()
address += adjust;
memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
#endif
reinterpret_cast<CollectorBlock*>(address)->type = heapType;
return reinterpret_cast<CollectorBlock*>(address);
CollectorBlock* block = reinterpret_cast<CollectorBlock*>(address);
block->freeList = block->cells;
block->heap = this;
block->type = heapType;
CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
size_t numBlocks = heap.numBlocks;
if (heap.usedBlocks == numBlocks) {
static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR;
if (numBlocks > maxNumBlocks)
CRASH();
numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
heap.numBlocks = numBlocks;
heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*)));
}
heap.blocks[heap.usedBlocks++] = block;
return block;
}
static void freeBlock(CollectorBlock* block)
template <HeapType heapType>
NEVER_INLINE void Heap::freeBlock(size_t block)
{
CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
freeBlock(heap.blocks[block]);
// swap with the last block so we compact as we go
heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];
heap.usedBlocks--;
if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) {
heap.numBlocks = heap.numBlocks / GROWTH_FACTOR;
heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*)));
}
}
NEVER_INLINE void Heap::freeBlock(CollectorBlock* block)
{
#if PLATFORM(DARWIN)
vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE);
......@@ -291,7 +322,7 @@ static void freeBlock(CollectorBlock* block)
#endif
}
static void freeHeap(CollectorHeap* heap)
void Heap::freeBlocks(CollectorHeap* heap)
{
for (size_t i = 0; i < heap->usedBlocks; ++i)
if (heap->blocks[i])
......@@ -394,27 +425,13 @@ collect:
if (foundGarbage)
goto scan;
}
// didn't find a block, and GC didn't reclaim anything, need to allocate a new block
size_t numBlocks = heap.numBlocks;
if (usedBlocks == numBlocks) {
static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR;
if (numBlocks > maxNumBlocks)
CRASH();
numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
heap.numBlocks = numBlocks;
heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*)));
}
// didn't find a block, and GC didn't reclaim anything, need to allocate a new block
targetBlock = reinterpret_cast<Block*>(allocateBlock<heapType>());
targetBlock->freeList = targetBlock->cells;
targetBlock->heap = this;
heap.firstBlockWithPossibleSpace = heap.usedBlocks - 1;
targetBlockUsedCells = 0;
heap.blocks[usedBlocks] = reinterpret_cast<CollectorBlock*>(targetBlock);
heap.usedBlocks = usedBlocks + 1;
heap.firstBlockWithPossibleSpace = usedBlocks;
}
// find a free spot in the block and detach it from the free list
Cell* newCell = targetBlock->freeList;
......@@ -986,13 +1003,6 @@ void Heap::unprotect(JSValue k)
m_protectedValuesMutex->unlock();
}
Heap* Heap::heap(JSValue v)
{
if (!v.isCell())
return 0;
return Heap::cellBlock(v.asCell())->heap;
}
void Heap::markProtectedObjects(MarkStack& markStack)
{
if (m_protectedValuesMutex)
......@@ -1106,18 +1116,8 @@ template <HeapType heapType> size_t Heap::sweep()
if (curBlock->usedCells)
continue;
#if !DEBUG_COLLECTOR
freeBlock(reinterpret_cast<CollectorBlock*>(curBlock));
#endif
// swap with the last block so we compact as we go
heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];
heap.usedBlocks--;
freeBlock<heapType>(block);
block--; // Don't move forward a step in this case
if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) {
heap.numBlocks = heap.numBlocks / GROWTH_FACTOR;
heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*)));
}
}
return numLiveObjects;
......
......@@ -101,6 +101,7 @@ namespace JSC {
void unprotect(JSValue);
static Heap* heap(JSValue); // 0 for immediate values
static Heap* heap(JSCell*);
size_t globalObjectCount();
size_t protectedObjectCount();
......@@ -133,6 +134,11 @@ namespace JSC {
Heap(JSGlobalData*);
~Heap();
template <HeapType heapType> NEVER_INLINE CollectorBlock* allocateBlock();
template <HeapType heapType> NEVER_INLINE void freeBlock(size_t);
NEVER_INLINE void freeBlock(CollectorBlock*);
void freeBlocks(CollectorHeap*);
void recordExtraCost(size_t);
void markProtectedObjects(MarkStack&);
void markCurrentThreadConservatively(MarkStack&);
......
......@@ -38,44 +38,6 @@ void GetterSetter::markChildren(MarkStack& markStack)
markStack.append(m_setter);
}
JSValue GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
ASSERT_NOT_REACHED();
return jsNull();
}
bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValue& value)
{
ASSERT_NOT_REACHED();
number = 0;
value = JSValue();
return true;
}
bool GetterSetter::toBoolean(ExecState*) const
{
ASSERT_NOT_REACHED();
return false;
}
double GetterSetter::toNumber(ExecState*) const
{
ASSERT_NOT_REACHED();
return 0.0;
}
UString GetterSetter::toString(ExecState*) const
{
ASSERT_NOT_REACHED();
return UString::null();
}
JSObject* GetterSetter::toObject(ExecState* exec) const
{
ASSERT_NOT_REACHED();
return jsNull().toObject(exec);
}
bool GetterSetter::isGetterSetter() const
{
return true;
......
......@@ -55,13 +55,6 @@ namespace JSC {
private:
virtual bool isGetterSetter() const;
virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
virtual JSObject* toObject(ExecState*) const;
JSObject* m_getter;
JSObject* m_setter;
};
......
......@@ -28,40 +28,4 @@
namespace JSC {
JSValue JSAPIValueWrapper::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
ASSERT_NOT_REACHED();
return JSValue();
}
bool JSAPIValueWrapper::getPrimitiveNumber(ExecState*, double&, JSValue&)
{
ASSERT_NOT_REACHED();
return false;
}
bool JSAPIValueWrapper::toBoolean(ExecState*) const
{
ASSERT_NOT_REACHED();
return false;
}
double JSAPIValueWrapper::toNumber(ExecState*) const
{
ASSERT_NOT_REACHED();
return 0;
}
UString JSAPIValueWrapper::toString(ExecState*) const
{
ASSERT_NOT_REACHED();
return UString();
}
JSObject* JSAPIValueWrapper::toObject(ExecState*) const
{
ASSERT_NOT_REACHED();
return 0;
}
} // namespace JSC
......@@ -37,12 +37,6 @@ namespace JSC {
virtual bool isAPIValueWrapper() const { return true; }
virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
virtual JSObject* toObject(ExecState*) const;
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(CompoundType));
......
......@@ -197,4 +197,40 @@ bool JSCell::isGetterSetter() const
return false;
}
JSValue JSCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
ASSERT_NOT_REACHED();
return JSValue();
}
bool JSCell::getPrimitiveNumber(ExecState*, double&, JSValue&)
{
ASSERT_NOT_REACHED();
return false;
}
bool JSCell::toBoolean(ExecState*) const
{
ASSERT_NOT_REACHED();
return false;
}
double JSCell::toNumber(ExecState*) const
{
ASSERT_NOT_REACHED();
return 0;
}
UString JSCell::toString(ExecState*) const
{
ASSERT_NOT_REACHED();
return UString();
}
JSObject* JSCell::toObject(ExecState*) const
{
ASSERT_NOT_REACHED();
return 0;
}
} // namespace JSC
......@@ -45,6 +45,7 @@ namespace JSC {
private:
explicit JSCell(Structure*);
JSCell(); // Only used for initializing Collector blocks.
virtual ~JSCell();
public:
......@@ -74,12 +75,12 @@ namespace JSC {
virtual bool getUInt32(uint32_t&) const;
// Basic conversions.
virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&) = 0;
virtual bool toBoolean(ExecState*) const = 0;
virtual double toNumber(ExecState*) const = 0;
virtual UString toString(ExecState*) const = 0;
virtual JSObject* toObject(ExecState*) const = 0;
virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
virtual JSObject* toObject(ExecState*) const;
// Garbage collection.
void* operator new(size_t, ExecState*);
......@@ -124,6 +125,11 @@ namespace JSC {
{
}
// Only used for initializing Collector blocks.
inline JSCell::JSCell()
{
}
inline JSCell::~JSCell()
{
}
......@@ -361,6 +367,19 @@ namespace JSC {
if (cell->structure()->typeInfo().type() >= CompoundType)
m_values.append(cell);
}
inline Heap* Heap::heap(JSValue v)
{
if (!v.isCell())
return 0;
return heap(v.asCell());
}
inline Heap* Heap::heap(JSCell* c)
{
return cellBlock(c)->heap;
}
} // namespace JSC
#endif // JSCell_h
......@@ -37,42 +37,6 @@ JSPropertyNameIterator::~JSPropertyNameIterator()
{
}
JSValue JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
ASSERT_NOT_REACHED();
return JSValue();
}
bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValue&)
{
ASSERT_NOT_REACHED();
return false;
}
bool JSPropertyNameIterator::toBoolean(ExecState*) const
{
ASSERT_NOT_REACHED();
return false;
}
double JSPropertyNameIterator::toNumber(ExecState*) const
{
ASSERT_NOT_REACHED();
return 0;
}
UString JSPropertyNameIterator::toString(ExecState*) const
{
ASSERT_NOT_REACHED();
return "";
}
JSObject* JSPropertyNameIterator::toObject(ExecState*) const
{
ASSERT_NOT_REACHED();
return 0;
}
void JSPropertyNameIterator::markChildren(MarkStack& markStack)
{
JSCell::markChildren(markStack);
......
......@@ -44,13 +44,6 @@ namespace JSC {
virtual ~JSPropertyNameIterator();
virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double&, JSValue&);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
virtual JSObject* toObject(ExecState*) const;
virtual void markChildren(MarkStack&);
JSValue next(ExecState*);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment