All C++ accesses to JSObject::m_butterfly should do caging
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Aug 2017 01:32:07 +0000 (01:32 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Aug 2017 01:32:07 +0000 (01:32 +0000)
https://bugs.webkit.org/show_bug.cgi?id=175039

Reviewed by Keith Miller.

Source/JavaScriptCore:

Makes JSObject::m_butterfly a AuxiliaryBarrier<CagedPtr<Butterfly>> and adopts the CagedPtr<> API.
This ensures that you can't cause C++ code to access a butterfly that has been rewired to point
outside the gigacage.

* runtime/JSArray.cpp:
(JSC::JSArray::setLength):
(JSC::JSArray::pop):
(JSC::JSArray::push):
(JSC::JSArray::shiftCountWithAnyIndexingType):
(JSC::JSArray::unshiftCountWithAnyIndexingType):
(JSC::JSArray::fillArgList):
(JSC::JSArray::copyToArguments):
* runtime/JSObject.cpp:
(JSC::JSObject::heapSnapshot):
(JSC::JSObject::createInitialIndexedStorage):
(JSC::JSObject::createArrayStorage):
(JSC::JSObject::convertUndecidedToInt32):
(JSC::JSObject::convertUndecidedToDouble):
(JSC::JSObject::convertUndecidedToContiguous):
(JSC::JSObject::convertInt32ToDouble):
(JSC::JSObject::convertInt32ToArrayStorage):
(JSC::JSObject::convertDoubleToContiguous):
(JSC::JSObject::convertDoubleToArrayStorage):
(JSC::JSObject::convertContiguousToArrayStorage):
(JSC::JSObject::defineOwnIndexedProperty):
(JSC::JSObject::putByIndexBeyondVectorLengthWithoutAttributes):
(JSC::JSObject::ensureLengthSlow):
(JSC::JSObject::allocateMoreOutOfLineStorage):
* runtime/JSObject.h:
(JSC::JSObject::canGetIndexQuickly):
(JSC::JSObject::getIndexQuickly):
(JSC::JSObject::tryGetIndexQuickly const):
(JSC::JSObject::canSetIndexQuickly):
(JSC::JSObject::setIndexQuickly):
(JSC::JSObject::initializeIndex):
(JSC::JSObject::initializeIndexWithoutBarrier):
(JSC::JSObject::butterfly const):
(JSC::JSObject::butterfly):

Source/WTF:

Adds a smart pointer class that does various kinds of caging for you.

* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/CagedPtr.h: Added.
(WTF::CagedPtr::CagedPtr):
(WTF::CagedPtr::get const):
(WTF::CagedPtr::getMayBeNull const):
(WTF::CagedPtr::operator== const):
(WTF::CagedPtr::operator!= const):
(WTF::CagedPtr::operator bool const):
(WTF::CagedPtr::operator* const):
(WTF::CagedPtr::operator-> const):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/CMakeLists.txt
Source/WTF/wtf/CagedPtr.h [new file with mode: 0644]
Source/bmalloc/bmalloc/Gigacage.h

index b37bce1..64599c8 100644 (file)
@@ -1,5 +1,51 @@
 2017-08-02  Filip Pizlo  <fpizlo@apple.com>
 
+        All C++ accesses to JSObject::m_butterfly should do caging
+        https://bugs.webkit.org/show_bug.cgi?id=175039
+
+        Reviewed by Keith Miller.
+        
+        Makes JSObject::m_butterfly a AuxiliaryBarrier<CagedPtr<Butterfly>> and adopts the CagedPtr<> API.
+        This ensures that you can't cause C++ code to access a butterfly that has been rewired to point
+        outside the gigacage.
+
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::setLength):
+        (JSC::JSArray::pop):
+        (JSC::JSArray::push):
+        (JSC::JSArray::shiftCountWithAnyIndexingType):
+        (JSC::JSArray::unshiftCountWithAnyIndexingType):
+        (JSC::JSArray::fillArgList):
+        (JSC::JSArray::copyToArguments):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::heapSnapshot):
+        (JSC::JSObject::createInitialIndexedStorage):
+        (JSC::JSObject::createArrayStorage):
+        (JSC::JSObject::convertUndecidedToInt32):
+        (JSC::JSObject::convertUndecidedToDouble):
+        (JSC::JSObject::convertUndecidedToContiguous):
+        (JSC::JSObject::convertInt32ToDouble):
+        (JSC::JSObject::convertInt32ToArrayStorage):
+        (JSC::JSObject::convertDoubleToContiguous):
+        (JSC::JSObject::convertDoubleToArrayStorage):
+        (JSC::JSObject::convertContiguousToArrayStorage):
+        (JSC::JSObject::defineOwnIndexedProperty):
+        (JSC::JSObject::putByIndexBeyondVectorLengthWithoutAttributes):
+        (JSC::JSObject::ensureLengthSlow):
+        (JSC::JSObject::allocateMoreOutOfLineStorage):
+        * runtime/JSObject.h:
+        (JSC::JSObject::canGetIndexQuickly):
+        (JSC::JSObject::getIndexQuickly):
+        (JSC::JSObject::tryGetIndexQuickly const):
+        (JSC::JSObject::canSetIndexQuickly):
+        (JSC::JSObject::setIndexQuickly):
+        (JSC::JSObject::initializeIndex):
+        (JSC::JSObject::initializeIndexWithoutBarrier):
+        (JSC::JSObject::butterfly const):
+        (JSC::JSObject::butterfly):
+
+2017-08-02  Filip Pizlo  <fpizlo@apple.com>
+
         We should be OK with the gigacage being disabled on gmalloc
         https://bugs.webkit.org/show_bug.cgi?id=175082
 
