2011-05-13 Oliver Hunt <oliver@apple.com>
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 May 2011 23:07:09 +0000 (23:07 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 May 2011 23:07:09 +0000 (23:07 +0000)
        Reviewed by Geoffrey Garen.

        Make GC validation more aggressive
        https://bugs.webkit.org/show_bug.cgi?id=60802

        This patch makes the checks performed under GC_VALIDATION
        much more aggressive, and adds the checks to more places
        in order to allow us to catch GC bugs much closer to the
        point of failure.

        * JavaScriptCore.exp:
        * JavaScriptCore.xcodeproj/project.pbxproj:
        * debugger/DebuggerActivation.cpp:
        (JSC::DebuggerActivation::visitChildren):
        * heap/MarkedBlock.cpp:
        (JSC::MarkedBlock::MarkedBlock):
        * heap/MarkedSpace.cpp:
        * runtime/Arguments.cpp:
        (JSC::Arguments::visitChildren):
        * runtime/Executable.cpp:
        (JSC::EvalExecutable::visitChildren):
        (JSC::ProgramExecutable::visitChildren):
        (JSC::FunctionExecutable::visitChildren):
        * runtime/Executable.h:
        * runtime/GetterSetter.cpp:
        (JSC::GetterSetter::visitChildren):
        * runtime/GetterSetter.h:
        * runtime/JSAPIValueWrapper.h:
        (JSC::JSAPIValueWrapper::createStructure):
        (JSC::JSAPIValueWrapper::JSAPIValueWrapper):
        * runtime/JSActivation.cpp:
        (JSC::JSActivation::visitChildren):
        * runtime/JSArray.cpp:
        (JSC::JSArray::visitChildren):
        * runtime/JSCell.cpp:
        (JSC::slowValidateCell):
        * runtime/JSCell.h:
        (JSC::JSCell::JSCell::unvalidatedStructure):
        (JSC::JSCell::JSCell::JSCell):
        * runtime/JSFunction.cpp:
        (JSC::JSFunction::visitChildren):
        * runtime/JSGlobalObject.cpp:
        (JSC::JSGlobalObject::visitChildren):
        (JSC::slowValidateCell):
        * runtime/JSONObject.h:
        * runtime/JSObject.cpp:
        (JSC::JSObject::visitChildren):
        * runtime/JSPropertyNameIterator.cpp:
        (JSC::JSPropertyNameIterator::visitChildren):
        * runtime/JSPropertyNameIterator.h:
        * runtime/JSStaticScopeObject.cpp:
        (JSC::JSStaticScopeObject::visitChildren):
        * runtime/JSString.h:
        (JSC::RopeBuilder::JSString):
        * runtime/JSWrapperObject.cpp:
        (JSC::JSWrapperObject::visitChildren):
        * runtime/NativeErrorConstructor.cpp:
        (JSC::NativeErrorConstructor::visitChildren):
        * runtime/PropertyMapHashTable.h:
        (JSC::PropertyMapEntry::PropertyMapEntry):
        * runtime/RegExpObject.cpp:
        (JSC::RegExpObject::visitChildren):
        * runtime/ScopeChain.cpp:
        (JSC::ScopeChainNode::visitChildren):
        * runtime/ScopeChain.h:
        (JSC::ScopeChainNode::ScopeChainNode):
        * runtime/Structure.cpp:
        (JSC::Structure::Structure):
        (JSC::Structure::addPropertyTransition):
        (JSC::Structure::visitChildren):
        * runtime/Structure.h:
        (JSC::JSCell::classInfo):
        * runtime/StructureChain.cpp:
        (JSC::StructureChain::visitChildren):
        * runtime/StructureChain.h:
        * runtime/WriteBarrier.h:
        (JSC::validateCell):
        (JSC::JSCell):
        (JSC::JSGlobalObject):
        (JSC::WriteBarrierBase::set):
        (JSC::WriteBarrierBase::setMayBeNull):
        (JSC::WriteBarrierBase::setEarlyValue):
        (JSC::WriteBarrierBase::get):
        (JSC::WriteBarrierBase::operator*):
        (JSC::WriteBarrierBase::operator->):
        (JSC::WriteBarrierBase::unvalidatedGet):
        (JSC::WriteBarrier::WriteBarrier):
        * wtf/Assertions.h:
2011-05-13  Oliver Hunt  <oliver@apple.com>

        Reviewed by Geoffrey Garen.

        Make GC validation more aggressive
        https://bugs.webkit.org/show_bug.cgi?id=60802

        This makes GC_VALIDATION much more aggressive in webcore,
        adding logic to every visitChildren method to ensure that
        the structure still has correct flags.

        Additionally every function generated for the dom bindings
        makes use of the new GC_VALIDATION object assertions to further
        ensure that the object appears to be sensible.

        * bindings/js/JSAttrCustom.cpp:
        (WebCore::JSAttr::visitChildren):
        * bindings/js/JSAudioContextCustom.cpp:
        (WebCore::JSAudioContext::visitChildren):
        * bindings/js/JSCSSRuleCustom.cpp:
        (WebCore::JSCSSRule::visitChildren):
        * bindings/js/JSCSSStyleDeclarationCustom.cpp:
        (WebCore::JSCSSStyleDeclaration::visitChildren):
        * bindings/js/JSCanvasRenderingContextCustom.cpp:
        (WebCore::JSCanvasRenderingContext::visitChildren):
        * bindings/js/JSDOMGlobalObject.cpp:
        (WebCore::JSDOMGlobalObject::visitChildren):
        (WebCore::JSDOMGlobalObject::setInjectedScript):
        * bindings/js/JSDOMWindowCustom.cpp:
        (WebCore::JSDOMWindow::visitChildren):
        * bindings/js/JSDOMWindowShell.cpp:
        (WebCore::JSDOMWindowShell::visitChildren):
        * bindings/js/JSEventListener.cpp:
        (WebCore::JSEventListener::JSEventListener):
        * bindings/js/JSEventListener.h:
        (WebCore::JSEventListener::jsFunction):
        * bindings/js/JSJavaScriptAudioNodeCustom.cpp:
        (WebCore::JSJavaScriptAudioNode::visitChildren):
        * bindings/js/JSMessageChannelCustom.cpp:
        (WebCore::JSMessageChannel::visitChildren):
        * bindings/js/JSMessagePortCustom.cpp:
        (WebCore::JSMessagePort::visitChildren):
        * bindings/js/JSNamedNodeMapCustom.cpp:
        (WebCore::JSNamedNodeMap::visitChildren):
        * bindings/js/JSNodeCustom.cpp:
        (WebCore::JSNode::visitChildren):
        * bindings/js/JSNodeFilterCustom.cpp:
        (WebCore::JSNodeFilter::visitChildren):
        * bindings/js/JSNodeIteratorCustom.cpp:
        (WebCore::JSNodeIterator::visitChildren):
        * bindings/js/JSSVGElementInstanceCustom.cpp:
        (WebCore::JSSVGElementInstance::visitChildren):
        * bindings/js/JSSharedWorkerCustom.cpp:
        (WebCore::JSSharedWorker::visitChildren):
        * bindings/js/JSStyleSheetCustom.cpp:
        (WebCore::JSStyleSheet::visitChildren):
        * bindings/js/JSTreeWalkerCustom.cpp:
        (WebCore::JSTreeWalker::visitChildren):
        * bindings/js/JSWebGLRenderingContextCustom.cpp:
        (WebCore::JSWebGLRenderingContext::visitChildren):
        * bindings/js/JSWorkerContextCustom.cpp:
        (WebCore::JSWorkerContext::visitChildren):
        * bindings/js/JSXMLHttpRequestCustom.cpp:
        (WebCore::JSXMLHttpRequest::visitChildren):
        * bindings/js/JSXPathResultCustom.cpp:
        (WebCore::JSXPathResult::visitChildren):
        * bindings/scripts/CodeGeneratorJS.pm:
2011-05-13  Oliver Hunt  <oliver@apple.com>

        Reviewed by Geoffrey Garen.

        Make GC validation more aggressive
        https://bugs.webkit.org/show_bug.cgi?id=60802

        Add GC_VALIDATION calls to all the JSNPObject methods.

        * WebProcess/Plugins/Netscape/JSNPObject.cpp:
        (WebKit::JSNPObject::invalidate):
        (WebKit::JSNPObject::callMethod):
        (WebKit::JSNPObject::callObject):
        (WebKit::JSNPObject::callConstructor):
        (WebKit::JSNPObject::getCallData):
        (WebKit::JSNPObject::getConstructData):
        (WebKit::JSNPObject::getOwnPropertySlot):
        (WebKit::JSNPObject::getOwnPropertyDescriptor):
        (WebKit::JSNPObject::put):
        (WebKit::JSNPObject::getOwnPropertyNames):
        (WebKit::JSNPObject::propertyGetter):
        (WebKit::JSNPObject::methodGetter):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@86469 268f45cc-cd09-0410-ab3c-d52691b4dbfc

66 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.exp
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/debugger/DebuggerActivation.cpp
Source/JavaScriptCore/heap/MarkedBlock.cpp
Source/JavaScriptCore/heap/MarkedSpace.cpp
Source/JavaScriptCore/runtime/Arguments.cpp
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/GetterSetter.cpp
Source/JavaScriptCore/runtime/GetterSetter.h
Source/JavaScriptCore/runtime/JSAPIValueWrapper.h
Source/JavaScriptCore/runtime/JSActivation.cpp
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSCell.cpp
Source/JavaScriptCore/runtime/JSCell.h
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSONObject.h
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
Source/JavaScriptCore/runtime/JSString.h
Source/JavaScriptCore/runtime/JSWrapperObject.cpp
Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
Source/JavaScriptCore/runtime/PropertyMapHashTable.h
Source/JavaScriptCore/runtime/RegExpObject.cpp
Source/JavaScriptCore/runtime/ScopeChain.cpp
Source/JavaScriptCore/runtime/ScopeChain.h
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/Structure.h
Source/JavaScriptCore/runtime/StructureChain.cpp
Source/JavaScriptCore/runtime/StructureChain.h
Source/JavaScriptCore/runtime/WriteBarrier.h
Source/JavaScriptCore/wtf/Assertions.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSAttrCustom.cpp
Source/WebCore/bindings/js/JSAudioContextCustom.cpp
Source/WebCore/bindings/js/JSCSSRuleCustom.cpp
Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp
Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
Source/WebCore/bindings/js/JSDOMWindowShell.cpp
Source/WebCore/bindings/js/JSEventListener.cpp
Source/WebCore/bindings/js/JSEventListener.h
Source/WebCore/bindings/js/JSJavaScriptAudioNodeCustom.cpp
Source/WebCore/bindings/js/JSMessageChannelCustom.cpp
Source/WebCore/bindings/js/JSMessagePortCustom.cpp
Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp
Source/WebCore/bindings/js/JSNodeCustom.cpp
Source/WebCore/bindings/js/JSNodeFilterCustom.cpp
Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp
Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
Source/WebCore/bindings/js/JSSharedWorkerCustom.cpp
Source/WebCore/bindings/js/JSStyleSheetCustom.cpp
Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp
Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp
Source/WebCore/bindings/js/JSWorkerContextCustom.cpp
Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
Source/WebCore/bindings/js/JSXPathResultCustom.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp

index 40c8a31..46af79a 100644 (file)
@@ -1,3 +1,94 @@
+2011-05-13  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Geoffrey Garen.
+
+        Make GC validation more aggressive
+        https://bugs.webkit.org/show_bug.cgi?id=60802
+
+        This patch makes the checks performed under GC_VALIDATION
+        much more aggressive, and adds the checks to more places
+        in order to allow us to catch GC bugs much closer to the
+        point of failure.
+
+        * JavaScriptCore.exp:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * debugger/DebuggerActivation.cpp:
+        (JSC::DebuggerActivation::visitChildren):
+        * heap/MarkedBlock.cpp:
+        (JSC::MarkedBlock::MarkedBlock):
+        * heap/MarkedSpace.cpp:
+        * runtime/Arguments.cpp:
+        (JSC::Arguments::visitChildren):
+        * runtime/Executable.cpp:
+        (JSC::EvalExecutable::visitChildren):
+        (JSC::ProgramExecutable::visitChildren):
+        (JSC::FunctionExecutable::visitChildren):
+        * runtime/Executable.h:
+        * runtime/GetterSetter.cpp:
+        (JSC::GetterSetter::visitChildren):
+        * runtime/GetterSetter.h:
+        * runtime/JSAPIValueWrapper.h:
+        (JSC::JSAPIValueWrapper::createStructure):
+        (JSC::JSAPIValueWrapper::JSAPIValueWrapper):
+        * runtime/JSActivation.cpp:
+        (JSC::JSActivation::visitChildren):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::visitChildren):
+        * runtime/JSCell.cpp:
+        (JSC::slowValidateCell):
+        * runtime/JSCell.h:
+        (JSC::JSCell::JSCell::unvalidatedStructure):
+        (JSC::JSCell::JSCell::JSCell):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::visitChildren):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::visitChildren):
+        (JSC::slowValidateCell):
+        * runtime/JSONObject.h:
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::visitChildren):
+        * runtime/JSPropertyNameIterator.cpp:
+        (JSC::JSPropertyNameIterator::visitChildren):
+        * runtime/JSPropertyNameIterator.h:
+        * runtime/JSStaticScopeObject.cpp:
+        (JSC::JSStaticScopeObject::visitChildren):
+        * runtime/JSString.h:
+        (JSC::RopeBuilder::JSString):
+        * runtime/JSWrapperObject.cpp:
+        (JSC::JSWrapperObject::visitChildren):
+        * runtime/NativeErrorConstructor.cpp:
+        (JSC::NativeErrorConstructor::visitChildren):
+        * runtime/PropertyMapHashTable.h:
+        (JSC::PropertyMapEntry::PropertyMapEntry):
+        * runtime/RegExpObject.cpp:
+        (JSC::RegExpObject::visitChildren):
+        * runtime/ScopeChain.cpp:
+        (JSC::ScopeChainNode::visitChildren):
+        * runtime/ScopeChain.h:
+        (JSC::ScopeChainNode::ScopeChainNode):
+        * runtime/Structure.cpp:
+        (JSC::Structure::Structure):
+        (JSC::Structure::addPropertyTransition):
+        (JSC::Structure::visitChildren):
+        * runtime/Structure.h:
+        (JSC::JSCell::classInfo):
+        * runtime/StructureChain.cpp:
+        (JSC::StructureChain::visitChildren):
+        * runtime/StructureChain.h:
+        * runtime/WriteBarrier.h:
+        (JSC::validateCell):
+        (JSC::JSCell):
+        (JSC::JSGlobalObject):
+        (JSC::WriteBarrierBase::set):
+        (JSC::WriteBarrierBase::setMayBeNull):
+        (JSC::WriteBarrierBase::setEarlyValue):
+        (JSC::WriteBarrierBase::get):
+        (JSC::WriteBarrierBase::operator*):
+        (JSC::WriteBarrierBase::operator->):
+        (JSC::WriteBarrierBase::unvalidatedGet):
+        (JSC::WriteBarrier::WriteBarrier):
+        * wtf/Assertions.h:
+
 2011-05-01  Holger Hans Peter Freyther  <holger@moiji-mobile.com>
 
         Reviewed by Steve Block.
