Title: [123690] trunk/Source/_javascript_Core
Revision
123690
Author
[email protected]
Date
2012-07-25 18:22:59 -0700 (Wed, 25 Jul 2012)

Log Message

JSC GC object copying APIs should allow for greater flexibility
https://bugs.webkit.org/show_bug.cgi?id=92316

Reviewed by Mark Hahnenberg.

It's now the case that visitChildren() methods can directly pin and allocate in new space during copying.
They can also do the copying and marking themselves. This new API is only used for JSObjects for now.

* _javascript_Core.xcodeproj/project.pbxproj:
* heap/MarkStack.cpp:
(JSC::SlotVisitor::allocateNewSpaceSlow):
(JSC::SlotVisitor::allocateNewSpaceOrPin):
(JSC):
(JSC::SlotVisitor::copyAndAppend):
* heap/MarkStack.h:
(MarkStack):
(JSC::MarkStack::appendUnbarrieredValue):
(JSC):
* heap/SlotVisitor.h:
* heap/SlotVisitorInlineMethods.h: Added.
(JSC):
(JSC::SlotVisitor::checkIfShouldCopyAndPinOtherwise):
(JSC::SlotVisitor::allocateNewSpace):
* runtime/JSObject.cpp:
(JSC::JSObject::visitOutOfLineStorage):
(JSC):
(JSC::JSObject::visitChildren):
(JSC::JSFinalObject::visitChildren):
* runtime/JSObject.h:
(JSObject):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (123689 => 123690)


--- trunk/Source/_javascript_Core/ChangeLog	2012-07-26 01:05:23 UTC (rev 123689)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-07-26 01:22:59 UTC (rev 123690)
@@ -1,3 +1,36 @@
+2012-07-25  Filip Pizlo  <[email protected]>
+
+        JSC GC object copying APIs should allow for greater flexibility
+        https://bugs.webkit.org/show_bug.cgi?id=92316
+
+        Reviewed by Mark Hahnenberg.
+
+        It's now the case that visitChildren() methods can directly pin and allocate in new space during copying.
+        They can also do the copying and marking themselves. This new API is only used for JSObjects for now.
+
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * heap/MarkStack.cpp:
+        (JSC::SlotVisitor::allocateNewSpaceSlow):
+        (JSC::SlotVisitor::allocateNewSpaceOrPin):
+        (JSC):
+        (JSC::SlotVisitor::copyAndAppend):
+        * heap/MarkStack.h:
+        (MarkStack):
+        (JSC::MarkStack::appendUnbarrieredValue):
+        (JSC):
+        * heap/SlotVisitor.h:
+        * heap/SlotVisitorInlineMethods.h: Added.
+        (JSC):
+        (JSC::SlotVisitor::checkIfShouldCopyAndPinOtherwise):
+        (JSC::SlotVisitor::allocateNewSpace):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::visitOutOfLineStorage):
+        (JSC):
+        (JSC::JSObject::visitChildren):
+        (JSC::JSFinalObject::visitChildren):
+        * runtime/JSObject.h:
+        (JSObject):
+
 2012-07-25  Mark Hahnenberg  <[email protected]>
 
         Remove JSObject::m_inheritorID

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (123689 => 123690)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2012-07-26 01:05:23 UTC (rev 123689)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2012-07-26 01:22:59 UTC (rev 123690)
@@ -949,6 +949,7 @@
 		0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierSupport.h; sourceTree = "<group>"; };
 		0FC815121405118600CFA603 /* VTableSpectrum.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VTableSpectrum.cpp; sourceTree = "<group>"; };
 		0FC815141405118D00CFA603 /* VTableSpectrum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTableSpectrum.h; sourceTree = "<group>"; };
+		0FCB408515C0A3C30048932B /* SlotVisitorInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotVisitorInlineMethods.h; sourceTree = "<group>"; };
 		0FD3C82014115CF800FD81CB /* DFGDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDriver.cpp; path = dfg/DFGDriver.cpp; sourceTree = "<group>"; };
 		0FD3C82214115D0E00FD81CB /* DFGDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDriver.h; path = dfg/DFGDriver.h; sourceTree = "<group>"; };
 		0FD81ACF154FB4EB00983E72 /* DFGDominators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDominators.cpp; path = dfg/DFGDominators.cpp; sourceTree = "<group>"; };
@@ -1800,6 +1801,7 @@
 				142D6F0F13539A4100B02E86 /* MarkStack.h */,
 				1497209014EB831500FEB1B7 /* PassWeak.h */,
 				14BA78F013AAB88F005B7C2C /* SlotVisitor.h */,
