[JSC] Remove ArrayBufferNeuteringWatchpointSet
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Dec 2019 22:17:27 +0000 (22:17 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Dec 2019 22:17:27 +0000 (22:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=205194

Reviewed by Saam Barati.

Source/JavaScriptCore:

This patch removes ArrayBufferNeuteringWatchpointSet, and instead putting InlineWatchpointSet directly into ArrayBuffer, since this is much simpler.
The main reason why we are using ArrayBufferNeuteringWatchpointSet is not to increase sizeof(ArrayBuffer). But this complicates the implementation.
So, not to increase sizeof(ArrayBuffer), we use PackedRefPtr in ArrayBuffer, which is RefPtr while the pointer is packed. This gives us 8 bytes which is
suitable for placing InlineWatchpointSet without increasing sizeof(ArrayBuffer). We also convert Function<> in ArrayBuffer to PackedRefPtr<SharedTask<>>,
and share Gigacage::free destructor by multiple ArrayBuffer. This is memory efficient since this is the common case, and we can pack this field easily.

* API/JSTypedArray.cpp:
(JSObjectMakeTypedArrayWithBytesNoCopy):
(JSObjectMakeArrayBufferWithBytesNoCopy):
* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* dfg/DFGDesiredWatchpoints.cpp:
(JSC::DFG::ArrayBufferViewWatchpointAdaptor::add):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::tryGetFoldableView):
* runtime/ArrayBuffer.cpp:
(JSC::ArrayBuffer::primitiveGigacageDestructor):
(JSC::SharedArrayBufferContents::~SharedArrayBufferContents):
(JSC::ArrayBufferContents::destroy):
(JSC::ArrayBufferContents::reset):
(JSC::ArrayBufferContents::tryAllocate):
(JSC::ArrayBufferContents::makeShared):
(JSC::ArrayBufferContents::shareWith):
(JSC::ArrayBuffer::createAdopted):
(JSC::ArrayBuffer::transferTo):
(JSC::ArrayBuffer::neuter):
(JSC::ArrayBuffer::notifyIncommingReferencesOfTransfer):
* runtime/ArrayBuffer.h:
(JSC::ArrayBuffer::neuteringWatchpointSet):
* runtime/ArrayBufferNeuteringWatchpointSet.cpp: Removed.
* runtime/FileBasedFuzzerAgent.cpp:
(JSC::FileBasedFuzzerAgent::getPredictionInternal):
* runtime/FileBasedFuzzerAgentBase.cpp:
(JSC::FileBasedFuzzerAgentBase::createLookupKey):
* runtime/PredictionFileCreatingFuzzerAgent.cpp:
(JSC::PredictionFileCreatingFuzzerAgent::getPredictionInternal):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
* wasm/js/JSWebAssemblyMemory.cpp:
(JSC::JSWebAssemblyMemory::buffer):

Source/WebCore:

* bindings/js/SerializedScriptValue.h:
(WebCore::SerializedScriptValue::decode):

Source/WTF:

This patch adds PackedRef and PackedRefPtr. They are Ref and RefPtr, but its internal pointer is packed.
So we can represent them in 6 bytes with 1 byte alignment.

* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/Packed.h:
(WTF::alignof):
* wtf/PackedRef.h: Copied from Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpointSet.h.
* wtf/PackedRefPtr.h: Renamed from Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpointSet.h.
* wtf/RefPtr.h:
(WTF::RefPtr::operator UnspecifiedBoolType const):
(WTF::RefPtr::unspecifiedBoolTypeInstance const):

Tools:

Add tests for PackedRef and PackedRefPtr.

* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/PackedRef.cpp: Added.
(TestWebKitAPI::TEST):
(TestWebKitAPI::passWithRef):
(TestWebKitAPI::PackedRefCheckingRefLogger::PackedRefCheckingRefLogger):
(TestWebKitAPI::PackedRefCheckingRefLogger::ref):
(TestWebKitAPI::PackedRefCheckingRefLogger::deref):
(TestWebKitAPI::DerivedPackedRefCheckingRefLogger::DerivedPackedRefCheckingRefLogger):
* TestWebKitAPI/Tests/WTF/PackedRefPtr.cpp: Copied from Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp.
(TestWebKitAPI::TEST):
(TestWebKitAPI::f1):
(TestWebKitAPI::ConstRefCounted::create):
(TestWebKitAPI::returnConstRefCountedRef):
(TestWebKitAPI::returnRefCountedRef):
(TestWebKitAPI::PackedRefPtrCheckingRefLogger::PackedRefPtrCheckingRefLogger):
(TestWebKitAPI::loggerName):
(TestWebKitAPI::PackedRefPtrCheckingRefLogger::ref):
(TestWebKitAPI::PackedRefPtrCheckingRefLogger::deref):
* TestWebKitAPI/Tests/WTF/RefPtr.cpp:
(TestWebKitAPI::f1):
(TestWebKitAPI::returnConstRefCountedRef):
(TestWebKitAPI::returnRefCountedRef):

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

30 files changed:
Source/JavaScriptCore/API/JSTypedArray.cpp
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/runtime/ArrayBuffer.cpp
Source/JavaScriptCore/runtime/ArrayBuffer.h
Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpointSet.cpp [deleted file]
Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.cpp
Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.cpp
Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.cpp
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/CMakeLists.txt
Source/WTF/wtf/Packed.h
Source/WTF/wtf/PackedRef.h [moved from Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpointSet.h with 63% similarity]
Source/WTF/wtf/PackedRefPtr.h [new file with mode: 0644]
Source/WTF/wtf/RefPtr.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/SerializedScriptValue.h
Tools/ChangeLog
Tools/TestWebKitAPI/CMakeLists.txt
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WTF/PackedRef.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WTF/PackedRefPtr.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp

index eb9dc30..46035a9 100644 (file)
@@ -184,10 +184,10 @@ JSObjectRef JSObjectMakeTypedArrayWithBytesNoCopy(JSContextRef ctx, JSTypedArray
 
     unsigned elementByteSize = elementSize(toTypedArrayType(arrayType));
 
-    auto buffer = ArrayBuffer::createFromBytes(bytes, length, [=](void* p) {
+    auto buffer = ArrayBuffer::createFromBytes(bytes, length, createSharedTask<void(void*)>([=](void* p) {
         if (destructor)
             destructor(p, destructorContext);
-    });
+    }));
     JSObject* result = createTypedArray(globalObject, arrayType, WTFMove(buffer), 0, length / elementByteSize);
     if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
         return nullptr;
@@ -312,10 +312,10 @@ JSObjectRef JSObjectMakeArrayBufferWithBytesNoCopy(JSContextRef ctx, void* bytes
     JSLockHolder locker(vm);
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
-    auto buffer = ArrayBuffer::createFromBytes(bytes, byteLength, [=](void* p) {
+    auto buffer = ArrayBuffer::createFromBytes(bytes, byteLength, createSharedTask<void(void*)>([=](void* p) {
         if (bytesDeallocator)
             bytesDeallocator(p, deallocatorContext);
-    });
+    }));
 
     JSArrayBuffer* jsBuffer = JSArrayBuffer::create(vm, globalObject->arrayBufferStructure(ArrayBufferSharingMode::Default), WTFMove(buffer));
     if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
index d092da6..9ad408f 100644 (file)
@@ -1,3 +1,52 @@
+2019-12-16  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Remove ArrayBufferNeuteringWatchpointSet
+        https://bugs.webkit.org/show_bug.cgi?id=205194
+
+        Reviewed by Saam Barati.
+
+        This patch removes ArrayBufferNeuteringWatchpointSet, and instead putting InlineWatchpointSet directly into ArrayBuffer, since this is much simpler.
+        The main reason why we are using ArrayBufferNeuteringWatchpointSet is not to increase sizeof(ArrayBuffer). But this complicates the implementation.
+        So, not to increase sizeof(ArrayBuffer), we use PackedRefPtr in ArrayBuffer, which is RefPtr while the pointer is packed. This gives us 8 bytes which is
+        suitable for placing InlineWatchpointSet without increasing sizeof(ArrayBuffer). We also convert Function<> in ArrayBuffer to PackedRefPtr<SharedTask<>>,
+        and share Gigacage::free destructor by multiple ArrayBuffer. This is memory efficient since this is the common case, and we can pack this field easily.
+
+        * API/JSTypedArray.cpp:
+        (JSObjectMakeTypedArrayWithBytesNoCopy):
+        (JSObjectMakeArrayBufferWithBytesNoCopy):
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * dfg/DFGDesiredWatchpoints.cpp:
+        (JSC::DFG::ArrayBufferViewWatchpointAdaptor::add):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::tryGetFoldableView):
+        * runtime/ArrayBuffer.cpp:
+        (JSC::ArrayBuffer::primitiveGigacageDestructor):
+        (JSC::SharedArrayBufferContents::~SharedArrayBufferContents):
+        (JSC::ArrayBufferContents::destroy):
+        (JSC::ArrayBufferContents::reset):
+        (JSC::ArrayBufferContents::tryAllocate):
+        (JSC::ArrayBufferContents::makeShared):
+        (JSC::ArrayBufferContents::shareWith):
+        (JSC::ArrayBuffer::createAdopted):
+        (JSC::ArrayBuffer::transferTo):
+        (JSC::ArrayBuffer::neuter):
+        (JSC::ArrayBuffer::notifyIncommingReferencesOfTransfer):
+        * runtime/ArrayBuffer.h:
+        (JSC::ArrayBuffer::neuteringWatchpointSet):
+        * runtime/ArrayBufferNeuteringWatchpointSet.cpp: Removed.
+        * runtime/FileBasedFuzzerAgent.cpp:
+        (JSC::FileBasedFuzzerAgent::getPredictionInternal):
+        * runtime/FileBasedFuzzerAgentBase.cpp:
+        (JSC::FileBasedFuzzerAgentBase::createLookupKey):
+        * runtime/PredictionFileCreatingFuzzerAgent.cpp:
+        (JSC::PredictionFileCreatingFuzzerAgent::getPredictionInternal):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+        * wasm/js/JSWebAssemblyMemory.cpp:
+        (JSC::JSWebAssemblyMemory::buffer):
+
 2019-12-14  Adrian Perez de Castro  <aperez@igalia.com>
 
         [GTK][WPE] Fix various non-unified build issues introduced since r251698
index d996c1e..dbce5ba 100644 (file)
                0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */; };
                0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpointSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpointSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */; };
                0FFFC95A14EF90A900C72532 /* DFGCSEPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94E14EF909500C72532 /* DFGCSEPhase.h */; };
                0FFFC95C14EF90AF00C72532 /* DFGPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC95014EF909500C72532 /* DFGPhase.h */; };
                0FFB80BB20A794700006AAF6 /* JITCodeInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCodeInlines.h; sourceTree = "<group>"; };
                0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPropertyTypeKey.h; path = dfg/DFGPropertyTypeKey.h; sourceTree = "<group>"; };
                0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
-               0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpointSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpointSet.cpp; sourceTree = "<group>"; };
-               0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpointSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpointSet.h; sourceTree = "<group>"; };
                0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCFAPhase.cpp; path = dfg/DFGCFAPhase.cpp; sourceTree = "<group>"; };
                0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFAPhase.h; path = dfg/DFGCFAPhase.h; sourceTree = "<group>"; };
                0FFFC94D14EF909500C72532 /* DFGCSEPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCSEPhase.cpp; path = dfg/DFGCSEPhase.cpp; sourceTree = "<group>"; };
                                0F6B1CB71861244C00845D97 /* ArityCheckMode.h */,
                                A7A8AF2517ADB5F2005AB174 /* ArrayBuffer.cpp */,
                                A7A8AF2617ADB5F3005AB174 /* ArrayBuffer.h */,
