2011-04-25 Geoffrey Garen <ggaren@apple.com>
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Apr 2011 06:23:14 +0000 (06:23 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Apr 2011 06:23:14 +0000 (06:23 +0000)
        Reviewed by Oliver Hunt.

        Custom prototypes on DOM objects don't persist after garbage collection
        https://bugs.webkit.org/show_bug.cgi?id=59412

        SunSpider reports no change.

        The hasCustomProperties() check didn't check for a custom prototype.

        * runtime/JSObject.h:
        (JSC::JSObject::hasCustomProperties): Changed to delegate to Structure
        because it is the "truth" about an object's pedigree.

        * runtime/Structure.cpp:
        (JSC::Structure::Structure):
        * runtime/Structure.h:
        (JSC::Structure::didTransition): Track whether a Structure has ever
        transitioned for any reason. If so, we have to assume that the object
        holding it is custom in some way.
2011-04-25  Geoffrey Garen  <ggaren@apple.com>

        Reviewed by Oliver Hunt.

        Custom prototypes on DOM objects don't persist after garbage collection
        https://bugs.webkit.org/show_bug.cgi?id=59412

        * fast/dom/gc-custom-prototype-expected.txt: Added.
        * fast/dom/gc-custom-prototype.html: Added.
        * fast/dom/script-tests/dataset-gc.js:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@84882 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/dom/gc-custom-prototype-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/gc-custom-prototype.html [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/Structure.h

index a585129..e65499d 100644 (file)
@@ -1,3 +1,14 @@
+2011-04-25  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Custom prototypes on DOM objects don't persist after garbage collection
+        https://bugs.webkit.org/show_bug.cgi?id=59412
+
+        * fast/dom/gc-custom-prototype-expected.txt: Added.
+        * fast/dom/gc-custom-prototype.html: Added.
+        * fast/dom/script-tests/dataset-gc.js:
+
 2011-04-25  Daniel Bates  <dbates@webkit.org>
 
         Update some call sites that referenced the old location for
diff --git a/LayoutTests/fast/dom/gc-custom-prototype-expected.txt b/LayoutTests/fast/dom/gc-custom-prototype-expected.txt
new file mode 100644 (file)
index 0000000..07cb33f
--- /dev/null
@@ -0,0 +1,6 @@
+Tests that custom prototypes on DOM objects persist after garbage collection.
+
+PASS: $('p').__proto__ should be null and is.
+PASS: $('p').__proto__ should be null and is.
+PASS: $('p').__proto__ should be null and is.
+
diff --git a/LayoutTests/fast/dom/gc-custom-prototype.html b/LayoutTests/fast/dom/gc-custom-prototype.html
new file mode 100644 (file)
index 0000000..3783d54
--- /dev/null
@@ -0,0 +1,70 @@
+<p>Tests that custom prototypes on DOM objects persist after garbage collection.</p>
+<pre id="console"></pre>
+
+<p id="p"></p>
+
+<script>
+function $(id)
+{
+    return document.getElementById(id);
+}
+
+function log(s)
+{
+    $("console").appendChild(document.createTextNode(s + "\n"));
+}
+
+function shouldBe(aDescription, a, b)
+{
+    if (a != b) {
+        log("FAIL: " + aDescription + " should be " + b + " but instead is " + a + ".");
+        return;
+    }
+
+    log("PASS: " + aDescription + " should be " + b + " and is.");
+}
+
+function gc()
+{
+    if (window.GCController) {
+        GCController.collect();
+        return;
+    }
+    
+    for (var i = 0; i < 10000; ++i)
+        new Object;
+}
+
+function shouldBeNull(aDescription, a)
+{
+    if (a == null) {
+        log("PASS: " + aDescription + " should be null and is.");
+        return;
+    }
+    
+    log("FAIL: " + aDescription + " should be null but instead is " + a + ".");
+}
+
+function shouldBeNonNull(aDescription, a)
+{
+    if (a != null) {
+        log("PASS: " + aDescription + " should be null and is.");
+        return;
+    }
+    
+    log("FAIL: " + aDescription + " should be null but instead is " + a + ".");
+}
+
+(function () {
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+    shouldBeNonNull("$('p').__proto__", $('p').__proto__);
+    $('p').__proto__ = null;
+    shouldBeNull("$('p').__proto__", $('p').__proto__);
+
+    gc();
+
+    shouldBeNull("$('p').__proto__", $('p').__proto__);
+})();
+</script>
index 5c6113f..dd6a815 100644 (file)
@@ -1,3 +1,25 @@
+2011-04-25  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Custom prototypes on DOM objects don't persist after garbage collection
+        https://bugs.webkit.org/show_bug.cgi?id=59412
+        
+        SunSpider reports no change.
+        
+        The hasCustomProperties() check didn't check for a custom prototype.
+
+        * runtime/JSObject.h:
+        (JSC::JSObject::hasCustomProperties): Changed to delegate to Structure
+        because it is the "truth" about an object's pedigree.
+
+        * runtime/Structure.cpp:
+        (JSC::Structure::Structure):
+        * runtime/Structure.h:
+        (JSC::Structure::didTransition): Track whether a Structure has ever
+        transitioned for any reason. If so, we have to assume that the object
+        holding it is custom in some way.
+
 2011-04-25  Gavin Barraclough  <barraclough@apple.com>
 
         Reviewed by Geoff Garen.
index b033475..a6b78bd 100644 (file)
@@ -173,7 +173,7 @@ namespace JSC {
         void transitionTo(JSGlobalData&, Structure*);
 
         void removeDirect(JSGlobalData&, const Identifier& propertyName);
-        bool hasCustomProperties() { return !m_structure->isEmpty(); }
+        bool hasCustomProperties() { return m_structure->didTransition(); }
         bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); }
 
         bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&);
