summaryrefslogtreecommitdiffstats
path: root/Source/JavaScriptCore/runtime/Heap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/Heap.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/Heap.cpp187
1 files changed, 93 insertions, 94 deletions
diff --git a/Source/JavaScriptCore/runtime/Heap.cpp b/Source/JavaScriptCore/runtime/Heap.cpp
index 3966324..c05233c 100644
--- a/Source/JavaScriptCore/runtime/Heap.cpp
+++ b/Source/JavaScriptCore/runtime/Heap.cpp
@@ -21,7 +21,8 @@
#include "config.h"
#include "Heap.h"
-#include "CollectorHeapIterator.h"
+#include "CodeBlock.h"
+#include "ConservativeSet.h"
#include "GCActivityCallback.h"
#include "GCHandle.h"
#include "Interpreter.h"
@@ -30,14 +31,19 @@
#include "JSLock.h"
#include "JSONObject.h"
#include "Tracing.h"
+#include <algorithm>
#define COLLECT_ON_EVERY_ALLOCATION 0
+using namespace std;
+
namespace JSC {
+const size_t minBytesPerCycle = 512 * 1024;
+
Heap::Heap(JSGlobalData* globalData)
- : m_markedSpace(globalData)
- , m_operationInProgress(NoOperation)
+ : m_operationInProgress(NoOperation)
+ , m_markedSpace(globalData)
, m_markListSet(0)
, m_activityCallback(DefaultGCActivityCallback::create(this))
, m_globalData(globalData)
@@ -71,14 +77,12 @@ void Heap::destroy()
delete m_markListSet;
m_markListSet = 0;
- ProtectCountSet protectedValuesCopy = m_protectedValues;
- m_markedSpace.destroy(protectedValuesCopy);
- ASSERT(!protectedObjectCount());
+ m_markedSpace.destroy();
m_globalData = 0;
}
-void Heap::recordExtraCost(size_t cost)
+void Heap::reportExtraMemoryCostSlowCase(size_t cost)
{
// Our frequency of garbage collection tries to balance memory use against speed
// by collecting based on the number of newly created values. However, for values
@@ -91,20 +95,8 @@ void Heap::recordExtraCost(size_t cost)
// if a large value survives one garbage collection, there is not much point to
// collecting more frequently as long as it stays alive.
- if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.size() / 2) {
- JAVASCRIPTCORE_GC_BEGIN();
-
- markRoots();
-
- JAVASCRIPTCORE_GC_MARKED();
-
- m_markedSpace.reset();
- m_extraCost = 0;
-
- JAVASCRIPTCORE_GC_END();
-
- (*m_activityCallback)();
- }
+ if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.capacity() / 2)
+ collectAllGarbage();
m_extraCost += cost;
}
@@ -113,7 +105,7 @@ void* Heap::allocate(size_t s)
ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
ASSERT(JSLock::lockCount() > 0);
ASSERT(JSLock::currentThreadIsHoldingLock());
- ASSERT_UNUSED(s, s <= HeapConstants::cellSize);
+ ASSERT_UNUSED(s, s <= MarkedBlock::CELL_SIZE);
ASSERT(m_operationInProgress == NoOperation);
#if COLLECT_ON_EVERY_ALLOCATION
@@ -124,34 +116,18 @@ void* Heap::allocate(size_t s)
m_operationInProgress = Allocation;
void* result = m_markedSpace.allocate(s);
m_operationInProgress = NoOperation;
-
if (!result) {
- JAVASCRIPTCORE_GC_BEGIN();
-
- markRoots();
-
- JAVASCRIPTCORE_GC_MARKED();
-
- m_markedSpace.reset();
- m_extraCost = 0;
-
- JAVASCRIPTCORE_GC_END();
-
- (*m_activityCallback)();
+ reset(DoNotSweep);
m_operationInProgress = Allocation;
result = m_markedSpace.allocate(s);
m_operationInProgress = NoOperation;
}
+
ASSERT(result);
return result;
}
-void Heap::markConservatively(ConservativeSet& conservativeSet, void* start, void* end)
-{
- m_markedSpace.markConservatively(conservativeSet, start, end);
-}
-
void Heap::updateWeakGCHandles()
{
for (unsigned i = 0; i < m_weakGCHandlePools.size(); ++i)
@@ -163,7 +139,7 @@ void WeakGCHandlePool::update()
for (unsigned i = 1; i < WeakGCHandlePool::numPoolEntries; ++i) {
if (m_entries[i].isValidPtr()) {
JSCell* cell = m_entries[i].get();
- if (!cell || !Heap::isCellMarked(cell))
+ if (!cell || !Heap::isMarked(cell))
m_entries[i].invalidate();
}
}
@@ -208,7 +184,7 @@ void Heap::markProtectedObjects(MarkStack& markStack)
{
ProtectCountSet::iterator end = m_protectedValues.end();
for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
- markStack.append(it->first);
+ markStack.deprecatedAppend(&it->first);
}
void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector)
@@ -233,11 +209,16 @@ void Heap::markTempSortVectors(MarkStack& markStack)
Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) {
if (vectorIt->first)
- markStack.append(vectorIt->first);
+ markStack.deprecatedAppend(&vectorIt->first);
}
}
}
-
+
+inline RegisterFile& Heap::registerFile()
+{
+ return m_globalData->interpreter->registerFile();
+}
+
void Heap::markRoots()
{
#ifndef NDEBUG
@@ -256,12 +237,11 @@ void Heap::markRoots()
// We gather the conservative set before clearing mark bits, because
// conservative gathering uses the mark bits from our last mark pass to
// determine whether a reference is valid.
- ConservativeSet conservativeSet;
+ ConservativeSet conservativeSet(this);
m_machineStackMarker.markMachineStackConservatively(conservativeSet);
- m_globalData->interpreter->registerFile().markCallFrames(conservativeSet, this);
+ conservativeSet.add(registerFile().start(), registerFile().end());
- // Reset mark bits.
- m_markedSpace.clearMarkBits();
+ m_markedSpace.clearMarks();
MarkStack& markStack = m_markStack;
conservativeSet.mark(markStack);
@@ -274,12 +254,17 @@ void Heap::markRoots()
// Mark temporary vector for Array sorting
markTempSortVectors(markStack);
markStack.drain();
+
+ HashSet<GlobalCodeBlock*>::const_iterator end = m_codeBlocks.end();
+ for (HashSet<GlobalCodeBlock*>::const_iterator it = m_codeBlocks.begin(); it != end; ++it)
+ (*it)->markAggregate(markStack);
+ markStack.drain();
// Mark misc. other roots.
if (m_markListSet && m_markListSet->size())
MarkedArgumentBuffer::markLists(markStack, *m_markListSet);
if (m_globalData->exception)
- markStack.append(m_globalData->exception);
+ markStack.append(&m_globalData->exception);
if (m_globalData->firstStringifierToMark)
JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark);
markStack.drain();
@@ -301,39 +286,30 @@ size_t Heap::objectCount() const
return m_markedSpace.objectCount();
}
-MarkedSpace::Statistics Heap::statistics() const
+size_t Heap::size() const
{
- return m_markedSpace.statistics();
+ return m_markedSpace.size();
}
-size_t Heap::size() const
+size_t Heap::capacity() const
{
- return m_markedSpace.size();
+ return m_markedSpace.capacity();
}
size_t Heap::globalObjectCount()
{
- size_t count = 0;
- if (JSGlobalObject* head = m_globalData->head) {
- JSGlobalObject* o = head;
- do {
- ++count;
- o = o->next();
- } while (o != head);
- }
- return count;
+ return m_globalData->globalObjects.uncheckedSize();
}
size_t Heap::protectedGlobalObjectCount()
{
size_t count = 0;
- if (JSGlobalObject* head = m_globalData->head) {
- JSGlobalObject* o = head;
- do {
- if (m_protectedValues.contains(o))
- ++count;
- o = o->next();
- } while (o != head);
+
+ GlobalObjectMap& map = m_globalData->globalObjects;
+ GlobalObjectMap::iterator end = map.uncheckedEnd();
+ for (GlobalObjectMap::iterator it = map.uncheckedBegin(); it != end; ++it) {
+ if (map.isValid(it) && m_protectedValues.contains(it->second.get()))
+ ++count;
}
return count;
@@ -344,7 +320,23 @@ size_t Heap::protectedObjectCount()
return m_protectedValues.size();
}
-static const char* typeName(JSCell* cell)
+class TypeCounter {
+public:
+ TypeCounter();
+ void operator()(JSCell*);
+ PassOwnPtr<TypeCountSet> take();
+
+private:
+ const char* typeName(JSCell*);
+ OwnPtr<TypeCountSet> m_typeCountSet;
+};
+
+inline TypeCounter::TypeCounter()
+ : m_typeCountSet(new TypeCountSet)
+{
+}
+
+inline const char* TypeCounter::typeName(JSCell* cell)
{
if (cell->isString())
return "string";
@@ -360,27 +352,32 @@ static const char* typeName(JSCell* cell)
return info ? info->className : "Object";
}
-HashCountedSet<const char*>* Heap::protectedObjectTypeCounts()
+inline void TypeCounter::operator()(JSCell* cell)
+{
+ m_typeCountSet->add(typeName(cell));
+}
+
+inline PassOwnPtr<TypeCountSet> TypeCounter::take()
+{
+ return m_typeCountSet.release();
+}
+
+PassOwnPtr<TypeCountSet> Heap::protectedObjectTypeCounts()
{
- HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
+ TypeCounter typeCounter;
ProtectCountSet::iterator end = m_protectedValues.end();
for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
- counts->add(typeName(it->first));
+ typeCounter(it->first);
- return counts;
+ return typeCounter.take();
}
-HashCountedSet<const char*>* Heap::objectTypeCounts()
+PassOwnPtr<TypeCountSet> Heap::objectTypeCounts()
{
- HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
-
- LiveObjectIterator it = primaryHeapBegin();
- LiveObjectIterator heapEnd = primaryHeapEnd();
- for ( ; it != heapEnd; ++it)
- counts->add(typeName(*it));
-
- return counts;
+ TypeCounter typeCounter;
+ forEach(typeCounter);
+ return typeCounter.take();
}
bool Heap::isBusy()
@@ -390,6 +387,11 @@ bool Heap::isBusy()
void Heap::collectAllGarbage()
{
+ reset(DoSweep);
+}
+
+void Heap::reset(SweepToggle sweepToggle)
+{
ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
JAVASCRIPTCORE_GC_BEGIN();
@@ -398,22 +400,19 @@ void Heap::collectAllGarbage()
JAVASCRIPTCORE_GC_MARKED();
m_markedSpace.reset();
- m_markedSpace.sweep();
m_extraCost = 0;
- JAVASCRIPTCORE_GC_END();
+ if (sweepToggle == DoSweep) {
+ m_markedSpace.sweep();
+ m_markedSpace.shrink();
+ }
- (*m_activityCallback)();
-}
+ size_t proportionalBytes = static_cast<size_t>(1.5 * m_markedSpace.size());
+ m_markedSpace.setHighWaterMark(max(proportionalBytes, minBytesPerCycle));
-LiveObjectIterator Heap::primaryHeapBegin()
-{
- return m_markedSpace.primaryHeapBegin();
-}
+ JAVASCRIPTCORE_GC_END();
-LiveObjectIterator Heap::primaryHeapEnd()
-{
- return m_markedSpace.primaryHeapEnd();
+ (*m_activityCallback)();
}
void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)