-                               0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpointSet.cpp */,
-                               0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpointSet.h */,
                                0F30FB601DC2DE96003124F2 /* ArrayBufferSharingMode.h */,
                                A7A8AF2717ADB5F3005AB174 /* ArrayBufferView.cpp */,
                                A7A8AF2817ADB5F3005AB174 /* ArrayBufferView.h */,
                                86ADD1450FDDEA980006FFCC /* ARMv7Registers.h in Headers */,
                                0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */,
                                A7A8AF3517ADB5F3005AB174 /* ArrayBuffer.h in Headers */,
-                               0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpointSet.h in Headers */,
                                0F30FB611DC2DE99003124F2 /* ArrayBufferSharingMode.h in Headers */,
                                A7A8AF3717ADB5F3005AB174 /* ArrayBufferView.h in Headers */,
                                BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */,
index 1818bf7..47b0ca7 100644 (file)
@@ -703,7 +703,6 @@ profiler/ProfilerUID.cpp
 runtime/AbstractModuleRecord.cpp
 runtime/ArgList.cpp
 runtime/ArrayBuffer.cpp
-runtime/ArrayBufferNeuteringWatchpointSet.cpp
 runtime/ArrayBufferView.cpp
 runtime/ArrayConstructor.cpp
 runtime/ArrayConventions.cpp
index c2431f0..07babe7 100644 (file)
@@ -28,7 +28,6 @@
 
 #if ENABLE(DFG_JIT)
 
-#include "ArrayBufferNeuteringWatchpointSet.h"
 #include "CodeBlock.h"
 #include "DFGGraph.h"
 #include "JSCInlines.h"
