Title: [185277] trunk/Source/_javascript_Core
Revision
185277
Author
[email protected]
Date
2015-06-05 17:33:43 -0700 (Fri, 05 Jun 2015)

Log Message

Subclasses of JSNonFinalObject with gc'able children need to implement visitChildren().
https://bugs.webkit.org/show_bug.cgi?id=145709

Reviewed by Geoffrey Garen.

* jsc.cpp:
(functionSetElementRoot):
- The Element class has a member of type Root which extends JSDestructibleObject.
  It should be stored in a WriteBarrier, and visited by visitChildren().  

* runtime/ClonedArguments.cpp:
(JSC::ClonedArguments::materializeSpecialsIfNecessary):
(JSC::ClonedArguments::visitChildren):
* runtime/ClonedArguments.h:
- Add missing visitChildren().

* tests/stress/cloned-arguments-should-visit-callee-during-gc.js: Added.
(makeTransientFunction.transientFunc):
(makeTransientFunction):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (185276 => 185277)


--- trunk/Source/_javascript_Core/ChangeLog	2015-06-06 00:04:40 UTC (rev 185276)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-06-06 00:33:43 UTC (rev 185277)
@@ -1,3 +1,25 @@
+2015-06-05  Mark Lam  <[email protected]>
+
+        Subclasses of JSNonFinalObject with gc'able children need to implement visitChildren().
+        https://bugs.webkit.org/show_bug.cgi?id=145709
+
+        Reviewed by Geoffrey Garen.
+
+        * jsc.cpp:
+        (functionSetElementRoot):
+        - The Element class has a member of type Root which extends JSDestructibleObject.
+          It should be stored in a WriteBarrier, and visited by visitChildren().  
+
+        * runtime/ClonedArguments.cpp:
+        (JSC::ClonedArguments::materializeSpecialsIfNecessary):
+        (JSC::ClonedArguments::visitChildren):
+        * runtime/ClonedArguments.h:
+        - Add missing visitChildren().
+
+        * tests/stress/cloned-arguments-should-visit-callee-during-gc.js: Added.
+        (makeTransientFunction.transientFunc):
+        (makeTransientFunction):
+
 2015-06-05  Geoffrey Garen  <[email protected]>
 
         DropAllLocks RELEASE_ASSERT on iOS

Modified: trunk/Source/_javascript_Core/jsc.cpp (185276 => 185277)


--- trunk/Source/_javascript_Core/jsc.cpp	2015-06-06 00:04:40 UTC (rev 185276)
+++ trunk/Source/_javascript_Core/jsc.cpp	2015-06-06 00:33:43 UTC (rev 185277)
@@ -130,28 +130,35 @@
 
 class Element : public JSNonFinalObject {
 public:
-    Element(VM& vm, Structure* structure, Root* root)
+    Element(VM& vm, Structure* structure)
         : 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; }
+    Root* root() const { return m_root.get(); }
+    void setRoot(VM& vm, Root* root) { m_root.set(vm, this, root); }
 
     static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
     {
         Structure* structure = createStructure(vm, globalObject, jsNull());
-        Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure, root);
-        element->finishCreation(vm);
+        Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure);
+        element->finishCreation(vm, root);
         return element;
     }
 
-    void finishCreation(VM&);
+    void finishCreation(VM&, Root*);
 
+    static void visitChildren(JSCell* cell, SlotVisitor& visitor)
+    {
+        Element* thisObject = jsCast<Element*>(cell);
+        ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+        Base::visitChildren(thisObject, visitor);
+        visitor.append(&thisObject->m_root);
+    }
+
     static ElementHandleOwner* handleOwner();
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
@@ -162,7 +169,7 @@
     DECLARE_INFO;
 
 private:
-    Root* m_root;
+    WriteBarrier<Root> m_root;
 };
 
 class ElementHandleOwner : public WeakHandleOwner {
@@ -421,9 +428,10 @@
     return owner;
 }
 
-void Element::finishCreation(VM& vm)
+void Element::finishCreation(VM& vm, Root* root)
 {
     Base::finishCreation(vm);
+    setRoot(vm, root);
     m_root->setElement(this);
 }
 
@@ -786,7 +794,7 @@
     JSLockHolder lock(exec);
     Element* element = jsCast<Element*>(exec->argument(0));
     Root* root = jsCast<Root*>(exec->argument(1));
-    element->setRoot(root);
+    element->setRoot(exec->vm(), root);
     return JSValue::encode(jsUndefined());
 }
 

Modified: trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp (185276 => 185277)


--- trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp	2015-06-06 00:04:40 UTC (rev 185276)
+++ trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp	2015-06-06 00:33:43 UTC (rev 185277)
@@ -218,5 +218,13 @@
         materializeSpecials(exec);
 }
 
+void ClonedArguments::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    ClonedArguments* thisObject = jsCast<ClonedArguments*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    Base::visitChildren(thisObject, visitor);
+    visitor.append(&thisObject->m_callee);
+}
+
 } // namespace JSC
 

Modified: trunk/Source/_javascript_Core/runtime/ClonedArguments.h (185276 => 185277)


--- trunk/Source/_javascript_Core/runtime/ClonedArguments.h	2015-06-06 00:04:40 UTC (rev 185276)
+++ trunk/Source/_javascript_Core/runtime/ClonedArguments.h	2015-06-06 00:33:43 UTC (rev 185277)
@@ -55,6 +55,8 @@
     
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
 
+    static void visitChildren(JSCell*, SlotVisitor&);
+
     DECLARE_INFO;
 
 private:

Added: trunk/Source/_javascript_Core/tests/stress/cloned-arguments-should-visit-callee-during-gc.js (0 => 185277)


--- trunk/Source/_javascript_Core/tests/stress/cloned-arguments-should-visit-callee-during-gc.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/cloned-arguments-should-visit-callee-during-gc.js	2015-06-06 00:33:43 UTC (rev 185277)
@@ -0,0 +1,34 @@
+// Test that the ClonedArguments created by the Function.arguments will properly
+// keep its callee alive.  This test should not crash and should not print any error
+// messages.
+
+var cachedArguments = [];
+var numberOfEntries = 1000;
+
+function makeTransientFunction(i) {
+    function transientFunc() {
+        cachedArguments[i] = transientFunc.arguments;
+    }
+    return transientFunc;
+}
+
+for (i = 0; i < numberOfEntries; i++) {
+    var transientFunc = makeTransientFunction(i);
+    transientFunc();
+    // At this point, the only reference to the transient function is from
+    // cachedArguments[i].callee.
+}
+
+gc();
+
+// Allocate a bunch of memory to stomp over the transient functions that may have been
+// erroneously collected. webkit.org/b/145709
+for (i = 0; i < numberOfEntries; i++) {
+    new Object();
+}
+
+for (i = 0; i < numberOfEntries; i++) {
+    var callee = cachedArguments[i].callee;
+    if (typeof callee != "function")
+        print("ERROR: callee is " + callee); 
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to