Commit 05937580 authored by fpizlo@apple.com's avatar fpizlo@apple.com
Browse files

Copied space should be able to handle more than one copied backing store per JSCell

https://bugs.webkit.org/show_bug.cgi?id=119471

Reviewed by Mark Hahnenberg.
        
This allows a cell to call copyLater() multiple times for multiple different
backing stores, and then have copyBackingStore() called exactly once for each
of those. A token tells it which backing store to copy. All backing stores
must be named using the CopyToken, an enumeration which currently cannot
exceed eight entries.
        
When copyBackingStore() is called, it's up to the callee to (a) use the token
to decide what to copy and (b) call its base class's copyBackingStore() in
case the base class had something that needed copying. The only exception is
that JSCell never asks anything to be copied, and so if your base is JSCell
then you don't have to do anything.

* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* heap/CopiedBlock.h:
* heap/CopiedBlockInlines.h:
(JSC::CopiedBlock::reportLiveBytes):
* heap/CopyToken.h: Added.
* heap/CopyVisitor.cpp:
(JSC::CopyVisitor::copyFromShared):
* heap/CopyVisitor.h:
* heap/CopyVisitorInlines.h:
(JSC::CopyVisitor::visitItem):
* heap/CopyWorkList.h:
(JSC::CopyWorklistItem::CopyWorklistItem):
(JSC::CopyWorklistItem::cell):
(JSC::CopyWorklistItem::token):
(JSC::CopyWorkListSegment::get):
(JSC::CopyWorkListSegment::append):
(JSC::CopyWorkListSegment::data):
(JSC::CopyWorkListIterator::get):
(JSC::CopyWorkListIterator::operator*):
(JSC::CopyWorkListIterator::operator->):
(JSC::CopyWorkList::append):
* heap/SlotVisitor.h:
* heap/SlotVisitorInlines.h:
(JSC::SlotVisitor::copyLater):
* runtime/ClassInfo.h:
* runtime/JSCell.cpp:
(JSC::JSCell::copyBackingStore):
* runtime/JSCell.h:
* runtime/JSObject.cpp:
(JSC::JSObject::visitButterfly):
(JSC::JSObject::copyBackingStore):
* runtime/JSObject.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153720 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 184ac0f2
2013-08-03 Filip Pizlo <fpizlo@apple.com>
Copied space should be able to handle more than one copied backing store per JSCell
https://bugs.webkit.org/show_bug.cgi?id=119471
Reviewed by Mark Hahnenberg.
This allows a cell to call copyLater() multiple times for multiple different
backing stores, and then have copyBackingStore() called exactly once for each
of those. A token tells it which backing store to copy. All backing stores
must be named using the CopyToken, an enumeration which currently cannot
exceed eight entries.
When copyBackingStore() is called, it's up to the callee to (a) use the token
to decide what to copy and (b) call its base class's copyBackingStore() in
case the base class had something that needed copying. The only exception is
that JSCell never asks anything to be copied, and so if your base is JSCell
then you don't have to do anything.
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* heap/CopiedBlock.h:
* heap/CopiedBlockInlines.h:
(JSC::CopiedBlock::reportLiveBytes):
* heap/CopyToken.h: Added.
* heap/CopyVisitor.cpp:
(JSC::CopyVisitor::copyFromShared):
* heap/CopyVisitor.h:
* heap/CopyVisitorInlines.h:
(JSC::CopyVisitor::visitItem):
* heap/CopyWorkList.h:
(JSC::CopyWorklistItem::CopyWorklistItem):
(JSC::CopyWorklistItem::cell):
(JSC::CopyWorklistItem::token):
(JSC::CopyWorkListSegment::get):
(JSC::CopyWorkListSegment::append):
(JSC::CopyWorkListSegment::data):
(JSC::CopyWorkListIterator::get):
(JSC::CopyWorkListIterator::operator*):
(JSC::CopyWorkListIterator::operator->):
(JSC::CopyWorkList::append):
* heap/SlotVisitor.h:
* heap/SlotVisitorInlines.h:
(JSC::SlotVisitor::copyLater):
* runtime/ClassInfo.h:
* runtime/JSCell.cpp:
(JSC::JSCell::copyBackingStore):
* runtime/JSCell.h:
* runtime/JSObject.cpp:
(JSC::JSObject::visitButterfly):
(JSC::JSObject::copyBackingStore):
* runtime/JSObject.h:
2013-08-05 Zan Dobersek <zdobersek@igalia.com>
 