@@ -38,19 +37,17 @@ namespace JSC { namespace DFG {
 void ArrayBufferViewWatchpointAdaptor::add(
     CodeBlock* codeBlock, JSArrayBufferView* view, CommonData& common)
 {
-    VM& vm = codeBlock->vm();
+    // view is already frozen. If it is deallocated, jettisoning happens.
     CodeBlockJettisoningWatchpoint* watchpoint = nullptr;
     {
         ConcurrentJSLocker locker(codeBlock->m_lock);
         watchpoint = common.watchpoints.add(codeBlock);
     }
-    ArrayBufferNeuteringWatchpointSet* neuteringWatchpoint =
-        ArrayBufferNeuteringWatchpointSet::create(vm);
-    neuteringWatchpoint->set().add(WTFMove(watchpoint));
-    codeBlock->addConstant(ConcurrentJSLocker(codeBlock->m_lock), neuteringWatchpoint);
+    ArrayBuffer* arrayBuffer = view->possiblySharedBuffer();
+    RELEASE_ASSERT(arrayBuffer);
     // FIXME: We don't need to set this watchpoint at all for shared buffers.
     // https://bugs.webkit.org/show_bug.cgi?id=164108
-    vm.heap.addReference(neuteringWatchpoint, view->possiblySharedBuffer());
+    arrayBuffer->neuteringWatchpointSet().add(WTFMove(watchpoint));
 }
 
 void SymbolTableAdaptor::add(
index 7964985..b320f70 100644 (file)
@@ -1399,6 +1399,7 @@ JSArrayBufferView* Graph::tryGetFoldableView(JSValue value)
     if (!view->length())
         return nullptr;
     WTF::loadLoadFence();
+    freeze(view);
     watchpoints().addLazily(view);
     return view;
 }
index 07bda38..2e7b1fa 100644 (file)
 #include "config.h"
 #include "ArrayBuffer.h"
 
-#include "ArrayBufferNeuteringWatchpointSet.h"
 #include "JSArrayBufferView.h"
 #include "JSCInlines.h"
 #include <wtf/Gigacage.h>
 
 namespace JSC {
 
+Ref<SharedTask<void(void*)>> ArrayBuffer::primitiveGigacageDestructor()
+{
+    static LazyNeverDestroyed<Ref<SharedTask<void(void*)>>> destructor;
+    static std::once_flag onceKey;
+    std::call_once(onceKey, [&] {
+        destructor.construct(createSharedTask<void(void*)>([] (void* p) { Gigacage::free(Gigacage::Primitive, p); }));
+    });
+    return destructor.get().copyRef();
+}
+
 SharedArrayBufferContents::SharedArrayBufferContents(void* data, unsigned size, ArrayBufferDestructorFunction&& destructor)
     : m_data(data, size)
     , m_destructor(WTFMove(destructor))
@@ -42,8 +51,10 @@ SharedArrayBufferContents::SharedArrayBufferContents(void* data, unsigned size,
 
 SharedArrayBufferContents::~SharedArrayBufferContents()
 {
-    // FIXME: we shouldn't use getUnsafe here https://bugs.webkit.org/show_bug.cgi?id=197698
-    m_destructor(m_data.getUnsafe());
+    if (m_destructor) {
+        // FIXME: we shouldn't use getUnsafe here https://bugs.webkit.org/show_bug.cgi?id=197698
+        m_destructor->run(m_data.getUnsafe());
+    }
 }
 
 ArrayBufferContents::ArrayBufferContents()
@@ -84,15 +95,17 @@ void ArrayBufferContents::clear()
 
 void ArrayBufferContents::destroy()
 {
-    // FIXME: We shouldn't use getUnsafe here: https://bugs.webkit.org/show_bug.cgi?id=197698
-    m_destructor(m_data.getUnsafe());
+    if (m_destructor) {
+        // FIXME: We shouldn't use getUnsafe here: https://bugs.webkit.org/show_bug.cgi?id=197698
+        m_destructor->run(m_data.getUnsafe());
+    }
 }
 
 void ArrayBufferContents::reset()
 {
-    m_destructor = [] (void*) { };
-    m_shared = nullptr;
     m_data = nullptr;
+    m_destructor = nullptr;
+    m_shared = nullptr;
     m_sizeInBytes = 0;
 }
 
@@ -123,13 +136,13 @@ void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByte
 
     m_sizeInBytes = sizeInBytes;
     RELEASE_ASSERT(m_sizeInBytes <= MAX_ARRAY_BUFFER_SIZE);
-    m_destructor = [] (void* p) { Gigacage::free(Gigacage::Primitive, p); };
+    m_destructor = ArrayBuffer::primitiveGigacageDestructor();
 }
 
 void ArrayBufferContents::makeShared()
 {
     m_shared = adoptRef(new SharedArrayBufferContents(data(), sizeInBytes(), WTFMove(m_destructor)));
-    m_destructor = [] (void*) { };
+    m_destructor = nullptr;
 }
 
 void ArrayBufferContents::transferTo(ArrayBufferContents& other)
@@ -158,9 +171,9 @@ void ArrayBufferContents::shareWith(ArrayBufferContents& other)
 {
     ASSERT(!other.m_data);
     ASSERT(m_shared);
-    other.m_destructor = [] (void*) { };
-    other.m_shared = m_shared;
     other.m_data = m_data;
+    other.m_destructor = nullptr;
+    other.m_shared = m_shared;
     other.m_sizeInBytes = m_sizeInBytes;
     RELEASE_ASSERT(other.m_sizeInBytes <= MAX_ARRAY_BUFFER_SIZE);
 }
@@ -197,7 +210,7 @@ Ref<ArrayBuffer> ArrayBuffer::create(ArrayBufferContents&& contents)
 //   from the cage.
 Ref<ArrayBuffer> ArrayBuffer::createAdopted(const void* data, unsigned byteLength)
 {
-    return createFromBytes(data, byteLength, [] (void* p) { Gigacage::free(Gigacage::Primitive, p); });
+    return createFromBytes(data, byteLength, ArrayBuffer::primitiveGigacageDestructor());
 }
 
 // FIXME: We cannot use this except if the memory comes from the cage.
@@ -370,7 +383,7 @@ bool ArrayBuffer::transferTo(VM& vm, ArrayBufferContents& result)
     }
 
     m_contents.transferTo(result);
-    notifyIncommingReferencesOfTransfer(vm);
+    notifyNeutering(vm);
     return true;
 }
 
@@ -380,18 +393,17 @@ void ArrayBuffer::neuter(VM& vm)
     ASSERT(isWasmMemory());
     ArrayBufferContents unused;
     m_contents.transferTo(unused);
-    notifyIncommingReferencesOfTransfer(vm);
+    notifyNeutering(vm);
 }
 
-void ArrayBuffer::notifyIncommingReferencesOfTransfer(VM& vm)
+void ArrayBuffer::notifyNeutering(VM& vm)
 {
     for (size_t i = numberOfIncomingReferences(); i--;) {
         JSCell* cell = incomingReferenceAt(i);
         if (JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(vm, cell))
             view->neuter();
-        else if (ArrayBufferNeuteringWatchpointSet* watchpoint = jsDynamicCast<ArrayBufferNeuteringWatchpointSet*>(vm, cell))
-            watchpoint->fireAll();
     }
+    m_neuteringWatchpointSet.fireAll(vm, "Array buffer was neutered");
 }
 
 ASCIILiteral errorMesasgeForTransfer(ArrayBuffer* buffer)
index e6f55ce..fd11dc6 100644 (file)
 
 #include "ArrayBufferSharingMode.h"
 #include "GCIncomingRefCounted.h"
+#include "Watchpoint.h"
 #include "Weak.h"
 #include <wtf/CagedPtr.h>
 #include <wtf/CheckedArithmetic.h>
-#include <wtf/Function.h>
+#include <wtf/PackedRefPtr.h>
+#include <wtf/SharedTask.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/text/WTFString.h>
@@ -44,7 +46,8 @@ class ArrayBuffer;
 class ArrayBufferView;
 class JSArrayBuffer;
 
-typedef Function<void(void*)> ArrayBufferDestructorFunction;
+using ArrayBufferDestructorFunction = RefPtr<SharedTask<void(void*)>>;
+using PackedArrayBufferDestructorFunction = PackedRefPtr<SharedTask<void(void*)>>;
 
 class SharedArrayBufferContents : public ThreadSafeRefCounted<SharedArrayBufferContents> {
 public:
@@ -56,7 +59,7 @@ public:
 private:
     using DataType = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>;
     DataType m_data;
-    ArrayBufferDestructorFunction m_destructor;
+    PackedArrayBufferDestructorFunction m_destructor;
     unsigned m_sizeInBytes;
 };
 
@@ -98,10 +101,10 @@ private:
     void copyTo(ArrayBufferContents&);
     void shareWith(ArrayBufferContents&);
 
-    ArrayBufferDestructorFunction m_destructor;
-    RefPtr<SharedArrayBufferContents> m_shared;
     using DataType = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>;
     DataType m_data;
+    PackedArrayBufferDestructorFunction m_destructor;
+    PackedRefPtr<SharedArrayBufferContents> m_shared;
     unsigned m_sizeInBytes;
 };
 
@@ -148,11 +151,14 @@ public:
 
     void neuter(VM&);
     bool isNeutered() { return !m_contents.m_data; }
+    InlineWatchpointSet& neuteringWatchpointSet() { return m_neuteringWatchpointSet; }
 
     static ptrdiff_t offsetOfData() { return OBJECT_OFFSETOF(ArrayBuffer, m_contents) + OBJECT_OFFSETOF(ArrayBufferContents, m_data); }
 
     ~ArrayBuffer() { }
 
+    JS_EXPORT_PRIVATE static Ref<SharedTask<void(void*)>> primitiveGigacageDestructor();
+
 private:
     static Ref<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
     static Ref<ArrayBuffer> createInternal(ArrayBufferContents&&, const void*, unsigned);
@@ -162,17 +168,18 @@ private:
     inline unsigned clampIndex(double index) const;
     static inline unsigned clampValue(double x, unsigned left, unsigned right);
 
-    void notifyIncommingReferencesOfTransfer(VM&);
+    void notifyNeutering(VM&);
 
     ArrayBufferContents m_contents;
