<!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>[163507] 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/163507">163507</a></dd>
<dt>Author</dt> <dd>mhahnenberg@apple.com</dd>
<dt>Date</dt> <dd>2014-02-05 19:38:19 -0800 (Wed, 05 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Handling of opaque roots is wrong in EdenCollections
https://bugs.webkit.org/show_bug.cgi?id=128210

Reviewed by Oliver Hunt.

The set of opaque roots is always cleared during each collection. We should instead persist
the set of opaque roots across EdenCollections and only clear it at the beginning of FullCollections.

Also added a couple of custom objects to the jsc shell that allow us to test this.

* heap/GCThreadSharedData.cpp:
(JSC::GCThreadSharedData::reset):
(JSC::GCThreadSharedData::didStartMarking):
* heap/Heap.cpp:
(JSC::Heap::markRoots):
* heap/Heap.h:
(JSC::Heap::setShouldDoFullCollection):
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::didStartMarking):
(JSC::SlotVisitor::reset):
* heap/SlotVisitor.h:
* jsc.cpp:
(WTF::Element::Element):
(WTF::Element::root):
(WTF::Element::setRoot):
(WTF::Element::create):
(WTF::Element::createStructure):
(WTF::ElementHandleOwner::isReachableFromOpaqueRoots):
(WTF::Root::Root):
(WTF::Root::element):
(WTF::Root::setElement):
(WTF::Root::create):
(WTF::Root::createStructure):
(WTF::Root::visitChildren):
(WTF::Element::handleOwner):
(WTF::Element::finishCreation):
(GlobalObject::finishCreation):
(functionCreateRoot):
(functionCreateElement):
(functionGetElement):
(functionSetElementRoot):
(functionGCAndSweep):
(functionFullGC):
(functionEdenGC):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapGCThreadSharedDatacpp">trunk/Source/JavaScriptCore/heap/GCThreadSharedData.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorcpp">trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorh">trunk/Source/JavaScriptCore/heap/SlotVisitor.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (163506 => 163507)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-02-06 03:07:17 UTC (rev 163506)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-02-06 03:38:19 UTC (rev 163507)
</span><span class="lines">@@ -1,3 +1,50 @@
</span><ins>+2014-02-05  Mark Hahnenberg  &lt;mhahnenberg@apple.com&gt;
+
+        Handling of opaque roots is wrong in EdenCollections
+        https://bugs.webkit.org/show_bug.cgi?id=128210
+
+        Reviewed by Oliver Hunt.
+
+        The set of opaque roots is always cleared during each collection. We should instead persist 
+        the set of opaque roots across EdenCollections and only clear it at the beginning of FullCollections.
+
+        Also added a couple of custom objects to the jsc shell that allow us to test this.
+
+        * heap/GCThreadSharedData.cpp:
+        (JSC::GCThreadSharedData::reset):
+        (JSC::GCThreadSharedData::didStartMarking):
+        * heap/Heap.cpp:
+        (JSC::Heap::markRoots):
+        * heap/Heap.h:
+        (JSC::Heap::setShouldDoFullCollection):
+        * heap/SlotVisitor.cpp:
+        (JSC::SlotVisitor::didStartMarking):
+        (JSC::SlotVisitor::reset):
+        * heap/SlotVisitor.h:
+        * jsc.cpp:
+        (WTF::Element::Element):
+        (WTF::Element::root):
+        (WTF::Element::setRoot):
+        (WTF::Element::create):
+        (WTF::Element::createStructure):
+        (WTF::ElementHandleOwner::isReachableFromOpaqueRoots):
+        (WTF::Root::Root):
+        (WTF::Root::element):
+        (WTF::Root::setElement):
+        (WTF::Root::create):
+        (WTF::Root::createStructure):
+        (WTF::Root::visitChildren):
+        (WTF::Element::handleOwner):
+        (WTF::Element::finishCreation):
+        (GlobalObject::finishCreation):
+        (functionCreateRoot):
+        (functionCreateElement):
+        (functionGetElement):
+        (functionSetElementRoot):
+        (functionGCAndSweep):
+        (functionFullGC):
+        (functionEdenGC):
+
</ins><span class="cx"> 2014-02-05  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove unused functions.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCThreadSharedDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/GCThreadSharedData.cpp (163506 => 163507)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCThreadSharedData.cpp        2014-02-06 03:07:17 UTC (rev 163506)
+++ trunk/Source/JavaScriptCore/heap/GCThreadSharedData.cpp        2014-02-06 03:38:19 UTC (rev 163507)
</span><span class="lines">@@ -118,16 +118,11 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><del>-    
</del><ins>+
</ins><span class="cx"> void GCThreadSharedData::reset()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_sharedMarkStack.isEmpty());
</span><span class="cx">     
</span><del>-#if ENABLE(PARALLEL_GC)
-    m_opaqueRoots.clear();
-#else
-    ASSERT(m_opaqueRoots.isEmpty());
-#endif
</del><span class="cx">     m_weakReferenceHarvesters.removeAll();
</span><span class="cx"> 
</span><span class="cx">     if (m_shouldHashCons) {
</span><span class="lines">@@ -158,6 +153,13 @@
</span><span class="cx"> 
</span><span class="cx"> void GCThreadSharedData::didStartMarking()
</span><span class="cx"> {
</span><ins>+    if (m_vm-&gt;heap.operationInProgress() == FullCollection) {
+#if ENABLE(PARALLEL_GC)
+        m_opaqueRoots.clear();
+#else
+        ASSERT(m_opaqueRoots.isEmpty());
+#endif
+}
</ins><span class="cx">     std::lock_guard&lt;std::mutex&gt; lock(m_markingMutex);
</span><span class="cx">     m_parallelMarkersShouldExit = false;
</span><span class="cx">     startNextPhase(Mark);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (163506 => 163507)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2014-02-06 03:07:17 UTC (rev 163506)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2014-02-06 03:38:19 UTC (rev 163507)
</span><span class="lines">@@ -490,7 +490,7 @@
</span><span class="cx"> 
</span><span class="cx">     m_sharedData.didStartMarking();
</span><span class="cx">     SlotVisitor&amp; visitor = m_slotVisitor;
</span><del>-    visitor.setup();
</del><ins>+    visitor.didStartMarking();
</ins><span class="cx">     HeapRootVisitor heapRootVisitor(visitor);
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(GGC)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (163506 => 163507)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2014-02-06 03:07:17 UTC (rev 163506)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2014-02-06 03:38:19 UTC (rev 163507)
</span><span class="lines">@@ -148,7 +148,8 @@
</span><span class="cx">         JS_EXPORT_PRIVATE void collectAllGarbage();
</span><span class="cx">         bool shouldCollect();
</span><span class="cx">         void gcTimerDidFire() { m_shouldDoFullCollection = true; }
</span><del>-        void collect();
</del><ins>+        void setShouldDoFullCollection(bool shouldDoFullCollection) { m_shouldDoFullCollection = shouldDoFullCollection; }
+        JS_EXPORT_PRIVATE void collect();
</ins><span class="cx">         bool collectIfNecessaryOrDefer(); // Returns true if it did collect.
</span><span class="cx"> 
</span><span class="cx">         void reportExtraMemoryCost(size_t cost);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp (163506 => 163507)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2014-02-06 03:07:17 UTC (rev 163506)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2014-02-06 03:38:19 UTC (rev 163507)
</span><span class="lines">@@ -36,8 +36,16 @@
</span><span class="cx">     clearMarkStack();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SlotVisitor::setup()
</del><ins>+void SlotVisitor::didStartMarking()
</ins><span class="cx"> {
</span><ins>+    if (heap()-&gt;operationInProgress() == FullCollection) {
+#if ENABLE(PARALLEL_GC)
+        ASSERT(m_opaqueRoots.isEmpty()); // Should have merged by now.
+#else
+        m_opaqueRoots.clear();
+#endif
+    }
+
</ins><span class="cx">     m_shared.m_shouldHashCons = m_shared.m_vm-&gt;haveEnoughNewStringsToHashCons();
</span><span class="cx">     m_shouldHashCons = m_shared.m_shouldHashCons;
</span><span class="cx"> #if ENABLE(PARALLEL_GC)
</span><span class="lines">@@ -52,11 +60,6 @@
</span><span class="cx">     m_bytesCopied = 0;
</span><span class="cx">     m_visitCount = 0;
</span><span class="cx">     ASSERT(m_stack.isEmpty());
</span><del>-#if ENABLE(PARALLEL_GC)
-    ASSERT(m_opaqueRoots.isEmpty()); // Should have merged by now.
-#else
-    m_opaqueRoots.clear();
-#endif
</del><span class="cx">     if (m_shouldHashCons) {
</span><span class="cx">         m_uniqueStrings.clear();
</span><span class="cx">         m_shouldHashCons = false;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.h (163506 => 163507)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2014-02-06 03:07:17 UTC (rev 163506)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2014-02-06 03:38:19 UTC (rev 163507)
</span><span class="lines">@@ -78,7 +78,7 @@
</span><span class="cx">     GCThreadSharedData&amp; sharedData() const { return m_shared; }
</span><span class="cx">     bool isEmpty() { return m_stack.isEmpty(); }
</span><span class="cx"> 
</span><del>-    void setup();
</del><ins>+    void didStartMarking();
</ins><span class="cx">     void reset();
</span><span class="cx">     void clearMarkStack();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (163506 => 163507)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2014-02-06 03:07:17 UTC (rev 163506)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2014-02-06 03:38:19 UTC (rev 163507)
</span><span class="lines">@@ -92,13 +92,136 @@
</span><span class="cx"> using namespace JSC;
</span><span class="cx"> using namespace WTF;
</span><span class="cx"> 
</span><ins>+namespace {
+
+class Element;
+class ElementHandleOwner;
+class Root;
+
+class Element : public JSNonFinalObject {
+public:
+    Element(VM&amp; vm, Structure* structure, Root* root)
+        : Base(vm, structure)
+        , m_root(root)
+    {
+    }
+
+    typedef JSNonFinalObject Base;
+    static const bool needsDestruction = false;
+
+    Root* root() const { return m_root; }
+    void setRoot(Root* root) { m_root = root; }
+
+    static Element* create(VM&amp; vm, JSGlobalObject* globalObject, Root* root)
+    {
+        Structure* structure = createStructure(vm, globalObject, jsNull());
+        Element* element = new (NotNull, allocateCell&lt;Element&gt;(vm.heap, sizeof(Element))) Element(vm, structure, root);
+        element-&gt;finishCreation(vm);
+        return element;
+    }
+
+    void finishCreation(VM&amp;);
+
+    static ElementHandleOwner* handleOwner();
+
+    static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+    }
+
+    DECLARE_INFO;
+
+private:
+    Root* m_root;
+};
+
+class ElementHandleOwner : public WeakHandleOwner {
+public:
+    virtual bool isReachableFromOpaqueRoots(Handle&lt;JSC::Unknown&gt; handle, void*, SlotVisitor&amp; visitor)
+    {
+        Element* element = jsCast&lt;Element*&gt;(handle.slot()-&gt;asCell());
+        return visitor.containsOpaqueRoot(element-&gt;root());
+    }
+};
+
+class Root : public JSDestructibleObject {
+public:
+    Root(VM&amp; vm, Structure* structure)
+        : Base(vm, structure)
+    {
+    }
+
+    Element* element()
+    {
+        return m_element.get();
+    }
+
+    void setElement(Element* element)
+    {
+        Weak&lt;Element&gt; newElement(element, Element::handleOwner());
+        m_element.swap(newElement);
+    }
+
+    static Root* create(VM&amp; vm, JSGlobalObject* globalObject)
+    {
+        Structure* structure = createStructure(vm, globalObject, jsNull());
+        Root* root = new (NotNull, allocateCell&lt;Root&gt;(vm.heap, sizeof(Root))) Root(vm, structure);
+        root-&gt;finishCreation(vm);
+        return root;
+    }
+
+    typedef JSDestructibleObject Base;
+
+    DECLARE_INFO;
+    static const bool needsDestruction = true;
+
+    static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+    }
+
+    static void visitChildren(JSCell* thisObject, SlotVisitor&amp; visitor)
+    {
+        Base::visitChildren(thisObject, visitor);
+        visitor.addOpaqueRoot(thisObject);
+    }
+
+private:
+    Weak&lt;Element&gt; m_element;
+};
+
+const ClassInfo Element::s_info = { &quot;Element&quot;, &amp;Base::s_info, 0, 0, CREATE_METHOD_TABLE(Element) };
+const ClassInfo Root::s_info = { &quot;Root&quot;, &amp;Base::s_info, 0, 0, CREATE_METHOD_TABLE(Root) };
+
+ElementHandleOwner* Element::handleOwner()
+{
+    static ElementHandleOwner* owner = 0;
+    if (!owner)
+        owner = new ElementHandleOwner();
+    return owner;
+}
+
+void Element::finishCreation(VM&amp; vm)
+{
+    Base::finishCreation(vm);
+    m_root-&gt;setElement(this);
+}
+
+}
+
</ins><span class="cx"> static bool fillBufferWithContentsOfFile(const String&amp; fileName, Vector&lt;char&gt;&amp; buffer);
</span><span class="cx"> 
</span><ins>+static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);
</ins><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
</span><del>-static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
</del><ins>+static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
</span><span class="lines">@@ -219,7 +342,9 @@
</span><span class="cx">         addFunction(vm, &quot;describe&quot;, functionDescribe, 1);
</span><span class="cx">         addFunction(vm, &quot;print&quot;, functionPrint, 1);
</span><span class="cx">         addFunction(vm, &quot;quit&quot;, functionQuit, 0);
</span><del>-        addFunction(vm, &quot;gc&quot;, functionGC, 0);
</del><ins>+        addFunction(vm, &quot;gc&quot;, functionGCAndSweep, 0);
+        addFunction(vm, &quot;fullGC&quot;, functionFullGC, 0);
+        addFunction(vm, &quot;edenGC&quot;, functionEdenGC, 0);
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx">         addFunction(vm, &quot;dumpCallFrame&quot;, functionDumpCallFrame, 0);
</span><span class="cx">         addFunction(vm, &quot;releaseExecutableMemory&quot;, functionReleaseExecutableMemory, 0);
</span><span class="lines">@@ -241,6 +366,10 @@
</span><span class="cx">         addFunction(vm, &quot;setSamplingFlags&quot;, functionSetSamplingFlags, 1);
</span><span class="cx">         addFunction(vm, &quot;clearSamplingFlags&quot;, functionClearSamplingFlags, 1);
</span><span class="cx"> #endif
</span><ins>+        addConstructableFunction(vm, &quot;Root&quot;, functionCreateRoot, 0);
+        addConstructableFunction(vm, &quot;Element&quot;, functionCreateElement, 1);
+        addFunction(vm, &quot;getElement&quot;, functionGetElement, 1);
+        addFunction(vm, &quot;setElementRoot&quot;, functionSetElementRoot, 2);
</ins><span class="cx">         
</span><span class="cx">         JSArray* array = constructEmptyArray(globalExec(), 0);
</span><span class="cx">         for (size_t i = 0; i &lt; arguments.size(); ++i)
</span><span class="lines">@@ -357,13 +486,60 @@
</span><span class="cx">     return JSValue::encode(jsUndefined());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
</del><ins>+EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
</ins><span class="cx"> {
</span><span class="cx">     JSLockHolder lock(exec);
</span><ins>+    return JSValue::encode(Root::create(exec-&gt;vm(), exec-&gt;lexicalGlobalObject()));
+}
+
+EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
+{
+    JSLockHolder lock(exec);
+    JSValue arg = exec-&gt;argument(0);
+    return JSValue::encode(Element::create(exec-&gt;vm(), exec-&gt;lexicalGlobalObject(), arg.isNull() ? nullptr : jsCast&lt;Root*&gt;(exec-&gt;argument(0))));
+}
+
+EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
+{
+    JSLockHolder lock(exec);
+    Element* result = jsCast&lt;Root*&gt;(exec-&gt;argument(0).asCell())-&gt;element();
+    return JSValue::encode(result ? result : jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
+{
+    JSLockHolder lock(exec);
+    Element* element = jsCast&lt;Element*&gt;(exec-&gt;argument(0));
+    Root* root = jsCast&lt;Root*&gt;(exec-&gt;argument(1));
+    element-&gt;setRoot(root);
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
+{
+    JSLockHolder lock(exec);
</ins><span class="cx">     exec-&gt;heap()-&gt;collectAllGarbage();
</span><span class="cx">     return JSValue::encode(jsUndefined());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
+{
+    JSLockHolder lock(exec);
+    Heap* heap = exec-&gt;heap();
+    heap-&gt;setShouldDoFullCollection(true);
+    exec-&gt;heap()-&gt;collect();
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
+{
+    JSLockHolder lock(exec);
+    Heap* heap = exec-&gt;heap();
+    heap-&gt;setShouldDoFullCollection(false);
+    heap-&gt;collect();
+    return JSValue::encode(jsUndefined());
+}
+
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
</span><span class="cx"> {
</span></span></pre>
</div>
</div>

</body>
</html>