+				0FCB408515C0A3C30048932B /* SlotVisitorInlineMethods.h */,
 				142E3132134FF0A600AFADB5 /* Strong.h */,
 				145722851437E140005FDE26 /* StrongInlines.h */,
 				141448CC13A1783700F5BA1A /* TinyBloomFilter.h */,

Modified: trunk/Source/_javascript_Core/heap/MarkStack.cpp (123689 => 123690)


--- trunk/Source/_javascript_Core/heap/MarkStack.cpp	2012-07-26 01:05:23 UTC (rev 123689)
+++ trunk/Source/_javascript_Core/heap/MarkStack.cpp	2012-07-26 01:22:59 UTC (rev 123690)
@@ -35,6 +35,7 @@
 #include "JSCell.h"
 #include "JSObject.h"
 #include "ScopeChain.h"
+#include "SlotVisitorInlineMethods.h"
 #include "Structure.h"
 #include "UString.h"
 #include "WriteBarrier.h"
@@ -518,28 +519,25 @@
     ASSERT(!m_copiedAllocator.isValid());
 }
 
-void* SlotVisitor::allocateNewSpace(void* ptr, size_t bytes)
+void* SlotVisitor::allocateNewSpaceSlow(size_t bytes)
 {
-    if (CopiedSpace::isOversize(bytes)) {
-        m_shared.m_copiedSpace->pin(CopiedSpace::oversizeBlockFor(ptr));
-        return 0;
-    }
-
-    if (m_shared.m_copiedSpace->isPinned(ptr))
-        return 0;
-    
-    void* result = 0; // Compilers don't realize that this will be assigned.
-    if (m_copiedAllocator.tryAllocate(bytes, &result))
-        return result;
-    
     m_shared.m_copiedSpace->doneFillingBlock(m_copiedAllocator.resetCurrentBlock());
     m_copiedAllocator.setCurrentBlock(m_shared.m_copiedSpace->allocateBlockForCopyingPhase());
 
+    void* result = 0;
     CheckedBoolean didSucceed = m_copiedAllocator.tryAllocate(bytes, &result);
     ASSERT(didSucceed);
     return result;
 }
 