index ca7507e..12b3158 100644 (file)
@@ -167,6 +167,7 @@ __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
 __ZN3JSC14MachineThreads16addCurrentThreadEv
 __ZN3JSC14SamplingThread4stopEv
 __ZN3JSC14SamplingThread5startEj
+__ZN3JSC14ScopeChainNode6s_infoE
 __ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
 __ZN3JSC14TimeoutChecker5resetEv
 __ZN3JSC14throwTypeErrorEPNS_9ExecStateE
@@ -183,6 +184,8 @@ __ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3JSC16createRangeErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC16slowValidateCellEPNS_14JSGlobalObjectE
+__ZN3JSC16slowValidateCellEPNS_6JSCellE
 __ZN3JSC16throwSyntaxErrorEPNS_9ExecStateE
 __ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb
 __ZN3JSC17PropertyNameArray3addEPN3WTF10StringImplE
index a77e885..22ce6a6 100644 (file)
@@ -317,6 +317,8 @@ EXPORTS
     ?signal@ThreadCondition@WTF@@QAEXXZ
     ?size@Heap@JSC@@QBEIXZ
     ?slowAppend@MarkedArgumentBuffer@JSC@@AAEXVJSValue@2@@Z
+    ?slowValidateCell@JSC@@YAXPAVJSCell@1@@Z
+    ?slowValidateCell@JSC@@YAXPAVJSGlobalObject@1@@Z
     ?startProfiling@Profiler@JSC@@QAEXPAVExecState@2@ABVUString@2@@Z
     ?startSampling@JSGlobalData@JSC@@QAEXXZ
     ?stopProfiling@Profiler@JSC@@QAE?AV?$PassRefPtr@VProfile@JSC@@@WTF@@PAVExecState@2@ABVUString@2@@Z