[Automake] Define ENABLE_JIT through the Autoconf header
......
......@@ -373,6 +373,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/heap/CopiedSpace.cpp \
Source/JavaScriptCore/heap/CopiedSpace.h \
Source/JavaScriptCore/heap/CopiedSpaceInlines.h \
Source/JavaScriptCore/heap/CopyToken.h \
Source/JavaScriptCore/heap/CopyVisitor.h \
Source/JavaScriptCore/heap/CopyVisitorInlines.h \
Source/JavaScriptCore/heap/CopyVisitor.cpp \
......
......@@ -641,6 +641,7 @@
<ClInclude Include="..\heap\CopiedBlockInlines.h" />
<ClInclude Include="..\heap\CopiedSpace.h" />
<ClInclude Include="..\heap\CopiedSpaceInlines.h" />
<ClInclude Include="..\heap\CopyToken.h" />
<ClInclude Include="..\heap\CopyVisitor.h" />
<ClInclude Include="..\heap\CopyVisitorInlines.h" />
<ClInclude Include="..\heap\CopyWorkList.h" />
......
......@@ -174,6 +174,7 @@
0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F56A1D115000F31002992B1 /* ExecutionCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F56A1D515001CF4002992B1 /* ExecutionCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */; };
0F572D4F16879FDD00E57FBD /* ThunkGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F572D4D16879FDB00E57FBD /* ThunkGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F5A52D017ADD717008ECB2D /* CopyToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5A52CF17ADD717008ECB2D /* CopyToken.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F5EF91E16878F7A003E5C25 /* JITThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5EF91B16878F78003E5C25 /* JITThunks.cpp */; };
0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -1246,6 +1247,7 @@
0F56A1D115000F31002992B1 /* ExecutionCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionCounter.h; sourceTree = "<group>"; };
0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutionCounter.cpp; sourceTree = "<group>"; };
0F572D4D16879FDB00E57FBD /* ThunkGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThunkGenerator.h; sourceTree = "<group>"; };
0F5A52CF17ADD717008ECB2D /* CopyToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyToken.h; sourceTree = "<group>"; };
0F5EF91B16878F78003E5C25 /* JITThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITThunks.cpp; sourceTree = "<group>"; };
0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; };
0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnconditionalFinalizer.h; sourceTree = "<group>"; };
......@@ -2515,6 +2517,7 @@
C240305314B404C90079EB64 /* CopiedSpace.cpp */,
C2EAA3F8149A830800FCE112 /* CopiedSpace.h */,
C2C8D02B14A3C6B200578E65 /* CopiedSpaceInlines.h */,
0F5A52CF17ADD717008ECB2D /* CopyToken.h */,
C2239D1216262BDD005AC5FD /* CopyVisitor.cpp */,
C2239D1316262BDD005AC5FD /* CopyVisitor.h */,
C2239D1416262BDD005AC5FD /* CopyVisitorInlines.h */,
......@@ -3684,6 +3687,7 @@
0FEA0A231709606900BB722C /* FTLCommonValues.h in Headers */,
0FEA0A0C170513DB00BB722C /* FTLCompile.h in Headers */,
0F235BD417178E1C00690C7F /* FTLExitArgument.h in Headers */,
0F5A52D017ADD717008ECB2D /* CopyToken.h in Headers */,
0F235BD617178E1C00690C7F /* FTLExitArgumentForOperand.h in Headers */,
0F235BD717178E1C00690C7F /* FTLExitArgumentList.h in Headers */,
0F235BD917178E1C00690C7F /* FTLExitThunkGenerator.h in Headers */,
......
......@@ -52,7 +52,7 @@ public:
bool isOversize();
unsigned liveBytes();
void reportLiveBytes(JSCell*, unsigned);
void reportLiveBytes(JSCell*, CopyToken, unsigned);
void didSurviveGC();
void didEvacuateBytes(unsigned);
bool shouldEvacuate();
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
* Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -31,7 +31,7 @@
namespace JSC {
inline void CopiedBlock::reportLiveBytes(JSCell* owner, unsigned bytes)
inline void CopiedBlock::reportLiveBytes(JSCell* owner, CopyToken token, unsigned bytes)
{
#if ENABLE(PARALLEL_GC)
SpinLockHolder locker(&m_workListLock);
......@@ -46,7 +46,7 @@ inline void CopiedBlock::reportLiveBytes(JSCell* owner, unsigned bytes)
if (!m_workList)
m_workList = adoptPtr(new CopyWorkList(Heap::heap(owner)->blockAllocator()));
m_workList->append(owner);
m_workList->append(CopyWorklistItem(owner, token));
}
} // namespace JSC
......
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CopyToken_h
#define CopyToken_h
namespace JSC {
enum CopyToken {
ButterflyCopyToken
};
} // namespace JSC
#endif // CopyToken_h
......@@ -32,6 +32,7 @@
#include "GCThreadSharedData.h"
#include "JSCell.h"
#include "JSObject.h"
#include "Operations.h"
#include <wtf/Threading.h>
namespace JSC {
......@@ -53,7 +54,7 @@ void CopyVisitor::copyFromShared()
CopyWorkList& workList = block->workList();
for (CopyWorkList::iterator it = workList.begin(); it != workList.end(); ++it)
visitCell(*it);
visitItem(*it);
ASSERT(!block->liveBytes());
m_shared.m_copiedSpace->recycleEvacuatedBlock(block);
......
......@@ -51,7 +51,7 @@ public:
private:
void* allocateNewSpaceSlow(size_t);
void visitCell(JSCell*);
void visitItem(CopyWorklistItem);
GCThreadSharedData& m_shared;
CopiedAllocator m_copiedAllocator;
......
......@@ -34,10 +34,15 @@
namespace JSC {
inline void CopyVisitor::visitCell(JSCell* cell)
inline void CopyVisitor::visitItem(CopyWorklistItem item)
{
ASSERT(cell->structure()->classInfo()->methodTable.copyBackingStore == JSObject::copyBackingStore);
JSObject::copyBackingStore(cell, *this);
if (item.token() == ButterflyCopyToken) {
ASSERT(item.cell()->structure()->classInfo()->methodTable.copyBackingStore == JSObject::copyBackingStore);
JSObject::copyBackingStore(item.cell(), *this, ButterflyCopyToken);
return;
}
item.cell()->methodTable()->copyBackingStore(item.cell(), *this, item.token());
}
inline bool CopyVisitor::checkIfShouldCopy(void* oldPtr)
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
* Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -26,12 +26,37 @@
#ifndef CopyWorkList_h
#define CopyWorkList_h
#include "CopyToken.h"
#include <wtf/Vector.h>
namespace JSC {
class JSCell;
class CopyWorklistItem {
public:
CopyWorklistItem()
: m_value(0)
{
}
CopyWorklistItem(JSCell* cell, CopyToken token)
: m_value(bitwise_cast<uintptr_t>(cell) | static_cast<uintptr_t>(token))
{
ASSERT(!(bitwise_cast<uintptr_t>(cell) & static_cast<uintptr_t>(mask)));
ASSERT(static_cast<uintptr_t>(token) <= mask);
}
JSCell* cell() const { return bitwise_cast<JSCell*>(m_value & ~static_cast<uintptr_t>(mask)); }
CopyToken token() const { return static_cast<CopyToken>(m_value & mask); }
private:
static const unsigned requiredAlignment = 8;
static const unsigned mask = requiredAlignment - 1;
uintptr_t m_value;
};
class CopyWorkListSegment : public HeapBlock<CopyWorkListSegment> {
public:
static CopyWorkListSegment* create(DeadBlock* block)
......@@ -41,12 +66,12 @@ public:
size_t size() { return m_size; }
bool isFull() { return reinterpret_cast<char*>(&data()[size()]) >= endOfBlock(); }
JSCell* get(size_t index) { return data()[index]; }
CopyWorklistItem get(size_t index) { return data()[index]; }
void append(JSCell* cell)
void append(CopyWorklistItem item)
{
ASSERT(!isFull());
data()[m_size] = cell;
data()[m_size] = item;
m_size += 1;
}
......@@ -59,7 +84,7 @@ private:
{
}
JSCell** data() { return reinterpret_cast<JSCell**>(this + 1); }
CopyWorklistItem* data() { return reinterpret_cast<CopyWorklistItem*>(this + 1); }
char* endOfBlock() { return reinterpret_cast<char*>(this) + blockSize; }
size_t m_size;
......@@ -68,9 +93,9 @@ private:
class CopyWorkListIterator {
friend class CopyWorkList;
public:
JSCell* get() { return m_currentSegment->get(m_currentIndex); }
JSCell* operator*() { return get(); }
JSCell* operator->() { return get(); }
CopyWorklistItem get() { return m_currentSegment->get(m_currentIndex); }
CopyWorklistItem operator*() { return get(); }
CopyWorklistItem operator->() { return get(); }
CopyWorkListIterator& operator++()
{
......@@ -120,7 +145,7 @@ public:
CopyWorkList(BlockAllocator&);
~CopyWorkList();
void append(JSCell*);
void append(CopyWorklistItem);
iterator begin();
iterator end();
......@@ -140,14 +165,14 @@ inline CopyWorkList::~CopyWorkList()
m_blockAllocator.deallocate(CopyWorkListSegment::destroy(m_segments.removeHead()));
}
inline void CopyWorkList::append(JSCell* cell)
inline void CopyWorkList::append(CopyWorklistItem item)
{
if (m_segments.isEmpty() || m_segments.tail()->isFull())
m_segments.append(CopyWorkListSegment::create(m_blockAllocator.allocate<CopyWorkListSegment>()));
ASSERT(!m_segments.tail()->isFull());
m_segments.tail()->append(cell);
m_segments.tail()->append(item);
}
inline CopyWorkList::iterator CopyWorkList::begin()
......
......@@ -26,6 +26,7 @@
#ifndef SlotVisitor_h
#define SlotVisitor_h
#include "CopyToken.h"
#include "HandleTypes.h"
#include "MarkStackInlines.h"
......@@ -83,7 +84,7 @@ public:
void harvestWeakReferences();
void finalizeUnconditionalFinalizers();
void copyLater(JSCell*, void*, size_t);
void copyLater(JSCell*, CopyToken, void*, size_t);
void reportExtraMemoryUsage(size_t size);
......
......@@ -208,7 +208,7 @@ inline void SlotVisitor::donateAndDrain()
drain();
}
inline void SlotVisitor::copyLater(JSCell* owner, void* ptr, size_t bytes)
inline void SlotVisitor::copyLater(JSCell* owner, CopyToken token, void* ptr, size_t bytes)
{
CopiedBlock* block = CopiedSpace::blockFor(ptr);
if (block->isOversize()) {
......@@ -219,7 +219,7 @@ inline void SlotVisitor::copyLater(JSCell* owner, void* ptr, size_t bytes)
if (block->isPinned())
return;
block->reportLiveBytes(owner, bytes);
block->reportLiveBytes(owner, token, bytes);
}
inline void SlotVisitor::reportExtraMemoryUsage(size_t size)
......
......@@ -25,6 +25,7 @@
#include "CallFrame.h"
#include "ConstructData.h"
#include "CopyToken.h"
#include "JSCell.h"
namespace JSC {
......@@ -39,7 +40,7 @@ struct MethodTable {
typedef void (*VisitChildrenFunctionPtr)(JSCell*, SlotVisitor&);
VisitChildrenFunctionPtr visitChildren;
typedef void (*CopyBackingStoreFunctionPtr)(JSCell*, CopyVisitor&);
typedef void (*CopyBackingStoreFunctionPtr)(JSCell*, CopyVisitor&, CopyToken);
CopyBackingStoreFunctionPtr copyBackingStore;
typedef CallType (*GetCallDataFunctionPtr)(JSCell*, CallData&);
......
......@@ -39,7 +39,7 @@ void JSCell::destroy(JSCell* cell)
cell->JSCell::~JSCell();
}
void JSCell::copyBackingStore(JSCell*, CopyVisitor&)
void JSCell::copyBackingStore(JSCell*, CopyVisitor&, CopyToken)
{
}
......
......@@ -101,7 +101,7 @@ public:
JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const;
static void visitChildren(JSCell*, SlotVisitor&);
JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&);
JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken);
// Object operations, with the toObject operation included.
const ClassInfo* classInfo() const;
......
......@@ -185,7 +185,9 @@ ALWAYS_INLINE void JSObject::visitButterfly(SlotVisitor& visitor, Butterfly* but
// Mark the properties.
visitor.appendValues(butterfly->propertyStorage() - storageSize, storageSize);
visitor.copyLater(this, butterfly->base(preCapacity, propertyCapacity), capacityInBytes);
visitor.copyLater(
this, ButterflyCopyToken,
butterfly->base(preCapacity, propertyCapacity), capacityInBytes);
// Mark the array if appropriate.
switch (structure->indexingType()) {
......@@ -222,11 +224,14 @@ void JSObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
#endif
}
void JSObject::copyBackingStore(JSCell* cell, CopyVisitor& visitor)
void JSObject::copyBackingStore(JSCell* cell, CopyVisitor& visitor, CopyToken token)
{
JSObject* thisObject = jsCast<JSObject*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
if (token != ButterflyCopyToken)
return;
Butterfly* butterfly = thisObject->butterfly();
if (butterfly)
thisObject->copyButterfly(visitor, butterfly, thisObject->structure()->outOfLineSize());
......
......@@ -115,7 +115,7 @@ public:
}
JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&);
JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken);
JS_EXPORT_PRIVATE static String className(const JSObject*);
......
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