+    InlineWatchpointSet m_neuteringWatchpointSet { IsWatched };
+public:
+    Weak<JSArrayBuffer> m_wrapper;
+private:
     Checked<unsigned> m_pinCount;
     bool m_isWasmMemory;
     // m_locked == true means that some API user fetched m_contents directly from a TypedArray object,
     // the buffer is backed by a WebAssembly.Memory, or is a SharedArrayBuffer.
     bool m_locked;
-
-public:
-    Weak<JSArrayBuffer> m_wrapper;
 };
 
 void* ArrayBuffer::data()
diff --git a/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpointSet.cpp b/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpointSet.cpp
deleted file mode 100644 (file)
index 0b16d81..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2013-2019 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. ``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
- * 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. 
- */
-
-#include "config.h"
-#include "ArrayBufferNeuteringWatchpointSet.h"
-
-#include "JSCInlines.h"
-
-namespace JSC {
-
-const ClassInfo ArrayBufferNeuteringWatchpointSet::s_info = {
-    "ArrayBufferNeuteringWatchpointSet", nullptr, nullptr, nullptr,
-    CREATE_METHOD_TABLE(ArrayBufferNeuteringWatchpointSet)
-};
-
-ArrayBufferNeuteringWatchpointSet::ArrayBufferNeuteringWatchpointSet(VM& vm)
-    : Base(vm, vm.arrayBufferNeuteringWatchpointStructure.get())
-    , m_set(adoptRef(*new WatchpointSet(IsWatched)))
-{
-}
-
-void ArrayBufferNeuteringWatchpointSet::destroy(JSCell* cell)
-{
-    static_cast<ArrayBufferNeuteringWatchpointSet*>(cell)->ArrayBufferNeuteringWatchpointSet::~ArrayBufferNeuteringWatchpointSet();
-}
-
-ArrayBufferNeuteringWatchpointSet* ArrayBufferNeuteringWatchpointSet::create(VM& vm)
-{
-    ArrayBufferNeuteringWatchpointSet* result = new
-        (NotNull, allocateCell<ArrayBufferNeuteringWatchpointSet>(vm.heap))
-        ArrayBufferNeuteringWatchpointSet(vm);
-    result->finishCreation(vm);
-    return result;
-}
-
-Structure* ArrayBufferNeuteringWatchpointSet::createStructure(VM& vm)
-{
-    return Structure::create(vm, 0, jsNull(), TypeInfo(CellType, StructureFlags), info());
-}
-
-void ArrayBufferNeuteringWatchpointSet::fireAll()
-{
-    m_set->fireAll(vm(), "Array buffer was neutered");
-}
-
-} // namespace JSC
-
index a7cd4c1..cf54507 100644 (file)
@@ -100,7 +100,7 @@ SpeculatedType FileBasedFuzzerAgent::getPredictionInternal(CodeBlock* codeBlock,
         break;
 
     default:
-        RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("Unhandled opcode %s", toString(target.opcodeId).utf8().data());
+        RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("Unhandled opcode %s", opcodeNames[target.opcodeId]);
     }
     if (!generated) {
         if (Options::dumpFuzzerAgentPredictions())
index 4718097..b7112e1 100644 (file)
@@ -40,7 +40,7 @@ String FileBasedFuzzerAgentBase::createLookupKey(const String& sourceFilename, O
     StringBuilder lookupKey;
     lookupKey.append(sourceFilename);
     lookupKey.append("|");
-    lookupKey.append(toString(opcodeAliasForLookupKey(opcodeId)));
+    lookupKey.append(opcodeNames[opcodeAliasForLookupKey(opcodeId)]);
     lookupKey.append("|");
     lookupKey.append(startLocation);
     lookupKey.append("|");
index c0d25cb..cdcfa99 100644 (file)
@@ -64,7 +64,7 @@ SpeculatedType PredictionFileCreatingFuzzerAgent::getPredictionInternal(CodeBloc
         break;
 
     default:
-        RELEASE_ASSERT_WITH_MESSAGE(false, "unhandled opcode: %s", toString(predictionTarget.opcodeId).utf8().data());
+        RELEASE_ASSERT_WITH_MESSAGE(false, "unhandled opcode: %s", opcodeNames[predictionTarget.opcodeId]);
     }
     return original;
 }
index 9d54fdc..198c0e5 100644 (file)
@@ -30,7 +30,6 @@
 #include "VM.h"
 
 #include "ArgList.h"
-#include "ArrayBufferNeuteringWatchpointSet.h"
 #include "BigIntObject.h"
 #include "BooleanObject.h"
 #include "BuiltinExecutables.h"
@@ -464,7 +463,6 @@ VM::VM(VMType vmType, HeapType heapType)
     structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull()));
     sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull()));
     templateObjectDescriptorStructure.set(*this, JSTemplateObjectDescriptor::createStructure(*this, 0, jsNull()));
-    arrayBufferNeuteringWatchpointStructure.set(*this, ArrayBufferNeuteringWatchpointSet::createStructure(*this));
     unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull()));
     unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull()));
     unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull()));
index e9a90f0..9d9cefd 100644 (file)
@@ -667,7 +667,6 @@ public:
     Strong<Structure> structureChainStructure;
     Strong<Structure> sparseArrayValueMapStructure;
     Strong<Structure> templateObjectDescriptorStructure;
-    Strong<Structure> arrayBufferNeuteringWatchpointStructure;
     Strong<Structure> unlinkedFunctionExecutableStructure;
     Strong<Structure> unlinkedProgramCodeBlockStructure;
     Strong<Structure> unlinkedEvalCodeBlockStructure;
index 3f8be36..13c62f6 100644 (file)
@@ -79,7 +79,7 @@ JSArrayBuffer* JSWebAssemblyMemory::buffer(VM& vm, JSGlobalObject* globalObject)
 
     // We can't use a ref here since it doesn't have a copy constructor...
     Ref<Wasm::Memory> protectedMemory = m_memory.get();
-    auto destructor = [protectedMemory = WTFMove(protectedMemory)] (void*) { };
+    auto destructor = createSharedTask<void(void*)>([protectedMemory = WTFMove(protectedMemory)] (void*) { });
     m_buffer = ArrayBuffer::createFromBytes(memory().memory(), memory().size(), WTFMove(destructor));
     m_buffer->makeWasmMemory();
     m_bufferWrapper.set(vm, this, JSArrayBuffer::create(vm, globalObject->arrayBufferStructure(ArrayBufferSharingMode::Default), m_buffer.get()));
index 4ba8e0a..214bd05 100644 (file)
@@ -1,3 +1,23 @@
+2019-12-16  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Remove ArrayBufferNeuteringWatchpointSet
+        https://bugs.webkit.org/show_bug.cgi?id=205194
+
+        Reviewed by Saam Barati.
+
+        This patch adds PackedRef and PackedRefPtr. They are Ref and RefPtr, but its internal pointer is packed.
+        So we can represent them in 6 bytes with 1 byte alignment.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/Packed.h:
+        (WTF::alignof):
+        * wtf/PackedRef.h: Copied from Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpointSet.h.
+        * wtf/PackedRefPtr.h: Renamed from Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpointSet.h.
+        * wtf/RefPtr.h:
+        (WTF::RefPtr::operator UnspecifiedBoolType const):
+        (WTF::RefPtr::unspecifiedBoolTypeInstance const):
+
 2019-12-13  Saam Barati  <sbarati@apple.com>
 
         Add a Heap::finalize function that takes WTF::Function<void()>
index 8e8ec15..5bd7ab4 100644 (file)
                E34CD0D022810A020020D299 /* Packed.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Packed.h; sourceTree = "<group>"; };
                E360C7642127B85B00C90F0E /* UnalignedAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnalignedAccess.h; sourceTree = "<group>"; };
                E360C7652127B85C00C90F0E /* Unexpected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unexpected.h; sourceTree = "<group>"; };
+               E36895CB23A445CD008DD4C8 /* PackedRef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PackedRef.h; sourceTree = "<group>"; };
+               E36895CC23A445EE008DD4C8 /* PackedRefPtr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PackedRefPtr.h; sourceTree = "<group>"; };
                E388886D20C9095100E632BC /* WorkerPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerPool.cpp; sourceTree = "<group>"; };
                E388886E20C9095100E632BC /* WorkerPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WorkerPool.h; sourceTree = "<group>"; };
                E38C41241EB4E04C0042957D /* CPUTimeCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CPUTimeCocoa.cpp; sourceTree = "<group>"; };
                                A8A472DB151A825B004123FF /* OSRandomSource.h */,
                                E34CD0D022810A020020D299 /* Packed.h */,
                                A8A472DF151A825B004123FF /* PackedIntVector.h */,
