Title: [210659] branches/safari-603-branch/Source/_javascript_Core

Diff

Modified: branches/safari-603-branch/Source/_javascript_Core/ChangeLog (210658 => 210659)


--- branches/safari-603-branch/Source/_javascript_Core/ChangeLog	2017-01-12 16:46:02 UTC (rev 210658)
+++ branches/safari-603-branch/Source/_javascript_Core/ChangeLog	2017-01-12 16:46:05 UTC (rev 210659)
@@ -1,5 +1,41 @@
 2017-01-12  Matthew Hanson  <matthew_han...@apple.com>
 
+        Merge r210553. rdar://problem/29941356
+
+    2017-01-09  Filip Pizlo  <fpi...@apple.com>
+
+            JSArray has some object scanning races
+            https://bugs.webkit.org/show_bug.cgi?id=166874
+
+            Reviewed by Mark Lam.
+
+            This fixes two separate bugs, both of which I detected by running
+            array-splice-contiguous.js in extreme anger:
+
+            1) Some of the paths of shifting and unshifting were not grabbing the internal cell
+               lock. This was causing the array storage scan to crash, even though it was well
+               synchronized (the scan does hold the lock). The fix is just to hold the lock anywhere
+               that memmoves the innards of the butterfly.
+
+            2) Out of line property scanning was synchronized using double collect snapshot. Array
+               storage scanning was synchronized using locks. But what if array storage
+               transformations messed up the out of line properties? It turns out that we actually
+               need to hoist the array storage scanner's locking up into the double collect
+               snapshot.
+
+            I don't know how to write a test that does any better of a job of catching this than
+            array-splice-contiguous.js.
+
+            * heap/DeferGC.h: Make DisallowGC usable even if NDEBUG.
+            * runtime/JSArray.cpp:
+            (JSC::JSArray::unshiftCountSlowCase):
+            (JSC::JSArray::shiftCountWithArrayStorage):
+            (JSC::JSArray::unshiftCountWithArrayStorage):
+            * runtime/JSObject.cpp:
+            (JSC::JSObject::visitButterflyImpl):
+
+2017-01-12  Matthew Hanson  <matthew_han...@apple.com>
+
         Merge r210530. rdar://problem/29909896
 
     2017-01-09  Filip Pizlo  <fpi...@apple.com>

Modified: branches/safari-603-branch/Source/_javascript_Core/heap/DeferGC.h (210658 => 210659)


--- branches/safari-603-branch/Source/_javascript_Core/heap/DeferGC.h	2017-01-12 16:46:02 UTC (rev 210658)
+++ branches/safari-603-branch/Source/_javascript_Core/heap/DeferGC.h	2017-01-12 16:46:05 UTC (rev 210659)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -67,31 +67,41 @@
     Heap& m_heap;
 };
 
-#ifndef NDEBUG
 class DisallowGC {
     WTF_MAKE_NONCOPYABLE(DisallowGC);
 public:
     DisallowGC()
     {
+#ifndef NDEBUG
         WTF::threadSpecificSet(s_isGCDisallowedOnCurrentThread, reinterpret_cast<void*>(true));
+#endif
     }
 
     ~DisallowGC()
     {
+#ifndef NDEBUG
         WTF::threadSpecificSet(s_isGCDisallowedOnCurrentThread, reinterpret_cast<void*>(false));
+#endif
     }
 
     static bool isGCDisallowedOnCurrentThread()
     {
+#ifndef NDEBUG
         return !!WTF::threadSpecificGet(s_isGCDisallowedOnCurrentThread);
+#else
+        return false;
+#endif
     }
     static void initialize()
     {
+#ifndef NDEBUG
         WTF::threadSpecificKeyCreate(&s_isGCDisallowedOnCurrentThread, 0);
+#endif
     }
 
+#ifndef NDEBUG
     JS_EXPORT_PRIVATE static WTF::ThreadSpecificKey s_isGCDisallowedOnCurrentThread;
+#endif
 };
-#endif // NDEBUG
 
 } // namespace JSC

Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/JSArray.cpp (210658 => 210659)


--- branches/safari-603-branch/Source/_javascript_Core/runtime/JSArray.cpp	2017-01-12 16:46:02 UTC (rev 210658)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/JSArray.cpp	2017-01-12 16:46:05 UTC (rev 210659)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (por...@kde.org)
- *  Copyright (C) 2003, 2007-2009, 2012-2013, 2015-2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
  *  Copyright (C) 2003 Peter Kelly (p...@post.com)
  *  Copyright (C) 2006 Alexey Proskuryakov (a...@nypop.com)
  *
@@ -298,7 +298,7 @@
 }
 
 // This method makes room in the vector, but leaves the new space for count slots uncleared.