+void* SlotVisitor::allocateNewSpaceOrPin(void* ptr, size_t bytes)
+{
+    if (!checkIfShouldCopyAndPinOtherwise(ptr, bytes))
+        return 0;
+    
+    return allocateNewSpace(bytes);
+}
+
 ALWAYS_INLINE bool JSString::tryHashConstLock()
 {
 #if ENABLE(PARALLEL_GC)
@@ -616,7 +614,7 @@
 void SlotVisitor::copyAndAppend(void** ptr, size_t bytes, JSValue* values, unsigned length)
 {
     void* oldPtr = *ptr;
-    void* newPtr = allocateNewSpace(oldPtr, bytes);
+    void* newPtr = allocateNewSpaceOrPin(oldPtr, bytes);
     if (newPtr) {
         size_t jsValuesOffset = static_cast<size_t>(reinterpret_cast<char*>(values) - static_cast<char*>(oldPtr));
 

Modified: trunk/Source/_javascript_Core/heap/MarkStack.h (123689 => 123690)


--- trunk/Source/_javascript_Core/heap/MarkStack.h	2012-07-26 01:05:23 UTC (rev 123689)
+++ trunk/Source/_javascript_Core/heap/MarkStack.h	2012-07-26 01:22:59 UTC (rev 123690)
@@ -253,6 +253,7 @@
         
         template<typename T>
         void appendUnbarrieredPointer(T**);
+        void appendUnbarrieredValue(JSValue*);
         
         void addOpaqueRoot(void*);
         bool containsOpaqueRoot(void*);
@@ -453,6 +454,12 @@
         internalAppend(*slot);
     }
 
+    ALWAYS_INLINE void MarkStack::appendUnbarrieredValue(JSValue* slot)
+    {
+        ASSERT(slot);
+        internalAppend(*slot);
+    }
+
     ALWAYS_INLINE void MarkStack::append(JSCell** slot)
     {
         ASSERT(slot);

Modified: trunk/Source/_javascript_Core/heap/SlotVisitor.h (123689 => 123690)


--- trunk/Source/_javascript_Core/heap/SlotVisitor.h	2012-07-26 01:05:23 UTC (rev 123689)
+++ trunk/Source/_javascript_Core/heap/SlotVisitor.h	2012-07-26 01:22:59 UTC (rev 123690)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -62,11 +62,23 @@
     void finalizeUnconditionalFinalizers();
 
     void startCopying();
+    
+    // High-level API for copying, appropriate for cases where the object's heap references
+    // fall into a contiguous region of the storage chunk and if the object for which you're
+    // doing copying does not occur frequently.
     void copyAndAppend(void**, size_t, JSValue*, unsigned);
+    
+    // Low-level API for copying, appropriate for cases where the object's heap references
+    // are discontiguous or if the object occurs frequently enough that you need to focus on
+    // performance. Use this with care as it is easy to shoot yourself in the foot.
+    bool checkIfShouldCopyAndPinOtherwise(void* oldPtr, size_t);
+    void* allocateNewSpace(size_t);
+    
     void doneCopying(); 
         
 private:
-    void* allocateNewSpace(void*, size_t);
+    void* allocateNewSpaceOrPin(void*, size_t);
+    void* allocateNewSpaceSlow(size_t);
 
     void donateKnownParallel();
 

Added: trunk/Source/_javascript_Core/heap/SlotVisitorInlineMethods.h (0 => 123690)


--- trunk/Source/_javascript_Core/heap/SlotVisitorInlineMethods.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/heap/SlotVisitorInlineMethods.h	2012-07-26 01:22:59 UTC (rev 123690)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SlotVisitorInlineMethods_h
+#define SlotVisitorInlineMethods_h
+
+#include "CopiedSpaceInlineMethods.h"
+#include "SlotVisitor.h"
+
+namespace JSC {
+
+ALWAYS_INLINE bool SlotVisitor::checkIfShouldCopyAndPinOtherwise(void* oldPtr, size_t bytes)
+{
+    if (CopiedSpace::isOversize(bytes)) {
+        m_shared.m_copiedSpace->pin(CopiedSpace::oversizeBlockFor(oldPtr));
+        return false;
+    }
+
+    if (m_shared.m_copiedSpace->isPinned(oldPtr))
+        return false;
+    
+    return true;
+}
+
+ALWAYS_INLINE void* SlotVisitor::allocateNewSpace(size_t bytes)
+{
+    void* result = 0; // Compilers don't realize that this will be assigned.
+    if (LIKELY(m_copiedAllocator.tryAllocate(bytes, &result)))
+        return result;
+    
+    result = allocateNewSpaceSlow(bytes);
+    ASSERT(result);
+    return result;
+}       
+
+} // namespace JSC
+
+#endif // SlotVisitorInlineMethods_h
+

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (123689 => 123690)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2012-07-26 01:05:23 UTC (rev 123689)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2012-07-26 01:22:59 UTC (rev 123690)
@@ -38,6 +38,7 @@
 #include "Operations.h"
 #include "PropertyDescriptor.h"
 #include "PropertyNameArray.h"
+#include "SlotVisitorInlineMethods.h"
 #include <math.h>
 #include <wtf/Assertions.h>
 
@@ -85,6 +86,31 @@
     }
 }
 
+ALWAYS_INLINE void JSObject::visitOutOfLineStorage(SlotVisitor& visitor, PropertyStorage storage, size_t storageSize)
+{
+    ASSERT(storage);
+    ASSERT(storageSize);
+    
+    size_t capacity = structure()->outOfLineCapacity();
+    ASSERT(capacity);
+    size_t capacityInBytes = capacity * sizeof(WriteBarrierBase<Unknown>);
+    PropertyStorage baseOfStorage = storage - capacity - 1;
+    if (visitor.checkIfShouldCopyAndPinOtherwise(baseOfStorage, capacityInBytes)) {
+        PropertyStorage newBaseOfStorage = static_cast<PropertyStorage>(visitor.allocateNewSpace(capacityInBytes));
+        PropertyStorage currentTarget = newBaseOfStorage + capacity;
+        PropertyStorage newStorage = currentTarget + 1;
+        PropertyStorage currentSource = storage - 1;
+        for (size_t count = storageSize; count--;) {
+            JSValue value = (--currentSource)->get();
+            ASSERT(value);
+            visitor.appendUnbarrieredValue(&value);
+            (--currentTarget)->setWithoutWriteBarrier(value);
+        }
+        m_outOfLineStorage.set(newStorage, StorageBarrier::Unchecked);
+    } else
+        visitor.appendValues(storage - storageSize - 1, storageSize);
+}
+
 void JSObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     JSObject* thisObject = jsCast<JSObject*>(cell);
@@ -97,15 +123,8 @@
     JSCell::visitChildren(thisObject, visitor);
 
     PropertyStorage storage = thisObject->outOfLineStorage();
-    if (storage) {
-        size_t storageSize = thisObject->structure()->outOfLineSizeForKnownNonFinalObject();
-        size_t capacity = thisObject->structure()->outOfLineCapacity();
-        // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers.
-        void* temp = storage - capacity - 1;
-        visitor.copyAndAppend(&temp, capacity * sizeof(WriteBarrierBase<Unknown>), (storage - storageSize - 1)->slot(), storageSize);
-        storage = static_cast<PropertyStorage>(temp) + capacity + 1;
-        thisObject->m_outOfLineStorage.set(storage, StorageBarrier::Unchecked);
-    }
+    if (storage)
+        thisObject->visitOutOfLineStorage(visitor, storage, thisObject->structure()->outOfLineSizeForKnownNonFinalObject());
 
 #if !ASSERT_DISABLED
     visitor.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
@@ -124,15 +143,8 @@
     JSCell::visitChildren(thisObject, visitor);
 
     PropertyStorage storage = thisObject->outOfLineStorage();
-    if (storage) {
-        size_t storageSize = thisObject->structure()->outOfLineSizeForKnownFinalObject();
-        size_t capacity = thisObject->structure()->outOfLineCapacity();
-        // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers.
-        void* temp = storage - capacity - 1;
-        visitor.copyAndAppend(&temp, thisObject->structure()->outOfLineCapacity() * sizeof(WriteBarrierBase<Unknown>), (storage - storageSize - 1)->slot(), storageSize);
-        storage = static_cast<PropertyStorage>(temp) + capacity + 1;
-        thisObject->m_outOfLineStorage.set(storage, StorageBarrier::Unchecked);
-    }
+    if (storage)
+        thisObject->visitOutOfLineStorage(visitor, storage, thisObject->structure()->outOfLineSizeForKnownFinalObject());
 
     size_t storageSize = thisObject->structure()->inlineSizeForKnownFinalObject();
     visitor.appendValues(thisObject->inlineStorage(), storageSize);

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (123689 => 123690)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2012-07-26 01:05:23 UTC (rev 123689)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2012-07-26 01:22:59 UTC (rev 123690)
@@ -325,6 +325,8 @@
         {
             removeDirect(globalData, globalData.m_inheritorIDKey);
         }
+        
+        void visitOutOfLineStorage(SlotVisitor&, PropertyStorage, size_t storageSize);
 
     private:
         friend class LLIntOffsetsExtractor;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to