Ignore:
Timestamp:
Mar 20, 2015, 11:08:29 AM (10 years ago)
Author:
[email protected]
Message:

JSCallbackObject<JSGlobalObject> should not destroy its JSCallbackObjectData before all its finalizers have been called.
<https://webkit.org/b/142846>

Reviewed by Geoffrey Garen.

Currently, JSCallbackObject<JSGlobalObject> registers weak finalizers via 2 mechanisms:

  1. JSCallbackObject<Parent>::init() registers a weak finalizer for all JSClassRef that a JSCallbackObject references.
  2. JSCallbackObject<JSGlobalObject>::create() registers a finalizer via vm.heap.addFinalizer() which destroys the JSCallbackObject.

The first finalizer is implemented as a virtual function of a JSCallbackObjectData
instance that will be destructed if the 2nd finalizer is called. Hence, if the
2nd finalizer if called first, the later invocation of the 1st finalizer will
result in a crash.

This patch fixes the issue by eliminating the finalizer registration in init().
Instead, we'll have the JSCallbackObject destructor call all the JSClassRef finalizers
if needed. This ensures that these finalizers are called before the JSCallbackObject
is destructor.

Also added assertions to a few Heap functions because JSCell::classInfo() expects
all objects that are allocated from MarkedBlock::Normal blocks to be derived from
JSDestructibleObject. These assertions will help us catch violations of this
expectation earlier.

  • API/JSCallbackObject.cpp:

(JSC::JSCallbackObjectData::finalize): Deleted.

  • API/JSCallbackObject.h:

(JSC::JSCallbackObjectData::~JSCallbackObjectData):

  • API/JSCallbackObjectFunctions.h:

(JSC::JSCallbackObject<Parent>::~JSCallbackObject):
(JSC::JSCallbackObject<Parent>::init):

  • API/tests/GlobalContextWithFinalizerTest.cpp: Added.

(finalize):
(testGlobalContextWithFinalizer):

  • API/tests/GlobalContextWithFinalizerTest.h: Added.
  • API/tests/testapi.c:

(main):

(JSC::Heap::allocateObjectOfType):
(JSC::Heap::subspaceForObjectOfType):
(JSC::Heap::allocatorForObjectOfType):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h

    r181064 r181806  
    7575
    7676template <class Parent>
     77JSCallbackObject<Parent>::~JSCallbackObject()
     78{
     79    JSObjectRef thisRef = toRef(static_cast<JSObject*>(this));
     80    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
     81        if (JSObjectFinalizeCallback finalize = jsClass->finalize)
     82            finalize(thisRef);
     83    }
     84}
     85   
     86template <class Parent>
    7787void JSCallbackObject<Parent>::finishCreation(ExecState* exec)
    7888{
     
    109119        JSObjectInitializeCallback initialize = initRoutines[i];
    110120        initialize(toRef(exec), toRef(this));
    111     }
    112 
    113     for (JSClassRef jsClassPtr = classRef(); jsClassPtr; jsClassPtr = jsClassPtr->parentClass) {
    114         if (jsClassPtr->finalize) {
    115             WeakSet::allocate(this, m_callbackObjectData.get(), classRef());
    116             break;
    117         }
    118121    }
    119122}
Note: See TracChangeset for help on using the changeset viewer.