-bool JSArray::unshiftCountSlowCase(VM& vm, DeferGC&, bool addToFront, unsigned count)
+bool JSArray::unshiftCountSlowCase(const AbstractLocker&, VM& vm, DeferGC&, bool addToFront, unsigned count)
 {
     ArrayStorage* storage = ensureArrayStorage(vm);
     Butterfly* butterfly = storage->butterfly();
@@ -892,6 +892,9 @@
     if (startIndex >= vectorLength)
         return true;
     
+    DisallowGC disallowGC;
+    auto locker = holdLock(*this);
+    
     if (startIndex + count > vectorLength)
         count = vectorLength - startIndex;
     
@@ -930,7 +933,7 @@
         // the start of the Butterfly, which needs to point at the first indexed property in the used
         // portion of the vector.
         Butterfly* butterfly = m_butterfly.get()->shift(structure(), count);
-        m_butterfly.setWithoutBarrier(butterfly);
+        setButterfly(vm, butterfly);
         storage = butterfly->arrayStorage();
         storage->m_indexBias += count;
 
@@ -1098,7 +1101,7 @@
         setButterfly(vm, newButterfly);
     } else if (!moveFront && vectorLength - length >= count)
         storage = storage->butterfly()->arrayStorage();
-    else if (unshiftCountSlowCase(vm, deferGC, moveFront, count))
+    else if (unshiftCountSlowCase(locker, vm, deferGC, moveFront, count))
         storage = arrayStorage();
     else {
         throwOutOfMemoryError(exec, scope);

Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/JSArray.h (210658 => 210659)


--- branches/safari-603-branch/Source/_javascript_Core/runtime/JSArray.h	2017-01-12 16:46:02 UTC (rev 210658)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/JSArray.h	2017-01-12 16:46:05 UTC (rev 210659)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (por...@kde.org)
- *  Copyright (C) 2003, 2007, 2008, 2009, 2012, 2015-2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -177,7 +177,7 @@
 
     bool unshiftCountWithAnyIndexingType(ExecState*, unsigned startIndex, unsigned count);
     bool unshiftCountWithArrayStorage(ExecState*, unsigned startIndex, unsigned count, ArrayStorage*);
-    bool unshiftCountSlowCase(VM&, DeferGC&, bool, unsigned);
+    bool unshiftCountSlowCase(const AbstractLocker&, VM&, DeferGC&, bool, unsigned);
 
     bool setLengthWithArrayStorage(ExecState*, unsigned newLength, bool throwException, ArrayStorage*);
     void setLengthWritable(ExecState*, bool writable);

Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/JSObject.cpp (210658 => 210659)


--- branches/safari-603-branch/Source/_javascript_Core/runtime/JSObject.cpp	2017-01-12 16:46:02 UTC (rev 210658)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/JSObject.cpp	2017-01-12 16:46:05 UTC (rev 210659)
@@ -383,6 +383,20 @@
         return nullptr;
     structure = vm.getStructure(structureID);
     lastOffset = structure->lastOffset();
+    IndexingType indexingType = structure->indexingType();
+    Locker<JSCell> locker(NoLockingNecessary);
+    switch (indexingType) {
+    case ALL_CONTIGUOUS_INDEXING_TYPES:
+    case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+        // We need to hold this lock to protect against changes to the innards of the butterfly
+        // that can happen when the butterfly is used for array storage. We conservatively
+        // assume that a contiguous butterfly may transform into an array storage one, though
+        // this is probably more conservative than necessary.
+        locker = Locker<JSCell>(*this);
+        break;
+    default:
+        break;
+    }
     WTF::loadLoadFence();
     butterfly = this->butterfly();
     if (!butterfly)
@@ -395,27 +409,17 @@
     
     markAuxiliaryAndVisitOutOfLineProperties(visitor, butterfly, structure, lastOffset);
     
-    IndexingType oldType = structure->indexingType();
-    switch (oldType) {
+    ASSERT(indexingType == structure->indexingType());
+    
+    switch (indexingType) {
     case ALL_CONTIGUOUS_INDEXING_TYPES:
-    case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
-        // This lock is here to protect Contiguous->ArrayStorage transitions, but we could make that
-        // race work if we needed to.
-        auto locker = holdLock(*this);
-        IndexingType newType = this->indexingType();
-        butterfly = this->butterfly();
-        switch (newType) {
-        case ALL_CONTIGUOUS_INDEXING_TYPES:
-            visitor.appendValuesHidden(butterfly->contiguous().data(), butterfly->publicLength());
-            break;
-        default: // ALL_ARRAY_STORAGE_INDEXING_TYPES
-            visitor.appendValuesHidden(butterfly->arrayStorage()->m_vector, butterfly->arrayStorage()->vectorLength());
-            if (butterfly->arrayStorage()->m_sparseMap)
-                visitor.append(butterfly->arrayStorage()->m_sparseMap);
-            break;
-        }
+        visitor.appendValuesHidden(butterfly->contiguous().data(), butterfly->publicLength());
         break;
-    }
+    case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+        visitor.appendValuesHidden(butterfly->arrayStorage()->m_vector, butterfly->arrayStorage()->vectorLength());
+        if (butterfly->arrayStorage()->m_sparseMap)
+            visitor.append(butterfly->arrayStorage()->m_sparseMap);
+        break;
     default:
         break;
     }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to