Commit 3dd5a9ce authored by oliver@apple.com's avatar oliver@apple.com
Browse files

Add zombies to JSC

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

Reviewed by Gavin Barraclough.

Add a compile time flag to make the JSC collector replace "unreachable"
objects with zombie objects.  The zombie object is a JSCell subclass that
ASSERTs on any attempt to use the JSCell methods.  In addition there are
a number of additional assertions in bottleneck code to catch zombie usage
as quickly as possible.

Grrr. Argh. Brains.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@51624 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 1da3d318
2009-12-02 Oliver Hunt <oliver@apple.com>
Reviewed by Gavin Barraclough.
Add zombies to JSC
https://bugs.webkit.org/show_bug.cgi?id=32103
Add a compile time flag to make the JSC collector replace "unreachable"
objects with zombie objects. The zombie object is a JSCell subclass that
ASSERTs on any attempt to use the JSCell methods. In addition there are
a number of additional assertions in bottleneck code to catch zombie usage
as quickly as possible.
Grrr. Argh. Brains.
* JavaScriptCore.xcodeproj/project.pbxproj:
* interpreter/Register.h:
(JSC::Register::Register):
* runtime/ArgList.h:
(JSC::MarkedArgumentBuffer::append):
(JSC::ArgList::ArgList):
* runtime/Collector.cpp:
(JSC::Heap::destroy):
(JSC::Heap::sweep):
* runtime/Collector.h:
* runtime/JSCell.h:
(JSC::JSCell::isZombie):
(JSC::JSValue::isZombie):
* runtime/JSValue.h:
(JSC::JSValue::decode):
(JSC::JSValue::JSValue):
* wtf/Platform.h:
2009-12-01 Jens Alfke <snej@chromium.org>
Reviewed by Darin Adler.
......
......@@ -284,6 +284,7 @@
A7A1F7AC0F252B3C00E184E2 /* ByteArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */; };
A7A1F7AD0F252B3C00E184E2 /* ByteArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */; };
A7C2217810C7479400F97913 /* JSZombie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C2216B10C7469C00F97913 /* JSZombie.cpp */; };
A7C530E4102A3813005BC741 /* MarkStackPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */; };
A7D649AA1015224E009B2E1B /* PossiblyNull.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D649A91015224E009B2E1B /* PossiblyNull.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */ = {isa = PBXBuildFile; fileRef = A7E2EA690FB460CF00601F06 /* LiteralParser.h */; };
......@@ -837,6 +838,8 @@
A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByteArray.h; sourceTree = "<group>"; };
A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableAllocator.h; sourceTree = "<group>"; };
A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocator.cpp; sourceTree = "<group>"; };
A7C2216810C745E000F97913 /* JSZombie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSZombie.h; sourceTree = "<group>"; };
A7C2216B10C7469C00F97913 /* JSZombie.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSZombie.cpp; sourceTree = "<group>"; };
A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkStackPosix.cpp; sourceTree = "<group>"; };
A7D649A91015224E009B2E1B /* PossiblyNull.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PossiblyNull.h; sourceTree = "<group>"; };
A7E2EA690FB460CF00601F06 /* LiteralParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralParser.h; sourceTree = "<group>"; };
......@@ -1596,6 +1599,8 @@
F692A8850255597D01FF60F7 /* UString.cpp */,
F692A8860255597D01FF60F7 /* UString.h */,
1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
A7C2216810C745E000F97913 /* JSZombie.h */,
A7C2216B10C7469C00F97913 /* JSZombie.cpp */,
);
path = runtime;
sourceTree = "<group>";
......@@ -2448,6 +2453,7 @@
1429DA820ED2482900B89619 /* WRECFunctors.cpp in Sources */,
1429DAE10ED2645B00B89619 /* WRECGenerator.cpp in Sources */,
1429DAC00ED263E700B89619 /* WRECParser.cpp in Sources */,
A7C2217810C7479400F97913 /* JSZombie.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -104,6 +104,9 @@ namespace JSC {
ALWAYS_INLINE Register::Register(JSValue v)
{
#if ENABLE(JSC_ZOMBIES)
ASSERT(!v.isZombie());
#endif
u.value = JSValue::encode(v);
}
......
......@@ -104,7 +104,11 @@ namespace JSC {
void append(JSValue v)
{
ASSERT(!m_isReadOnly);
#if ENABLE(JSC_ZOMBIES)
ASSERT(!v.isZombie());
#endif
if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
m_vector.uncheckedAppend(v);
++m_size;
......@@ -187,6 +191,10 @@ namespace JSC {
: m_args(args)
, m_argCount(argCount)
{
#if ENABLE(JSC_ZOMBIES)
for (size_t i = 0; i < argCount; i++)
ASSERT(!m_args[i].isZombie());
#endif
}
ArgList(Register* args, int argCount)
......
......@@ -32,6 +32,7 @@
#include "JSONObject.h"
#include "JSString.h"
#include "JSValue.h"
#include "JSZombie.h"
#include "MarkStack.h"
#include "Nodes.h"
#include "Tracing.h"
......@@ -194,9 +195,11 @@ void Heap::destroy()
sweep<PrimaryHeap>();
// No need to sweep number heap, because the JSNumber destructor doesn't do anything.
#if ENABLE(JSC_ZOMBIES)
ASSERT(primaryHeap.numLiveObjects == primaryHeap.numZombies);
#else
ASSERT(!primaryHeap.numLiveObjects);
#endif
freeBlocks(&primaryHeap);
freeBlocks(&numberHeap);
......@@ -1036,17 +1039,26 @@ template <HeapType heapType> size_t Heap::sweep()
// assumes the object has a valid vptr.)
if (cell->u.freeCell.zeroIfFree == 0)
continue;
#if ENABLE(JSC_ZOMBIES)
if (!imp->isZombie()) {
const ClassInfo* info = imp->classInfo();
imp->~JSCell();
new (imp) JSZombie(info, JSZombie::leakedZombieStructure());
heap.numZombies++;
}
#else
imp->~JSCell();
#endif
}
--usedCells;
--numLiveObjects;
#if !ENABLE(JSC_ZOMBIES)
--usedCells;
// put cell on the free list
cell->u.freeCell.zeroIfFree = 0;
cell->u.freeCell.next = freeList - (cell + 1);
freeList = cell;
#endif
}
}
} else {
......@@ -1059,8 +1071,18 @@ template <HeapType heapType> size_t Heap::sweep()
if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
if (heapType != NumberHeap) {
JSCell* imp = reinterpret_cast<JSCell*>(cell);
#if ENABLE(JSC_ZOMBIES)
if (!imp->isZombie()) {
const ClassInfo* info = imp->classInfo();
imp->~JSCell();
new (imp) JSZombie(info, JSZombie::leakedZombieStructure());
heap.numZombies++;
}
#else
imp->~JSCell();
#endif
}
#if !ENABLE(JSC_ZOMBIES)
--usedCells;
--numLiveObjects;
......@@ -1068,6 +1090,7 @@ template <HeapType heapType> size_t Heap::sweep()
cell->u.freeCell.zeroIfFree = 0;
cell->u.freeCell.next = freeList - (cell + 1);
freeList = cell;
#endif
}
}
}
......
......@@ -60,6 +60,9 @@ namespace JSC {
size_t numLiveObjects;
size_t numLiveObjectsAtLastCollect;
size_t extraCost;
#if ENABLE(JSC_ZOMBIES)
size_t numZombies;
#endif
OperationInProgress operationInProgress;
};
......
......@@ -42,6 +42,7 @@ namespace JSC {
friend class JSString;
friend class JSValue;
friend class JSAPIValueWrapper;
friend class JSZombie;
friend struct VPtrSet;
private:
......@@ -90,6 +91,9 @@ namespace JSC {
void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
virtual void markChildren(MarkStack&);
#if ENABLE(JSC_ZOMBIES)
virtual bool isZombie() const { return false; }
#endif
// Object operations, with the toObject operation included.
virtual const ClassInfo* classInfo() const;
......@@ -342,7 +346,13 @@ namespace JSC {
{
return cellBlock(c)->heap;
}
#if ENABLE(JSC_ZOMBIES)
inline bool JSValue::isZombie() const
{
return isCell() && asCell() && asCell()->isZombie();
}
#endif
} // namespace JSC
#endif // JSCell_h
......@@ -168,6 +168,10 @@ namespace JSC {
uint32_t toUInt32(ExecState*) const;
uint32_t toUInt32(ExecState*, bool& ok) const;
#if ENABLE(JSC_ZOMBIES)
bool isZombie() const;
#endif
// Floating point conversions (this is a convenience method for webcore;
// signle precision float is not a representation used in JS or JSC).
float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
......@@ -438,6 +442,9 @@ namespace JSC {
{
JSValue v;
v.u.asEncodedJSValue = encodedJSValue;
#if ENABLE(JSC_ZOMBIES)
ASSERT(!v.isZombie());
#endif
return v;
}
......@@ -484,6 +491,9 @@ namespace JSC {
else
u.asBits.tag = EmptyValueTag;
u.asBits.payload = reinterpret_cast<int32_t>(ptr);
#if ENABLE(JSC_ZOMBIES)
ASSERT(!isZombie());
#endif
}
inline JSValue::JSValue(const JSCell* ptr)
......@@ -493,6 +503,9 @@ namespace JSC {
else
u.asBits.tag = EmptyValueTag;
u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
#if ENABLE(JSC_ZOMBIES)
ASSERT(!isZombie());
#endif
}
inline JSValue::operator bool() const
......@@ -793,11 +806,17 @@ namespace JSC {
inline JSValue::JSValue(JSCell* ptr)
: m_ptr(ptr)
{
#if ENABLE(JSC_ZOMBIES)
ASSERT(!isZombie());
#endif
}
inline JSValue::JSValue(const JSCell* ptr)
: m_ptr(const_cast<JSCell*>(ptr))
{
#if ENABLE(JSC_ZOMBIES)
ASSERT(!isZombie());
#endif
}
inline JSValue::operator bool() const
......
......@@ -923,4 +923,6 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
/* Set up a define for a common error that is intended to cause a build error -- thus the space after Error. */
#define WTF_PLATFORM_CFNETWORK Error USE_macro_should_be_used_with_CFNETWORK
#define ENABLE_JSC_ZOMBIES 0
#endif /* WTF_Platform_h */
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