index ffc7cb2..ab114a4 100644 (file)
                        isa = PBXProject;
                        attributes = {
                                BuildIndependentTargetsInParallel = YES;
+                               LastUpgradeCheck = 0420;
                        };
                        buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */;
                        compatibilityVersion = "Xcode 3.1";
index 47dcd7f..4385542 100644 (file)
@@ -40,6 +40,9 @@ DebuggerActivation::DebuggerActivation(JSGlobalData& globalData, JSObject* activ
 
 void DebuggerActivation::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     JSObject::visitChildren(visitor);
 
     if (m_activation)
index a10a778..f1f630c 100644 (file)
@@ -60,7 +60,7 @@ MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, JSGlobalData*
 
     Structure* dummyMarkableCellStructure = globalData->dummyMarkableCellStructure.get();
     for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell)
-        new (&atoms()[i]) JSCell(*globalData, dummyMarkableCellStructure);
+        new (&atoms()[i]) JSCell(*globalData, dummyMarkableCellStructure, JSCell::CreatingEarlyCell);
 }
 
 void MarkedBlock::sweep()
index d9a1e42..77f6e52 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "MarkedSpace.h"
 
+#include "JSGlobalObject.h"
 #include "JSCell.h"
 #include "JSGlobalData.h"
 #include "JSLock.h"
index 838fd09..ec6cc8f 100644 (file)
@@ -45,6 +45,9 @@ Arguments::~Arguments()
 
 void Arguments::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     JSObject::visitChildren(visitor);
 
     if (d->registerArray)
index cf51ac2..aefaedc 100644 (file)
@@ -145,6 +145,9 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
 
 void EvalExecutable::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     ScriptExecutable::visitChildren(visitor);
     if (m_evalCodeBlock)
         m_evalCodeBlock->visitAggregate(visitor);
@@ -237,6 +240,9 @@ static bool tryDFGCompile(JSGlobalData* globalData, CodeBlock* codeBlock, JITCod
 
 void ProgramExecutable::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     ScriptExecutable::visitChildren(visitor);
     if (m_programCodeBlock)
         m_programCodeBlock->visitAggregate(visitor);
@@ -349,6 +355,9 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope
 
 void FunctionExecutable::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     ScriptExecutable::visitChildren(visitor);
     if (m_codeBlockForCall)
         m_codeBlockForCall->visitAggregate(visitor);
index 70b12a5..692e347 100644 (file)
@@ -66,10 +66,11 @@ namespace JSC {
         }
 
         static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); }
+        
+        static const ClassInfo s_info;
 
     protected:
         static const unsigned StructureFlags = 0;
-        static const ClassInfo s_info;
         int m_numParametersForCall;
         int m_numParametersForConstruct;
 
@@ -117,7 +118,9 @@ namespace JSC {
         NativeFunction function() { return m_function; }
 
         static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(LeafType, StructureFlags), AnonymousSlotCount, &s_info); }
-
+        
+        static const ClassInfo s_info;
+    
     private:
 #if ENABLE(JIT)
         NativeExecutable(JSGlobalData& globalData, JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor)
@@ -143,7 +146,6 @@ namespace JSC {
         // Probably should be a NativeConstructor, but this will currently require rewriting the JIT
         // trampoline. It may be easier to make NativeFunction be passed 'this' as a part of the ArgList.
         NativeFunction m_constructor;
-        static const ClassInfo s_info;
     };
 
     class ScriptExecutable : public ExecutableBase {
@@ -236,10 +238,10 @@ namespace JSC {
         {
             return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info);
         }
-
+        
+        static const ClassInfo s_info;
     private:
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
-        static const ClassInfo s_info;
         EvalExecutable(ExecState*, const SourceCode&, bool);
 
         JSObject* compileInternal(ExecState*, ScopeChainNode*);
@@ -286,10 +288,11 @@ namespace JSC {
         {
             return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info);
         }
+        
+        static const ClassInfo s_info;
 
     private:
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
-        static const ClassInfo s_info;
         ProgramExecutable(ExecState*, const SourceCode&);
 
         JSObject* compileInternal(ExecState*, ScopeChainNode*);
@@ -382,6 +385,8 @@ namespace JSC {
         {
             return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info);
         }
+        
+        static const ClassInfo s_info;
 
     private:
         FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine);