index b5a9254..8645bd2 100644 (file)
@@ -189,6 +189,7 @@ Structure::Structure(JSGlobalData& globalData, JSValue prototype, const TypeInfo
     , m_specificFunctionThrashCount(0)
     , m_anonymousSlotCount(anonymousSlotCount)
     , m_preventExtensions(false)
+    , m_didTransition(false)
 {
     ASSERT(m_prototype);
     ASSERT(m_prototype.isObject() || m_prototype.isNull());
@@ -211,6 +212,7 @@ Structure::Structure(JSGlobalData& globalData)
     , m_specificFunctionThrashCount(0)
     , m_anonymousSlotCount(0)
     , m_preventExtensions(false)
+    , m_didTransition(false)
 {
     ASSERT(m_prototype);
     ASSERT(m_prototype.isNull());
@@ -232,6 +234,7 @@ Structure::Structure(JSGlobalData& globalData, const Structure* previous)
     , m_specificFunctionThrashCount(previous->m_specificFunctionThrashCount)
     , m_anonymousSlotCount(previous->anonymousSlotCount())
     , m_preventExtensions(previous->m_preventExtensions)
+    , m_didTransition(true)
 {
     ASSERT(m_prototype);
     ASSERT(m_prototype.isObject() || m_prototype.isNull());
index ab7fb9f..7556da9 100644 (file)
@@ -84,6 +84,7 @@ namespace JSC {
         bool isSealed(JSGlobalData&);
         bool isFrozen(JSGlobalData&);
         bool isExtensible() const { return !m_preventExtensions; }
+        bool didTransition() const { return m_didTransition; }
 
         Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
 
@@ -247,7 +248,8 @@ namespace JSC {
         unsigned m_specificFunctionThrashCount : 2;
         unsigned m_anonymousSlotCount : 5;
         unsigned m_preventExtensions : 1;
-        // 4 free bits
+        unsigned m_didTransition : 1;
+        // 3 free bits
     };
 
     inline size_t Structure::get(JSGlobalData& globalData, const Identifier& propertyName)