Changeset 171527 in webkit


Ignore:
Timestamp:
Jul 24, 2014, 3:01:40 PM (11 years ago)
Author:
mark.lam@apple.com
Message:

JSWrapperMap's jsWrapperForObject() needs to defer GC.
<https://webkit.org/b/135258>

Reviewed by Oliver Hunt.

In the process of creating a JS wrapper, jsWrapperForObject() will create
the prototype and constructor of the corresponding ObjC class, as well as
for classes in its inheritance chain. These prototypes and constructors
are stored in Weak references in the JSObjCClassInfo objects. During all
the allocation that is being done to create all the prototypes and
constructors as well as the wrapper objects, a GC may occur thereby
collecting one or more of these newly created prototype and constructor
objects.

One example of where this problem can manifest is in wrapperForObject()
which is called from jsWrapperForObject(). In wrapperFoObject(), we do
the following steps:

  1. reallocateConstructorAndOrPrototype() which creates the prototype object and store it in JSObjCClassInfo's m_prototype which is a Weak ref.
  2. makeWrapper() to create the wrapper object, which may trigger a GC. GC will collect the prototype object and nullify the corresponding JSObjCClassInfo's m_prototype Weak ref.
  3. call JSObjectSetPrototype() to set the JSObjCClassInfo's m_prototype in the newly created wrapper. This results in the wrapper getting a jsNull as a prototype instead of the expected prototype object.

To ensure that the prototype and constructor objects are retained until
they can be referenced properly from the wrapper object,
jsWrapperForObject() should defer GC until it's done with its work.

  • API/JSWrapperMap.mm:

(-[JSWrapperMap jsWrapperForObject:]):

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSWrapperMap.mm

    r165074 r171527  
    583583- (JSValue *)jsWrapperForObject:(id)object
    584584{
     585    JSC::ExecState* exec = toJS([m_context JSGlobalContextRef]);
     586    JSC::DeferGC deferGC(exec->vm().heap);
     587
    585588    JSC::JSObject* jsWrapper = m_cachedJSWrappers.get(object);
    586589    if (jsWrapper)
     
    600603    // (2) A long lived object may rack up many JSValues. When the contexts are released these will unprotect the associated JavaScript objects,
    601604    //     but still, would probably nicer if we made it so that only one associated object was required, broadcasting object dealloc.
    602     JSC::ExecState* exec = toJS([m_context JSGlobalContextRef]);
    603605    jsWrapper = toJS(exec, valueInternalValue(wrapper)).toObject(exec);
    604606    m_cachedJSWrappers.set(object, jsWrapper);
  • trunk/Source/JavaScriptCore/ChangeLog

    r171483 r171527  
     12014-07-24  Mark Lam  <mark.lam@apple.com>
     2
     3        JSWrapperMap's jsWrapperForObject() needs to defer GC.
     4        <https://webkit.org/b/135258>
     5
     6        Reviewed by Oliver Hunt.
     7
     8        In the process of creating a JS wrapper, jsWrapperForObject() will create
     9        the prototype and constructor of the corresponding ObjC class, as well as
     10        for classes in its inheritance chain.  These prototypes and constructors
     11        are stored in Weak references in the JSObjCClassInfo objects.  During all
     12        the allocation that is being done to create all the prototypes and
     13        constructors as well as the wrapper objects, a GC may occur thereby
     14        collecting one or more of these newly created prototype and constructor
     15        objects.
     16
     17        One example of where this problem can manifest is in wrapperForObject()
     18        which is called from jsWrapperForObject().  In wrapperFoObject(), we do
     19        the following steps:
     20
     21        1. reallocateConstructorAndOrPrototype() which creates the prototype
     22           object and store it in JSObjCClassInfo's m_prototype which is a Weak
     23           ref.
     24        2. makeWrapper() to create the wrapper object, which may trigger a GC.
     25           GC will collect the prototype object and nullify the corresponding
     26           JSObjCClassInfo's m_prototype Weak ref.
     27        3. call JSObjectSetPrototype() to set the JSObjCClassInfo's m_prototype
     28           in the newly created wrapper.  This results in the wrapper getting a
     29           jsNull as a prototype instead of the expected prototype object.
     30
     31        To ensure that the prototype and constructor objects are retained until
     32        they can be referenced properly from the wrapper object,
     33        jsWrapperForObject() should defer GC until it's done with its work.
     34
     35        * API/JSWrapperMap.mm:
     36        (-[JSWrapperMap jsWrapperForObject:]):
     37
    1382014-07-23  Brent Fulgham  <bfulgham@apple.com>
    239
Note: See TracChangeset for help on using the changeset viewer.