@@ -391,7 +396,6 @@ namespace JSC {
         JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*);
         
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
-        static const ClassInfo s_info;
         unsigned m_numCapturedVariables : 31;
         bool m_forceUsesArguments : 1;
 
index be9eb48..04193ea 100644 (file)
@@ -32,6 +32,8 @@ const ClassInfo GetterSetter::s_info = { "GetterSetter", 0, 0, 0 };
 
 void GetterSetter::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     JSCell::visitChildren(visitor);
 
     if (m_getter)
index ceb2af3..aca7e3c 100644 (file)
@@ -52,9 +52,11 @@ namespace JSC {
         {
             return Structure::create(globalData, prototype, TypeInfo(GetterSetterType, OverridesVisitChildren), AnonymousSlotCount, &s_info);
         }
+        
+        static const ClassInfo s_info;
+
     private:
         virtual bool isGetterSetter() const;
-        static const ClassInfo s_info;
 
         WriteBarrier<JSObject> m_getter;
         WriteBarrier<JSObject> m_setter;  
index 4dca9f4..38cbb56 100644 (file)
@@ -40,8 +40,9 @@ namespace JSC {
         {
             return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesVisitChildren | OverridesGetPropertyNames), AnonymousSlotCount, &s_info);
         }
-
         
+        static const ClassInfo s_info;
+
     private:
         JSAPIValueWrapper(ExecState* exec, JSValue value)
             : JSCell(exec->globalData(), exec->globalData().apiWrapperStructure.get())
@@ -49,7 +50,6 @@ namespace JSC {
             m_value.set(exec->globalData(), this, value);
             ASSERT(!value.isCell());
         }
-        static const ClassInfo s_info;
 
         WriteBarrier<Unknown> m_value;
     };
index 81e18c1..09d985a 100644 (file)
@@ -60,6 +60,9 @@ JSActivation::~JSActivation()
 
 void JSActivation::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     // No need to mark our registers if they're still in the RegisterFile.
index b0ae89a..f04f243 100644 (file)
@@ -859,6 +859,9 @@ void JSArray::unshiftCount(ExecState* exec, int count)
 
 void JSArray::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     visitChildrenDirect(visitor);
 }
 
index 93331b3..0606cd4 100644 (file)
@@ -221,4 +221,9 @@ bool isZombie(const JSCell* cell)
 #endif
 }
 
+void slowValidateCell(JSCell* cell)
+{
+    ASSERT_GC_OBJECT_LOOKS_VALID(cell);
+}
+
 } // namespace JSC
index 08aab62..7d2c5df 100644 (file)
@@ -71,6 +71,7 @@ namespace JSC {
         friend class ScopeChainNode;
         friend class Structure;
         friend class StructureChain;
+        enum CreatingEarlyCellTag { CreatingEarlyCell };
 
     protected:
         enum VPtrStealingHackType { VPtrStealingHack };
@@ -78,6 +79,7 @@ namespace JSC {
     private:
         explicit JSCell(VPtrStealingHackType) { }
         JSCell(JSGlobalData&, Structure*);
+        JSCell(JSGlobalData&, Structure*, CreatingEarlyCellTag);
         virtual ~JSCell();
         static const ClassInfo s_dummyCellInfo;
 
@@ -148,6 +150,10 @@ namespace JSC {
             return OBJECT_OFFSETOF(JSCell, m_structure);
         }
 
+#if ENABLE(GC_VALIDATION)
+        Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); }
+#endif
+        
     protected:
         static const unsigned AnonymousSlotCount = 0;
 
@@ -162,6 +168,15 @@ namespace JSC {
     inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure)
         : m_structure(globalData, this, structure)
     {
+        ASSERT(m_structure);
+    }
+
+    inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure, CreatingEarlyCellTag)
+    {
+#if ENABLE(GC_VALIDATION)
+        if (structure)
+#endif
+            m_structure.setEarlyValue(globalData, this, structure);
         // Very first set of allocations won't have a real structure.
         ASSERT(m_structure || !globalData.dummyMarkableCellStructure);
     }
index 4e9cd37..e4680cc 100644 (file)
@@ -135,6 +135,9 @@ const UString JSFunction::calculatedDisplayName(ExecState* exec)
 
 void JSFunction::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     visitor.append(&m_scopeChain);
index 9c77146..391a655 100644 (file)
@@ -310,6 +310,9 @@ void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype)
 
 void JSGlobalObject::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     JSVariableObject::visitChildren(visitor);
 
     visitIfNeeded(visitor, &m_globalScopeChain);
@@ -459,4 +462,11 @@ DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSG
     }
 }
 
+void slowValidateCell(JSGlobalObject* globalObject)
+{
+    if (!globalObject->isGlobalObject())
+        CRASH();
+    ASSERT_GC_OBJECT_INHERITS(globalObject, &JSGlobalObject::s_info);
+}
+
 } // namespace JSC
