<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[171527] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/171527">171527</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2014-07-24 15:01:40 -0700 (Thu, 24 Jul 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>JSWrapperMap's jsWrapperForObject() needs to defer GC.
&lt;https://webkit.org/b/135258&gt;

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:]):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreAPIJSWrapperMapmm">trunk/Source/JavaScriptCore/API/JSWrapperMap.mm</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreAPIJSWrapperMapmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/JSWrapperMap.mm (171526 => 171527)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/JSWrapperMap.mm        2014-07-24 21:37:43 UTC (rev 171526)
+++ trunk/Source/JavaScriptCore/API/JSWrapperMap.mm        2014-07-24 22:01:40 UTC (rev 171527)
</span><span class="lines">@@ -582,6 +582,9 @@
</span><span class="cx"> 
</span><span class="cx"> - (JSValue *)jsWrapperForObject:(id)object
</span><span class="cx"> {
</span><ins>+    JSC::ExecState* exec = toJS([m_context JSGlobalContextRef]);
+    JSC::DeferGC deferGC(exec-&gt;vm().heap);
+
</ins><span class="cx">     JSC::JSObject* jsWrapper = m_cachedJSWrappers.get(object);
</span><span class="cx">     if (jsWrapper)
</span><span class="cx">         return [JSValue valueWithJSValueRef:toRef(jsWrapper) inContext:m_context];
</span><span class="lines">@@ -599,7 +602,6 @@
</span><span class="cx">     // (1) For immortal objects JSValues will effectively leak and this results in error output being logged - we should avoid adding associated objects to immortal objects.
</span><span class="cx">     // (2) A long lived object may rack up many JSValues. When the contexts are released these will unprotect the associated JavaScript objects,
</span><span class="cx">     //     but still, would probably nicer if we made it so that only one associated object was required, broadcasting object dealloc.
</span><del>-    JSC::ExecState* exec = toJS([m_context JSGlobalContextRef]);
</del><span class="cx">     jsWrapper = toJS(exec, valueInternalValue(wrapper)).toObject(exec);
</span><span class="cx">     m_cachedJSWrappers.set(object, jsWrapper);
</span><span class="cx">     return wrapper;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (171526 => 171527)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-07-24 21:37:43 UTC (rev 171526)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-07-24 22:01:40 UTC (rev 171527)
</span><span class="lines">@@ -1,3 +1,40 @@
</span><ins>+2014-07-24  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        JSWrapperMap's jsWrapperForObject() needs to defer GC.
+        &lt;https://webkit.org/b/135258&gt;
+
+        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:]):
+
</ins><span class="cx"> 2014-07-23  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Build fix after r171482.
</span></span></pre>
</div>
</div>

</body>
</html>