index 670763a..eb3a3c4 100644 (file)
@@ -550,7 +550,7 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().getMayBeNull();
     switch (indexingType()) {
     case ArrayClass:
         if (!newLength)
@@ -620,7 +620,7 @@ JSValue JSArray::pop(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().getMayBeNull();
     
     switch (indexingType()) {
     case ArrayClass:
@@ -722,7 +722,7 @@ void JSArray::push(ExecState* exec, JSValue value)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().getMayBeNull();
     
     switch (indexingType()) {
     case ArrayClass: {
@@ -1015,7 +1015,7 @@ bool JSArray::shiftCountWithAnyIndexingType(ExecState* exec, unsigned& startInde
     VM& vm = exec->vm();
     RELEASE_ASSERT(count > 0);
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().getMayBeNull();
     
     switch (indexingType()) {
     case ArrayClass:
@@ -1171,7 +1171,7 @@ bool JSArray::unshiftCountWithAnyIndexingType(ExecState* exec, unsigned startInd
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().getMayBeNull();
     
     switch (indexingType()) {
     case ArrayClass:
@@ -1194,7 +1194,7 @@ bool JSArray::unshiftCountWithAnyIndexingType(ExecState* exec, unsigned startInd
             throwOutOfMemoryError(exec, scope);
             return false;
         }
-        butterfly = m_butterfly.get();
+        butterfly = m_butterfly.get().getMayBeNull();
 
         // We have to check for holes before we start moving things around so that we don't get halfway 
         // through shifting and then realize we should have been in ArrayStorage mode.
@@ -1238,7 +1238,7 @@ bool JSArray::unshiftCountWithAnyIndexingType(ExecState* exec, unsigned startInd
             throwOutOfMemoryError(exec, scope);
             return false;
         }
-        butterfly = m_butterfly.get();
+        butterfly = m_butterfly.get().getMayBeNull();
         
         // We have to check for holes before we start moving things around so that we don't get halfway 
         // through shifting and then realize we should have been in ArrayStorage mode.
@@ -1281,7 +1281,7 @@ void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
     unsigned vectorEnd;
     WriteBarrier<Unknown>* vector;
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().getMayBeNull();
     
     switch (indexingType()) {
     case ArrayClass:
@@ -1354,7 +1354,7 @@ void JSArray::copyToArguments(ExecState* exec, VirtualRegister firstElementDest,
     // FIXME: What prevents this from being called with a RuntimeArray? The length function will always return 0 in that case.
     ASSERT(length == this->length());
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().getMayBeNull();
     switch (indexingType()) {
     case ArrayClass:
         return;
index 353c485..3788a0f 100644 (file)
@@ -463,7 +463,7 @@ void JSObject::heapSnapshot(JSCell* cell, HeapSnapshotBuilder& builder)
             builder.appendPropertyNameEdge(thisObject, toValue.asCell(), entry.key);
     }
 
-    Butterfly* butterfly = thisObject->m_butterfly.get();
+    Butterfly* butterfly = thisObject->m_butterfly.get().getMayBeNull();
     if (butterfly) {
         WriteBarrier<Unknown>* data = nullptr;
         uint32_t count = 0;
@@ -1011,7 +1011,7 @@ Butterfly* JSObject::createInitialIndexedStorage(VM& vm, unsigned length)
     unsigned propertyCapacity = structure->outOfLineCapacity();
     unsigned vectorLength = Butterfly::optimalContiguousVectorLength(propertyCapacity, length);
     Butterfly* newButterfly = Butterfly::createOrGrowArrayRight(
-        m_butterfly.get(), vm, this, structure, propertyCapacity, false, 0,
+        m_butterfly.get().getMayBeNull(), vm, this, structure, propertyCapacity, false, 0,
         sizeof(EncodedJSValue) * vectorLength);
     newButterfly->setPublicLength(length);
     newButterfly->setVectorLength(vectorLength);
@@ -1099,7 +1099,7 @@ ArrayStorage* JSObject::createArrayStorage(VM& vm, unsigned length, unsigned vec
     IndexingType oldType = indexingType();
     ASSERT_UNUSED(oldType, !hasIndexedProperties(oldType));
 
-    Butterfly* newButterfly = createArrayStorageButterfly(vm, this, oldStructure, length, vectorLength, m_butterfly.get());
+    Butterfly* newButterfly = createArrayStorageButterfly(vm, this, oldStructure, length, vectorLength, m_butterfly.get().getMayBeNull());
     ArrayStorage* result = newButterfly->arrayStorage();
     Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, oldStructure->suggestedArrayStorageTransition());
     nukeStructureAndSetButterfly(vm, oldStructureID, newButterfly);
@@ -1117,7 +1117,7 @@ ContiguousJSValues JSObject::convertUndecidedToInt32(VM& vm)
 {
     ASSERT(hasUndecided(indexingType()));
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().getMayBeNull();
     for (unsigned i = butterfly->vectorLength(); i--;)
         butterfly->contiguousInt32()[i].setWithoutWriteBarrier(JSValue());
 
@@ -1129,7 +1129,7 @@ ContiguousDoubles JSObject::convertUndecidedToDouble(VM& vm)
 {
     ASSERT(hasUndecided(indexingType()));
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().get();
     for (unsigned i = butterfly->vectorLength(); i--;)
         butterfly->contiguousDouble()[i] = PNaN;
     
@@ -1141,7 +1141,7 @@ ContiguousJSValues JSObject::convertUndecidedToContiguous(VM& vm)
 {
     ASSERT(hasUndecided(indexingType()));
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().get();
     for (unsigned i = butterfly->vectorLength(); i--;)
         butterfly->contiguous()[i].setWithoutWriteBarrier(JSValue());
 
@@ -1203,7 +1203,7 @@ ContiguousDoubles JSObject::convertInt32ToDouble(VM& vm)
 {
     ASSERT(hasInt32(indexingType()));
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().get();
     for (unsigned i = butterfly->vectorLength(); i--;) {
         WriteBarrier<Unknown>* current = &butterfly->contiguousInt32()[i];
         double* currentAsDouble = bitwise_cast<double*>(current);
@@ -1236,7 +1236,7 @@ ArrayStorage* JSObject::convertInt32ToArrayStorage(VM& vm, NonPropertyTransition
 
     unsigned vectorLength = m_butterfly.get()->vectorLength();
     ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(vm, vectorLength);
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().get();
     for (unsigned i = 0; i < vectorLength; i++) {
         JSValue v = butterfly->contiguous()[i].get();
         newStorage->m_vector[i].setWithoutWriteBarrier(v);
@@ -1261,7 +1261,7 @@ ContiguousJSValues JSObject::convertDoubleToContiguous(VM& vm)
 {
     ASSERT(hasDouble(indexingType()));
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().get();
     for (unsigned i = butterfly->vectorLength(); i--;) {
         double* current = &butterfly->contiguousDouble()[i];
         WriteBarrier<Unknown>* currentAsValue = bitwise_cast<WriteBarrier<Unknown>*>(current);
@@ -1286,7 +1286,7 @@ ArrayStorage* JSObject::convertDoubleToArrayStorage(VM& vm, NonPropertyTransitio
 
     unsigned vectorLength = m_butterfly.get()->vectorLength();
     ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(vm, vectorLength);
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().get();
     for (unsigned i = 0; i < vectorLength; i++) {
         double value = butterfly->contiguousDouble()[i];
         if (value != value) {
@@ -1317,7 +1317,7 @@ ArrayStorage* JSObject::convertContiguousToArrayStorage(VM& vm, NonPropertyTrans
 
     unsigned vectorLength = m_butterfly.get()->vectorLength();
     ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(vm, vectorLength);
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().get();
     for (unsigned i = 0; i < vectorLength; i++) {
         JSValue v = butterfly->contiguous()[i].get();
         newStorage->m_vector[i].setWithoutWriteBarrier(v);
@@ -2427,7 +2427,7 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const P
         entryInMap->get(defaults);
 
         putIndexedDescriptor(exec, entryInMap, descriptor, defaults);
-        Butterfly* butterfly = m_butterfly.get();
+        Butterfly* butterfly = m_butterfly.get().get();
         if (index >= butterfly->arrayStorage()->length())
             butterfly->arrayStorage()->setLength(index + 1);
         return true;
@@ -2559,7 +2559,7 @@ bool JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, un
     ASSERT((indexingType() & IndexingShapeMask) == indexingShape);
     ASSERT(!indexingShouldBeSparse());
 
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().get();
     
     // For us to get here, the index is either greater than the public length, or greater than
     // or equal to the vector length.
@@ -2581,7 +2581,7 @@ bool JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, un
         throwOutOfMemoryError(exec, scope);
         return false;
     }
-    butterfly = m_butterfly.get();
+    butterfly = m_butterfly.get().get();
 
     RELEASE_ASSERT(i < butterfly->vectorLength());
     switch (indexingShape) {
@@ -3132,7 +3132,7 @@ bool JSObject::increaseVectorLength(VM& vm, unsigned newLength)
 
 bool JSObject::ensureLengthSlow(VM& vm, unsigned length)
 {
-    Butterfly* butterfly = m_butterfly.get();
+    Butterfly* butterfly = m_butterfly.get().get();
     
     ASSERT(length <= MAX_STORAGE_VECTOR_LENGTH);
     ASSERT(hasContiguous(indexingType()) || hasInt32(indexingType()) || hasDouble(indexingType()) || hasUndecided(indexingType()));
@@ -3206,7 +3206,7 @@ Butterfly* JSObject::allocateMoreOutOfLineStorage(VM& vm, size_t oldSize, size_t
     // It's important that this function not rely on structure(), for the property
     // capacity, since we might have already mutated the structure in-place.
 
-    return Butterfly::createOrGrowPropertyStorage(m_butterfly.get(), vm, this, structure(vm), oldSize, newSize);
+    return Butterfly::createOrGrowPropertyStorage(m_butterfly.get().getMayBeNull(), vm, this, structure(vm), oldSize, newSize);
 }
 
 static JSCustomGetterSetterFunction* getCustomGetterSetterFunctionForGetterSetter(ExecState* exec, PropertyName propertyName, CustomGetterSetter* getterSetter, JSCustomGetterSetterFunction::Type type)
index 6501277..683d966 100644 (file)
@@ -43,6 +43,7 @@
 #include "VM.h"
 #include "JSString.h"
 #include "SparseArrayValueMap.h"
+#include <wtf/CagedPtr.h>
 #include <wtf/StdLibExtras.h>
 
 namespace JSC {
@@ -254,7 +255,7 @@ public:
     
     bool canGetIndexQuickly(unsigned i)
     {
-        Butterfly* butterfly = m_butterfly.get();
+        Butterfly* butterfly = m_butterfly.get().getMayBeNull();
         switch (indexingType()) {
         case ALL_BLANK_INDEXING_TYPES:
         case ALL_UNDECIDED_INDEXING_TYPES:
@@ -280,7 +281,7 @@ public:
         
     JSValue getIndexQuickly(unsigned i)
     {
-        Butterfly* butterfly = m_butterfly.get();
+        Butterfly* butterfly = m_butterfly.get().get();
         switch (indexingType()) {
         case ALL_INT32_INDEXING_TYPES:
             return jsNumber(butterfly->contiguous()[i].get().asInt32());
@@ -298,7 +299,7 @@ public:
         
     JSValue tryGetIndexQuickly(unsigned i) const
     {
-        Butterfly* butterfly = m_butterfly.get();
+        Butterfly* butterfly = m_butterfly.get().getMayBeNull();
         switch (indexingType()) {
         case ALL_BLANK_INDEXING_TYPES:
         case ALL_UNDECIDED_INDEXING_TYPES:
@@ -352,7 +353,7 @@ public:
         
     bool canSetIndexQuickly(unsigned i)
     {
-        Butterfly* butterfly = m_butterfly.get();
+        Butterfly* butterfly = m_butterfly.get().getMayBeNull();
         switch (indexingType()) {
         case ALL_BLANK_INDEXING_TYPES:
         case ALL_UNDECIDED_INDEXING_TYPES:
@@ -375,7 +376,7 @@ public:
         
     void setIndexQuickly(VM& vm, unsigned i, JSValue v)
     {
-        Butterfly* butterfly = m_butterfly.get();
+        Butterfly* butterfly = m_butterfly.get().get();
         switch (indexingType()) {
         case ALL_INT32_INDEXING_TYPES: {
             ASSERT(i < butterfly->vectorLength());
@@ -435,7 +436,7 @@ public:
     ALWAYS_INLINE void initializeIndex(ObjectInitializationScope& scope, unsigned i, JSValue v, IndexingType indexingType)
     {
         VM& vm = scope.vm();
-        Butterfly* butterfly = m_butterfly.get();
+        Butterfly* butterfly = m_butterfly.get().get();
         switch (indexingType) {
         case ALL_UNDECIDED_INDEXING_TYPES: {
             setIndexQuicklyToUndecided(vm, i, v);
@@ -492,7 +493,7 @@ public:
     // barriers. This implies not having any data format conversions.
     ALWAYS_INLINE void initializeIndexWithoutBarrier(ObjectInitializationScope&, unsigned i, JSValue v, IndexingType indexingType)
     {
-        Butterfly* butterfly = m_butterfly.get();
+        Butterfly* butterfly = m_butterfly.get().get();
         switch (indexingType) {
         case ALL_UNDECIDED_INDEXING_TYPES: {
             RELEASE_ASSERT_NOT_REACHED();
@@ -668,8 +669,8 @@ public:
         return inlineStorageUnsafe();
     }
         
-    const Butterfly* butterfly() const { return m_butterfly.get(); }
-    Butterfly* butterfly() { return m_butterfly.get(); }
+    const Butterfly* butterfly() const { return m_butterfly.get().getMayBeNull(); }
+    Butterfly* butterfly() { return m_butterfly.get().getMayBeNull(); }
     
     ConstPropertyStorage outOfLineStorage() const { return m_butterfly.get()->propertyStorage(); }
     PropertyStorage outOfLineStorage() { return m_butterfly.get()->propertyStorage(); }
@@ -1045,9 +1046,7 @@ private:
     PropertyOffset prepareToPutDirectWithoutTransition(VM&, PropertyName, unsigned attributes, StructureID, Structure*);
 
 protected:
-    // FIXME: This should do caging.
-    // https://bugs.webkit.org/show_bug.cgi?id=175039
-    AuxiliaryBarrier<Butterfly*> m_butterfly;
+    AuxiliaryBarrier<CagedPtr<Butterfly>> m_butterfly;
 #if USE(JSVALUE32_64)
 private:
     uint32_t m_padding;
index aaa74b5..27d72d7 100644 (file)
@@ -1,5 +1,26 @@
 2017-08-02  Filip Pizlo  <fpizlo@apple.com>
 
+        All C++ accesses to JSObject::m_butterfly should do caging
+        https://bugs.webkit.org/show_bug.cgi?id=175039
+
+        Reviewed by Keith Miller.
+        
+        Adds a smart pointer class that does various kinds of caging for you.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/CagedPtr.h: Added.
+        (WTF::CagedPtr::CagedPtr):
+        (WTF::CagedPtr::get const):
+        (WTF::CagedPtr::getMayBeNull const):
+        (WTF::CagedPtr::operator== const):
+        (WTF::CagedPtr::operator!= const):
+        (WTF::CagedPtr::operator bool const):
+        (WTF::CagedPtr::operator* const):
+        (WTF::CagedPtr::operator-> const):
+
+2017-08-02  Filip Pizlo  <fpizlo@apple.com>
+
         We should be OK with the gigacage being disabled on gmalloc
         https://bugs.webkit.org/show_bug.cgi?id=175082
 
index 417b7f6..d85690f 100644 (file)
                0F43D8F01DB5ADDC00108FB6 /* AutomaticThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutomaticThread.h; sourceTree = "<group>"; };
                0F4570421BE5B58F0062A629 /* Dominators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Dominators.h; sourceTree = "<group>"; };
                0F4570441BE834410062A629 /* BubbleSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BubbleSort.h; sourceTree = "<group>"; };
+               0F5BF1651F2317830029D91D /* NaturalLoops.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NaturalLoops.h; sourceTree = "<group>"; };
                0F5BF1741F23D49A0029D91D /* Gigacage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Gigacage.cpp; sourceTree = "<group>"; };
                0F5BF1751F23D49A0029D91D /* Gigacage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Gigacage.h; sourceTree = "<group>"; };
-               0F5BF1651F2317830029D91D /* NaturalLoops.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NaturalLoops.h; sourceTree = "<group>"; };
                0F60F32D1DFCBD1B00416D6C /* LockedPrintStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LockedPrintStream.cpp; sourceTree = "<group>"; };
                0F60F32E1DFCBD1B00416D6C /* LockedPrintStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LockedPrintStream.h; sourceTree = "<group>"; };
                0F66B2801DC97BAB004A1D3F /* ClockType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClockType.cpp; sourceTree = "<group>"; };
                0FE4479B1B7AAA03009498EB /* WordLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WordLock.h; sourceTree = "<group>"; };
                0FEB3DCE1BB5D684009D7AAD /* SharedTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedTask.h; sourceTree = "<group>"; };
                0FEB3DD01BB7366B009D7AAD /* ParallelVectorIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParallelVectorIterator.h; sourceTree = "<group>"; };
+               0FEC3C4F1F323C6800F59B6C /* CagedPtr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CagedPtr.h; sourceTree = "<group>"; };
                0FEC84AE1BD825310080FF74 /* GraphNodeWorklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GraphNodeWorklist.h; sourceTree = "<group>"; };
                0FEC84B01BDACD390080FF74 /* ScopedLambda.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScopedLambda.h; sourceTree = "<group>"; };
                0FED67B51B22D4D80066CE15 /* TinyPtrSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyPtrSet.h; sourceTree = "<group>"; };
                                0F4570441BE834410062A629 /* BubbleSort.h */,
                                A8A47267151A825A004123FF /* BumpPointerAllocator.h */,
                                EB95E1EF161A72410089A2F5 /* ByteOrder.h */,
+                               0FEC3C4F1F323C6800F59B6C /* CagedPtr.h */,
                                A8A4726A151A825A004123FF /* CheckedArithmetic.h */,
                                A8A4726B151A825A004123FF /* CheckedBoolean.h */,
                                0F66B2801DC97BAB004A1D3F /* ClockType.cpp */,
index dafe822..3e01b0d 100644 (file)
@@ -13,6 +13,7 @@ set(WTF_HEADERS
     BumpPointerAllocator.h
     ByteOrder.h
     CPUTime.h
+    CagedPtr.h
     ClockType.h
     CompilationThread.h
     Compiler.h
diff --git a/Source/WTF/wtf/CagedPtr.h b/Source/WTF/wtf/CagedPtr.h
new file mode 100644 (file)
index 0000000..3f77645
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 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
+ * 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.
+ */
+
+#pragma once
+
+#include <wtf/Gigacage.h>
+
+namespace WTF {
+
+template<typename T>
+class CagedPtr {
+public:
+    CagedPtr(T* ptr = nullptr)
+        : m_ptr(ptr)
+    {
+    }
+    
+    T* get() const
+    {
+        ASSERT(m_ptr);
+        return Gigacage::caged(m_ptr);
+    }
+    
+    T* getMayBeNull() const
+    {
+        if (!m_ptr)
+            return nullptr;
+        return get();
+    }
+    
+    bool operator==(const CagedPtr& other) const
+    {
+        return getMayBeNull() == other.getMayBeNull();
+    }
+    
+    bool operator!=(const CagedPtr& other) const
+    {
+        return !(*this == other);
+    }
+    
+    explicit operator bool() const
+    {
+        return *this != CagedPtr();
+    }
+    
+    T& operator*() const { return *get(); }
+    T* operator->() const { return get(); }
+    
+private:
+    T* m_ptr;
+};
+
+} // namespace WTF
+
+using WTF::CagedPtr;
+
index 83998f9..0bd0974 100644 (file)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "BAssert.h"
 #include "BExport.h"
 #include "BPlatform.h"
 #include <inttypes.h>
@@ -58,6 +59,7 @@ BEXPORT void removeDisableCallback(void (*)(void*), void*);
 template<typename T>
 T* caged(T* ptr)
 {
+    BASSERT(ptr);
     void* gigacageBasePtr = g_gigacageBasePtr;
     if (!gigacageBasePtr)
         return ptr;