Changeset 128813 in webkit


Ignore:
Timestamp:
Sep 17, 2012 3:16:10 PM (12 years ago)
Author:
mhahnenberg@apple.com
Message:

Delayed structure sweep can leak structures without bound
https://bugs.webkit.org/show_bug.cgi?id=96546

Reviewed by Gavin Barraclough.

This patch gets rid of the separate Structure allocator in the MarkedSpace and adds two new destructor-only
allocators. We now have separate allocators for our three types of objects: those objects with no destructors,
those objects with destructors and with immortal structures, and those objects with destructors that don't have
immortal structures. All of the objects of the third type (destructors without immortal structures) now
inherit from a new class named JSDestructibleObject (which in turn is a subclass of JSNonFinalObject), which stores
the ClassInfo for these classes at a fixed offset for safe retrieval during sweeping/destruction.

Source/JavaScriptCore:

  • API/JSCallbackConstructor.cpp: Use JSDestructibleObject for JSCallbackConstructor.

(JSC):
(JSC::JSCallbackConstructor::JSCallbackConstructor):

  • API/JSCallbackConstructor.h:

(JSCallbackConstructor):

  • API/JSCallbackObject.cpp: Inherit from JSDestructibleObject for normal JSCallbackObjects and use a finalizer for

JSCallbackObject<JSGlobalObject>, since JSGlobalObject also uses a finalizer.
(JSC):
(JSC::::create): We need to move the create function for JSCallbackObject<JSGlobalObject> out of line so we can add
the finalizer for it. We don't want to add the finalizer is something like finishCreation in case somebody decides
to subclass this. We use this same technique for many other subclasses of JSGlobalObject.
(JSC::::createStructure):

  • API/JSCallbackObject.h:

(JSCallbackObject):
(JSC):

  • API/JSClassRef.cpp: Change all the JSCallbackObject<JSNonFinalObject> to use JSDestructibleObject instead.

(OpaqueJSClass::prototype):

  • API/JSObjectRef.cpp: Ditto.

(JSObjectMake):
(JSObjectGetPrivate):
(JSObjectSetPrivate):
(JSObjectGetPrivateProperty):
(JSObjectSetPrivateProperty):
(JSObjectDeletePrivateProperty):

  • API/JSValueRef.cpp: Ditto.

(JSValueIsObjectOfClass):

  • API/JSWeakObjectMapRefPrivate.cpp: Ditto.
  • JSCTypedArrayStubs.h:

(JSC):

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • dfg/DFGSpeculativeJIT.h: Use the proper allocator type when doing inline allocation in the DFG.

(JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
(JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject):

  • heap/Heap.cpp:

(JSC):

  • heap/Heap.h: Add accessors for the various types of allocators now. Also remove the isSafeToSweepStructures function

since it's always safe to sweep Structures now.
(JSC::Heap::allocatorForObjectWithNormalDestructor):
(JSC::Heap::allocatorForObjectWithImmortalStructureDestructor):
(Heap):
(JSC::Heap::allocateWithNormalDestructor):
(JSC):
(JSC::Heap::allocateWithImmortalStructureDestructor):

  • heap/IncrementalSweeper.cpp: Remove all the logic to detect when it's safe to sweep Structures from the

IncrementalSweeper since it's always safe to sweep Structures now.
(JSC::IncrementalSweeper::IncrementalSweeper):
(JSC::IncrementalSweeper::sweepNextBlock):
(JSC::IncrementalSweeper::startSweeping):
(JSC::IncrementalSweeper::willFinishSweeping):
(JSC):

  • heap/IncrementalSweeper.h:

(IncrementalSweeper):

  • heap/MarkedAllocator.cpp: Remove the logic that was preventing us from sweeping Structures if it wasn't safe. Add

tracking of the specific destructor type of allocator.
(JSC::MarkedAllocator::tryAllocateHelper):
(JSC::MarkedAllocator::allocateBlock):

  • heap/MarkedAllocator.h:

(JSC::MarkedAllocator::destructorType):
(MarkedAllocator):
(JSC::MarkedAllocator::MarkedAllocator):
(JSC::MarkedAllocator::init):

  • heap/MarkedBlock.cpp: Add all the destructor type stuff to MarkedBlocks so that we do the right thing when sweeping.

We also use the stored destructor type to determine the right thing to do in all JSCell::classInfo() calls.
(JSC::MarkedBlock::create):
(JSC::MarkedBlock::MarkedBlock):
(JSC):
(JSC::MarkedBlock::specializedSweep):
(JSC::MarkedBlock::sweep):
(JSC::MarkedBlock::sweepHelper):

  • heap/MarkedBlock.h:

(JSC):
(JSC::MarkedBlock::allocator):
(JSC::MarkedBlock::destructorType):

  • heap/MarkedSpace.cpp: Add the new destructor allocators to MarkedSpace.

(JSC::MarkedSpace::MarkedSpace):
(JSC::MarkedSpace::resetAllocators):
(JSC::MarkedSpace::canonicalizeCellLivenessData):
(JSC::MarkedSpace::isPagedOut):
(JSC::MarkedSpace::freeBlock):

  • heap/MarkedSpace.h:

(MarkedSpace):
(JSC::MarkedSpace::immortalStructureDestructorAllocatorFor):
(JSC::MarkedSpace::normalDestructorAllocatorFor):
(JSC::MarkedSpace::allocateWithImmortalStructureDestructor):
(JSC::MarkedSpace::allocateWithNormalDestructor):
(JSC::MarkedSpace::forEachBlock):

  • heap/SlotVisitor.cpp: Add include because the symbol was needed in an inlined function.
  • jit/JIT.h: Make sure we use the correct allocator when doing inline allocations in the baseline JIT.
  • jit/JITInlineMethods.h:

(JSC::JIT::emitAllocateBasicJSObject):
(JSC::JIT::emitAllocateJSFinalObject):
(JSC::JIT::emitAllocateJSArray):

  • jsc.cpp:

(GlobalObject::create): Add finalizer here since JSGlobalObject needs to use a finalizer instead of inheriting from
JSDestructibleObject.

  • runtime/Arguments.cpp: Inherit from JSDestructibleObject.

(JSC):

  • runtime/Arguments.h:

(Arguments):
(JSC::Arguments::Arguments):

  • runtime/ErrorPrototype.cpp: Added an assert to make sure we have a trivial destructor.

(JSC):

  • runtime/Executable.h: Indicate that all of the Executable* classes have immortal Structures.

(JSC):

  • runtime/InternalFunction.cpp: Inherit from JSDestructibleObject.

(JSC):
(JSC::InternalFunction::InternalFunction):

  • runtime/InternalFunction.h:

(InternalFunction):

  • runtime/JSCell.h: Added the NEEDS_DESTRUCTOR macro to make it easier for classes to indicate that instead of being

allocated in a destructor MarkedAllocator that they will handle their destruction themselves through the
use of a finalizer.
(JSC):
(HasImmortalStructure): New template to help us determine at compile-time if a particular class
should be allocated in the immortal structure MarkedAllocator. The default value is false. In order
to be allocated in the immortal structure allocator, classes must specialize this template. Also added
a macro to make it easier for classes to specialize the template.
(JSC::allocateCell): Use the appropriate allocator depending on the destructor type.

  • runtime/JSDestructibleObject.h: Added. New class that stores the ClassInfo of any subclass so that it can be

accessed safely when the object is being destroyed.
(JSC):
(JSDestructibleObject):
(JSC::JSDestructibleObject::classInfo):
(JSC::JSDestructibleObject::JSDestructibleObject):
(JSC::JSCell::classInfo): Checks the current MarkedBlock to see where it should get the ClassInfo from so that it's always safe.

  • runtime/JSGlobalObject.cpp: JSGlobalObject now uses a finalizer instead of a destructor so that it can avoid forcing all

of its relatives in the inheritance hierarchy (e.g. JSScope) to use destructors as well.
(JSC::JSGlobalObject::reset):

  • runtime/JSGlobalObject.h:

(JSGlobalObject):
(JSC::JSGlobalObject::createRareDataIfNeeded): Since we always create a finalizer now, we don't have to worry about adding one
for the m_rareData field when it's created.
(JSC::JSGlobalObject::create):
(JSC):

  • runtime/JSGlobalThis.h: Inherit from JSDestructibleObject.

(JSGlobalThis):
(JSC::JSGlobalThis::JSGlobalThis):

  • runtime/JSPropertyNameIterator.h: Has an immortal Structure.

(JSC):

  • runtime/JSScope.cpp:

(JSC):

  • runtime/JSString.h: Has an immortal Structure.

(JSC):

  • runtime/JSWrapperObject.h: Inherit from JSDestructibleObject.

(JSWrapperObject):
(JSC::JSWrapperObject::JSWrapperObject):

  • runtime/MathObject.cpp: Cleaning up some of the inheritance stuff.

(JSC):

  • runtime/NameInstance.h: Inherit from JSDestructibleObject.

(NameInstance):

  • runtime/RegExp.h: Has immortal Structure.

(JSC):

  • runtime/RegExpObject.cpp: Inheritance cleanup.

(JSC):

  • runtime/SparseArrayValueMap.h: Has immortal Structure.

(JSC):

  • runtime/Structure.h: Has immortal Structure.

(JSC):

  • runtime/StructureChain.h: Ditto.

(JSC):

  • runtime/SymbolTable.h: Ditto.

(SharedSymbolTable):
(JSC):

Source/WebCore:

No new tests.

  • ForwardingHeaders/runtime/JSDestructableObject.h: Added.
  • bindings/js/JSDOMWrapper.h: Inherits from JSDestructibleObject.

(JSDOMWrapper):
(WebCore::JSDOMWrapper::JSDOMWrapper):

  • bindings/scripts/CodeGeneratorJS.pm: Add finalizers to anything that inherits from JSGlobalObject,

e.g. JSDOMWindow and JSWorkerContexts. For those classes we also need to use the NEEDS_DESTRUCTOR macro.
(GenerateHeader):

  • bridge/objc/objc_runtime.h: Inherit from JSDestructibleObject.

(ObjcFallbackObjectImp):

  • bridge/objc/objc_runtime.mm:

(Bindings):
(JSC::Bindings::ObjcFallbackObjectImp::ObjcFallbackObjectImp):

  • bridge/runtime_array.cpp: Use a finalizer so that JSArray isn't forced to inherit from JSDestructibleObject.

(JSC):
(JSC::RuntimeArray::destroy):

  • bridge/runtime_array.h:

(JSC::RuntimeArray::create):
(JSC):

  • bridge/runtime_object.cpp: Inherit from JSDestructibleObject.

(Bindings):
(JSC::Bindings::RuntimeObject::RuntimeObject):

  • bridge/runtime_object.h:

(RuntimeObject):

Location:
trunk/Source
Files:
2 added
60 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSCallbackConstructor.cpp

    r118616 r128813  
    3737namespace JSC {
    3838
    39 const ClassInfo JSCallbackConstructor::s_info = { "CallbackConstructor", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackConstructor) };
     39const ClassInfo JSCallbackConstructor::s_info = { "CallbackConstructor", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackConstructor) };
    4040
    4141JSCallbackConstructor::JSCallbackConstructor(JSGlobalObject* globalObject, Structure* structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback)
    42     : JSNonFinalObject(globalObject->globalData(), structure)
     42    : JSDestructibleObject(globalObject->globalData(), structure)
    4343    , m_class(jsClass)
    4444    , m_callback(callback)
  • trunk/Source/JavaScriptCore/API/JSCallbackConstructor.h

    r103243 r128813  
    2828
    2929#include "JSObjectRef.h"
    30 #include <runtime/JSObject.h>
     30#include "runtime/JSDestructibleObject.h"
    3131
    3232namespace JSC {
    3333
    34 class JSCallbackConstructor : public JSNonFinalObject {
     34class JSCallbackConstructor : public JSDestructibleObject {
    3535public:
    36     typedef JSNonFinalObject Base;
     36    typedef JSDestructibleObject Base;
    3737
    3838    static JSCallbackConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSClassRef classRef, JSObjectCallAsConstructorCallback callback)
  • trunk/Source/JavaScriptCore/API/JSCallbackObject.cpp

    r118616 r128813  
    3333namespace JSC {
    3434
    35 ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSNonFinalObject>);
     35ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSDestructibleObject>);
    3636ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSGlobalObject>);
    3737
    3838// Define the two types of JSCallbackObjects we support.
    39 template <> const ClassInfo JSCallbackObject<JSNonFinalObject>::s_info = { "CallbackObject", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackObject) };
    40 template <> const ClassInfo JSCallbackObject<JSGlobalObject>::s_info = { "CallbackGlobalObject", &JSGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackObject) };
     39template <> const ClassInfo JSCallbackObject<JSDestructibleObject>::s_info = { "CallbackObject", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackObject) };
     40template <> const ClassInfo JSCallbackObject<JSGlobalObject>::s_info = { "CallbackGlobalObject", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackObject) };
     41
     42template<>
     43JSCallbackObject<JSGlobalObject>* JSCallbackObject<JSGlobalObject>::create(JSGlobalData& globalData, JSClassRef classRef, Structure* structure)
     44{
     45    JSCallbackObject<JSGlobalObject>* callbackObject = new (NotNull, allocateCell<JSCallbackObject<JSGlobalObject> >(globalData.heap)) JSCallbackObject(globalData, classRef, structure);
     46    callbackObject->finishCreation(globalData);
     47    globalData.heap.addFinalizer(callbackObject, destroy);
     48    return callbackObject;
     49}
    4150
    4251template <>
    43 Structure* JSCallbackObject<JSNonFinalObject>::createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
     52Structure* JSCallbackObject<JSDestructibleObject>::createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
    4453{
    4554    return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info);
  • trunk/Source/JavaScriptCore/API/JSCallbackObject.h

    r128400 r128813  
    134134        return callbackObject;
    135135    }
    136     static JSCallbackObject* create(JSGlobalData& globalData, JSClassRef classRef, Structure* structure)
    137     {
    138         JSCallbackObject* callbackObject = new (NotNull, allocateCell<JSCallbackObject>(globalData.heap)) JSCallbackObject(globalData, classRef, structure);
    139         callbackObject->finishCreation(globalData);
    140         return callbackObject;
    141     }
    142 
     136    static JSCallbackObject<Parent>* create(JSGlobalData&, JSClassRef, Structure*);
    143137    void setPrivate(void* data);
    144138    void* getPrivate();
     
    218212};
    219213
     214NEEDS_DESTRUCTOR(JSCallbackObject<JSGlobalObject>, false);
     215
    220216} // namespace JSC
    221217
  • trunk/Source/JavaScriptCore/API/JSClassRef.cpp

    r127191 r128813  
    200200
    201201    // Recursive, but should be good enough for our purposes
    202     JSObject* prototype = JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData); // set jsClassData as the object's private data, so it can clear our reference on destruction
     202    JSObject* prototype = JSCallbackObject<JSDestructibleObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData); // set jsClassData as the object's private data, so it can clear our reference on destruction
    203203    if (parentClass) {
    204204        if (JSObject* parentPrototype = parentClass->prototype(exec))
  • trunk/Source/JavaScriptCore/API/JSObjectRef.cpp

    r128400 r128813  
    8484        return toRef(constructEmptyObject(exec));
    8585
    86     JSCallbackObject<JSNonFinalObject>* object = JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
     86    JSCallbackObject<JSDestructibleObject>* object = JSCallbackObject<JSDestructibleObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
    8787    if (JSObject* prototype = jsClass->prototype(exec))
    8888        object->setPrototype(exec->globalData(), prototype);
     
    342342    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
    343343        return jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
    344     if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
    345         return jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivate();
     344    if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info))
     345        return jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivate();
    346346   
    347347    return 0;
     
    356356        return true;
    357357    }
    358     if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
    359         jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivate(data);
     358    if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info)) {
     359        jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivate(data);
    360360        return true;
    361361    }
     
    373373    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
    374374        result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
    375     else if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
    376         result = jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivateProperty(name);
     375    else if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info))
     376        result = jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivateProperty(name);
    377377    return toRef(exec, result);
    378378}
     
    389389        return true;
    390390    }
    391     if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
    392         jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
     391    if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info)) {
     392        jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
    393393        return true;
    394394    }
     
    406406        return true;
    407407    }
    408     if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
    409         jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->deletePrivateProperty(name);
     408    if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info)) {
     409        jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->deletePrivateProperty(name);
    410410        return true;
    411411    }
  • trunk/Source/JavaScriptCore/API/JSValueRef.cpp

    r127958 r128813  
    132132        if (o->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
    133133            return jsCast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
    134         if (o->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
    135             return jsCast<JSCallbackObject<JSNonFinalObject>*>(o)->inherits(jsClass);
     134        if (o->inherits(&JSCallbackObject<JSDestructibleObject>::s_info))
     135            return jsCast<JSCallbackObject<JSDestructibleObject>*>(o)->inherits(jsClass);
    136136    }
    137137    return false;
  • trunk/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp

    r118483 r128813  
    5858    if (!obj)
    5959        return;
    60     ASSERT(obj->inherits(&JSCallbackObject<JSGlobalObject>::s_info) || obj->inherits(&JSCallbackObject<JSNonFinalObject>::s_info));
     60    ASSERT(obj->inherits(&JSCallbackObject<JSGlobalObject>::s_info) || obj->inherits(&JSCallbackObject<JSDestructibleObject>::s_info));
    6161    map->map().set(exec->globalData(), key, obj);
    6262}
  • trunk/Source/JavaScriptCore/ChangeLog

    r128802 r128813  
     12012-09-16  Mark Hahnenberg  <mhahnenberg@apple.com>
     2
     3        Delayed structure sweep can leak structures without bound
     4        https://bugs.webkit.org/show_bug.cgi?id=96546
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        This patch gets rid of the separate Structure allocator in the MarkedSpace and adds two new destructor-only
     9        allocators. We now have separate allocators for our three types of objects: those objects with no destructors,
     10        those objects with destructors and with immortal structures, and those objects with destructors that don't have
     11        immortal structures. All of the objects of the third type (destructors without immortal structures) now
     12        inherit from a new class named JSDestructibleObject (which in turn is a subclass of JSNonFinalObject), which stores
     13        the ClassInfo for these classes at a fixed offset for safe retrieval during sweeping/destruction.
     14
     15        * API/JSCallbackConstructor.cpp: Use JSDestructibleObject for JSCallbackConstructor.
     16        (JSC):
     17        (JSC::JSCallbackConstructor::JSCallbackConstructor):
     18        * API/JSCallbackConstructor.h:
     19        (JSCallbackConstructor):
     20        * API/JSCallbackObject.cpp: Inherit from JSDestructibleObject for normal JSCallbackObjects and use a finalizer for
     21        JSCallbackObject<JSGlobalObject>, since JSGlobalObject also uses a finalizer.
     22        (JSC):
     23        (JSC::::create): We need to move the create function for JSCallbackObject<JSGlobalObject> out of line so we can add
     24        the finalizer for it. We don't want to add the finalizer is something like finishCreation in case somebody decides
     25        to subclass this. We use this same technique for many other subclasses of JSGlobalObject.
     26        (JSC::::createStructure):
     27        * API/JSCallbackObject.h:
     28        (JSCallbackObject):
     29        (JSC):
     30        * API/JSClassRef.cpp: Change all the JSCallbackObject<JSNonFinalObject> to use JSDestructibleObject instead.
     31        (OpaqueJSClass::prototype):
     32        * API/JSObjectRef.cpp: Ditto.
     33        (JSObjectMake):
     34        (JSObjectGetPrivate):
     35        (JSObjectSetPrivate):
     36        (JSObjectGetPrivateProperty):
     37        (JSObjectSetPrivateProperty):
     38        (JSObjectDeletePrivateProperty):
     39        * API/JSValueRef.cpp: Ditto.
     40        (JSValueIsObjectOfClass):
     41        * API/JSWeakObjectMapRefPrivate.cpp: Ditto.
     42        * JSCTypedArrayStubs.h:
     43        (JSC):
     44        * JavaScriptCore.xcodeproj/project.pbxproj:
     45        * dfg/DFGSpeculativeJIT.h: Use the proper allocator type when doing inline allocation in the DFG.
     46        (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
     47        (JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject):
     48        * heap/Heap.cpp:
     49        (JSC):
     50        * heap/Heap.h: Add accessors for the various types of allocators now. Also remove the isSafeToSweepStructures function
     51        since it's always safe to sweep Structures now.
     52        (JSC::Heap::allocatorForObjectWithNormalDestructor):
     53        (JSC::Heap::allocatorForObjectWithImmortalStructureDestructor):
     54        (Heap):
     55        (JSC::Heap::allocateWithNormalDestructor):
     56        (JSC):
     57        (JSC::Heap::allocateWithImmortalStructureDestructor):
     58        * heap/IncrementalSweeper.cpp: Remove all the logic to detect when it's safe to sweep Structures from the
     59        IncrementalSweeper since it's always safe to sweep Structures now.
     60        (JSC::IncrementalSweeper::IncrementalSweeper):
     61        (JSC::IncrementalSweeper::sweepNextBlock):
     62        (JSC::IncrementalSweeper::startSweeping):
     63        (JSC::IncrementalSweeper::willFinishSweeping):
     64        (JSC):
     65        * heap/IncrementalSweeper.h:
     66        (IncrementalSweeper):
     67        * heap/MarkedAllocator.cpp: Remove the logic that was preventing us from sweeping Structures if it wasn't safe. Add
     68        tracking of the specific destructor type of allocator.
     69        (JSC::MarkedAllocator::tryAllocateHelper):
     70        (JSC::MarkedAllocator::allocateBlock):
     71        * heap/MarkedAllocator.h:
     72        (JSC::MarkedAllocator::destructorType):
     73        (MarkedAllocator):
     74        (JSC::MarkedAllocator::MarkedAllocator):
     75        (JSC::MarkedAllocator::init):
     76        * heap/MarkedBlock.cpp: Add all the destructor type stuff to MarkedBlocks so that we do the right thing when sweeping.
     77        We also use the stored destructor type to determine the right thing to do in all JSCell::classInfo() calls.
     78        (JSC::MarkedBlock::create):
     79        (JSC::MarkedBlock::MarkedBlock):
     80        (JSC):
     81        (JSC::MarkedBlock::specializedSweep):
     82        (JSC::MarkedBlock::sweep):
     83        (JSC::MarkedBlock::sweepHelper):
     84        * heap/MarkedBlock.h:
     85        (JSC):
     86        (JSC::MarkedBlock::allocator):
     87        (JSC::MarkedBlock::destructorType):
     88        * heap/MarkedSpace.cpp: Add the new destructor allocators to MarkedSpace.
     89        (JSC::MarkedSpace::MarkedSpace):
     90        (JSC::MarkedSpace::resetAllocators):
     91        (JSC::MarkedSpace::canonicalizeCellLivenessData):
     92        (JSC::MarkedSpace::isPagedOut):
     93        (JSC::MarkedSpace::freeBlock):
     94        * heap/MarkedSpace.h:
     95        (MarkedSpace):
     96        (JSC::MarkedSpace::immortalStructureDestructorAllocatorFor):
     97        (JSC::MarkedSpace::normalDestructorAllocatorFor):
     98        (JSC::MarkedSpace::allocateWithImmortalStructureDestructor):
     99        (JSC::MarkedSpace::allocateWithNormalDestructor):
     100        (JSC::MarkedSpace::forEachBlock):
     101        * heap/SlotVisitor.cpp: Add include because the symbol was needed in an inlined function.
     102        * jit/JIT.h: Make sure we use the correct allocator when doing inline allocations in the baseline JIT.
     103        * jit/JITInlineMethods.h:
     104        (JSC::JIT::emitAllocateBasicJSObject):
     105        (JSC::JIT::emitAllocateJSFinalObject):
     106        (JSC::JIT::emitAllocateJSArray):
     107        * jsc.cpp:
     108        (GlobalObject::create): Add finalizer here since JSGlobalObject needs to use a finalizer instead of inheriting from
     109        JSDestructibleObject.
     110        * runtime/Arguments.cpp: Inherit from JSDestructibleObject.
     111        (JSC):
     112        * runtime/Arguments.h:
     113        (Arguments):
     114        (JSC::Arguments::Arguments):
     115        * runtime/ErrorPrototype.cpp: Added an assert to make sure we have a trivial destructor.
     116        (JSC):
     117        * runtime/Executable.h: Indicate that all of the Executable* classes have immortal Structures.
     118        (JSC):
     119        * runtime/InternalFunction.cpp: Inherit from JSDestructibleObject.
     120        (JSC):
     121        (JSC::InternalFunction::InternalFunction):
     122        * runtime/InternalFunction.h:
     123        (InternalFunction):
     124        * runtime/JSCell.h: Added the NEEDS_DESTRUCTOR  macro to make it easier for classes to indicate that instead of being
     125        allocated in a destructor MarkedAllocator that they will handle their destruction themselves through the
     126        use of a finalizer.
     127        (JSC):
     128        (HasImmortalStructure): New template to help us determine at compile-time if a particular class
     129        should be allocated in the immortal structure MarkedAllocator. The default value is false. In order
     130        to be allocated in the immortal structure allocator, classes must specialize this template. Also added
     131        a macro to make it easier for classes to specialize the template.
     132        (JSC::allocateCell): Use the appropriate allocator depending on the destructor type.
     133        * runtime/JSDestructibleObject.h: Added. New class that stores the ClassInfo of any subclass so that it can be
     134        accessed safely when the object is being destroyed.
     135        (JSC):
     136        (JSDestructibleObject):
     137        (JSC::JSDestructibleObject::classInfo):
     138        (JSC::JSDestructibleObject::JSDestructibleObject):
     139        (JSC::JSCell::classInfo): Checks the current MarkedBlock to see where it should get the ClassInfo from so that it's always safe.
     140        * runtime/JSGlobalObject.cpp: JSGlobalObject now uses a finalizer instead of a destructor so that it can avoid forcing all
     141        of its relatives in the inheritance hierarchy (e.g. JSScope) to use destructors as well.
     142        (JSC::JSGlobalObject::reset):
     143        * runtime/JSGlobalObject.h:
     144        (JSGlobalObject):
     145        (JSC::JSGlobalObject::createRareDataIfNeeded): Since we always create a finalizer now, we don't have to worry about adding one
     146        for the m_rareData field when it's created.
     147        (JSC::JSGlobalObject::create):
     148        (JSC):
     149        * runtime/JSGlobalThis.h: Inherit from JSDestructibleObject.
     150        (JSGlobalThis):
     151        (JSC::JSGlobalThis::JSGlobalThis):
     152        * runtime/JSPropertyNameIterator.h: Has an immortal Structure.
     153        (JSC):
     154        * runtime/JSScope.cpp:
     155        (JSC):
     156        * runtime/JSString.h: Has an immortal Structure.
     157        (JSC):
     158        * runtime/JSWrapperObject.h: Inherit from JSDestructibleObject.
     159        (JSWrapperObject):
     160        (JSC::JSWrapperObject::JSWrapperObject):
     161        * runtime/MathObject.cpp: Cleaning up some of the inheritance stuff.
     162        (JSC):
     163        * runtime/NameInstance.h: Inherit from JSDestructibleObject.
     164        (NameInstance):
     165        * runtime/RegExp.h: Has immortal Structure.
     166        (JSC):
     167        * runtime/RegExpObject.cpp: Inheritance cleanup.
     168        (JSC):
     169        * runtime/SparseArrayValueMap.h: Has immortal Structure.
     170        (JSC):
     171        * runtime/Structure.h: Has immortal Structure.
     172        (JSC):
     173        * runtime/StructureChain.h: Ditto.
     174        (JSC):
     175        * runtime/SymbolTable.h: Ditto.
     176        (SharedSymbolTable):
     177        (JSC):
     178
     179<<<<<<< .mine
     1802012-09-16  Mark Hahnenberg  <mhahnenberg@apple.com>
     181
     182        Delayed structure sweep can leak structures without bound
     183        https://bugs.webkit.org/show_bug.cgi?id=96546
     184
     185        Reviewed by Gavin Barraclough.
     186
     187        This patch gets rid of the separate Structure allocator in the MarkedSpace and adds two new destructor-only
     188        allocators. We now have separate allocators for our three types of objects: those objects with no destructors,
     189        those objects with destructors and with immortal structures, and those objects with destructors that don't have
     190        immortal structures. All of the objects of the third type (destructors without immortal structures) now
     191        inherit from a new class named JSDestructibleObject (which in turn is a subclass of JSNonFinalObject), which stores
     192        the ClassInfo for these classes at a fixed offset for safe retrieval during sweeping/destruction.
     193
     194        * API/JSCallbackConstructor.cpp: Use JSDestructibleObject for JSCallbackConstructor.
     195        (JSC):
     196        (JSC::JSCallbackConstructor::JSCallbackConstructor):
     197        * API/JSCallbackConstructor.h:
     198        (JSCallbackConstructor):
     199        * API/JSCallbackObject.cpp: Inherit from JSDestructibleObject for normal JSCallbackObjects and use a finalizer for
     200        JSCallbackObject<JSGlobalObject>, since JSGlobalObject also uses a finalizer.
     201        (JSC):
     202        (JSC::::create): We need to move the create function for JSCallbackObject<JSGlobalObject> out of line so we can add
     203        the finalizer for it. We don't want to add the finalizer is something like finishCreation in case somebody decides
     204        to subclass this. We use this same technique for many other subclasses of JSGlobalObject.
     205        (JSC::::createStructure):
     206        * API/JSCallbackObject.h:
     207        (JSCallbackObject):
     208        (JSC):
     209        * API/JSClassRef.cpp: Change all the JSCallbackObject<JSNonFinalObject> to use JSDestructibleObject instead.
     210        (OpaqueJSClass::prototype):
     211        * API/JSObjectRef.cpp: Ditto.
     212        (JSObjectMake):
     213        (JSObjectGetPrivate):
     214        (JSObjectSetPrivate):
     215        (JSObjectGetPrivateProperty):
     216        (JSObjectSetPrivateProperty):
     217        (JSObjectDeletePrivateProperty):
     218        * API/JSValueRef.cpp: Ditto.
     219        (JSValueIsObjectOfClass):
     220        * API/JSWeakObjectMapRefPrivate.cpp: Ditto.
     221        * JSCTypedArrayStubs.h:
     222        (JSC):
     223        * JavaScriptCore.xcodeproj/project.pbxproj:
     224        * dfg/DFGSpeculativeJIT.h: Use the proper allocator type when doing inline allocation in the DFG.
     225        (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
     226        (JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject):
     227        * heap/Heap.cpp:
     228        (JSC):
     229        * heap/Heap.h: Add accessors for the various types of allocators now. Also remove the isSafeToSweepStructures function
     230        since it's always safe to sweep Structures now.
     231        (JSC::Heap::allocatorForObjectWithNormalDestructor):
     232        (JSC::Heap::allocatorForObjectWithImmortalStructureDestructor):
     233        (Heap):
     234        (JSC::Heap::allocateWithNormalDestructor):
     235        (JSC):
     236        (JSC::Heap::allocateWithImmortalStructureDestructor):
     237        * heap/IncrementalSweeper.cpp: Remove all the logic to detect when it's safe to sweep Structures from the
     238        IncrementalSweeper since it's always safe to sweep Structures now.
     239        (JSC::IncrementalSweeper::IncrementalSweeper):
     240        (JSC::IncrementalSweeper::sweepNextBlock):
     241        (JSC::IncrementalSweeper::startSweeping):
     242        (JSC::IncrementalSweeper::willFinishSweeping):
     243        (JSC):
     244        * heap/IncrementalSweeper.h:
     245        (IncrementalSweeper):
     246        * heap/MarkedAllocator.cpp: Remove the logic that was preventing us from sweeping Structures if it wasn't safe. Add
     247        tracking of the specific destructor type of allocator.
     248        (JSC::MarkedAllocator::tryAllocateHelper):
     249        (JSC::MarkedAllocator::allocateBlock):
     250        * heap/MarkedAllocator.h:
     251        (JSC::MarkedAllocator::destructorType):
     252        (MarkedAllocator):
     253        (JSC::MarkedAllocator::MarkedAllocator):
     254        (JSC::MarkedAllocator::init):
     255        * heap/MarkedBlock.cpp: Add all the destructor type stuff to MarkedBlocks so that we do the right thing when sweeping.
     256        We also use the stored destructor type to determine the right thing to do in all JSCell::classInfo() calls.
     257        (JSC::MarkedBlock::create):
     258        (JSC::MarkedBlock::MarkedBlock):
     259        (JSC):
     260        (JSC::MarkedBlock::specializedSweep):
     261        (JSC::MarkedBlock::sweep):
     262        (JSC::MarkedBlock::sweepHelper):
     263        * heap/MarkedBlock.h:
     264        (JSC):
     265        (JSC::MarkedBlock::allocator):
     266        (JSC::MarkedBlock::destructorType):
     267        * heap/MarkedSpace.cpp: Add the new destructor allocators to MarkedSpace.
     268        (JSC::MarkedSpace::MarkedSpace):
     269        (JSC::MarkedSpace::resetAllocators):
     270        (JSC::MarkedSpace::canonicalizeCellLivenessData):
     271        (JSC::MarkedSpace::isPagedOut):
     272        (JSC::MarkedSpace::freeBlock):
     273        * heap/MarkedSpace.h:
     274        (MarkedSpace):
     275        (JSC::MarkedSpace::immortalStructureDestructorAllocatorFor):
     276        (JSC::MarkedSpace::normalDestructorAllocatorFor):
     277        (JSC::MarkedSpace::allocateWithImmortalStructureDestructor):
     278        (JSC::MarkedSpace::allocateWithNormalDestructor):
     279        (JSC::MarkedSpace::forEachBlock):
     280        * heap/SlotVisitor.cpp: Add include because the symbol was needed in an inlined function.
     281        * jit/JIT.h: Make sure we use the correct allocator when doing inline allocations in the baseline JIT.
     282        * jit/JITInlineMethods.h:
     283        (JSC::JIT::emitAllocateBasicJSObject):
     284        (JSC::JIT::emitAllocateJSFinalObject):
     285        (JSC::JIT::emitAllocateJSArray):
     286        * jsc.cpp:
     287        (GlobalObject::create): Add finalizer here since JSGlobalObject needs to use a finalizer instead of inheriting from
     288        JSDestructibleObject.
     289        * runtime/Arguments.cpp: Inherit from JSDestructibleObject.
     290        (JSC):
     291        * runtime/Arguments.h:
     292        (Arguments):
     293        (JSC::Arguments::Arguments):
     294        * runtime/ErrorPrototype.cpp: Added an assert to make sure we have a trivial destructor.
     295        (JSC):
     296        * runtime/Executable.h: Indicate that all of the Executable* classes have immortal Structures.
     297        (JSC):
     298        * runtime/InternalFunction.cpp: Inherit from JSDestructibleObject.
     299        (JSC):
     300        (JSC::InternalFunction::InternalFunction):
     301        * runtime/InternalFunction.h:
     302        (InternalFunction):
     303        * runtime/JSCell.h: Added the NEEDS_DESTRUCTOR  macro to make it easier for classes to indicate that instead of being
     304        allocated in a destructor MarkedAllocator that they will handle their destruction themselves through the
     305        use of a finalizer.
     306        (JSC):
     307        (HasImmortalStructure): New template to help us determine at compile-time if a particular class
     308        should be allocated in the immortal structure MarkedAllocator. The default value is false. In order
     309        to be allocated in the immortal structure allocator, classes must specialize this template. Also added
     310        a macro to make it easier for classes to specialize the template.
     311        (JSC::allocateCell): Use the appropriate allocator depending on the destructor type.
     312        * runtime/JSDestructibleObject.h: Added. New class that stores the ClassInfo of any subclass so that it can be
     313        accessed safely when the object is being destroyed.
     314        (JSC):
     315        (JSDestructibleObject):
     316        (JSC::JSDestructibleObject::classInfo):
     317        (JSC::JSDestructibleObject::JSDestructibleObject):
     318        (JSC::JSCell::classInfo): Checks the current MarkedBlock to see where it should get the ClassInfo from so that it's always safe.
     319        * runtime/JSGlobalObject.cpp: JSGlobalObject now uses a finalizer instead of a destructor so that it can avoid forcing all
     320        of its relatives in the inheritance hierarchy (e.g. JSScope) to use destructors as well.
     321        (JSC::JSGlobalObject::reset):
     322        * runtime/JSGlobalObject.h:
     323        (JSGlobalObject):
     324        (JSC::JSGlobalObject::createRareDataIfNeeded): Since we always create a finalizer now, we don't have to worry about adding one
     325        for the m_rareData field when it's created.
     326        (JSC::JSGlobalObject::create):
     327        (JSC):
     328        * runtime/JSGlobalThis.h: Inherit from JSDestructibleObject.
     329        (JSGlobalThis):
     330        (JSC::JSGlobalThis::JSGlobalThis):
     331        * runtime/JSPropertyNameIterator.h: Has an immortal Structure.
     332        (JSC):
     333        * runtime/JSScope.cpp:
     334        (JSC):
     335        * runtime/JSString.h: Has an immortal Structure.
     336        (JSC):
     337        * runtime/JSWrapperObject.h: Inherit from JSDestructibleObject.
     338        (JSWrapperObject):
     339        (JSC::JSWrapperObject::JSWrapperObject):
     340        * runtime/MathObject.cpp: Cleaning up some of the inheritance stuff.
     341        (JSC):
     342        * runtime/NameInstance.h: Inherit from JSDestructibleObject.
     343        (NameInstance):
     344        * runtime/RegExp.h: Has immortal Structure.
     345        (JSC):
     346        * runtime/RegExpObject.cpp: Inheritance cleanup.
     347        (JSC):
     348        * runtime/SparseArrayValueMap.h: Has immortal Structure.
     349        (JSC):
     350        * runtime/Structure.h: Has immortal Structure.
     351        (JSC):
     352        * runtime/StructureChain.h: Ditto.
     353        (JSC):
     354        * runtime/SymbolTable.h: Ditto.
     355        (SharedSymbolTable):
     356        (JSC):
     357
     358=======
    13592012-09-17  Filip Pizlo  <fpizlo@apple.com>
    2360
     
    234592        * llint/LowLevelInterpreter64.asm:
    235593
     594>>>>>>> .r128811
    2365952012-09-17  Mark Lam  <mark.lam@apple.com>
    237596
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r128680 r128813  
    534534        Source/JavaScriptCore/runtime/JSDateMath.cpp \
    535535        Source/JavaScriptCore/runtime/JSDateMath.h \
     536    Source/JavaScriptCore/runtime/JSDestructibleObject.h \
    536537        Source/JavaScriptCore/runtime/JSFunction.cpp \
    537538        Source/JavaScriptCore/runtime/JSFunction.h \
  • trunk/Source/JavaScriptCore/JSCTypedArrayStubs.h

    r116828 r128813  
    2727#define JSCTypedArrayStubs_h
    2828
    29 #include "JSObject.h"
     29#include "JSDestructibleObject.h"
    3030#include "ObjectPrototype.h"
    3131#include <wtf/Float32Array.h>
     
    4343   
    4444#define TYPED_ARRAY(name, type) \
    45 class JS##name##Array : public JSNonFinalObject { \
     45class JS##name##Array : public JSDestructibleObject { \
    4646public: \
    47     typedef JSNonFinalObject Base; \
     47    typedef JSDestructibleObject Base; \
    4848    static JS##name##Array* create(JSC::Structure* structure, JSGlobalObject* globalObject, PassRefPtr<name##Array> impl) \
    4949    { \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r128771 r128813  
    842842                                >
    843843                        </File>
     844            <File
     845                RelativePath="..\..\runtime\JSDestructibleObject.h"
     846                >
     847            </File>
    844848                        <File
    845849                                RelativePath="..\..\runtime\JSFunction.cpp"
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r128680 r128813  
    709709                C22B31B9140577D700DB475A /* SamplingCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F77008E1402FDD60078EB39 /* SamplingCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
    710710                C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C240305314B404C90079EB64 /* CopiedSpace.cpp */; };
     711                C25177F81607D0A6000A233C /* JSDestructibleObject.h in Headers */ = {isa = PBXBuildFile; fileRef = C25177F71607D0A6000A233C /* JSDestructibleObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
    711712                C25F8BCD157544A900245B71 /* IncrementalSweeper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */; };
    712713                C25F8BCE157544A900245B71 /* IncrementalSweeper.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F8BCC157544A900245B71 /* IncrementalSweeper.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    14821483                C225494215F7DBAA0065E898 /* SlotVisitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SlotVisitor.cpp; sourceTree = "<group>"; };
    14831484                C240305314B404C90079EB64 /* CopiedSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CopiedSpace.cpp; sourceTree = "<group>"; };
     1485                C25177F71607D0A6000A233C /* JSDestructibleObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDestructibleObject.h; sourceTree = "<group>"; };
    14841486                C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IncrementalSweeper.cpp; sourceTree = "<group>"; };
    14851487                C25F8BCC157544A900245B71 /* IncrementalSweeper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IncrementalSweeper.h; sourceTree = "<group>"; };
     
    20442046                        isa = PBXGroup;
    20452047                        children = (
     2048                                C25177F71607D0A6000A233C /* JSDestructibleObject.h */,
    20462049                                0F0CD4C315F6B6B50032F1C0 /* SparseArrayValueMap.cpp */,
    20472050                                0F0CD4C015F1A6040032F1C0 /* PutDirectIndexMode.h */,
     
    25642567                                C2EAD2FC14F0249800A4B159 /* CopiedAllocator.h in Headers */,
    25652568                                C2B916C214DA014E00CBAC86 /* MarkedAllocator.h in Headers */,
     2569                                C25177F81607D0A6000A233C /* JSDestructibleObject.h in Headers */,
    25662570                                FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */,
    25672571                                C21122E215DD9AB300790E3A /* GCThreadSharedData.h in Headers */,
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r128400 r128813  
    21902190    // It is NOT okay for the structure and the scratch register to be the same thing because if they are then the Structure will
    21912191    // get clobbered.
    2192     template <typename ClassType, bool destructor, typename StructureType>
     2192    template <typename ClassType, MarkedBlock::DestructorType destructorType, typename StructureType>
    21932193    void emitAllocateBasicJSObject(StructureType structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
    21942194    {
    21952195        MarkedAllocator* allocator = 0;
    2196         if (destructor)
    2197             allocator = &m_jit.globalData()->heap.allocatorForObjectWithDestructor(sizeof(ClassType));
     2196        if (destructorType == MarkedBlock::Normal)
     2197            allocator = &m_jit.globalData()->heap.allocatorForObjectWithNormalDestructor(sizeof(ClassType));
     2198        else if (destructorType == MarkedBlock::ImmortalStructure)
     2199            allocator = &m_jit.globalData()->heap.allocatorForObjectWithImmortalStructureDestructor(sizeof(ClassType));
    21982200        else
    21992201            allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType));
     
    22172219    void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
    22182220    {
    2219         return emitAllocateBasicJSObject<JSFinalObject, false>(structure, resultGPR, scratchGPR, slowPath);
     2221        return emitAllocateBasicJSObject<JSFinalObject, MarkedBlock::None>(structure, resultGPR, scratchGPR, slowPath);
    22202222    }
    22212223
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r128498 r128813  
    831831}
    832832
    833 bool Heap::isSafeToSweepStructures()
    834 {
    835     return !m_sweeper || m_sweeper->structuresCanBeSwept();
    836 }
    837 
    838833void Heap::didStartVMShutdown()
    839834{
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r128260 r128813  
    113113        MarkedAllocator& firstAllocatorWithoutDestructors() { return m_objectSpace.firstAllocator(); }
    114114        MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
    115         MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
     115        MarkedAllocator& allocatorForObjectWithNormalDestructor(size_t bytes) { return m_objectSpace.normalDestructorAllocatorFor(bytes); }
     116        MarkedAllocator& allocatorForObjectWithImmortalStructureDestructor(size_t bytes) { return m_objectSpace.immortalStructureDestructorAllocatorFor(bytes); }
    116117        CopiedAllocator& storageAllocator() { return m_storageSpace.allocator(); }
    117118        CheckedBoolean tryAllocateStorage(size_t, void**);
     
    169170
    170171        bool isPagedOut(double deadline);
    171         bool isSafeToSweepStructures();
    172172        void didStartVMShutdown();
    173173
     
    185185        template<typename T> friend void* allocateCell(Heap&, size_t);
    186186
    187         void* allocateWithDestructor(size_t);
    188         void* allocateWithoutDestructor(size_t);
    189         void* allocateStructure(size_t);
     187        void* allocateWithImmortalStructureDestructor(size_t); // For use with special objects whose Structures never die.
     188        void* allocateWithNormalDestructor(size_t); // For use with objects that inherit directly or indirectly from JSDestructibleObject.
     189        void* allocateWithoutDestructor(size_t); // For use with objects without destructors.
    190190
    191191        static const size_t minExtraCost = 256;
     
    362362    }
    363363
    364     inline void* Heap::allocateWithDestructor(size_t bytes)
     364    inline void* Heap::allocateWithNormalDestructor(size_t bytes)
    365365    {
    366366        ASSERT(isValidAllocation(bytes));
    367         return m_objectSpace.allocateWithDestructor(bytes);
     367        return m_objectSpace.allocateWithNormalDestructor(bytes);
     368    }
     369   
     370    inline void* Heap::allocateWithImmortalStructureDestructor(size_t bytes)
     371    {
     372        ASSERT(isValidAllocation(bytes));
     373        return m_objectSpace.allocateWithImmortalStructureDestructor(bytes);
    368374    }
    369375   
     
    374380    }
    375381   
    376     inline void* Heap::allocateStructure(size_t bytes)
    377     {
    378         return m_objectSpace.allocateStructure(bytes);
    379     }
    380  
    381382    inline CheckedBoolean Heap::tryAllocateStorage(size_t bytes, void** outPtr)
    382383    {
  • trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp

    r127202 r128813  
    4949    : HeapTimer(heap->globalData(), runLoop)
    5050    , m_currentBlockToSweepIndex(0)
    51     , m_structuresCanBeSwept(false)
    5251{
    5352}
     
    7372    : HeapTimer(heap->globalData())
    7473    , m_currentBlockToSweepIndex(0)
    75     , m_structuresCanBeSwept(false)
    7674{
    7775}
     
    120118    while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
    121119        MarkedBlock* block = m_blocksToSweep[m_currentBlockToSweepIndex++];
    122         if (block->onlyContainsStructures())
    123             m_structuresCanBeSwept = true;
    124         else
    125             ASSERT(!m_structuresCanBeSwept);
    126120
    127121        if (!block->needsSweeping())
     
    140134    m_globalData->heap.objectSpace().forEachBlock(functor);
    141135    m_currentBlockToSweepIndex = 0;
    142     m_structuresCanBeSwept = false;
    143136    scheduleTimer();
    144137}
     
    147140{
    148141    m_currentBlockToSweepIndex = 0;
    149     m_structuresCanBeSwept = true;
    150142    m_blocksToSweep.clear();
    151143    if (m_globalData)
     
    157149IncrementalSweeper::IncrementalSweeper(JSGlobalData* globalData)
    158150    : HeapTimer(globalData)
    159     , m_structuresCanBeSwept(false)
    160151{
    161152}
     
    172163void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>&)
    173164{
    174     m_structuresCanBeSwept = false;
    175165}
    176166
    177167void IncrementalSweeper::willFinishSweeping()
    178168{
    179     m_structuresCanBeSwept = true;
    180169}
    181170
     
    186175#endif
    187176
    188 bool IncrementalSweeper::structuresCanBeSwept()
    189 {
    190     return m_structuresCanBeSwept;
    191 }
    192 
    193177} // namespace JSC
  • trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h

    r127185 r128813  
    5757    virtual void doWork();
    5858    void sweepNextBlock();
    59     bool structuresCanBeSwept();
    6059    void willFinishSweeping();
    6160
     
    7978   
    8079#endif
    81     bool m_structuresCanBeSwept;
    8280};
    8381
  • trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp

    r128563 r128813  
    3131{
    3232    if (!m_freeList.head) {
    33         if (m_onlyContainsStructures && !m_heap->isSafeToSweepStructures()) {
    34             if (m_currentBlock) {
    35                 m_currentBlock->didConsumeFreeList();
    36                 m_currentBlock = 0;
    37             }
    38             // We sweep another random block here so that we can make progress
    39             // toward being able to sweep Structures.
    40             m_heap->sweeper()->sweepNextBlock();
    41             return 0;
    42         }
    43 
    4433        for (MarkedBlock*& block = m_blocksToSweep; block; block = block->next()) {
    4534            MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList);
     
    125114    if (blockSize == MarkedBlock::blockSize) {
    126115        PageAllocationAligned allocation = m_heap->blockAllocator().allocate();
    127         return MarkedBlock::create(allocation, m_heap, cellSize, m_cellsNeedDestruction, m_onlyContainsStructures);
     116        return MarkedBlock::create(allocation, this, cellSize, m_destructorType);
    128117    }
    129118
     
    131120    if (!static_cast<bool>(allocation))
    132121        CRASH();
    133     return MarkedBlock::create(allocation, m_heap, cellSize, m_cellsNeedDestruction, m_onlyContainsStructures);
     122    return MarkedBlock::create(allocation, this, cellSize, m_destructorType);
    134123}
    135124
  • trunk/Source/JavaScriptCore/heap/MarkedAllocator.h

    r128563 r128813  
    2424    void canonicalizeCellLivenessData();
    2525    size_t cellSize() { return m_cellSize; }
    26     bool cellsNeedDestruction() { return m_cellsNeedDestruction; }
    27     bool onlyContainsStructures() { return m_onlyContainsStructures; }
     26    MarkedBlock::DestructorType destructorType() { return m_destructorType; }
    2827    void* allocate(size_t);
    2928    Heap* heap() { return m_heap; }
     
    3332    void addBlock(MarkedBlock*);
    3433    void removeBlock(MarkedBlock*);
    35     void init(Heap*, MarkedSpace*, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures);
     34    void init(Heap*, MarkedSpace*, size_t cellSize, MarkedBlock::DestructorType);
    3635
    3736    bool isPagedOut(double deadline);
     
    5049    DoublyLinkedList<MarkedBlock> m_blockList;
    5150    size_t m_cellSize;
    52     bool m_cellsNeedDestruction;
    53     bool m_onlyContainsStructures;
     51    MarkedBlock::DestructorType m_destructorType;
    5452    Heap* m_heap;
    5553    MarkedSpace* m_markedSpace;
     
    6058    , m_blocksToSweep(0)
    6159    , m_cellSize(0)
    62     , m_cellsNeedDestruction(true)
    63     , m_onlyContainsStructures(false)
     60    , m_destructorType(MarkedBlock::None)
    6461    , m_heap(0)
    6562    , m_markedSpace(0)
     
    6764}
    6865
    69 inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures)
     66inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, MarkedBlock::DestructorType destructorType)
    7067{
    7168    m_heap = heap;
    7269    m_markedSpace = markedSpace;
    7370    m_cellSize = cellSize;
    74     m_cellsNeedDestruction = cellsNeedDestruction;
    75     m_onlyContainsStructures = onlyContainsStructures;
     71    m_destructorType = destructorType;
    7672}
    7773
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp

    r128563 r128813  
    2929#include "IncrementalSweeper.h"
    3030#include "JSCell.h"
    31 #include "JSObject.h"
     31#include "JSDestructibleObject.h"
    3232
    3333
    3434namespace JSC {
    3535
    36 MarkedBlock* MarkedBlock::create(const PageAllocationAligned& allocation, Heap* heap, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures)
     36MarkedBlock* MarkedBlock::create(const PageAllocationAligned& allocation, MarkedAllocator* allocator, size_t cellSize, DestructorType destructorType)
    3737{
    38     return new (NotNull, allocation.base()) MarkedBlock(allocation, heap, cellSize, cellsNeedDestruction, onlyContainsStructures);
     38    return new (NotNull, allocation.base()) MarkedBlock(allocation, allocator, cellSize, destructorType);
    3939}
    4040
    41 MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, Heap* heap, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures)
     41MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, MarkedAllocator* allocator, size_t cellSize, DestructorType destructorType)
    4242    : HeapBlock<MarkedBlock>(allocation)
    4343    , m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
    4444    , m_endAtom(atomsPerBlock - m_atomsPerCell + 1)
    45     , m_cellsNeedDestruction(cellsNeedDestruction)
    46     , m_onlyContainsStructures(onlyContainsStructures)
     45    , m_destructorType(destructorType)
     46    , m_allocator(allocator)
    4747    , m_state(New) // All cells start out unmarked.
    48     , m_weakSet(heap->globalData())
     48    , m_weakSet(allocator->heap()->globalData())
    4949{
    50     ASSERT(heap);
     50    ASSERT(allocator);
    5151    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
    5252}
     
    6666}
    6767
    68 template<MarkedBlock::BlockState blockState, MarkedBlock::SweepMode sweepMode, bool destructorCallNeeded>
     68template<MarkedBlock::BlockState blockState, MarkedBlock::SweepMode sweepMode, MarkedBlock::DestructorType dtorType>
    6969MarkedBlock::FreeList MarkedBlock::specializedSweep()
    7070{
    7171    ASSERT(blockState != Allocated && blockState != FreeListed);
    72     ASSERT(destructorCallNeeded || sweepMode != SweepOnly);
     72    ASSERT(!(dtorType == MarkedBlock::None && sweepMode == SweepOnly));
    7373
    7474    // This produces a free list that is ordered in reverse through the block.
     
    8383        JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
    8484
    85         if (destructorCallNeeded && blockState != New)
     85        if (dtorType != MarkedBlock::None && blockState != New)
    8686            callDestructor(cell);
    8787
     
    104104    m_weakSet.sweep();
    105105
    106     if (sweepMode == SweepOnly && !m_cellsNeedDestruction)
     106    if (sweepMode == SweepOnly && m_destructorType == MarkedBlock::None)
    107107        return FreeList();
    108108
    109     if (m_cellsNeedDestruction)
    110         return sweepHelper<true>(sweepMode);
    111     return sweepHelper<false>(sweepMode);
     109    if (m_destructorType == MarkedBlock::ImmortalStructure)
     110        return sweepHelper<MarkedBlock::ImmortalStructure>(sweepMode);
     111    if (m_destructorType == MarkedBlock::Normal)
     112        return sweepHelper<MarkedBlock::Normal>(sweepMode);
     113    return sweepHelper<MarkedBlock::None>(sweepMode);
    112114}
    113115
    114 template<bool destructorCallNeeded>
     116template<MarkedBlock::DestructorType dtorType>
    115117MarkedBlock::FreeList MarkedBlock::sweepHelper(SweepMode sweepMode)
    116118{
     
    118120    case New:
    119121        ASSERT(sweepMode == SweepToFreeList);
    120         return specializedSweep<New, SweepToFreeList, destructorCallNeeded>();
     122        return specializedSweep<New, SweepToFreeList, dtorType>();
    121123    case FreeListed:
    122124        // Happens when a block transitions to fully allocated.
     
    127129        return FreeList();
    128130    case Marked:
    129         ASSERT(!m_onlyContainsStructures || heap()->isSafeToSweepStructures());
    130131        return sweepMode == SweepToFreeList
    131             ? specializedSweep<Marked, SweepToFreeList, destructorCallNeeded>()
    132             : specializedSweep<Marked, SweepOnly, destructorCallNeeded>();
     132            ? specializedSweep<Marked, SweepToFreeList, dtorType>()
     133            : specializedSweep<Marked, SweepOnly, dtorType>();
    133134    }
    134135
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.h

    r128563 r128813  
    5353    class Heap;
    5454    class JSCell;
     55    class MarkedAllocator;
    5556
    5657    typedef uintptr_t Bits;
     
    113114        };
    114115
    115         static MarkedBlock* create(const PageAllocationAligned&, Heap*, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures);
     116        enum DestructorType { None, ImmortalStructure, Normal };
     117        static MarkedBlock* create(const PageAllocationAligned&, MarkedAllocator*, size_t cellSize, DestructorType);
    116118
    117119        static bool isAtomAligned(const void*);
     
    121123        void lastChanceToFinalize();
    122124
     125        MarkedAllocator* allocator() const;
    123126        Heap* heap() const;
    124127        JSGlobalData* globalData() const;
     
    144147
    145148        size_t cellSize();
    146         bool cellsNeedDestruction();
    147         bool onlyContainsStructures();
     149        DestructorType destructorType();
    148150
    149151        size_t size();
     
    195197
    196198        enum BlockState { New, FreeListed, Allocated, Marked };
    197         template<bool destructorCallNeeded> FreeList sweepHelper(SweepMode = SweepOnly);
     199        template<DestructorType> FreeList sweepHelper(SweepMode = SweepOnly);
    198200
    199201        typedef char Atom[atomSize];
    200202
    201         MarkedBlock(const PageAllocationAligned&, Heap*, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures);
     203        MarkedBlock(const PageAllocationAligned&, MarkedAllocator*, size_t cellSize, DestructorType);
    202204        Atom* atoms();
    203205        size_t atomNumber(const void*);
    204206        void callDestructor(JSCell*);
    205         template<BlockState, SweepMode, bool destructorCallNeeded> FreeList specializedSweep();
     207        template<BlockState, SweepMode, DestructorType> FreeList specializedSweep();
    206208       
    207209#if ENABLE(GGC)
     
    216218        WTF::Bitmap<atomsPerBlock, WTF::BitmapNotAtomic> m_marks;
    217219#endif
    218         bool m_cellsNeedDestruction;
    219         bool m_onlyContainsStructures;
     220        DestructorType m_destructorType;
     221        MarkedAllocator* m_allocator;
    220222        BlockState m_state;
    221223        WeakSet m_weakSet;
     
    262264    }
    263265
     266    inline MarkedAllocator* MarkedBlock::allocator() const
     267    {
     268        return m_allocator;
     269    }
     270
    264271    inline Heap* MarkedBlock::heap() const
    265272    {
     
    327334    }
    328335
    329     inline bool MarkedBlock::cellsNeedDestruction()
    330     {
    331         return m_cellsNeedDestruction;
    332     }
    333 
    334     inline bool MarkedBlock::onlyContainsStructures()
    335     {
    336         return m_onlyContainsStructures;
     336    inline MarkedBlock::DestructorType MarkedBlock::destructorType()
     337    {
     338        return m_destructorType;
    337339    }
    338340
  • trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp

    r128563 r128813  
    8282{
    8383    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    84         allocatorFor(cellSize).init(heap, this, cellSize, false, false);
    85         destructorAllocatorFor(cellSize).init(heap, this, cellSize, true, false);
    86     }
    87 
    88     for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    89         allocatorFor(cellSize).init(heap, this, cellSize, false, false);
    90         destructorAllocatorFor(cellSize).init(heap, this, cellSize, true, false);
    91     }
    92 
    93     m_largeAllocator.init(heap, this, 0, true, false);
    94     m_structureAllocator.init(heap, this, WTF::roundUpToMultipleOf(32, sizeof(Structure)), true, true);
     84        allocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::None);
     85        normalDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::Normal);
     86        immortalStructureDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::ImmortalStructure);
     87    }
     88
     89    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
     90        allocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::None);
     91        normalDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::Normal);
     92        immortalStructureDestructorAllocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::ImmortalStructure);
     93    }
     94
     95    m_normalSpace.largeAllocator.init(heap, this, 0, MarkedBlock::None);
     96    m_normalDestructorSpace.largeAllocator.init(heap, this, 0, MarkedBlock::Normal);
     97    m_immortalStructureDestructorSpace.largeAllocator.init(heap, this, 0, MarkedBlock::ImmortalStructure);
    9598}
    9699
     
    121124    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    122125        allocatorFor(cellSize).reset();
    123         destructorAllocatorFor(cellSize).reset();
     126        normalDestructorAllocatorFor(cellSize).reset();
     127        immortalStructureDestructorAllocatorFor(cellSize).reset();
    124128    }
    125129
    126130    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    127131        allocatorFor(cellSize).reset();
    128         destructorAllocatorFor(cellSize).reset();
    129     }
    130 
    131     m_largeAllocator.reset();
    132     m_structureAllocator.reset();
     132        normalDestructorAllocatorFor(cellSize).reset();
     133        immortalStructureDestructorAllocatorFor(cellSize).reset();
     134    }
     135
     136    m_normalSpace.largeAllocator.reset();
     137    m_normalDestructorSpace.largeAllocator.reset();
     138    m_immortalStructureDestructorSpace.largeAllocator.reset();
    133139}
    134140
     
    148154    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    149155        allocatorFor(cellSize).canonicalizeCellLivenessData();
    150         destructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
     156        normalDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
     157        immortalStructureDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
    151158    }
    152159
    153160    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    154161        allocatorFor(cellSize).canonicalizeCellLivenessData();
    155         destructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
    156     }
    157 
    158     m_largeAllocator.canonicalizeCellLivenessData();
    159     m_structureAllocator.canonicalizeCellLivenessData();
     162        normalDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
     163        immortalStructureDestructorAllocatorFor(cellSize).canonicalizeCellLivenessData();
     164    }
     165
     166    m_normalSpace.largeAllocator.canonicalizeCellLivenessData();
     167    m_normalDestructorSpace.largeAllocator.canonicalizeCellLivenessData();
     168    m_immortalStructureDestructorSpace.largeAllocator.canonicalizeCellLivenessData();
    160169}
    161170
     
    163172{
    164173    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    165         if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
     174        if (allocatorFor(cellSize).isPagedOut(deadline)
     175            || normalDestructorAllocatorFor(cellSize).isPagedOut(deadline)
     176            || immortalStructureDestructorAllocatorFor(cellSize).isPagedOut(deadline))
    166177            return true;
    167178    }
    168179
    169180    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
    170         if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
     181        if (allocatorFor(cellSize).isPagedOut(deadline)
     182            || normalDestructorAllocatorFor(cellSize).isPagedOut(deadline)
     183            || immortalStructureDestructorAllocatorFor(cellSize).isPagedOut(deadline))
    171184            return true;
    172185    }
    173186
    174     if (m_largeAllocator.isPagedOut(deadline))
     187    if (m_normalSpace.largeAllocator.isPagedOut(deadline)
     188        || m_normalDestructorSpace.largeAllocator.isPagedOut(deadline)
     189        || m_immortalStructureDestructorSpace.largeAllocator.isPagedOut(deadline))
    175190        return true;
    176191
    177     if (m_structureAllocator.isPagedOut(deadline))
    178         return true;
    179 
    180192    return false;
    181193}
     
    183195void MarkedSpace::freeBlock(MarkedBlock* block)
    184196{
    185     allocatorFor(block).removeBlock(block);
     197    block->allocator()->removeBlock(block);
    186198    m_blocks.remove(block);
    187199    if (block->capacity() == MarkedBlock::blockSize) {
  • trunk/Source/JavaScriptCore/heap/MarkedSpace.h

    r128498 r128813  
    7777    MarkedAllocator& firstAllocator();
    7878    MarkedAllocator& allocatorFor(size_t);
    79     MarkedAllocator& allocatorFor(MarkedBlock*);
    80     MarkedAllocator& destructorAllocatorFor(size_t);
    81     void* allocateWithDestructor(size_t);
     79    MarkedAllocator& immortalStructureDestructorAllocatorFor(size_t);
     80    MarkedAllocator& normalDestructorAllocatorFor(size_t);
     81    void* allocateWithNormalDestructor(size_t);
     82    void* allocateWithImmortalStructureDestructor(size_t);
    8283    void* allocateWithoutDestructor(size_t);
    83     void* allocateStructure(size_t);
    8484 
    8585    void resetAllocators();
     
    130130        FixedArray<MarkedAllocator, preciseCount> preciseAllocators;
    131131        FixedArray<MarkedAllocator, impreciseCount> impreciseAllocators;
     132        MarkedAllocator largeAllocator;
    132133    };
    133134
    134     Subspace m_destructorSpace;
     135    Subspace m_normalDestructorSpace;
     136    Subspace m_immortalStructureDestructorSpace;
    135137    Subspace m_normalSpace;
    136     MarkedAllocator m_largeAllocator;
    137     MarkedAllocator m_structureAllocator;
    138138
    139139    Heap* m_heap;
     
    169169    if (bytes <= impreciseCutoff)
    170170        return m_normalSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
    171     return m_largeAllocator;
    172 }
    173 
    174 inline MarkedAllocator& MarkedSpace::allocatorFor(MarkedBlock* block)
    175 {
    176     if (block->onlyContainsStructures())
    177         return m_structureAllocator;
    178 
    179     if (block->cellsNeedDestruction())
    180         return destructorAllocatorFor(block->cellSize());
    181 
    182     return allocatorFor(block->cellSize());
    183 }
    184 
    185 inline MarkedAllocator& MarkedSpace::destructorAllocatorFor(size_t bytes)
     171    return m_normalSpace.largeAllocator;
     172}
     173
     174inline MarkedAllocator& MarkedSpace::immortalStructureDestructorAllocatorFor(size_t bytes)
    186175{
    187176    ASSERT(bytes);
    188177    if (bytes <= preciseCutoff)
    189         return m_destructorSpace.preciseAllocators[(bytes - 1) / preciseStep];
     178        return m_immortalStructureDestructorSpace.preciseAllocators[(bytes - 1) / preciseStep];
    190179    if (bytes <= impreciseCutoff)
    191         return m_normalSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
    192     return m_largeAllocator;
     180        return m_immortalStructureDestructorSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
     181    return m_immortalStructureDestructorSpace.largeAllocator;
     182}
     183
     184inline MarkedAllocator& MarkedSpace::normalDestructorAllocatorFor(size_t bytes)
     185{
     186    ASSERT(bytes);
     187    if (bytes <= preciseCutoff)
     188        return m_normalDestructorSpace.preciseAllocators[(bytes - 1) / preciseStep];
     189    if (bytes <= impreciseCutoff)
     190        return m_normalDestructorSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
     191    return m_normalDestructorSpace.largeAllocator;
    193192}
    194193
     
    198197}
    199198
    200 inline void* MarkedSpace::allocateWithDestructor(size_t bytes)
    201 {
    202     return destructorAllocatorFor(bytes).allocate(bytes);
    203 }
    204 
    205 inline void* MarkedSpace::allocateStructure(size_t bytes)
    206 {
    207     return m_structureAllocator.allocate(bytes);
     199inline void* MarkedSpace::allocateWithImmortalStructureDestructor(size_t bytes)
     200{
     201    return immortalStructureDestructorAllocatorFor(bytes).allocate(bytes);
     202}
     203
     204inline void* MarkedSpace::allocateWithNormalDestructor(size_t bytes)
     205{
     206    return normalDestructorAllocatorFor(bytes).allocate(bytes);
    208207}
    209208
     
    212211    for (size_t i = 0; i < preciseCount; ++i) {
    213212        m_normalSpace.preciseAllocators[i].forEachBlock(functor);
    214         m_destructorSpace.preciseAllocators[i].forEachBlock(functor);
     213        m_normalDestructorSpace.preciseAllocators[i].forEachBlock(functor);
     214        m_immortalStructureDestructorSpace.preciseAllocators[i].forEachBlock(functor);
    215215    }
    216216
    217217    for (size_t i = 0; i < impreciseCount; ++i) {
    218218        m_normalSpace.impreciseAllocators[i].forEachBlock(functor);
    219         m_destructorSpace.impreciseAllocators[i].forEachBlock(functor);
     219        m_normalDestructorSpace.impreciseAllocators[i].forEachBlock(functor);
     220        m_immortalStructureDestructorSpace.impreciseAllocators[i].forEachBlock(functor);
    220221    }
    221222
    222     m_largeAllocator.forEachBlock(functor);
    223     m_structureAllocator.forEachBlock(functor);
     223    m_normalSpace.largeAllocator.forEachBlock(functor);
     224    m_normalDestructorSpace.largeAllocator.forEachBlock(functor);
     225    m_immortalStructureDestructorSpace.largeAllocator.forEachBlock(functor);
    224226
    225227    return functor.returnValue();
  • trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp

    r128084 r128813  
    66#include "CopiedSpaceInlineMethods.h"
    77#include "JSArray.h"
     8#include "JSDestructibleObject.h"
    89#include "JSGlobalData.h"
    910#include "JSObject.h"
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r128802 r128813  
    435435        void emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode, WriteBarrierUseKind);
    436436
    437         template<typename ClassType, bool destructor, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr);
     437        template<typename ClassType, MarkedBlock::DestructorType, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr);
    438438        void emitAllocateBasicStorage(size_t, ptrdiff_t offsetFromBase, RegisterID result);
    439439        template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr);
  • trunk/Source/JavaScriptCore/jit/JITInlineMethods.h

    r128802 r128813  
    406406}
    407407
    408 template <typename ClassType, bool destructor, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, RegisterID result, RegisterID storagePtr)
     408template <typename ClassType, MarkedBlock::DestructorType destructorType, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, RegisterID result, RegisterID storagePtr)
    409409{
    410410    MarkedAllocator* allocator = 0;
    411     if (destructor)
    412         allocator = &m_globalData->heap.allocatorForObjectWithDestructor(sizeof(ClassType));
     411    if (destructorType == MarkedBlock::Normal)
     412        allocator = &m_globalData->heap.allocatorForObjectWithNormalDestructor(sizeof(ClassType));
     413    else if (destructorType == MarkedBlock::ImmortalStructure)
     414        allocator = &m_globalData->heap.allocatorForObjectWithImmortalStructureDestructor(sizeof(ClassType));
    413415    else
    414416        allocator = &m_globalData->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType));
     
    429431template <typename T> inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch)
    430432{
    431     emitAllocateBasicJSObject<JSFinalObject, false, T>(structure, result, scratch);
     433    emitAllocateBasicJSObject<JSFinalObject, MarkedBlock::None, T>(structure, result, scratch);
    432434}
    433435
     
    455457    // Allocate the cell for the array.
    456458    loadPtr(m_codeBlock->globalObject()->addressOfArrayStructure(), scratch);
    457     emitAllocateBasicJSObject<JSArray, false>(scratch, cellResult, storagePtr);
     459    emitAllocateBasicJSObject<JSArray, MarkedBlock::None>(scratch, cellResult, storagePtr);
    458460
    459461    // Store all the necessary info in the ArrayStorage.
  • trunk/Source/JavaScriptCore/jsc.cpp

    r128400 r128813  
    177177        GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure);
    178178        object->finishCreation(globalData, arguments);
     179        globalData.heap.addFinalizer(object, destroy);
    179180        return object;
    180181    }
     
    244245    }
    245246};
     247
     248
     249namespace JSC {
     250NEEDS_DESTRUCTOR(GlobalObject, false);
     251};
     252
    246253COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
    247254ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
  • trunk/Source/JavaScriptCore/runtime/Arguments.cpp

    r128400 r128813  
    3636ASSERT_CLASS_FITS_IN_CELL(Arguments);
    3737
    38 const ClassInfo Arguments::s_info = { "Arguments", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(Arguments) };
     38const ClassInfo Arguments::s_info = { "Arguments", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Arguments) };
    3939
    4040void Arguments::visitChildren(JSCell* cell, SlotVisitor& visitor)
  • trunk/Source/JavaScriptCore/runtime/Arguments.h

    r128260 r128813  
    2727#include "CodeOrigin.h"
    2828#include "JSActivation.h"
     29#include "JSDestructibleObject.h"
    2930#include "JSFunction.h"
    3031#include "JSGlobalObject.h"
     
    5859    };
    5960
    60     class Arguments : public JSNonFinalObject {
     61    class Arguments : public JSDestructibleObject {
    6162    public:
    62         typedef JSNonFinalObject Base;
     63        typedef JSDestructibleObject Base;
    6364
    6465        static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame)
     
    155156
    156157    inline Arguments::Arguments(CallFrame* callFrame)
    157         : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
     158        : JSDestructibleObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
    158159        , d(adoptPtr(new ArgumentsData))
    159160    {
     
    161162
    162163    inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
    163         : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
     164        : JSDestructibleObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
    164165        , d(adoptPtr(new ArgumentsData))
    165166    {
  • trunk/Source/JavaScriptCore/runtime/ErrorPrototype.cpp

    r127505 r128813  
    3232
    3333ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
     34ASSERT_HAS_TRIVIAL_DESTRUCTOR(ErrorPrototype);
    3435
    3536static EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*);
  • trunk/Source/JavaScriptCore/runtime/Executable.h

    r128265 r128813  
    258258    };
    259259
     260    HAS_IMMORTAL_STRUCTURE(ExecutableBase);
     261
    260262    class NativeExecutable : public ExecutableBase {
    261263        friend class JIT;
     
    340342    };
    341343
     344    HAS_IMMORTAL_STRUCTURE(NativeExecutable);
     345
    342346    class ScriptExecutable : public ExecutableBase {
    343347    public:
     
    468472    };
    469473
     474    HAS_IMMORTAL_STRUCTURE(EvalExecutable);
     475
    470476    class ProgramExecutable : public ScriptExecutable {
    471477        friend class LLIntOffsetsExtractor;
     
    534540        OwnPtr<ProgramCodeBlock> m_programCodeBlock;
    535541    };
     542
     543    HAS_IMMORTAL_STRUCTURE(ProgramExecutable);
    536544
    537545    class FunctionExecutable : public ScriptExecutable {
     
    755763        WriteBarrier<SharedSymbolTable> m_symbolTable;
    756764    };
     765
     766    HAS_IMMORTAL_STRUCTURE(FunctionExecutable);
    757767
    758768    inline JSFunction::JSFunction(JSGlobalData& globalData, FunctionExecutable* executable, JSScope* scope)
  • trunk/Source/JavaScriptCore/runtime/InternalFunction.cpp

    r127505 r128813  
    3333ASSERT_HAS_TRIVIAL_DESTRUCTOR(InternalFunction);
    3434
    35 const ClassInfo InternalFunction::s_info = { "Function", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(InternalFunction) };
     35const ClassInfo InternalFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(InternalFunction) };
    3636
    3737InternalFunction::InternalFunction(JSGlobalObject* globalObject, Structure* structure)
    38     : JSNonFinalObject(globalObject->globalData(), structure)
     38    : JSDestructibleObject(globalObject->globalData(), structure)
    3939{
    4040}
  • trunk/Source/JavaScriptCore/runtime/InternalFunction.h

    r127191 r128813  
    2525#define InternalFunction_h
    2626
    27 #include "JSObject.h"
    2827#include "Identifier.h"
     28#include "JSDestructibleObject.h"
    2929
    3030namespace JSC {
     
    3232    class FunctionPrototype;
    3333
    34     class InternalFunction : public JSNonFinalObject {
     34    class InternalFunction : public JSDestructibleObject {
    3535    public:
    36         typedef JSNonFinalObject Base;
     36        typedef JSDestructibleObject Base;
    3737
    3838        static JS_EXPORTDATA const ClassInfo s_info;
  • trunk/Source/JavaScriptCore/runtime/JSCell.h

    r128400 r128813  
    3737namespace JSC {
    3838
     39    class JSDestructibleObject;
    3940    class JSGlobalObject;
    4041    class LLIntOffsetsExtractor;
     
    322323#endif
    323324
     325    template<class T>
     326    struct HasImmortalStructure {
     327        static const bool value = false;
     328    };
     329
     330#define HAS_IMMORTAL_STRUCTURE(klass) \
     331    template <> \
     332    struct HasImmortalStructure<klass> {\
     333        static const bool value = true;\
     334    }
     335
     336#define NEEDS_DESTRUCTOR(klass, v) \
     337    template <> \
     338    struct NeedsDestructor<klass> {\
     339        static const bool value = v;\
     340    }
     341
    324342    template<typename T>
    325343    void* allocateCell(Heap& heap)
     
    330348#endif
    331349        JSCell* result = 0;
    332         if (NeedsDestructor<T>::value)
    333             result = static_cast<JSCell*>(heap.allocateWithDestructor(sizeof(T)));
    334         else {
    335             ASSERT(T::s_info.methodTable.destroy == JSCell::destroy);
     350        if (NeedsDestructor<T>::value && HasImmortalStructure<T>::value)
     351            result = static_cast<JSCell*>(heap.allocateWithImmortalStructureDestructor(sizeof(T)));
     352        else if (NeedsDestructor<T>::value && !HasImmortalStructure<T>::value)
     353            result = static_cast<JSCell*>(heap.allocateWithNormalDestructor(sizeof(T)));
     354        else
    336355            result = static_cast<JSCell*>(heap.allocateWithoutDestructor(sizeof(T)));
    337         }
    338356        result->clearStructure();
    339357        return result;
     
    349367#endif
    350368        JSCell* result = 0;
    351         if (NeedsDestructor<T>::value)
    352             result = static_cast<JSCell*>(heap.allocateWithDestructor(size));
     369        if (NeedsDestructor<T>::value && HasImmortalStructure<T>::value)
     370            result = static_cast<JSCell*>(heap.allocateWithImmortalStructureDestructor(size));
     371        else if (NeedsDestructor<T>::value && !HasImmortalStructure<T>::value)
     372            result = static_cast<JSCell*>(heap.allocateWithNormalDestructor(size));
    353373        else {
    354374            ASSERT(T::s_info.methodTable.destroy == JSCell::destroy);
     
    370390        return static_cast<To>(from);
    371391    }
    372 
     392   
    373393    template<typename To>
    374394    inline To jsCast(JSValue from)
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r128802 r128813  
    229229    m_argumentsStructure.set(exec->globalData(), this, Arguments::createStructure(exec->globalData(), this, m_objectPrototype.get()));
    230230    m_callbackConstructorStructure.set(exec->globalData(), this, JSCallbackConstructor::createStructure(exec->globalData(), this, m_objectPrototype.get()));
    231     m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSNonFinalObject>::createStructure(exec->globalData(), this, m_objectPrototype.get()));
     231    m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSDestructibleObject>::createStructure(exec->globalData(), this, m_objectPrototype.get()));
    232232
    233233    m_arrayPrototype.set(exec->globalData(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r128802 r128813  
    7878    class JSGlobalObject : public JSSegmentedVariableObject {
    7979    private:
    80         typedef JSSegmentedVariableObject Base;
    8180        typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
    8281
     
    169168                return;
    170169            m_rareData = adoptPtr(new JSGlobalObjectRareData);
    171             Heap::heap(this)->addFinalizer(this, clearRareData);
    172170        }
    173171       
    174172    public:
     173        typedef JSSegmentedVariableObject Base;
     174
    175175        static JSGlobalObject* create(JSGlobalData& globalData, Structure* structure)
    176176        {
    177177            JSGlobalObject* globalObject = new (NotNull, allocateCell<JSGlobalObject>(globalData.heap)) JSGlobalObject(globalData, structure);
    178178            globalObject->finishCreation(globalData);
     179            globalData.heap.addFinalizer(globalObject, destroy);
    179180            return globalObject;
    180181        }
     
    380381    };
    381382
     383    // We don't need to be allocated in the destructor space because we use a finalizer instead.
     384    NEEDS_DESTRUCTOR(JSGlobalObject, false);
     385
    382386    JSGlobalObject* asGlobalObject(JSValue);
    383387
  • trunk/Source/JavaScriptCore/runtime/JSGlobalThis.h

    r114457 r128813  
    2727#define JSGlobalThis_h
    2828
    29 #include "JSObject.h"
     29#include "JSDestructibleObject.h"
    3030
    3131namespace JSC {
    3232
    33 class JSGlobalThis : public JSNonFinalObject {
     33class JSGlobalThis : public JSDestructibleObject {
    3434public:
    35     typedef JSNonFinalObject Base;
     35    typedef JSDestructibleObject Base;
    3636
    3737    static JSGlobalThis* create(JSGlobalData& globalData, Structure* structure)
     
    5353protected:
    5454    JSGlobalThis(JSGlobalData& globalData, Structure* structure)
    55         : JSNonFinalObject(globalData, structure)
     55        : JSDestructibleObject(globalData, structure)
    5656    {
    5757    }
  • trunk/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h

    r127958 r128813  
    105105    };
    106106
     107    HAS_IMMORTAL_STRUCTURE(JSPropertyNameIterator);
     108
    107109    inline void Structure::setEnumerationCache(JSGlobalData& globalData, JSPropertyNameIterator* enumerationCache)
    108110    {
  • trunk/Source/JavaScriptCore/runtime/JSScope.cpp

    r127958 r128813  
    3535
    3636ASSERT_CLASS_FITS_IN_CELL(JSScope);
     37ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSScope);
    3738
    3839void JSScope::visitChildren(JSCell* cell, SlotVisitor& visitor)
  • trunk/Source/JavaScriptCore/runtime/JSString.h

    r127958 r128813  
    6060    JSRopeString* jsStringBuilder(JSGlobalData*);
    6161
     62    HAS_IMMORTAL_STRUCTURE(JSString);
     63
    6264    class JSString : public JSCell {
    6365    public:
     
    321323        mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers;
    322324    };
     325
     326    HAS_IMMORTAL_STRUCTURE(JSRopeString);
    323327
    324328    JSString* asString(JSValue);
  • trunk/Source/JavaScriptCore/runtime/JSWrapperObject.h

    r103083 r128813  
    2323#define JSWrapperObject_h
    2424
    25 #include "JSObject.h"
     25#include "JSDestructibleObject.h"
    2626
    2727namespace JSC {
     
    2929    // This class is used as a base for classes such as String,
    3030    // Number, Boolean and Date which are wrappers for primitive types.
    31     class JSWrapperObject : public JSNonFinalObject {
     31    class JSWrapperObject : public JSDestructibleObject {
    3232    public:
    33         typedef JSNonFinalObject Base;
     33        typedef JSDestructibleObject Base;
    3434
    3535        JSValue internalValue() const;
     
    5252
    5353    inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, Structure* structure)
    54         : JSNonFinalObject(globalData, structure)
     54        : JSDestructibleObject(globalData, structure)
    5555    {
    5656    }
  • trunk/Source/JavaScriptCore/runtime/MathObject.cpp

    r119775 r128813  
    3434
    3535ASSERT_CLASS_FITS_IN_CELL(MathObject);
     36ASSERT_HAS_TRIVIAL_DESTRUCTOR(MathObject);
    3637
    3738static EncodedJSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState*);
     
    6061namespace JSC {
    6162
    62 ASSERT_HAS_TRIVIAL_DESTRUCTOR(MathObject);
    63 
    64 const ClassInfo MathObject::s_info = { "Math", &JSNonFinalObject::s_info, 0, ExecState::mathTable, CREATE_METHOD_TABLE(MathObject) };
     63const ClassInfo MathObject::s_info = { "Math", &Base::s_info, 0, ExecState::mathTable, CREATE_METHOD_TABLE(MathObject) };
    6564
    6665/* Source for MathObject.lut.h
  • trunk/Source/JavaScriptCore/runtime/NameInstance.h

    r117859 r128813  
    2727#define NameInstance_h
    2828
    29 #include "JSObject.h"
     29#include "JSDestructibleObject.h"
    3030#include "PrivateName.h"
    3131
    3232namespace JSC {
    3333
    34 class NameInstance : public JSNonFinalObject {
     34class NameInstance : public JSDestructibleObject {
    3535public:
    36     typedef JSNonFinalObject Base;
     36    typedef JSDestructibleObject Base;
    3737
    3838    static const ClassInfo s_info;
  • trunk/Source/JavaScriptCore/runtime/RegExp.h

    r127191 r128813  
    124124    };
    125125
     126    HAS_IMMORTAL_STRUCTURE(RegExp);
     127
    126128} // namespace JSC
    127129
  • trunk/Source/JavaScriptCore/runtime/RegExpObject.cpp

    r128400 r128813  
    5151
    5252ASSERT_CLASS_FITS_IN_CELL(RegExpObject);
    53 
    54 const ClassInfo RegExpObject::s_info = { "RegExp", &JSNonFinalObject::s_info, 0, ExecState::regExpTable, CREATE_METHOD_TABLE(RegExpObject) };
     53ASSERT_HAS_TRIVIAL_DESTRUCTOR(RegExpObject);
     54
     55const ClassInfo RegExpObject::s_info = { "RegExp", &Base::s_info, 0, ExecState::regExpTable, CREATE_METHOD_TABLE(RegExpObject) };
    5556
    5657/* Source for RegExpObject.lut.h
  • trunk/Source/JavaScriptCore/runtime/SparseArrayValueMap.h

    r128802 r128813  
    132132};
    133133
     134HAS_IMMORTAL_STRUCTURE(SparseArrayValueMap);
     135
    134136} // namespace JSC
    135137
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r128802 r128813  
    474474    };
    475475
    476     template <> inline void* allocateCell<Structure>(Heap& heap)
    477     {
    478 #if ENABLE(GC_VALIDATION)
    479         ASSERT(!heap.globalData()->isInitializingObject());
    480         heap.globalData()->setInitializingObjectClass(&Structure::s_info);
    481 #endif
    482         JSCell* result = static_cast<JSCell*>(heap.allocateStructure(sizeof(Structure)));
    483         result->clearStructure();
    484         return result;
    485     }
     476    HAS_IMMORTAL_STRUCTURE(Structure);
    486477
    487478    inline Structure* Structure::create(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType)
     
    629620    }
    630621
    631     inline const ClassInfo* JSCell::classInfo() const
    632     {
    633 #if ENABLE(GC_VALIDATION)
    634         return m_structure.unvalidatedGet()->classInfo();
    635 #else
    636         return m_structure->classInfo();
    637 #endif
    638     }
    639 
    640622} // namespace JSC
    641623
  • trunk/Source/JavaScriptCore/runtime/StructureChain.h

    r108444 r128813  
    8383    };
    8484
     85    HAS_IMMORTAL_STRUCTURE(StructureChain);
     86
    8587} // namespace JSC
    8688
  • trunk/Source/JavaScriptCore/runtime/SymbolTable.h

    r128260 r128813  
    328328    class SharedSymbolTable : public JSCell, public SymbolTable {
    329329    public:
     330        typedef JSCell Base;
     331
    330332        static SharedSymbolTable* create(JSGlobalData& globalData)
    331333        {
     
    381383        int m_captureEnd;
    382384    };
    383    
     385   
     386    HAS_IMMORTAL_STRUCTURE(SharedSymbolTable);
     387 
    384388} // namespace JSC
    385389
  • trunk/Source/JavaScriptCore/testRegExp.cpp

    r127191 r128813  
    116116    static GlobalObject* create(JSGlobalData& globalData, Structure* structure, const Vector<String>& arguments)
    117117    {
    118         return new (NotNull, allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure, arguments);
     118        GlobalObject* globalObject = new (NotNull, allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure, arguments);
     119        globalData.heap.addFinalizer(globalObject, destroy);
     120        return globalObject;
    119121    }
    120122
     
    133135    }
    134136};
     137
     138namespace JSC {
     139NEEDS_DESTRUCTOR(GlobalObject, false);
     140}
    135141
    136142COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
  • trunk/Source/WebCore/ChangeLog

    r128812 r128813  
     12012-09-16  Mark Hahnenberg  <mhahnenberg@apple.com>
     2
     3        Delayed structure sweep can leak structures without bound
     4        https://bugs.webkit.org/show_bug.cgi?id=96546
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        This patch gets rid of the separate Structure allocator in the MarkedSpace and adds two new destructor-only
     9        allocators. We now have separate allocators for our three types of objects: those objects with no destructors,
     10        those objects with destructors and with immortal structures, and those objects with destructors that don't have
     11        immortal structures. All of the objects of the third type (destructors without immortal structures) now
     12        inherit from a new class named JSDestructibleObject (which in turn is a subclass of JSNonFinalObject), which stores
     13        the ClassInfo for these classes at a fixed offset for safe retrieval during sweeping/destruction.
     14
     15        No new tests.
     16
     17        * ForwardingHeaders/runtime/JSDestructableObject.h: Added.
     18        * bindings/js/JSDOMWrapper.h: Inherits from JSDestructibleObject.
     19        (JSDOMWrapper):
     20        (WebCore::JSDOMWrapper::JSDOMWrapper):
     21        * bindings/scripts/CodeGeneratorJS.pm: Add finalizers to anything that inherits from JSGlobalObject,
     22        e.g. JSDOMWindow and JSWorkerContexts. For those classes we also need to use the NEEDS_DESTRUCTOR macro.
     23        (GenerateHeader):
     24        * bridge/objc/objc_runtime.h: Inherit from JSDestructibleObject.
     25        (ObjcFallbackObjectImp):
     26        * bridge/objc/objc_runtime.mm:
     27        (Bindings):
     28        (JSC::Bindings::ObjcFallbackObjectImp::ObjcFallbackObjectImp):
     29        * bridge/runtime_array.cpp: Use a finalizer so that JSArray isn't forced to inherit from JSDestructibleObject.
     30        (JSC):
     31        (JSC::RuntimeArray::destroy):
     32        * bridge/runtime_array.h:
     33        (JSC::RuntimeArray::create):
     34        (JSC):
     35        * bridge/runtime_object.cpp: Inherit from JSDestructibleObject.
     36        (Bindings):
     37        (JSC::Bindings::RuntimeObject::RuntimeObject):
     38        * bridge/runtime_object.h:
     39        (RuntimeObject):
     40
     41<<<<<<< .mine
     422012-09-16  Mark Hahnenberg  <mhahnenberg@apple.com>
     43
     44        Delayed structure sweep can leak structures without bound
     45        https://bugs.webkit.org/show_bug.cgi?id=96546
     46
     47        Reviewed by Gavin Barraclough.
     48
     49        This patch gets rid of the separate Structure allocator in the MarkedSpace and adds two new destructor-only
     50        allocators. We now have separate allocators for our three types of objects: those objects with no destructors,
     51        those objects with destructors and with immortal structures, and those objects with destructors that don't have
     52        immortal structures. All of the objects of the third type (destructors without immortal structures) now
     53        inherit from a new class named JSDestructibleObject (which in turn is a subclass of JSNonFinalObject), which stores
     54        the ClassInfo for these classes at a fixed offset for safe retrieval during sweeping/destruction.
     55
     56        No new tests.
     57
     58        * ForwardingHeaders/runtime/JSDestructableObject.h: Added.
     59        * bindings/js/JSDOMWrapper.h: Inherits from JSDestructibleObject.
     60        (JSDOMWrapper):
     61        (WebCore::JSDOMWrapper::JSDOMWrapper):
     62        * bindings/scripts/CodeGeneratorJS.pm: Add finalizers to anything that inherits from JSGlobalObject,
     63        e.g. JSDOMWindow and JSWorkerContexts. For those classes we also need to use the NEEDS_DESTRUCTOR macro.
     64        (GenerateHeader):
     65        * bridge/objc/objc_runtime.h: Inherit from JSDestructibleObject.
     66        (ObjcFallbackObjectImp):
     67        * bridge/objc/objc_runtime.mm:
     68        (Bindings):
     69        (JSC::Bindings::ObjcFallbackObjectImp::ObjcFallbackObjectImp):
     70        * bridge/runtime_array.cpp: Use a finalizer so that JSArray isn't forced to inherit from JSDestructibleObject.
     71        (JSC):
     72        (JSC::RuntimeArray::destroy):
     73        * bridge/runtime_array.h:
     74        (JSC::RuntimeArray::create):
     75        (JSC):
     76        * bridge/runtime_object.cpp: Inherit from JSDestructibleObject.
     77        (Bindings):
     78        (JSC::Bindings::RuntimeObject::RuntimeObject):
     79        * bridge/runtime_object.h:
     80        (RuntimeObject):
     81
     82=======
    1832012-09-17  Sheriff Bot  <webkit.review.bot@gmail.com>
    284
     
    362444        (.css-named-flow-collections-view .split-view-contents .named-flow-element):
    363445
     446>>>>>>> .r128811
    3644472012-09-17  Zan Dobersek  <zandobersek@gmail.com>
    365448
  • trunk/Source/WebCore/bindings/js/JSDOMWrapper.h

    r125688 r128813  
    2424
    2525#include "JSDOMGlobalObject.h"
    26 #include <runtime/JSObject.h>
     26#include <runtime/JSDestructibleObject.h>
    2727
    2828namespace WebCore {
     
    3030class ScriptExecutionContext;
    3131
    32 class JSDOMWrapper : public JSC::JSNonFinalObject {
     32class JSDOMWrapper : public JSC::JSDestructibleObject {
    3333public:
     34    typedef JSC::JSDestructibleObject Base;
     35
    3436    JSDOMGlobalObject* globalObject() const { return JSC::jsCast<JSDOMGlobalObject*>(JSC::JSNonFinalObject::globalObject()); }
    3537    ScriptExecutionContext* scriptExecutionContext() const { return globalObject()->scriptExecutionContext(); }
     
    3739protected:
    3840    JSDOMWrapper(JSC::Structure* structure, JSC::JSGlobalObject* globalObject)
    39         : JSNonFinalObject(globalObject->globalData(), structure)
     41        : JSDestructibleObject(globalObject->globalData(), structure)
    4042    {
    4143        ASSERT(scriptExecutionContext());
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r128655 r128813  
    743743        push(@headerContent, "        $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalData.heap)) ${className}(globalData, structure, impl, windowShell);\n");
    744744        push(@headerContent, "        ptr->finishCreation(globalData, windowShell);\n");
     745        push(@headerContent, "        globalData.heap.addFinalizer(ptr, destroy);\n");
    745746        push(@headerContent, "        return ptr;\n");
    746747        push(@headerContent, "    }\n\n");
     
    750751        push(@headerContent, "        $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalData.heap)) ${className}(globalData, structure, impl);\n");
    751752        push(@headerContent, "        ptr->finishCreation(globalData);\n");
     753        push(@headerContent, "        globalData.heap.addFinalizer(ptr, destroy);\n");
    752754        push(@headerContent, "        return ptr;\n");
    753755        push(@headerContent, "    }\n\n");
     
    10081010
    10091011    push(@headerContent, "};\n\n");
     1012
     1013    if ($interfaceName eq "DOMWindow" || $dataNode->extendedAttributes->{"IsWorkerContext"}) {
     1014        push(@headerContent, "} // namespace WebCore\n\n");
     1015        push(@headerContent, "namespace JSC {\n");
     1016        push(@headerContent, "NEEDS_DESTRUCTOR(WebCore::${className}, false);\n\n");
     1017        push(@headerContent, "} // namespace JSC\n\n");
     1018        push(@headerContent, "namespace WebCore {\n\n");
     1019    }
    10101020
    10111021    if ($dataNode->extendedAttributes->{"JSInlineGetOwnPropertySlot"} && !$dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
  • trunk/Source/WebCore/bridge/objc/objc_runtime.h

    r127191 r128813  
    9191};
    9292
    93 class ObjcFallbackObjectImp : public JSNonFinalObject {
     93class ObjcFallbackObjectImp : public JSDestructibleObject {
    9494public:
    95     typedef JSNonFinalObject Base;
     95    typedef JSDestructibleObject Base;
    9696
    9797    static ObjcFallbackObjectImp* create(ExecState* exec, JSGlobalObject* globalObject, ObjcInstance* instance, const String& propertyName)
  • trunk/Source/WebCore/bridge/objc/objc_runtime.mm

    r127191 r128813  
    189189}
    190190
    191 const ClassInfo ObjcFallbackObjectImp::s_info = { "ObjcFallbackObject", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(ObjcFallbackObjectImp) };
     191const ClassInfo ObjcFallbackObjectImp::s_info = { "ObjcFallbackObject", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ObjcFallbackObjectImp) };
    192192
    193193ObjcFallbackObjectImp::ObjcFallbackObjectImp(JSGlobalObject* globalObject, Structure* structure, ObjcInstance* i, const String& propertyName)
    194     : JSNonFinalObject(globalObject->globalData(), structure)
     194    : JSDestructibleObject(globalObject->globalData(), structure)
    195195    , _instance(i)
    196196    , m_item(propertyName)
  • trunk/Source/WebCore/bridge/runtime_array.cpp

    r128400 r128813  
    3636namespace JSC {
    3737
    38 const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &JSArray::s_info, 0, 0, CREATE_METHOD_TABLE(RuntimeArray) };
     38const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(RuntimeArray) };
    3939
    4040RuntimeArray::RuntimeArray(ExecState* exec, Structure* structure)
     
    5858void RuntimeArray::destroy(JSCell* cell)
    5959{
    60     static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
     60    jsCast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
    6161}
    6262
  • trunk/Source/WebCore/bridge/runtime_array.h

    r128428 r128813  
    4444        RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(*exec->heap())) RuntimeArray(exec, domStructure);
    4545        runtimeArray->finishCreation(exec->globalData(), array);
     46        exec->globalData().heap.addFinalizer(runtimeArray, destroy);
    4647        return runtimeArray;
    4748    }
     
    8990    BindingsArray* m_array;
    9091};
     92
     93NEEDS_DESTRUCTOR(RuntimeArray, false);
    9194   
    9295} // namespace JSC
  • trunk/Source/WebCore/bridge/runtime_object.cpp

    r121316 r128813  
    3636namespace Bindings {
    3737
    38 const ClassInfo RuntimeObject::s_info = { "RuntimeObject", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(RuntimeObject) };
     38const ClassInfo RuntimeObject::s_info = { "RuntimeObject", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(RuntimeObject) };
    3939
    4040RuntimeObject::RuntimeObject(ExecState*, JSGlobalObject* globalObject, Structure* structure, PassRefPtr<Instance> instance)
    41     : JSNonFinalObject(globalObject->globalData(), structure)
     41    : JSDestructibleObject(globalObject->globalData(), structure)
    4242    , m_instance(instance)
    4343{
  • trunk/Source/WebCore/bridge/runtime_object.h

    r116828 r128813  
    3333namespace Bindings {
    3434
    35 class RuntimeObject : public JSNonFinalObject {
     35class RuntimeObject : public JSDestructibleObject {
    3636public:
    37     typedef JSNonFinalObject Base;
     37    typedef JSDestructibleObject Base;
    3838
    3939    static RuntimeObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, PassRefPtr<Instance> instance)
Note: See TracChangeset for help on using the changeset viewer.