+                               E36895CB23A445CD008DD4C8 /* PackedRef.h */,
+                               E36895CC23A445EE008DD4C8 /* PackedRefPtr.h */,
                                A8A472E0151A825B004123FF /* PageAllocation.h */,
                                A8A472E3151A825B004123FF /* PageBlock.cpp */,
                                A8A472E4151A825B004123FF /* PageBlock.h */,
index afcc60e..dae4a71 100644 (file)
@@ -155,6 +155,8 @@ set(WTF_PUBLIC_HEADERS
     Optional.h
     OrderMaker.h
     Packed.h
+    PackedRef.h
+    PackedRefPtr.h
     PackedIntVector.h
     PageAllocation.h
     PageBlock.h
index 839d3c8..b22fc76 100644 (file)
@@ -163,6 +163,10 @@ public:
     T* operator->() const { return get(); }
     T& operator*() const { return *get(); }
     bool operator!() const { return !get(); }
+
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
+    typedef T* (PackedAlignedPtr::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType() const { return get() ? &PackedAlignedPtr::m_storage : nullptr; }
     explicit operator bool() const { return get(); }
 
     PackedAlignedPtr& operator=(T* value)
@@ -172,9 +176,9 @@ public:
     }
 
     template<class U>
-    T exchange(U&& newValue)
+    T* exchange(U&& newValue)
     {
-        T oldValue = get();
+        T* oldValue = get();
         set(std::forward<U>(newValue));
         return oldValue;
     }
@@ -189,15 +193,15 @@ public:
     template<typename Other, typename = std::enable_if_t<Other::isPackedType>>
     void swap(Other& other)
     {
-        T t1 = get();
-        T t2 = other.get();
+        T* t1 = get();
+        T* t2 = other.get();
         set(t2);
         other.set(t1);
     }
 
-    void swap(T& t2)
+    void swap(T* t2)
     {
-        T t1 = get();
+        T* t1 = get();
         std::swap(t1, t2);
         set(t1);
     }
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 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. 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #pragma once
 
-#include "JSCast.h"
-#include "Watchpoint.h"
+#include <wtf/Packed.h>
+#include <wtf/Ref.h>
 
-namespace JSC {
+namespace WTF {
 
-class ArrayBufferNeuteringWatchpointSet final : public JSCell {
-public:
-    typedef JSCell Base;
-    static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+template<typename T>
+using PackedRef = Ref<T, PackedPtrTraits<T>>;
 
-    DECLARE_INFO;
-    
-    static ArrayBufferNeuteringWatchpointSet* create(VM&);
+} // namespace WTF
 
-    static constexpr bool needsDestruction = true;
-    static void destroy(JSCell*);
-    
-    static Structure* createStructure(VM&);
-    
-    WatchpointSet& set() { return m_set.get(); }
-    
-    void fireAll();
-
-private:
-    explicit ArrayBufferNeuteringWatchpointSet(VM&);
-    
-    Ref<WatchpointSet> m_set;
-};
-
-} // namespace JSC
+using WTF::PackedRef;
diff --git a/Source/WTF/wtf/PackedRefPtr.h b/Source/WTF/wtf/PackedRefPtr.h
new file mode 100644 (file)
index 0000000..3247d7d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 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. ``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
+ * 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/Packed.h>
+#include <wtf/RefPtr.h>
+
+namespace WTF {
+
+template<typename T>
+using PackedRefPtr = RefPtr<T, PackedPtrTraits<T>>;
+
+} // namespace WTF
+
+using WTF::PackedRefPtr;
index 5bec6c7..6d4c644 100644 (file)
@@ -81,8 +81,8 @@ public:
     bool operator!() const { return !m_ptr; }
 
     // This conversion operator allows implicit conversion to bool but not to other integer types.
-    typedef T* (RefPtr::*UnspecifiedBoolType);
-    operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : nullptr; }
+    using UnspecifiedBoolType = void (RefPtr::*)() const;
+    operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::unspecifiedBoolTypeInstance : nullptr; }
 
     explicit operator bool() const { return !!m_ptr; }
     
@@ -102,6 +102,8 @@ public:
     RefPtr copyRef() const & WARN_UNUSED_RETURN { return RefPtr(m_ptr); }
 
 private:
+    void unspecifiedBoolTypeInstance() const { }
+
     friend RefPtr adoptRef<T, PtrTraits>(T*);
     template<typename X, typename Y> friend class RefPtr;
 
index 17bf611..239db6c 100644 (file)
@@ -1,3 +1,13 @@
+2019-12-16  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Remove ArrayBufferNeuteringWatchpointSet
+        https://bugs.webkit.org/show_bug.cgi?id=205194
+
+        Reviewed by Saam Barati.
+
+        * bindings/js/SerializedScriptValue.h:
+        (WebCore::SerializedScriptValue::decode):
+
 2019-12-16  Doug Kelly  <dougk@apple.com>
 
         Ensure consistent sorting of identical track names
index e569628..a4b9f66 100644 (file)
@@ -170,14 +170,11 @@ RefPtr<SerializedScriptValue> SerializedScriptValue::decode(Decoder& decoder)
             return nullptr;
 
         auto buffer = Gigacage::tryMalloc(Gigacage::Primitive, bufferSize);
-        auto destructor = [] (void* ptr) {
-            Gigacage::free(Gigacage::Primitive, ptr);
-        };
         if (!decoder.decodeFixedLengthData(static_cast<uint8_t*>(buffer), bufferSize, 1)) {
-            destructor(buffer);
+            Gigacage::free(Gigacage::Primitive, buffer);
             return nullptr;
         }
-        arrayBufferContentsArray->append({ buffer, bufferSize, WTFMove(destructor) });
+        arrayBufferContentsArray->append({ buffer, bufferSize, ArrayBuffer::primitiveGigacageDestructor() });
     }
 
     return adoptRef(*new SerializedScriptValue(WTFMove(data), WTFMove(arrayBufferContentsArray)));
index d728ae6..0ebf25f 100644 (file)
@@ -1,3 +1,36 @@
+2019-12-16  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Remove ArrayBufferNeuteringWatchpointSet
+        https://bugs.webkit.org/show_bug.cgi?id=205194
+
+        Reviewed by Saam Barati.
+
+        Add tests for PackedRef and PackedRefPtr.
+
+        * TestWebKitAPI/CMakeLists.txt:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WTF/PackedRef.cpp: Added.
+        (TestWebKitAPI::TEST):
+        (TestWebKitAPI::passWithRef):
+        (TestWebKitAPI::PackedRefCheckingRefLogger::PackedRefCheckingRefLogger):
+        (TestWebKitAPI::PackedRefCheckingRefLogger::ref):
+        (TestWebKitAPI::PackedRefCheckingRefLogger::deref):
+        (TestWebKitAPI::DerivedPackedRefCheckingRefLogger::DerivedPackedRefCheckingRefLogger):
+        * TestWebKitAPI/Tests/WTF/PackedRefPtr.cpp: Copied from Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp.
+        (TestWebKitAPI::TEST):
+        (TestWebKitAPI::f1):
+        (TestWebKitAPI::ConstRefCounted::create):
+        (TestWebKitAPI::returnConstRefCountedRef):
+        (TestWebKitAPI::returnRefCountedRef):
+        (TestWebKitAPI::PackedRefPtrCheckingRefLogger::PackedRefPtrCheckingRefLogger):
+        (TestWebKitAPI::loggerName):
+        (TestWebKitAPI::PackedRefPtrCheckingRefLogger::ref):
+        (TestWebKitAPI::PackedRefPtrCheckingRefLogger::deref):
+        * TestWebKitAPI/Tests/WTF/RefPtr.cpp:
+        (TestWebKitAPI::f1):
+        (TestWebKitAPI::returnConstRefCountedRef):
+        (TestWebKitAPI::returnRefCountedRef):
+
 2019-12-16  Keith Miller  <keith_miller@apple.com>
 
         Fix btjs on current lldb