index c87c641..b773320 100644 (file)
@@ -40,6 +40,8 @@ namespace JSC {
         {
             return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
+        
+        static const ClassInfo s_info;
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
@@ -48,7 +50,6 @@ namespace JSC {
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
-        static const ClassInfo s_info;
     };
 
     UString JSONStringify(ExecState* exec, JSValue value, unsigned indent);
index ae29a7b..d6db612 100644 (file)
@@ -70,6 +70,7 @@ static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* class
 
 void JSObject::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
 #ifndef NDEBUG
     bool wasCheckingForDefaultMarkViolation = visitor.m_isCheckingForDefaultMarkViolation;
     visitor.m_isCheckingForDefaultMarkViolation = false;
index e6010de..e05bb3f 100644 (file)
@@ -97,6 +97,8 @@ JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
 
 void JSPropertyNameIterator::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     visitor.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues);
     if (m_cachedPrototypeChain)
         visitor.append(&m_cachedPrototypeChain);
index 1a57350..ff129f0 100644 (file)
@@ -75,9 +75,10 @@ namespace JSC {
 
         void setCachedPrototypeChain(JSGlobalData& globalData, StructureChain* cachedPrototypeChain) { m_cachedPrototypeChain.set(globalData, this, cachedPrototypeChain); }
         StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
+        
+        static const ClassInfo s_info;
 
     private:
-        static const ClassInfo s_info;
         JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
 
         WriteBarrier<Structure> m_cachedStructure;
index 88e4538..5206510 100644 (file)
@@ -34,6 +34,9 @@ ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
 
 void JSStaticScopeObject::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     JSVariableObject::visitChildren(visitor);
     visitor.append(&m_registerStore);
 }
index 0ac64bd..668064f 100644 (file)
@@ -330,6 +330,8 @@ namespace JSC {
         {
             return Structure::create(globalData, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, &s_info);
         }
+        
+        static const ClassInfo s_info;
 
     private:
         JSString(VPtrStealingHackType) 
@@ -337,7 +339,6 @@ namespace JSC {
             , m_fiberCount(0)
         {
         }
-        static const ClassInfo s_info;
 
         void resolveRope(ExecState*) const;
         void resolveRopeSlowCase(ExecState*, UChar*) const;
index 2bf4a90..8d6387e 100644 (file)
@@ -28,6 +28,9 @@ ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
 
 void JSWrapperObject::visitChildren(SlotVisitor& visitor) 
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     JSObject::visitChildren(visitor);
     if (m_internalValue)
         visitor.append(&m_internalValue);
index 5c4f009..2a7a7f5 100644 (file)
@@ -48,6 +48,9 @@ NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, JSGlobalObject*
 
 void NativeErrorConstructor::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     InternalFunction::visitChildren(visitor);
     if (m_errorStructure)
         visitor.append(&m_errorStructure);
index 6ea593a..28a9364 100644 (file)
@@ -80,7 +80,7 @@ struct PropertyMapEntry {
         : key(key)
         , offset(offset)
         , attributes(attributes)
-        , specificValue(globalData, owner, specificValue)
+        , specificValue(globalData, owner, specificValue, WriteBarrier<JSCell>::MayBeNull)
     {
     }
 };
index ffc0112..c023349 100644 (file)
@@ -74,6 +74,9 @@ RegExpObject::~RegExpObject()
 
 void RegExpObject::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
     if (UNLIKELY(!d->lastIndex.get().isInt32()))
         visitor.append(&d->lastIndex);
index ed60bb1..df4da41 100644 (file)
@@ -69,6 +69,9 @@ int ScopeChainNode::localDepth()
 
 void ScopeChainNode::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     if (next)
         visitor.append(&next);
     visitor.append(&object);
index 8481bdc..7fbb888 100644 (file)
@@ -39,7 +39,7 @@ namespace JSC {
         ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
             : JSCell(*globalData, globalData->scopeChainNodeStructure.get())
             , globalData(globalData)
-            , next(*globalData, this, next)
+            , next(*globalData, this, next, WriteBarrier<ScopeChainNode>::MayBeNull)
             , object(*globalData, this, object)
             , globalObject(*globalData, this, globalObject)
             , globalThis(*globalData, this, globalThis)
@@ -68,9 +68,10 @@ namespace JSC {
         
         static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); }
         virtual void visitChildren(SlotVisitor&);
+        static JS_EXPORTDATA const ClassInfo s_info;
+
     private:
         static const unsigned StructureFlags = OverridesVisitChildren;
-        static const ClassInfo s_info;
     };
 
     inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
index 6ba2777..a3fda54 100644 (file)
@@ -206,7 +206,7 @@ Structure::Structure(JSGlobalData& globalData, JSValue prototype, const TypeInfo
 const ClassInfo Structure::s_info = { "Structure", 0, 0, 0 };
 
 Structure::Structure(JSGlobalData& globalData)
-    : JSCell(globalData, this)
+    : JSCell(globalData, this, CreatingEarlyCell)
     , m_typeInfo(CompoundType, OverridesVisitChildren)
     , m_prototype(globalData, this, jsNull())
     , m_classInfo(&s_info)
@@ -358,11 +358,11 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure*
 
     Structure* transition = create(globalData, structure);
 
-    transition->m_cachedPrototypeChain.set(globalData, transition, structure->m_cachedPrototypeChain.get());
+    transition->m_cachedPrototypeChain.setMayBeNull(globalData, transition, structure->m_cachedPrototypeChain.get());
     transition->m_previous.set(globalData, transition, structure);
     transition->m_nameInPrevious = propertyName.impl();
     transition->m_attributesInPrevious = attributes;
-    transition->m_specificValueInPrevious.set(globalData, transition, specificValue);
+    transition->m_specificValueInPrevious.setMayBeNull(globalData, transition, specificValue);
 
     if (structure->m_propertyTable) {
         if (structure->m_isPinnedPropertyTable)
@@ -779,6 +779,8 @@ void Structure::getPropertyNames(JSGlobalData& globalData, PropertyNameArray& pr
 
 void Structure::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     JSCell::visitChildren(visitor);
     if (m_prototype)
         visitor.append(&m_prototype);
index a2857e1..1fa7f69 100644 (file)
@@ -160,6 +160,8 @@ namespace JSC {
             ASSERT(!globalData.structureStructure);
             return new (&globalData) Structure(globalData);
         }
+        
+        static JS_EXPORTDATA const ClassInfo s_info;
 
     private:
         Structure(JSGlobalData&, JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount, const ClassInfo*);
@@ -172,8 +174,6 @@ namespace JSC {
             return new (&globalData) Structure(globalData, structure);
         }
         
-        static JS_EXPORTDATA const ClassInfo s_info;
-
         typedef enum { 
             NoneDictionaryKind = 0,
             CachedDictionaryKind = 1,
@@ -278,7 +278,11 @@ namespace JSC {
 
     inline const ClassInfo* JSCell::classInfo() const
     {
+#if ENABLE(GC_VALIDATION)
+        return m_structure.unvalidatedGet()->classInfo();
+#else
         return m_structure->classInfo();
+#endif
     }
 
     inline Structure* JSCell::createDummyStructure(JSGlobalData& globalData)
index 062951d..89a0ec0 100644 (file)
@@ -55,6 +55,8 @@ StructureChain::~StructureChain()
 
 void StructureChain::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     size_t i = 0;
     while (m_vector[i])
         visitor.append(&m_vector[i++]);
index 50323fd..4fc1212 100644 (file)
@@ -47,12 +47,13 @@ namespace JSC {
         void visitChildren(SlotVisitor&);
 
         static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesVisitChildren), 0, &s_info); }
+        
+        static ClassInfo s_info;
 
     private:
         StructureChain(JSGlobalData&, Structure*, Structure* head);
         ~StructureChain();
         OwnArrayPtr<WriteBarrier<Structure> > m_vector;
-        static ClassInfo s_info;
     };
 
 } // namespace JSC
index 6355d9d..00bad9b 100644 (file)
 
 #include "HandleTypes.h"
 #include "Heap.h"
+#include "TypeTraits.h"
 
 namespace JSC {
 
 class JSCell;
 class JSGlobalData;
+class JSGlobalObject;
 
 template<class T> class WriteBarrierBase;
 template<> class WriteBarrierBase<JSValue>;
 
+void slowValidateCell(JSCell*);
+void slowValidateCell(JSGlobalObject*);
+    
+#if ENABLE(GC_VALIDATION)
+template<class T> static inline void validateCell(T cell)
+{
+    ASSERT_GC_OBJECT_INHERITS(cell, &WTF::RemovePointer<T>::Type::s_info);
+}
+
+template<> static inline void validateCell<JSCell*>(JSCell* cell)
+{
+    slowValidateCell(cell);
+}
+
+template<> static inline void validateCell<JSGlobalObject*>(JSGlobalObject* globalObject)
+{
+    slowValidateCell(globalObject);
+}
+#else
+template<class T> static inline void validateCell(T)
+{
+}
+#endif
+
 // We have a separate base class with no constructors for use in Unions.
 template <typename T> class WriteBarrierBase {
 public:
-    void set(JSGlobalData&, const JSCell* owner, T* value)
+    void set(JSGlobalData& globalData, const JSCell* owner, T* value)
+    {
+        ASSERT(value);
+        validateCell(value);
+        setEarlyValue(globalData, owner, value);
+    }
+
+    void setMayBeNull(JSGlobalData& globalData, const JSCell* owner, T* value)
+    {
+        if (value)
+            validateCell(value);
+        setEarlyValue(globalData, owner, value);
+    }
+
+    // Should only be used by JSCell during early initialisation
+    // when some basic types aren't yet completely instantiated
+    void setEarlyValue(JSGlobalData&, const JSCell* owner, T* value)
     {
         this->m_cell = reinterpret_cast<JSCell*>(value);
         Heap::writeBarrier(owner, this->m_cell);
@@ -52,6 +94,8 @@ public:
     
     T* get() const
     {
+        if (m_cell)
+            validateCell(m_cell);
         return reinterpret_cast<T*>(m_cell);
     }
 
@@ -61,12 +105,14 @@ public:
 #if ENABLE(JSC_ZOMBIES)
         ASSERT(!isZombie(m_cell));
 #endif
+        validateCell<T>(static_cast<T*>(m_cell));
         return static_cast<T*>(m_cell);
     }
 
     T* operator->() const
     {
         ASSERT(m_cell);
+        validateCell(static_cast<T*>(m_cell));
         return static_cast<T*>(m_cell);
     }
 
@@ -87,6 +133,10 @@ public:
 #endif
     }
 
+#if ENABLE(GC_VALIDATION)
+    T* unvalidatedGet() const { return reinterpret_cast<T*>(m_cell); }
+#endif
+
 private:
     JSCell* m_cell;
 };
@@ -151,6 +201,12 @@ public:
     {
         this->set(globalData, owner, value);
     }
+
+    enum MayBeNullTag { MayBeNull };
+    WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value, MayBeNullTag)
+    {
+        this->setMayBeNull(globalData, owner, value);
+    }
 };
 
 template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
index 862158b..136d5bc 100644 (file)
@@ -379,4 +379,23 @@ while (0)
 #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
 #endif
 
+#if ENABLE(GC_VALIDATION)
+#define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { \
+    if (!(cell))\
+        CRASH();\
+    if (cell->unvalidatedStructure()->unvalidatedStructure() != cell->unvalidatedStructure()->unvalidatedStructure()->unvalidatedStructure())\
+        CRASH();\
+} while (0)
+
+#define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do {\
+    ASSERT_GC_OBJECT_LOOKS_VALID(object); \
+    if (!object->inherits(classInfo)) \
+        CRASH();\
+} while (0)
+
+#else
+#define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { (void)cell; } while (0)
+#define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do { (void)object; (void)classInfo; } while (0)
+#endif
+
 #endif /* WTF_Assertions_h */
