Commit 264f9e28 authored by ggaren@apple.com's avatar ggaren@apple.com

2011-04-07 Geoffrey Garen <ggaren@apple.com>

        Reviewed by Maciej Stachowiak.

        Some Handle<T> cleanup
        https://bugs.webkit.org/show_bug.cgi?id=58109

        * bytecode/SamplingTool.h: Sorted alphabetically because that's the
        WebKit style. Added a Global.h #include that was previously missing
        but harmless.

        * collector/handles/Global.h:
        (JSC::Global::Global): Added a null constructor. No need for a special
        tag, and the tag is incompatible with some data structures.
        
        (JSC::Global::isHashTableDeletedValue):
        (JSC::Global::~Global):
        (JSC::Global::set):
        (JSC::Global::operator=):
        (JSC::Global::clear):
        (JSC::Global::hashTableDeletedValue): Reordered constructors to be near
        each other.

        (JSC::Global::setWithWriteBarrier): Renamed internalSet to
        setWithWriteBarrier for clarity, and funneled more code into using set
        and setWithWriteBarrier to reduce duplication.

        * collector/handles/Handle.h:
        (JSC::HandleBase::operator!):
        (JSC::HandleBase::HandleBase): Removed isEmpty(), since we already have
        boolean and ! operators.

        (JSC::HandleBase::slot):
        (JSC::HandleBase::setSlot):
        (JSC::Handle::Handle): Added general support for null Handles. This was
        previously outlawed by ASSERTs, but our code has grown to support and
        rely on null Handles.
        
        * collector/handles/HandleHeap.cpp:
        (JSC::HandleHeap::markWeakHandles):
        (JSC::HandleHeap::finalizeWeakHandles):
        (JSC::HandleHeap::isValidWeakNode): Migrated from isValidWeakHandle,
        and beefed this up a bit.

        * collector/handles/HandleHeap.h:
        (JSC::HandleHeap::globalData): Added accessor, used by some new set functions.

        * collector/handles/Local.h: Moved hash traits to the bottom of the file,
        since this file is about the Local class, not the traits.

        (JSC::::Local): Updated for removal of invalidate().

        (JSC::::operator): Deployed "using" to avoid a lot of this->
        template funny business.

        (JSC::::setWithSlotCheck): Renamed from internalSet, more specific now.

        * interpreter/RegisterFile.h:
        (JSC::RegisterFile::RegisterFile): Updated to use null constructor.

        * jit/JITStubs.cpp:
        (JSC::JITThunks::hostFunctionStub):

        * runtime/JSPropertyNameIterator.h:
        (JSC::Structure::setEnumerationCache):
        * runtime/Structure.h: Removed clearEnumerationCache
        because it was an unused holdover from when the enumeration cache was
        not a handle.

        * runtime/WeakGCMap.h:
        (JSC::WeakGCMap::set): Finish initializing our handle before putting it
        in the table. This seemed more logical, and at one point was required
        to avoid triggering an ASSERT.

        * runtime/WeakGCPtr.h: Inherit from Handle instead of rolling our own
        handle-like behavior, to avoid duplication.

        (JSC::WeakGCPtr::WeakGCPtr):
        (JSC::WeakGCPtr::~WeakGCPtr):
        (JSC::WeakGCPtr::get):
        (JSC::WeakGCPtr::clear):
        (JSC::WeakGCPtr::set):
        (JSC::WeakGCPtr::setWithWriteBarrier): Removed duplicate code and
        standardized on Handle idioms.
2011-04-07  Geoffrey Garen  <ggaren@apple.com>

        Reviewed by Maciej Stachowiak.

        Some Handle<T> cleanup
        https://bugs.webkit.org/show_bug.cgi?id=58109

        * JSRun.h:
        * JSValueWrapper.h: #include a file that was missing before, but was
        harmlessly so until now.