index 87f8442..c917036 100644 (file)
@@ -65,6 +65,8 @@ set(TestWTF_SOURCES
     Tests/WTF/OptionSet.cpp
     Tests/WTF/Optional.cpp
     Tests/WTF/Packed.cpp
+    Tests/WTF/PackedRef.cpp
+    Tests/WTF/PackedRefPtr.cpp
     Tests/WTF/ParkingLot.cpp
     Tests/WTF/PriorityQueue.cpp
     Tests/WTF/RedBlackTree.cpp
index 6cdca73..7c2f8f3 100644 (file)
                E35FC7B222B82A7300F32F98 /* JSLockTakesWebThreadLock.mm in Sources */ = {isa = PBXBuildFile; fileRef = E35FC7B122B82A6D00F32F98 /* JSLockTakesWebThreadLock.mm */; };
                E373D7911F2CF35200C6FAAF /* Signals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3953F951F2CF32100A76A2E /* Signals.cpp */; };
                E38A0D351FD50CC300E98C8B /* Threading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38A0D341FD50CBC00E98C8B /* Threading.cpp */; };
+               E38D65CA23A45FAA0063D69A /* PackedRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38D65C823A45FA90063D69A /* PackedRef.cpp */; };
+               E38D65CB23A45FAA0063D69A /* PackedRefPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38D65C923A45FA90063D69A /* PackedRefPtr.cpp */; };
                E3A1E77F21B25B39008C6007 /* URLParserTextEncoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3A1E77E21B25B39008C6007 /* URLParserTextEncoding.cpp */; };
                E3A1E78221B25B7A008C6007 /* URL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3A1E78021B25B79008C6007 /* URL.cpp */; };
                E3A1E78521B25B91008C6007 /* URLParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3A1E78421B25B91008C6007 /* URLParser.cpp */; };
                E35FC7B122B82A6D00F32F98 /* JSLockTakesWebThreadLock.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JSLockTakesWebThreadLock.mm; sourceTree = "<group>"; };
                E388887020C9098100E632BC /* WorkerPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerPool.cpp; sourceTree = "<group>"; };
                E38A0D341FD50CBC00E98C8B /* Threading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Threading.cpp; sourceTree = "<group>"; };
+               E38D65C823A45FA90063D69A /* PackedRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PackedRef.cpp; sourceTree = "<group>"; };
+               E38D65C923A45FA90063D69A /* PackedRefPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PackedRefPtr.cpp; sourceTree = "<group>"; };
                E3953F951F2CF32100A76A2E /* Signals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Signals.cpp; sourceTree = "<group>"; };
                E398BC0F2041C76300387136 /* UniqueArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniqueArray.cpp; sourceTree = "<group>"; };
                E3A1E77E21B25B39008C6007 /* URLParserTextEncoding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLParserTextEncoding.cpp; sourceTree = "<group>"; };
                                1AFDE6541953B2C000C48FFA /* Optional.cpp */,
                                CE50D8C81C8665CE0072EA5A /* OptionSet.cpp */,
                                E32B549122810AC0008AD702 /* Packed.cpp */,
+                               E38D65C823A45FA90063D69A /* PackedRef.cpp */,
+                               E38D65C923A45FA90063D69A /* PackedRefPtr.cpp */,
                                0FE447971B76F1E3009498EB /* ParkingLot.cpp */,
                                53EC253F1E96BC80000831B9 /* PriorityQueue.cpp */,
                                0FC6C4CB141027E0005B7F0C /* RedBlackTree.cpp */,
                                1A77BAA31D9AFFFC005FC568 /* OptionSet.cpp in Sources */,
                                7C83DF021D0A590C00FEBCF3 /* OSObjectPtr.cpp in Sources */,
                                E32B549222810AC4008AD702 /* Packed.cpp in Sources */,