index 9b6b736..c882140 100644 (file)
@@ -1,3 +1,71 @@
+2011-05-13  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Geoffrey Garen.
+
+        Make GC validation more aggressive
+        https://bugs.webkit.org/show_bug.cgi?id=60802
+
+        This makes GC_VALIDATION much more aggressive in webcore,
+        adding logic to every visitChildren method to ensure that
+        the structure still has correct flags.
+
+        Additionally every function generated for the dom bindings
+        makes use of the new GC_VALIDATION object assertions to further
+        ensure that the object appears to be sensible.
+
+        * bindings/js/JSAttrCustom.cpp:
+        (WebCore::JSAttr::visitChildren):
+        * bindings/js/JSAudioContextCustom.cpp:
+        (WebCore::JSAudioContext::visitChildren):
+        * bindings/js/JSCSSRuleCustom.cpp:
+        (WebCore::JSCSSRule::visitChildren):
+        * bindings/js/JSCSSStyleDeclarationCustom.cpp:
+        (WebCore::JSCSSStyleDeclaration::visitChildren):
+        * bindings/js/JSCanvasRenderingContextCustom.cpp:
+        (WebCore::JSCanvasRenderingContext::visitChildren):
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::JSDOMGlobalObject::visitChildren):
+        (WebCore::JSDOMGlobalObject::setInjectedScript):
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::JSDOMWindow::visitChildren):
+        * bindings/js/JSDOMWindowShell.cpp:
+        (WebCore::JSDOMWindowShell::visitChildren):
+        * bindings/js/JSEventListener.cpp:
+        (WebCore::JSEventListener::JSEventListener):
+        * bindings/js/JSEventListener.h:
+        (WebCore::JSEventListener::jsFunction):
+        * bindings/js/JSJavaScriptAudioNodeCustom.cpp:
+        (WebCore::JSJavaScriptAudioNode::visitChildren):
+        * bindings/js/JSMessageChannelCustom.cpp:
+        (WebCore::JSMessageChannel::visitChildren):
+        * bindings/js/JSMessagePortCustom.cpp:
+        (WebCore::JSMessagePort::visitChildren):
+        * bindings/js/JSNamedNodeMapCustom.cpp:
+        (WebCore::JSNamedNodeMap::visitChildren):
+        * bindings/js/JSNodeCustom.cpp:
+        (WebCore::JSNode::visitChildren):
+        * bindings/js/JSNodeFilterCustom.cpp:
+        (WebCore::JSNodeFilter::visitChildren):
+        * bindings/js/JSNodeIteratorCustom.cpp:
+        (WebCore::JSNodeIterator::visitChildren):
+        * bindings/js/JSSVGElementInstanceCustom.cpp:
+        (WebCore::JSSVGElementInstance::visitChildren):
+        * bindings/js/JSSharedWorkerCustom.cpp:
+        (WebCore::JSSharedWorker::visitChildren):
+        * bindings/js/JSStyleSheetCustom.cpp:
+        (WebCore::JSStyleSheet::visitChildren):
+        * bindings/js/JSTreeWalkerCustom.cpp:
+        (WebCore::JSTreeWalker::visitChildren):
+        * bindings/js/JSWebGLRenderingContextCustom.cpp:
+        (WebCore::JSWebGLRenderingContext::visitChildren):
+        * bindings/js/JSWorkerContextCustom.cpp:
+        (WebCore::JSWorkerContext::visitChildren):
+        * bindings/js/JSXMLHttpRequestCustom.cpp:
+        (WebCore::JSXMLHttpRequest::visitChildren):
+        * bindings/js/JSXPathResultCustom.cpp:
+        (WebCore::JSXPathResult::visitChildren):
+        * bindings/scripts/CodeGeneratorJS.pm:
+
 2011-05-13  Mikhail Naganov  <mnaganov@chromium.org>
 
         Web Inspector: Unreviewed image glyph position fix in CSS after r85588.
index 1cd3359..449a5ce 100644 (file)
@@ -41,6 +41,9 @@ using namespace HTMLNames;
 
 void JSAttr::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     Element* element = impl()->ownerElement();
index 83a0c39..2bc200f 100644 (file)
@@ -41,6 +41,9 @@ namespace WebCore {
 
 void JSAudioContext::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
     m_impl->visitJSEventListeners(visitor);
 }
index 40e4121..155ba6e 100644 (file)
@@ -50,6 +50,9 @@ namespace WebCore {
 
 void JSCSSRule::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
     visitor.addOpaqueRoot(root(impl()));
 }
index 84b59db..072033e 100644 (file)
@@ -46,6 +46,9 @@ namespace WebCore {
 
 void JSCSSStyleDeclaration::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
     visitor.addOpaqueRoot(root(impl()));
 }