2011-04-07  Geoffrey Garen  <ggaren@apple.com>

        Reviewed by Maciej Stachowiak.

        Some Handle<T> cleanup
        https://bugs.webkit.org/show_bug.cgi?id=58109

        * bindings/js/ScriptValue.h:
        (WebCore::ScriptValue::ScriptValue): Updated for new null constructor.
        (WebCore::ScriptValue::hasNoValue): Updated for removal of isEmpty().
2011-04-07  Geoffrey Garen  <ggaren@apple.com>

        Some Handle<T> cleanup
        https://bugs.webkit.org/show_bug.cgi?id=58109

        * WebProcess/Plugins/Netscape/NPJSObject.cpp:
        (WebKit::NPJSObject::NPJSObject): Updated for new null constructor.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@83259 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 8f74be2d
2011-04-07 Geoffrey Garen <ggaren@apple.com>
Reviewed by Maciej Stachowiak.
Some Handle<T> cleanup
https://bugs.webkit.org/show_bug.cgi?id=58109
* bytecode/SamplingTool.h: Sorted alphabetically because that's the
WebKit style. Added a Global.h #include that was previously missing
but harmless.
* collector/handles/Global.h:
(JSC::Global::Global): Added a null constructor. No need for a special
tag, and the tag is incompatible with some data structures.
(JSC::Global::isHashTableDeletedValue):
(JSC::Global::~Global):
(JSC::Global::set):
(JSC::Global::operator=):
(JSC::Global::clear):
(JSC::Global::hashTableDeletedValue): Reordered constructors to be near
each other.
(JSC::Global::setWithWriteBarrier): Renamed internalSet to
setWithWriteBarrier for clarity, and funneled more code into using set
and setWithWriteBarrier to reduce duplication.
* collector/handles/Handle.h:
(JSC::HandleBase::operator!):
(JSC::HandleBase::HandleBase): Removed isEmpty(), since we already have
boolean and ! operators.
(JSC::HandleBase::slot):
(JSC::HandleBase::setSlot):
(JSC::Handle::Handle): Added general support for null Handles. This was
previously outlawed by ASSERTs, but our code has grown to support and
rely on null Handles.
* collector/handles/HandleHeap.cpp:
(JSC::HandleHeap::markWeakHandles):
(JSC::HandleHeap::finalizeWeakHandles):
(JSC::HandleHeap::isValidWeakNode): Migrated from isValidWeakHandle,
and beefed this up a bit.
* collector/handles/HandleHeap.h:
(JSC::HandleHeap::globalData): Added accessor, used by some new set functions.
* collector/handles/Local.h: Moved hash traits to the bottom of the file,
since this file is about the Local class, not the traits.
(JSC::::Local): Updated for removal of invalidate().
(JSC::::operator): Deployed "using" to avoid a lot of this->
template funny business.
(JSC::::setWithSlotCheck): Renamed from internalSet, more specific now.
* interpreter/RegisterFile.h:
(JSC::RegisterFile::RegisterFile): Updated to use null constructor.
* jit/JITStubs.cpp:
(JSC::JITThunks::hostFunctionStub):
* runtime/JSPropertyNameIterator.h:
(JSC::Structure::setEnumerationCache):
* runtime/Structure.h: Removed clearEnumerationCache
because it was an unused holdover from when the enumeration cache was
not a handle.
* runtime/WeakGCMap.h:
(JSC::WeakGCMap::set): Finish initializing our handle before putting it
in the table. This seemed more logical, and at one point was required
to avoid triggering an ASSERT.
* runtime/WeakGCPtr.h: Inherit from Handle instead of rolling our own
handle-like behavior, to avoid duplication.
(JSC::WeakGCPtr::WeakGCPtr):
(JSC::WeakGCPtr::~WeakGCPtr):
(JSC::WeakGCPtr::get):
(JSC::WeakGCPtr::clear):
(JSC::WeakGCPtr::set):
(JSC::WeakGCPtr::setWithWriteBarrier): Removed duplicate code and
standardized on Handle idioms.
2011-04-07 Adam Barth <abarth@webkit.org>
Reviewed by Martin Robinson.
......
......@@ -29,13 +29,13 @@
#ifndef SamplingTool_h
#define SamplingTool_h
#include "Global.h"
#include "Nodes.h"
#include "Opcode.h"
#include <wtf/Assertions.h>
#include <wtf/HashMap.h>
#include <wtf/Threading.h>
#include "Nodes.h"
#include "Opcode.h"
namespace JSC {
class ScriptExecutable;
......
......@@ -33,114 +33,108 @@
namespace JSC {
/*
A Global is a persistent handle whose lifetime is not limited to any given
scope. Use Globals for data members and global variables.
*/
// A Global is a persistent handle whose lifetime is not limited to any given scope.
template <typename T> class Global : public Handle<T> {
using Handle<T>::slot;
using Handle<T>::setSlot;
public:
typedef typename Handle<T>::ExternalType ExternalType;
Global(JSGlobalData& globalData, ExternalType ptr = ExternalType())
Global()
: Handle<T>()
{
}
Global(JSGlobalData& globalData, ExternalType value = ExternalType())
: Handle<T>(globalData.allocateGlobalHandle())
{
internalSet(ptr);
set(value);
}
Global(JSGlobalData& globalData, Handle<T> handle)
: Handle<T>(globalData.allocateGlobalHandle())
{
internalSet(handle.get());
set(handle.get());
}
Global(const Global& other)
: Handle<T>()
{
if (!other.slot())
return;
setSlot(HandleHeap::heapFor(other.slot())->allocate());
set(other.get());
}
template <typename U> Global(const Global<U>& other)
: Handle<T>()
{
if (!other.slot())
return;
setSlot(HandleHeap::heapFor(other.slot())->allocate());
set(other.get());
}
enum EmptyValueTag { EmptyValue };
Global(EmptyValueTag)
: Handle<T>(0, HandleBase::DontNullCheckSlot)
enum HashTableDeletedValueTag { HashTableDeletedValue };
bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); }
Global(HashTableDeletedValueTag)
: Handle<T>(hashTableDeletedValue())
{
}
~Global()
{
HandleSlot slot = this->slot();
if (slot)
HandleHeap::heapFor(slot)->deallocate(slot);
clear();
}
void set(JSGlobalData& globalData, ExternalType value)
{
if (!value) {
clear();
return;
}
if (!this->slot())
this->setSlot(globalData.allocateGlobalHandle());
internalSet(value);
if (!slot())
setSlot(globalData.allocateGlobalHandle());
set(value);
}
template <typename U> Global& operator=(const Global<U>& handle)
template <typename U> Global& operator=(const Global<U>& other)
{
if (handle.slot()) {
if (!this->slot())
this->setSlot(HandleHeap::heapFor(handle.slot())->allocate());
internalSet(handle.get());
} else
if (!other.slot()) {
clear();
return *this;
}
set(*HandleHeap::heapFor(other.slot())->globalData(), other.get());
return *this;
}
Global& operator=(const Global& handle)
Global& operator=(const Global& other)
{
if (handle.slot()) {
if (!this->slot())
this->setSlot(HandleHeap::heapFor(handle.slot())->allocate());
internalSet(handle.get());
} else
if (!other.slot()) {
clear();
return *this;
}
set(*HandleHeap::heapFor(other.slot())->globalData(), other.get());
return *this;
}
void clear()
{
if (this->slot())
internalSet(ExternalType());
if (!slot())
return;
HandleHeap::heapFor(slot())->deallocate(slot());
setSlot(0);
}
enum HashTableDeletedValueType { HashTableDeletedValue };
const static intptr_t HashTableDeletedValueTag = 0x1;
Global(HashTableDeletedValueType)
: Handle<T>(reinterpret_cast<HandleSlot>(HashTableDeletedValueTag))
{
}
bool isHashTableDeletedValue() const { return slot() == reinterpret_cast<HandleSlot>(HashTableDeletedValueTag); }
private:
static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); }
template <typename U> Global(const Global<U>& other)
: Handle<T>(other.slot() ? HandleHeap::heapFor(other.slot())->allocate() : 0, Handle<T>::DontNullCheckSlot)
void set(ExternalType externalType)
{
if (other.slot())
internalSet(other.get());
ASSERT(slot());
JSValue value = HandleTypes<T>::toJSValue(externalType);
HandleHeap::heapFor(slot())->writeBarrier(slot(), value);
*slot() = value;
}
Global(const Global& other)
: Handle<T>(other.slot() ? HandleHeap::heapFor(other.slot())->allocate() : 0, Handle<T>::DontNullCheckSlot)
{
if (other.slot())
internalSet(other.get());
}
protected:
void internalSet(ExternalType value)
{
JSValue newValue(HandleTypes<T>::toJSValue(value));
HandleSlot slot = this->slot();
ASSERT(slot);
HandleHeap::heapFor(slot)->writeBarrier(slot, newValue);
*slot = newValue;
}
using Handle<T>::slot;
};
}
......@@ -149,7 +143,7 @@ namespace WTF {
template<typename P> struct HashTraits<JSC::Global<P> > : GenericHashTraits<JSC::Global<P> > {
static const bool emptyValueIsZero = true;
static JSC::Global<P> emptyValue() { return JSC::Global<P>(JSC::Global<P>::EmptyValue); }
static JSC::Global<P> emptyValue() { return JSC::Global<P>(); }
static void constructDeletedValue(JSC::Global<P>& slot) { new (&slot) JSC::Global<P>(JSC::Global<P>::HashTableDeletedValue); }
static bool isDeletedValue(const JSC::Global<P>& value) { return value.isHashTableDeletedValue(); }
};
......
......@@ -49,39 +49,21 @@ class HandleBase {
friend class HandleHeap;
public:
bool operator!() const { return isEmpty(); }
bool operator!() const { return !m_slot || !*m_slot; }
// This conversion operator allows implicit conversion to bool but not to other integer types.
typedef JSValue (HandleBase::*UnspecifiedBoolType);
operator UnspecifiedBoolType*() const { return (m_slot && *m_slot) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
bool isEmpty() const { return !m_slot || !*m_slot; }
protected:
HandleBase(HandleSlot slot)
: m_slot(slot)
{
ASSERT(slot);
}
enum DontNullCheckSlotTag { DontNullCheckSlot };
HandleBase(HandleSlot slot, DontNullCheckSlotTag)
: m_slot(slot)
{
}
HandleSlot slot() const { return m_slot; }
void invalidate()
{
// It is unsafe to use a handle after invalidating it.
m_slot = 0;
}
// needed by Global<>::operator= and Global<>::set if it's an empty handle
void setSlot(HandleSlot slot)
{
ASSERT(!m_slot);
ASSERT(slot);
m_slot = slot;
}
......@@ -165,15 +147,10 @@ public:
ExternalType get() const { return HandleTypes<T>::getFromSlot(this->slot()); }
protected:
Handle(HandleSlot slot)
Handle(HandleSlot slot = 0)
: HandleBase(slot)
{
}
Handle(HandleSlot slot, HandleBase::DontNullCheckSlotTag)
: HandleBase(slot, HandleBase::DontNullCheckSlot)
{
}
private:
friend class HandleHeap;
......
......@@ -30,26 +30,6 @@
namespace JSC {
#if !ASSERT_DISABLED
static inline bool isValidWeakHandle(HandleSlot handle)
{
JSValue value = *handle;
if (!value || !value.isCell())
return false;
JSCell* cell = value.asCell();
if (!cell || !cell->structure())
return false;
#if ENABLE(JSC_ZOMBIES)
if (cell->isZombie())
return false;
#endif
return true;
}
#endif
WeakHandleOwner::~WeakHandleOwner()
{
}
......@@ -97,7 +77,7 @@ void HandleHeap::markWeakHandles(HeapRootMarker& heapRootMarker)
Node* end = m_weakList.end();
for (Node* node = m_weakList.begin(); node != end; node = node->next()) {
ASSERT(isValidWeakHandle(node->slot()));
ASSERT(isValidWeakNode(node));
JSCell* cell = node->slot()->asCell();
if (Heap::isMarked(cell))
continue;
......@@ -120,7 +100,7 @@ void HandleHeap::finalizeWeakHandles()
for (Node* node = m_weakList.begin(); node != end; node = m_nextToFinalize) {
m_nextToFinalize = node->next();
ASSERT(isValidWeakHandle(node->slot()));
ASSERT(isValidWeakNode(node));
JSCell* cell = node->slot()->asCell();
if (Heap::isMarked(cell))
continue;
......@@ -173,4 +153,27 @@ unsigned HandleHeap::protectedGlobalObjectCount()
return count;
}
#if !ASSERT_DISABLED
bool HandleHeap::isValidWeakNode(Node* node)
{
if (!node->isWeak())
return false;
JSValue value = *node->slot();
if (!value || !value.isCell())
return false;
JSCell* cell = value.asCell();
if (!cell || !cell->structure())
return false;
#if ENABLE(JSC_ZOMBIES)
if (cell->isZombie())
return false;
#endif
return true;
}
#endif
} // namespace JSC
......@@ -51,6 +51,8 @@ public:
static HandleHeap* heapFor(HandleSlot);
HandleHeap(JSGlobalData*);
JSGlobalData* globalData();
HandleSlot allocate();
void deallocate(HandleSlot);
......@@ -105,6 +107,10 @@ private:
static Node* toNode(HandleSlot);
void grow();
#if !ASSERT_DISABLED
bool isValidWeakNode(Node*);
#endif
JSGlobalData* m_globalData;
BlockStack<Node> m_blockStack;
......@@ -121,6 +127,11 @@ inline HandleHeap* HandleHeap::heapFor(HandleSlot handle)
return toNode(handle)->handleHeap();
}
inline JSGlobalData* HandleHeap::globalData()
{
return m_globalData;
}
inline HandleSlot HandleHeap::toHandle(Node* node)
{
return reinterpret_cast<HandleSlot>(node);
......
......@@ -35,65 +35,43 @@
outside of any LocalScope.
*/
namespace JSC {
template <typename T> class Local;
}
namespace WTF {
template<typename T> struct VectorTraits<JSC::Local<T> > {
static const bool needsDestruction = false;
static const bool needsInitialization = true;
static const bool canInitializeWithMemset = false;
static const bool canMoveWithMemcpy = true;
static const bool canCopyWithMemcpy = false;
static const bool canFillWithMemset = false;
static const bool canCompareWithMemcmp = true;
};
}
namespace JSC {
template <typename T> class Local : public Handle<T> {
friend class LocalScope;
using Handle<T>::slot;
public:
typedef typename Handle<T>::ExternalType ExternalType;
Local(JSGlobalData&, ExternalType = ExternalType());
Local(JSGlobalData&, Handle<T>);
Local(const Local<T>&); // Adopting constructor. Used to return a Local to a calling function.
Local& operator=(ExternalType);
Local& operator=(Handle<T>);
using Handle<T>::slot;
private:
Local(HandleSlot, ExternalType); // Used by LocalScope::release() to move a Local to a containing scope.
void internalSet(ExternalType value)
{
JSValue newValue(HandleTypes<T>::toJSValue(value));
HandleSlot slot = this->slot();
*slot = newValue;
}
void set(ExternalType);
};
template <typename T> inline Local<T>::Local(JSGlobalData& globalData, ExternalType value)
: Handle<T>(globalData.allocateLocalHandle())
{
internalSet(value);
set(value);
}
template <typename T> inline Local<T>::Local(JSGlobalData& globalData, Handle<T> handle)
template <typename T> inline Local<T>::Local(JSGlobalData& globalData, Handle<T> other)
: Handle<T>(globalData.allocateLocalHandle())
{
internalSet(handle.get());
set(other.get());
}
template <typename T> inline Local<T>::Local(const Local<T>& o)
: Handle<T>(o.slot())
template <typename T> inline Local<T>::Local(const Local<T>& other)
: Handle<T>(other.slot())
{
const_cast<Local<T>&>(o).invalidate(); // Prevent accidental sharing.
const_cast<Local<T>&>(other).setSlot(0); // Prevent accidental sharing.
}
template <typename T> inline Local<T>::Local(HandleSlot slot, ExternalType value)
......@@ -103,16 +81,23 @@ template <typename T> inline Local<T>::Local(HandleSlot slot, ExternalType value
template <typename T> inline Local<T>& Local<T>::operator=(ExternalType value)
{
internalSet(value);
set(value);
return *this;
}
template <typename T> inline Local<T>& Local<T>::operator=(Handle<T> handle)
template <typename T> inline Local<T>& Local<T>::operator=(Handle<T> other)
{
internalSet(handle.get());
set(other.get());
return *this;
}
template <typename T> inline void Local<T>::set(ExternalType value)
{
ASSERT(slot());
*slot() = value;
}
template <typename T, unsigned inlineCapacity = 0> class LocalStack {
typedef typename Handle<T>::ExternalType ExternalType;
public:
......@@ -154,4 +139,18 @@ private:
}
namespace WTF {
template<typename T> struct VectorTraits<JSC::Local<T> > {
static const bool needsDestruction = false;
static const bool needsInitialization = true;
static const bool canInitializeWithMemset = false;
static const bool canMoveWithMemcpy = true;
static const bool canCopyWithMemcpy = false;
static const bool canFillWithMemset = false;
static const bool canCompareWithMemcmp = true;
};
}
#endif
......@@ -167,7 +167,7 @@ namespace JSC {
, m_start(0)
, m_end(0)
, m_max(0)
, m_globalObject(globalData, &m_globalObjectOwner, this)
, m_globalObject(globalData, 0, &m_globalObjectOwner, this)
{
ASSERT(maxGlobals && isPageAligned(maxGlobals));
ASSERT(capacity && isPageAligned(capacity));
......
......@@ -3495,7 +3495,7 @@ MacroAssemblerCodePtr JITThunks::ctiStub(JSGlobalData* globalData, ThunkGenerato
NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function)
{
std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Global<NativeExecutable>(Global<NativeExecutable>::EmptyValue));
std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Global<NativeExecutable>());
if (entry.second)
entry.first->second.set(*globalData, NativeExecutable::create(*globalData, JIT::compileCTINativeCall(globalData, m_executablePool, function), function, ctiNativeConstruct(), callHostFunctionAsConstructor));
return entry.first->second.get();
......@@ -3503,7 +3503,7 @@ NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFu
NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator)
{
std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Global<NativeExecutable>(Global<NativeExecutable>::EmptyValue));
std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Global<NativeExecutable>());
if (entry.second) {
MacroAssemblerCodePtr code = globalData->canUseJIT() ? generator(globalData, m_executablePool.get()) : MacroAssemblerCodePtr();
entry.first->second.set(*globalData, NativeExecutable::create(*globalData, code, function, ctiNativeConstruct(), callHostFunctionAsConstructor));
......
......@@ -93,12 +93,7 @@ namespace JSC {
inline void Structure::setEnumerationCache(JSGlobalData& globalData, JSPropertyNameIterator* enumerationCache)
{
ASSERT(!isDictionary());
m_enumerationCache.set(globalData, enumerationCache, 0);
}
inline void Structure::clearEnumerationCache()
{