+                               E38D65CA23A45FAA0063D69A /* PackedRef.cpp in Sources */,
+                               E38D65CB23A45FAA0063D69A /* PackedRefPtr.cpp in Sources */,
                                7C83DF591D0A590C00FEBCF3 /* ParkingLot.cpp in Sources */,
                                53EC25411E96FD87000831B9 /* PriorityQueue.cpp in Sources */,
                                7C83DF131D0A590C00FEBCF3 /* RedBlackTree.cpp in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WTF/PackedRef.cpp b/Tools/TestWebKitAPI/Tests/WTF/PackedRef.cpp
new file mode 100644 (file)
index 0000000..f7abeb7
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "config.h"
+
+#include "RefLogger.h"
+#include <wtf/PackedRef.h>
+#include <wtf/PackedRefPtr.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_PackedRef, Basic)
+{
+    DerivedRefLogger a("a");
+
+    {
+        PackedRef<RefLogger> ref(a);
+        EXPECT_EQ(&a, ref.ptr());
+        EXPECT_EQ(&a.name, &ref->name);
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRef<RefLogger> ref(adoptRef(a));
+        EXPECT_EQ(&a, ref.ptr());
+        EXPECT_EQ(&a.name, &ref->name);
+    }
+    EXPECT_STREQ("deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_PackedRef, Assignment)
+{
+    DerivedRefLogger a("a");
+    RefLogger b("b");
+    DerivedRefLogger c("c");
+
+    {
+        PackedRef<RefLogger> ref(a);
+        EXPECT_EQ(&a, ref.ptr());
+        log() << "| ";
+        ref = b;
+        EXPECT_EQ(&b, ref.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | ref(b) deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRef<RefLogger> ref(a);
+        EXPECT_EQ(&a, ref.ptr());
+        log() << "| ";
+        ref = c;
+        EXPECT_EQ(&c, ref.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | ref(c) deref(a) | deref(c) ", takeLogStr().c_str());
+
+    {
+        PackedRef<RefLogger> ref(a);
+        EXPECT_EQ(&a, ref.ptr());
+        log() << "| ";
+        ref = adoptRef(b);
+        EXPECT_EQ(&b, ref.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRef<RefLogger> ref(a);
+        EXPECT_EQ(&a, ref.ptr());
+        log() << "| ";
+        ref = adoptRef(c);
+        EXPECT_EQ(&c, ref.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | deref(a) | deref(c) ", takeLogStr().c_str());
+}
+
+static PackedRef<RefLogger> passWithRef(PackedRef<RefLogger>&& reference)
+{
+    return WTFMove(reference);
+}
+
+TEST(WTF_PackedRef, ReturnValue)
+{
+    DerivedRefLogger a("a");
+    RefLogger b("b");
+    DerivedRefLogger c("c");
+
+    {
+        PackedRef<RefLogger> ref(passWithRef(PackedRef<RefLogger>(a)));
+        EXPECT_EQ(&a, ref.ptr());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRef<RefLogger> ref(a);
+        EXPECT_EQ(&a, ref.ptr());
+        log() << "| ";
+        ref = passWithRef(b);
+        EXPECT_EQ(&b, ref.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | ref(b) deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr(passWithRef(a));
+        EXPECT_EQ(&a, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<DerivedRefLogger> ptr(&a);
+        PackedRefPtr<RefLogger> ptr2(WTFMove(ptr));
+        EXPECT_EQ(nullptr, ptr.get());
+        EXPECT_EQ(&a, ptr2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRef<DerivedRefLogger> derivedReference(a);
+        PackedRef<RefLogger> baseReference(passWithRef(derivedReference.copyRef()));
+        EXPECT_EQ(&a, derivedReference.ptr());
+        EXPECT_EQ(&a, baseReference.ptr());
+    }
+    EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_PackedRef, Swap)
+{
+    RefLogger a("a");
+    RefLogger b("b");
+
+    {
+        PackedRef<RefLogger> p1(a);
+        PackedRef<RefLogger> p2(b);
+        log() << "| ";
+        EXPECT_EQ(&a, p1.ptr());
+        EXPECT_EQ(&b, p2.ptr());
+        p1.swap(p2);
+        EXPECT_EQ(&b, p1.ptr());
+        EXPECT_EQ(&a, p2.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | | deref(a) deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRef<RefLogger> p1(a);
+        PackedRef<RefLogger> p2(b);
+        log() << "| ";
+        EXPECT_EQ(&a, p1.ptr());
+        EXPECT_EQ(&b, p2.ptr());
+        std::swap(p1, p2);
+        EXPECT_EQ(&b, p1.ptr());
+        EXPECT_EQ(&a, p2.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | | deref(a) deref(b) ", takeLogStr().c_str());
+}
+
+struct PackedRefCheckingRefLogger : RefLogger {
+    PackedRefCheckingRefLogger(const char* name);
+    void ref();
+    void deref();
+    const PackedRef<PackedRefCheckingRefLogger>* slotToCheck { nullptr };
+};
+
+struct DerivedPackedRefCheckingRefLogger : PackedRefCheckingRefLogger {
+    DerivedPackedRefCheckingRefLogger(const char* name);
+};
+
+PackedRefCheckingRefLogger::PackedRefCheckingRefLogger(const char* name)
+    : RefLogger { name }
+{
+}
+
+void PackedRefCheckingRefLogger::ref()
+{
+    if (slotToCheck)
+        log() << "slot=" << slotToCheck->get().name << " ";
+    RefLogger::ref();
+}
+
+void PackedRefCheckingRefLogger::deref()
+{
+    if (slotToCheck)
+        log() << "slot=" << slotToCheck->get().name << " ";
+    RefLogger::deref();
+}
+
+DerivedPackedRefCheckingRefLogger::DerivedPackedRefCheckingRefLogger(const char* name)
+    : PackedRefCheckingRefLogger { name }
+{
+}
+
+TEST(WTF_PackedRef, AssignBeforeDeref)
+{
+    DerivedPackedRefCheckingRefLogger a("a");
+    PackedRefCheckingRefLogger b("b");
+    DerivedPackedRefCheckingRefLogger c("c");
+
+    {
+        PackedRef<PackedRefCheckingRefLogger> ref(a);
+        EXPECT_EQ(&a, ref.ptr());
+        log() << "| ";
+        a.slotToCheck = &ref;
+        b.slotToCheck = &ref;
+        ref = b;
+        a.slotToCheck = nullptr;
+        b.slotToCheck = nullptr;
+        EXPECT_EQ(&b, ref.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | slot=a ref(b) slot=b deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRef<PackedRefCheckingRefLogger> ref(a);
+        EXPECT_EQ(&a, ref.ptr());
+        log() << "| ";
+        a.slotToCheck = &ref;
+        c.slotToCheck = &ref;
+        ref = c;
+        a.slotToCheck = nullptr;
+        c.slotToCheck = nullptr;
+        EXPECT_EQ(&c, ref.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | slot=a ref(c) slot=c deref(a) | deref(c) ", takeLogStr().c_str());
+
+    {
+        PackedRef<PackedRefCheckingRefLogger> ref(a);
+        EXPECT_EQ(&a, ref.ptr());
+        log() << "| ";
+        a.slotToCheck = &ref;
+        ref = adoptRef(b);
+        a.slotToCheck = nullptr;
+        EXPECT_EQ(&b, ref.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | slot=b deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRef<PackedRefCheckingRefLogger> ref(a);
+        EXPECT_EQ(&a, ref.ptr());
+        log() << "| ";
+        a.slotToCheck = &ref;
+        ref = adoptRef(c);
+        a.slotToCheck = nullptr;
+        EXPECT_EQ(&c, ref.ptr());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | slot=c deref(a) | deref(c) ", takeLogStr().c_str());
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/PackedRefPtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/PackedRefPtr.cpp
new file mode 100644 (file)
index 0000000..c1a7b0a
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "config.h"
+
+#include "RefLogger.h"
+#include "Utilities.h"
+#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/PackedRef.h>
+#include <wtf/PackedRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RunLoop.h>
+#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/Threading.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_PackedRefPtr, Basic)
+{
+    DerivedRefLogger a("a");
+
+    PackedRefPtr<RefLogger> empty;
+    EXPECT_EQ(nullptr, empty.get());
+
+    {
+        PackedRefPtr<RefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        EXPECT_EQ(&a, &*ptr);
+        EXPECT_EQ(&a.name, &ptr->name);
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr = &a;
+        EXPECT_EQ(&a, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1 = &a;
+        PackedRefPtr<RefLogger> p2(p1);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1 = &a;
+        PackedRefPtr<RefLogger> p2 = p1;
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1 = &a;
+        PackedRefPtr<RefLogger> p2 = WTFMove(p1);
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1 = &a;
+        PackedRefPtr<RefLogger> p2(WTFMove(p1));
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<DerivedRefLogger> p1 = &a;
+        PackedRefPtr<RefLogger> p2 = p1;
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<DerivedRefLogger> p1 = &a;
+        PackedRefPtr<RefLogger> p2 = WTFMove(p1);
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        ptr = nullptr;
+        EXPECT_EQ(nullptr, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_PackedRefPtr, AssignPassRefToRefPtr)
+{
+    DerivedRefLogger a("a");
+    {
+        PackedRef<RefLogger> passRef(a);
+        PackedRefPtr<RefLogger> ptr = WTFMove(passRef);
+        EXPECT_EQ(&a, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_PackedRefPtr, Adopt)
+{
+    DerivedRefLogger a("a");
+
+    PackedRefPtr<RefLogger> empty;
+    EXPECT_EQ(nullptr, empty.get());
+
+    {
+        PackedRefPtr<RefLogger> ptr(adoptRef(&a));
+        EXPECT_EQ(&a, ptr.get());
+        EXPECT_EQ(&a, &*ptr);
+        EXPECT_EQ(&a.name, &ptr->name);
+    }
+    EXPECT_STREQ("deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr = adoptRef(&a);
+        EXPECT_EQ(&a, ptr.get());
+    }
+    EXPECT_STREQ("deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_PackedRefPtr, Assignment)
+{
+    DerivedRefLogger a("a");
+    RefLogger b("b");
+    DerivedRefLogger c("c");
+
+    {
+        PackedRefPtr<RefLogger> p1(&a);
+        PackedRefPtr<RefLogger> p2(&b);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+        p1 = p2;
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | ref(b) deref(a) | deref(b) deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+        ptr = &b;
+        EXPECT_EQ(&b, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | ref(b) deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+        ptr = adoptRef(&b);
+        EXPECT_EQ(&b, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        ptr = nullptr;
+        EXPECT_EQ(nullptr, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1(&a);
+        PackedRefPtr<RefLogger> p2(&b);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+        p1 = WTFMove(p2);
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1(&a);
+        PackedRefPtr<DerivedRefLogger> p2(&c);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&c, p2.get());
+        log() << "| ";
+        p1 = p2;
+        EXPECT_EQ(&c, p1.get());
+        EXPECT_EQ(&c, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(c) | ref(c) deref(a) | deref(c) deref(c) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+        ptr = &c;
+        EXPECT_EQ(&c, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | ref(c) deref(a) | deref(c) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+        ptr = adoptRef(&c);
+        EXPECT_EQ(&c, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | deref(a) | deref(c) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1(&a);
+        PackedRefPtr<DerivedRefLogger> p2(&c);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&c, p2.get());
+        log() << "| ";
+        p1 = WTFMove(p2);
+        EXPECT_EQ(&c, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(c) | deref(a) | deref(c) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wunknown-warning-option"
+#pragma clang diagnostic ignored "-Wself-assign-overloaded"
+#endif
+        ptr = ptr;
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | ref(a) deref(a) | deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+        ptr = WTFMove(ptr);
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+        EXPECT_EQ(&a, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_PackedRefPtr, Swap)
+{
+    RefLogger a("a");
+    RefLogger b("b");
+
+    {
+        PackedRefPtr<RefLogger> p1(&a);
+        PackedRefPtr<RefLogger> p2(&b);
+        log() << "| ";
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        p1.swap(p2);
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(&a, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | | deref(a) deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1(&a);
+        PackedRefPtr<RefLogger> p2(&b);
+        log() << "| ";
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        std::swap(p1, p2);
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(&a, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | | deref(a) deref(b) ", takeLogStr().c_str());
+}
+
+TEST(WTF_PackedRefPtr, ReleaseNonNull)
+{
+    RefLogger a("a");
+
+    {
+        PackedRefPtr<RefLogger> refPtr = &a;
+        PackedRefPtr<RefLogger> ref = refPtr.releaseNonNull();
+    }
+
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_PackedRefPtr, Release)
+{
+    DerivedRefLogger a("a");
+    RefLogger b("b");
+    DerivedRefLogger c("c");
+
+    {
+        PackedRefPtr<RefLogger> p1 = &a;
+        PackedRefPtr<RefLogger> p2 = WTFMove(p1);
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1 = &a;
+        PackedRefPtr<RefLogger> p2(WTFMove(p1));
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<DerivedRefLogger> p1 = &a;
+        PackedRefPtr<RefLogger> p2 = WTFMove(p1);
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1(&a);
+        PackedRefPtr<RefLogger> p2(&b);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+        p1 = WTFMove(p2);
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<RefLogger> p1(&a);
+        PackedRefPtr<DerivedRefLogger> p2(&c);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&c, p2.get());
+        log() << "| ";
+        p1 = WTFMove(p2);
+        EXPECT_EQ(&c, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(c) | deref(a) | deref(c) ", takeLogStr().c_str());
+}
+
+static RefPtr<RefLogger> f1(RefLogger& logger)
+{
+    return PackedRefPtr<RefLogger>(&logger);
+}
+
+TEST(WTF_PackedRefPtr, ReturnValue)
+{
+    DerivedRefLogger a("a");
+
+    {
+        f1(a);
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        auto ptr = f1(a);
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+struct ConstRefCounted : RefCounted<ConstRefCounted> {
+    static Ref<ConstRefCounted> create() { return adoptRef(*new ConstRefCounted); }
+};
+
+static const ConstRefCounted& returnConstRefCountedRef()
+{
+    static NeverDestroyed<ConstRefCounted> instance;
+    return instance.get();
+}
+static ConstRefCounted& returnRefCountedRef()
+{
+    static NeverDestroyed<ConstRefCounted> instance;
+    return instance.get();
+}
+
+TEST(WTF_PackedRefPtr, Const)
+{
+    // This test passes if it compiles without an error.
+    auto a = ConstRefCounted::create();
+    PackedRef<const ConstRefCounted> b = WTFMove(a);
+    PackedRefPtr<const ConstRefCounted> c = b.ptr();
+    PackedRef<const ConstRefCounted> d = returnConstRefCountedRef();
+    PackedRefPtr<const ConstRefCounted> e = &returnConstRefCountedRef();
+    PackedRefPtr<ConstRefCounted> f = ConstRefCounted::create();
+    PackedRefPtr<const ConstRefCounted> g = f;
+    PackedRefPtr<const ConstRefCounted> h(f);
+    PackedRef<const ConstRefCounted> i(returnRefCountedRef());
+}
+
+struct PackedRefPtrCheckingRefLogger : RefLogger {
+    PackedRefPtrCheckingRefLogger(const char* name);
+    void ref();
+    void deref();
+    const PackedRefPtr<PackedRefPtrCheckingRefLogger>* slotToCheck { nullptr };
+};
+
+PackedRefPtrCheckingRefLogger::PackedRefPtrCheckingRefLogger(const char* name)
+    : RefLogger { name }
+{
+}
+
+static const char* loggerName(const PackedRefPtr<PackedRefPtrCheckingRefLogger>& pointer)
+{
+    return pointer ? &pointer->name : "null";
+}
+
+void PackedRefPtrCheckingRefLogger::ref()
+{
+    if (slotToCheck)
+        log() << "slot=" << loggerName(*slotToCheck) << " ";
+    RefLogger::ref();
+}
+
+void PackedRefPtrCheckingRefLogger::deref()
+{
+    if (slotToCheck)
+        log() << "slot=" << loggerName(*slotToCheck) << " ";
+    RefLogger::deref();
+}
+
+TEST(WTF_PackedRefPtr, AssignBeforeDeref)
+{
+    PackedRefPtrCheckingRefLogger a("a");
+    PackedRefPtrCheckingRefLogger b("b");
+
+    {
+        PackedRefPtr<PackedRefPtrCheckingRefLogger> p1(&a);
+        PackedRefPtr<PackedRefPtrCheckingRefLogger> p2(&b);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+        a.slotToCheck = &p1;
+        b.slotToCheck = &p1;
+        p1 = p2;
+        a.slotToCheck = nullptr;
+        b.slotToCheck = nullptr;
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | slot=a ref(b) slot=b deref(a) | deref(b) deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<PackedRefPtrCheckingRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+        a.slotToCheck = &ptr;
+        b.slotToCheck = &ptr;
+        ptr = &b;
+        a.slotToCheck = nullptr;
+        b.slotToCheck = nullptr;
+        EXPECT_EQ(&b, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | slot=a ref(b) slot=b deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<PackedRefPtrCheckingRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        a.slotToCheck = &ptr;
+        ptr = nullptr;
+        a.slotToCheck = nullptr;
+        EXPECT_EQ(nullptr, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) slot=null deref(a) ", takeLogStr().c_str());
+
+    {
+        PackedRefPtr<PackedRefPtrCheckingRefLogger> p1(&a);
+        PackedRefPtr<PackedRefPtrCheckingRefLogger> p2(&b);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+        a.slotToCheck = &p1;
+        b.slotToCheck = &p1;
+        p1 = WTFMove(p2);
+        a.slotToCheck = nullptr;
+        b.slotToCheck = nullptr;
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | slot=b deref(a) | deref(b) ", takeLogStr().c_str());
+}
+
+TEST(WTF_PackedRefPtr, ReleaseNonNullBeforeDeref)
+{
+    PackedRefPtrCheckingRefLogger a("a");
+
+    {
+        PackedRefPtr<PackedRefPtrCheckingRefLogger> refPtr = &a;
+        a.slotToCheck = &refPtr;
+        refPtr.releaseNonNull();
+        a.slotToCheck = nullptr;
+    }
+
+    EXPECT_STREQ("ref(a) slot=null deref(a) ", takeLogStr().c_str());
+}
+
+} // namespace TestWebKitAPI
index 0988306..f88359a 100644 (file)
@@ -391,7 +391,7 @@ TEST(WTF_RefPtr, Release)
     EXPECT_STREQ("ref(a) ref(c) | deref(a) | deref(c) ", takeLogStr().c_str());
 }
 
-RefPtr<RefLogger> f1(RefLogger& logger)
+static RefPtr<RefLogger> f1(RefLogger& logger)
 {
     return RefPtr<RefLogger>(&logger);
 }
@@ -415,12 +415,12 @@ struct ConstRefCounted : RefCounted<ConstRefCounted> {
     static Ref<ConstRefCounted> create() { return adoptRef(*new ConstRefCounted); }
 };
 
-const ConstRefCounted& returnConstRefCountedRef()
+static const ConstRefCounted& returnConstRefCountedRef()
 {
     static NeverDestroyed<ConstRefCounted> instance;
     return instance.get();
 }
-ConstRefCounted& returnRefCountedRef()
+static ConstRefCounted& returnRefCountedRef()
 {
     static NeverDestroyed<ConstRefCounted> instance;
     return instance.get();