index 53506e5..ad646a0 100644 (file)
@@ -41,6 +41,9 @@ namespace WebCore {
 
 void JSCanvasRenderingContext::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     visitor.addOpaqueRoot(root(impl()->canvas()));
index 3280a62..4dafa68 100644 (file)
@@ -52,6 +52,9 @@ JSDOMGlobalObject::JSDOMGlobalObject(JSGlobalData& globalData, Structure* struct
 
 void JSDOMGlobalObject::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     JSDOMStructureMap::iterator end = structures().end();
@@ -78,7 +81,7 @@ Event* JSDOMGlobalObject::currentEvent() const
 
 void JSDOMGlobalObject::setInjectedScript(JSObject* injectedScript)
 {
-    m_injectedScript.set(globalData(), this, injectedScript);
+    m_injectedScript.setMayBeNull(globalData(), this, injectedScript);
 }
 
 JSObject* JSDOMGlobalObject::injectedScript() const
index fcbca6a..aa7b038 100644 (file)
@@ -74,6 +74,9 @@ namespace WebCore {
 
 void JSDOMWindow::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     impl()->visitJSEventListeners(visitor);
index a986144..bf98583 100644 (file)
@@ -75,6 +75,9 @@ void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow)
 
 void JSDOMWindowShell::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
     if (m_window)
         visitor.append(&m_window);
index 5a7d725..b62145c 100644 (file)
@@ -40,7 +40,7 @@ JSEventListener::JSEventListener(JSObject* function, JSObject* wrapper, bool isA
     , m_isolatedWorld(isolatedWorld)
 {
     if (wrapper)
-        m_jsFunction.set(*m_isolatedWorld->globalData(), wrapper, function);
+        m_jsFunction.setMayBeNull(*m_isolatedWorld->globalData(), wrapper, function);
     else
         ASSERT(!function);
 
index 1590168..7197f7b 100644 (file)
@@ -75,7 +75,7 @@ namespace WebCore {
     inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext* scriptExecutionContext) const
     {
         if (!m_jsFunction)
-            m_jsFunction.set(*scriptExecutionContext->globalData(), m_wrapper.get(), initializeJSFunction(scriptExecutionContext));
+            m_jsFunction.setMayBeNull(*scriptExecutionContext->globalData(), m_wrapper.get(), initializeJSFunction(scriptExecutionContext));
 
         // Verify that we have a valid wrapper protecting our function from
         // garbage collection.
index 656925d..ebc23b3 100644 (file)
@@ -36,6 +36,9 @@ namespace WebCore {
 
 void JSJavaScriptAudioNode::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
     static_cast<JavaScriptAudioNode*>(impl())->visitJSEventListeners(visitor);
 }
index 6e8aa1a..34f5931 100644 (file)
@@ -35,6 +35,9 @@ namespace WebCore {
     
 void JSMessageChannel::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     if (MessagePort* port = m_impl->port1())
index 1bea4f7..d348e10 100644 (file)
@@ -43,6 +43,9 @@ namespace WebCore {
 
 void JSMessagePort::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     // If we have a locally entangled port, we can directly mark it as reachable. Ports that are remotely entangled are marked in-use by markActiveObjectsForContext().
index 1a36e33..47f56a2 100644 (file)
@@ -48,6 +48,9 @@ JSValue JSNamedNodeMap::nameGetter(ExecState* exec, JSValue slotBase, const Iden
 
 void JSNamedNodeMap::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     // We need to keep the wrapper for our underlying NamedNodeMap's element
index 43f4f66..51e3bb8 100644 (file)
@@ -194,6 +194,9 @@ ScopeChainNode* JSNode::pushEventHandlerScope(ExecState*, ScopeChainNode* node)
 
 void JSNode::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     Node* node = m_impl.get();
index 1fcf487..c151c54 100644 (file)
@@ -38,6 +38,9 @@ namespace WebCore {
 
 void JSNodeFilter::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
     visitor.addOpaqueRoot(impl());
 }
index 682e913..02d108d 100644 (file)
@@ -31,6 +31,9 @@ namespace WebCore {
 
 void JSNodeIterator::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     if (NodeFilter* filter = m_impl->filter())
index b3beeb5..41a84f6 100644 (file)
@@ -35,6 +35,9 @@ namespace WebCore {
 
 void JSSVGElementInstance::visitChildren(JSC::SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & JSC::OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
     visitor.addOpaqueRoot(root(impl()->correspondingElement()));
 }
index 3023bb2..d2bbf6c 100644 (file)
@@ -45,6 +45,9 @@ namespace WebCore {
 
 void JSSharedWorker::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     if (MessagePort* port = impl()->port())
index 40b7197..21e00b1 100644 (file)
@@ -37,6 +37,9 @@ namespace WebCore {
 
 void JSStyleSheet::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
     visitor.addOpaqueRoot(root(impl()));
 }
index 69f6c3b..dff3469 100644 (file)
@@ -31,6 +31,9 @@ namespace WebCore {
     
 void JSTreeWalker::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     if (NodeFilter* filter = m_impl->filter())
index 5efc61a..d4a702f 100644 (file)
@@ -194,6 +194,9 @@ static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, WebGLExten
 
 void JSWebGLRenderingContext::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
     visitor.addOpaqueRoot(impl());
 }
index ce30d44..058acf7 100644 (file)
@@ -55,6 +55,9 @@ namespace WebCore {
 
 void JSWorkerContext::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     if (WorkerLocation* location = impl()->optionalLocation())
index 900c79a..2575756 100644 (file)
@@ -56,6 +56,9 @@ namespace WebCore {
 
 void JSXMLHttpRequest::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     if (XMLHttpRequestUpload* upload = m_impl->optionalUpload())
index 3b83ee7..ad9005f 100644 (file)
@@ -38,6 +38,9 @@ namespace WebCore {
 
 void JSXPathResult::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
     Base::visitChildren(visitor);
 
     const XPath::Value& xpathValue = impl()->value();
index 92ae5f9..74c8d38 100644 (file)
@@ -907,10 +907,12 @@ sub GenerateHeader
     if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n");
         push(@headerContent, "{\n");
+        push(@headerContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
         push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
         push(@headerContent, "}\n\n");
         push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)\n");
         push(@headerContent, "{\n");
+        push(@headerContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
         push(@headerContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
         push(@headerContent, "}\n\n");
     }
@@ -1452,6 +1454,9 @@ sub GenerateImplementation
     if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) {
         push(@implContent, "void ${className}::visitChildren(SlotVisitor& visitor)\n");
         push(@implContent, "{\n");
+        push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
+        push(@implContent, "    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);\n");
+        push(@implContent, "    ASSERT(structure()->typeInfo().overridesVisitChildren());\n");
         push(@implContent, "    Base::visitChildren(visitor);\n");
         push(@implContent, "    impl()->visitJSEventListeners(visitor);\n");
         push(@implContent, "}\n\n");
@@ -1484,10 +1489,12 @@ sub GenerateImplementation
         if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
             push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
             push(@implContent, "{\n");
+            push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
             push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
             push(@implContent, "}\n\n");
             push(@implContent, "bool ${className}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
             push(@implContent, "{\n");
+            push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
             push(@implContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
             push(@implContent, "}\n\n");
         }
@@ -1496,6 +1503,7 @@ sub GenerateImplementation
                 && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
             push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)\n");
             push(@implContent, "{\n");
+            push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
             push(@implContent, "    if (propertyName < static_cast<$implClassName*>(impl())->length()) {\n");
             if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
                 push(@implContent, "        slot.setValue(getByIndex(exec, propertyName));\n");
@@ -1647,6 +1655,7 @@ sub GenerateImplementation
             if (!$dataNode->extendedAttributes->{"CustomPutFunction"}) {
                 push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\n");
                 push(@implContent, "{\n");
+                push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
                 if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
                     push(@implContent, "    bool ok;\n");
                     push(@implContent, "    unsigned index = propertyName.toUInt32(ok);\n");
@@ -1671,6 +1680,7 @@ sub GenerateImplementation
             if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
                 push(@implContent, "void ${className}::put(ExecState* exec, unsigned propertyName, JSValue value)\n");
                 push(@implContent, "{\n");
+                push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
                 push(@implContent, "    indexSetter(exec, propertyName, value);\n");
                 push(@implContent, "    return;\n");
                 push(@implContent, "}\n\n");
@@ -1825,6 +1835,7 @@ sub GenerateImplementation
     if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {
         push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n");
         push(@implContent, "{\n");
+        push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
         if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
             push(@implContent, "    for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n");
             push(@implContent, "        propertyNames.add(Identifier::from(exec, i));\n");
@@ -1875,6 +1886,7 @@ sub GenerateImplementation
                 push(@implContent, "        return throwVMTypeError(exec);\n");
                 push(@implContent, "    $className* castedThis = static_cast<$className*>(asObject(thisValue));\n");
             }
+            push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(castedThis, &${className}::s_info);\n");
 
             if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
                 !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
@@ -2106,6 +2118,7 @@ sub GenerateImplementation
         push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, JSValue slotBase, unsigned index)\n");
         push(@implContent, "{\n");
         push(@implContent, "    ${className}* thisObj = static_cast<$className*>(asObject(slotBase));\n");
+        push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObj, &s_info);\n");
         if (IndexGetterReturnsStrings($implClassName)) {
             $implIncludes{"KURL.h"} = 1;
             push(@implContent, "    return jsStringOrNull(exec, thisObj->impl()->item(index));\n");
@@ -2122,6 +2135,7 @@ sub GenerateImplementation
     if ($dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
         push(@implContent, "\nJSValue ${className}::getByIndex(ExecState*, unsigned index)\n");
         push(@implContent, "{\n");
+        push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\n");
         push(@implContent, "    return jsNumber(static_cast<$implClassName*>(impl())->item(index));\n");
         push(@implContent, "}\n\n");
         if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") {
index 8fb3523..3a294fe 100644 (file)
@@ -1,3 +1,26 @@
+2011-05-13  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Geoffrey Garen.
+
+        Make GC validation more aggressive
+        https://bugs.webkit.org/show_bug.cgi?id=60802
+
+        Add GC_VALIDATION calls to all the JSNPObject methods.
+
+        * WebProcess/Plugins/Netscape/JSNPObject.cpp:
+        (WebKit::JSNPObject::invalidate):
+        (WebKit::JSNPObject::callMethod):
+        (WebKit::JSNPObject::callObject):
+        (WebKit::JSNPObject::callConstructor):
+        (WebKit::JSNPObject::getCallData):
+        (WebKit::JSNPObject::getConstructData):
+        (WebKit::JSNPObject::getOwnPropertySlot):
+        (WebKit::JSNPObject::getOwnPropertyDescriptor):
+        (WebKit::JSNPObject::put):
+        (WebKit::JSNPObject::getOwnPropertyNames):
+        (WebKit::JSNPObject::propertyGetter):
+        (WebKit::JSNPObject::methodGetter):
+
 2011-05-13  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Sam Weinig.
index f23c83d..dd8749c 100644 (file)
@@ -72,6 +72,7 @@ JSNPObject::~JSNPObject()
 void JSNPObject::invalidate()
 {
     ASSERT(m_npObject);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
 
     releaseNPObject(m_npObject);
     m_npObject = 0;
@@ -79,6 +80,7 @@ void JSNPObject::invalidate()
 
 JSValue JSNPObject::callMethod(ExecState* exec, NPIdentifier methodName)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
     if (!m_npObject)
         return throwInvalidAccessError(exec);
 
@@ -118,6 +120,7 @@ JSValue JSNPObject::callMethod(ExecState* exec, NPIdentifier methodName)
 
 JSC::JSValue JSNPObject::callObject(JSC::ExecState* exec)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
     if (!m_npObject)
         return throwInvalidAccessError(exec);
 
@@ -157,6 +160,7 @@ JSC::JSValue JSNPObject::callObject(JSC::ExecState* exec)
 
 JSValue JSNPObject::callConstructor(ExecState* exec)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
     if (!m_npObject)
         return throwInvalidAccessError(exec);
 
@@ -200,6 +204,7 @@ static EncodedJSValue JSC_HOST_CALL callNPJSObject(ExecState* exec)
 
 JSC::CallType JSNPObject::getCallData(JSC::CallData& callData)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
     if (!m_npObject || !m_npObject->_class->invokeDefault)
         return CallTypeNone;
 
@@ -217,6 +222,7 @@ static EncodedJSValue JSC_HOST_CALL constructWithConstructor(ExecState* exec)
 
 ConstructType JSNPObject::getConstructData(ConstructData& constructData)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
     if (!m_npObject || !m_npObject->_class->construct)
         return ConstructTypeNone;
 
@@ -226,6 +232,7 @@ ConstructType JSNPObject::getConstructData(ConstructData& constructData)
 
 bool JSNPObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
     if (!m_npObject) {
         throwInvalidAccessError(exec);
         return false;
@@ -250,6 +257,7 @@ bool JSNPObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
 
 bool JSNPObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
     if (!m_npObject) {
         throwInvalidAccessError(exec);
         return false;
@@ -278,6 +286,7 @@ bool JSNPObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pro
 
 void JSNPObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
     if (!m_npObject) {
         throwInvalidAccessError(exec);
         return;
@@ -315,6 +324,7 @@ void JSNPObject::put(ExecState* exec, const Identifier& propertyName, JSValue va
 
 void JSNPObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNameArray, EnumerationMode mode)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
     if (!m_npObject) {
         throwInvalidAccessError(exec);
         return;
@@ -362,7 +372,8 @@ void JSNPObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propert
 JSValue JSNPObject::propertyGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
 {
     JSNPObject* thisObj = static_cast<JSNPObject*>(asObject(slotBase));
-
+    ASSERT_GC_OBJECT_INHERITS(thisObj, &s_info);
+    
     if (!thisObj->m_npObject)
         return throwInvalidAccessError(exec);
 
@@ -397,6 +408,7 @@ JSValue JSNPObject::propertyGetter(ExecState* exec, JSValue slotBase, const Iden
 JSValue JSNPObject::methodGetter(ExecState* exec, JSValue slotBase, const Identifier& methodName)
 {
     JSNPObject* thisObj = static_cast<JSNPObject*>(asObject(slotBase));
+    ASSERT_GC_OBJECT_INHERITS(thisObj, &s_info);
     
     if (!thisObj->m_npObject)
         return throwInvalidAccessError(exec);