PoisonedWriteBarrier
authorjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Jan 2018 23:47:58 +0000 (23:47 +0000)
committerjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Jan 2018 23:47:58 +0000 (23:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181599
<rdar://problem/36474351>

Reviewed by Mark Lam.

Source/JavaScriptCore:

Allow poisoning of WriteBarrier objects, and use this for
WebAssembly because it is perf-neutral, at least on WasmBench on
my MBP. If it indeed is perf-neutral according to the bots, start
using it in more performance-sensitive places.

* heap/HandleTypes.h:
* heap/SlotVisitor.h:
* heap/SlotVisitorInlines.h:
(JSC::SlotVisitor::append):
(JSC::SlotVisitor::appendHidden):
* runtime/JSCJSValue.h:
* runtime/JSCPoison.h:
* runtime/Structure.h:
* runtime/StructureInlines.h:
(JSC::Structure::setPrototypeWithoutTransition):
(JSC::Structure::setGlobalObject):
(JSC::Structure::setPreviousID):
* runtime/WriteBarrier.h:
(JSC::WriteBarrierBase::copyFrom):
(JSC::WriteBarrierBase::get const):
(JSC::WriteBarrierBase::operator* const):
(JSC::WriteBarrierBase::operator-> const):
(JSC::WriteBarrierBase::clear):
(JSC::WriteBarrierBase::slot):
(JSC::WriteBarrierBase::operator bool const):
(JSC::WriteBarrierBase::setWithoutWriteBarrier):
(JSC::WriteBarrierBase::unvalidatedGet const):
(JSC::operator==):
* runtime/WriteBarrierInlines.h:
(JSC::Traits>::set):
(JSC::Traits>::setMayBeNull):
(JSC::Traits>::setEarlyValue):
(JSC::DumbValueTraits<Unknown>>::set):
* wasm/WasmInstance.h:
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::JSWebAssemblyInstance):
(JSC::JSWebAssemblyInstance::finishCreation):
(JSC::JSWebAssemblyInstance::visitChildren):
(JSC::JSWebAssemblyInstance::create):
* wasm/js/JSWebAssemblyInstance.h:
(JSC::JSWebAssemblyInstance::offsetOfPoisonedCallee):
* wasm/js/JSWebAssemblyMemory.h:
* wasm/js/JSWebAssemblyModule.h:
* wasm/js/JSWebAssemblyTable.cpp:
(JSC::JSWebAssemblyTable::JSWebAssemblyTable):
(JSC::JSWebAssemblyTable::grow):
(JSC::JSWebAssemblyTable::clearFunction):
* wasm/js/JSWebAssemblyTable.h:
* wasm/js/WasmToJS.cpp:
(JSC::Wasm::materializeImportJSCell):
(JSC::Wasm::handleBadI64Use):
(JSC::Wasm::wasmToJS):
* wasm/js/WebAssemblyFunctionBase.h:
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
(JSC::WebAssemblyModuleRecord::evaluate):
* wasm/js/WebAssemblyModuleRecord.h:
* wasm/js/WebAssemblyToJSCallee.h:
* wasm/js/WebAssemblyWrapperFunction.h:

Source/WTF:

Supporting changes needed to allow poisoning of WriteBarrier
objects.

* WTF.xcodeproj/project.pbxproj:
* wtf/DumbPtrTraits.h:
* wtf/DumbValueTraits.h: Copied from Source/WTF/wtf/DumbPtrTraits.h.
(WTF::DumbValueTraits::exchange):
(WTF::DumbValueTraits::swap):
(WTF::DumbValueTraits::unwrap):
* wtf/Forward.h:
* wtf/Poisoned.h:
(WTF::ConstExprPoisonedValueTraits::exchange):
(WTF::ConstExprPoisonedValueTraits::swap):
(WTF::ConstExprPoisonedValueTraits::unwrap):

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

29 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/heap/HandleTypes.h
Source/JavaScriptCore/heap/SlotVisitor.h
Source/JavaScriptCore/heap/SlotVisitorInlines.h
Source/JavaScriptCore/runtime/JSCJSValue.h
Source/JavaScriptCore/runtime/JSCPoison.h
Source/JavaScriptCore/runtime/Structure.h
Source/JavaScriptCore/runtime/StructureInlines.h
Source/JavaScriptCore/runtime/WriteBarrier.h
Source/JavaScriptCore/runtime/WriteBarrierInlines.h
Source/JavaScriptCore/wasm/WasmInstance.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.h
Source/JavaScriptCore/wasm/js/WasmToJS.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyFunctionBase.h
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h
Source/JavaScriptCore/wasm/js/WebAssemblyToJSCallee.h
Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.h
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/DumbPtrTraits.h
Source/WTF/wtf/DumbValueTraits.h [new file with mode: 0644]
Source/WTF/wtf/Forward.h
Source/WTF/wtf/Poisoned.h

index 9f68099..d1793c9 100644 (file)
@@ -1,3 +1,71 @@
+2018-01-12  JF Bastien  <jfbastien@apple.com>
+
+        PoisonedWriteBarrier
+        https://bugs.webkit.org/show_bug.cgi?id=181599
+        <rdar://problem/36474351>
+
+        Reviewed by Mark Lam.
+
+        Allow poisoning of WriteBarrier objects, and use this for
+        WebAssembly because it is perf-neutral, at least on WasmBench on
+        my MBP. If it indeed is perf-neutral according to the bots, start
+        using it in more performance-sensitive places.
+
+        * heap/HandleTypes.h:
+        * heap/SlotVisitor.h:
+        * heap/SlotVisitorInlines.h:
+        (JSC::SlotVisitor::append):
+        (JSC::SlotVisitor::appendHidden):
+        * runtime/JSCJSValue.h:
+        * runtime/JSCPoison.h:
+        * runtime/Structure.h:
+        * runtime/StructureInlines.h:
+        (JSC::Structure::setPrototypeWithoutTransition):
+        (JSC::Structure::setGlobalObject):
+        (JSC::Structure::setPreviousID):
+        * runtime/WriteBarrier.h:
+        (JSC::WriteBarrierBase::copyFrom):
+        (JSC::WriteBarrierBase::get const):
+        (JSC::WriteBarrierBase::operator* const):
+        (JSC::WriteBarrierBase::operator-> const):
+        (JSC::WriteBarrierBase::clear):
+        (JSC::WriteBarrierBase::slot):
+        (JSC::WriteBarrierBase::operator bool const):
+        (JSC::WriteBarrierBase::setWithoutWriteBarrier):
+        (JSC::WriteBarrierBase::unvalidatedGet const):
+        (JSC::operator==):
+        * runtime/WriteBarrierInlines.h:
+        (JSC::Traits>::set):
+        (JSC::Traits>::setMayBeNull):
+        (JSC::Traits>::setEarlyValue):
+        (JSC::DumbValueTraits<Unknown>>::set):
+        * wasm/WasmInstance.h:
+        * wasm/js/JSWebAssemblyInstance.cpp:
+        (JSC::JSWebAssemblyInstance::JSWebAssemblyInstance):
+        (JSC::JSWebAssemblyInstance::finishCreation):
+        (JSC::JSWebAssemblyInstance::visitChildren):
+        (JSC::JSWebAssemblyInstance::create):
+        * wasm/js/JSWebAssemblyInstance.h:
+        (JSC::JSWebAssemblyInstance::offsetOfPoisonedCallee):
+        * wasm/js/JSWebAssemblyMemory.h:
+        * wasm/js/JSWebAssemblyModule.h:
+        * wasm/js/JSWebAssemblyTable.cpp:
+        (JSC::JSWebAssemblyTable::JSWebAssemblyTable):
+        (JSC::JSWebAssemblyTable::grow):
+        (JSC::JSWebAssemblyTable::clearFunction):
+        * wasm/js/JSWebAssemblyTable.h:
+        * wasm/js/WasmToJS.cpp:
+        (JSC::Wasm::materializeImportJSCell):
+        (JSC::Wasm::handleBadI64Use):
+        (JSC::Wasm::wasmToJS):
+        * wasm/js/WebAssemblyFunctionBase.h:
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::link):
+        (JSC::WebAssemblyModuleRecord::evaluate):
+        * wasm/js/WebAssemblyModuleRecord.h:
+        * wasm/js/WebAssemblyToJSCallee.h:
+        * wasm/js/WebAssemblyWrapperFunction.h:
+
 2018-01-12  Saam Barati  <sbarati@apple.com>
 
         CheckStructure can be incorrectly subsumed by CheckStructureOrEmpty
index 6cf11df..4e3530e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,7 +29,6 @@
 
 namespace JSC {
 
-typedef enum { } Unknown;
 typedef JSValue* HandleSlot;
 
 template<typename T> struct HandleTypes {
index 314ed3d..a4e9cc6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,6 +29,7 @@
 #include "IterationStatus.h"
 #include "MarkStack.h"
 #include "VisitRaceKey.h"
+#include <wtf/Forward.h>
 #include <wtf/MonotonicTime.h>
 #include <wtf/text/CString.h>
 
@@ -44,7 +45,7 @@ class MarkingConstraintSolver;
 class UnconditionalFinalizer;
 template<typename T> class Weak;
 class WeakReferenceHarvester;
-template<typename T> class WriteBarrierBase;
+template<typename T, typename Traits> class WriteBarrierBase;
 
 typedef uint32_t HeapVersion;
 
@@ -70,11 +71,11 @@ public:
 
     void append(ConservativeRoots&);
     
-    template<typename T> void append(const WriteBarrierBase<T>&);
-    template<typename T> void appendHidden(const WriteBarrierBase<T>&);
+    template<typename T, typename Traits> void append(const WriteBarrierBase<T, Traits>&);
+    template<typename T, typename Traits> void appendHidden(const WriteBarrierBase<T, Traits>&);
     template<typename Iterator> void append(Iterator begin , Iterator end);
-    void appendValues(const WriteBarrierBase<Unknown>*, size_t count);
-    void appendValuesHidden(const WriteBarrierBase<Unknown>*, size_t count);
+    void appendValues(const WriteBarrierBase<Unknown, DumbValueTraits<Unknown>>*, size_t count);
+    void appendValuesHidden(const WriteBarrierBase<Unknown, DumbValueTraits<Unknown>>*, size_t count);
     
     // These don't require you to prove that you have a WriteBarrier<>. That makes sense
     // for:
index ab09893..f36d17b 100644 (file)
@@ -103,14 +103,14 @@ ALWAYS_INLINE void SlotVisitor::append(const Weak<T>& weak)
     appendUnbarriered(weak.get());
 }
 
-template<typename T>
-ALWAYS_INLINE void SlotVisitor::append(const WriteBarrierBase<T>& slot)
+template<typename T, typename Traits>
+ALWAYS_INLINE void SlotVisitor::append(const WriteBarrierBase<T, Traits>& slot)
 {
     appendUnbarriered(slot.get());
 }
 
-template<typename T>
-ALWAYS_INLINE void SlotVisitor::appendHidden(const WriteBarrierBase<T>& slot)
+template<typename T, typename Traits>
+ALWAYS_INLINE void SlotVisitor::appendHidden(const WriteBarrierBase<T, Traits>& slot)
 {
     appendHiddenUnbarriered(slot.get());
 }
index 9f39a3c..59b434e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2018 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -68,8 +68,13 @@ struct ClassInfo;
 struct DumpContext;
 struct Instruction;
 struct MethodTable;
+enum class Unknown { };
 
-template <class T> class WriteBarrierBase;
+template <class T, typename Traits> class WriteBarrierBase;
+template<class T>
+using WriteBarrierTraitsSelect = typename std::conditional<std::is_same<T, Unknown>::value,
+    DumbValueTraits<T>, DumbPtrTraits<T>
+>::type;
 
 enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
 enum ECMAMode { StrictMode, NotStrictMode };
@@ -453,7 +458,7 @@ public:
 #endif
 
 private:
-    template <class T> JSValue(WriteBarrierBase<T>);
+    template <class T> JSValue(WriteBarrierBase<T, WriteBarrierTraitsSelect<T>>);
 
     enum HashTableDeletedValueTag { HashTableDeletedValue };
     JSValue(HashTableDeletedValueTag);
index ced0120..b57cb14 100644 (file)
@@ -51,6 +51,10 @@ enum Poison {
     JSWebAssemblyTablePoison,
     StructureTransitionTablePoison,
     UnlinkedSourceCodePoison,
+    WebAssemblyFunctionBasePoison,
+    WebAssemblyModuleRecordPoison,
+    WebAssemblyToJSCalleePoison,
+    WebAssemblyWrapperFunctionPoison,
 };
 
 } // namespace JSC
index 3a3fe31..9d454f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -211,7 +211,7 @@ public:
     PropertyOffset addPropertyWithoutTransition(VM&, PropertyName, unsigned attributes, const Func&);
     template<typename Func>
     PropertyOffset removePropertyWithoutTransition(VM&, PropertyName, const Func&);
-    void setPrototypeWithoutTransition(VM& vm, JSValue prototype) { m_prototype.set(vm, this, prototype); }
+    void setPrototypeWithoutTransition(VM&, JSValue prototype);
         
     bool isDictionary() const { return dictionaryKind() != NoneDictionaryKind; }
     bool isUncacheableDictionary() const { return dictionaryKind() == UncachedDictionaryKind; }
@@ -265,7 +265,7 @@ public:
 
     // NOTE: This method should only be called during the creation of structures, since the global
     // object of a structure is presumed to be immutable in a bunch of places.
-    void setGlobalObject(VM& vm, JSGlobalObject* globalObject) { m_globalObject.set(vm, this, globalObject); }
+    void setGlobalObject(VM&, JSGlobalObject*);
 
     ALWAYS_INLINE bool hasMonoProto() const
     {
@@ -738,13 +738,7 @@ private:
     PropertyTable* takePropertyTableOrCloneIfPinned(VM&);
     PropertyTable* copyPropertyTableForPinning(VM&);
 
-    void setPreviousID(VM& vm, Structure* structure)
-    {
-        if (hasRareData())
-            rareData()->setPreviousID(vm, structure);
-        else
-            m_previousOrRareData.set(vm, this, structure);
-    }
+    void setPreviousID(VM&, Structure*);
 
     void clearPreviousID()
     {
index 4e60f53..9047f22 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -441,11 +441,29 @@ inline PropertyOffset Structure::removePropertyWithoutTransition(VM&, PropertyNa
     return remove(propertyName, func);
 }
 
+ALWAYS_INLINE void Structure::setPrototypeWithoutTransition(VM& vm, JSValue prototype)
+{
+    m_prototype.set(vm, this, prototype);
+}
+
+ALWAYS_INLINE void Structure::setGlobalObject(VM& vm, JSGlobalObject* globalObject)
+{
+    m_globalObject.set(vm, this, globalObject);
+}
+
 ALWAYS_INLINE void Structure::setPropertyTable(VM& vm, PropertyTable* table)
 {
     m_propertyTableUnsafe.setMayBeNull(vm, this, table);
 }
 
+ALWAYS_INLINE void Structure::setPreviousID(VM& vm, Structure* structure)
+{
+    if (hasRareData())
+        rareData()->setPreviousID(vm, structure);
+    else
+        m_previousOrRareData.set(vm, this, structure);
+}
+
 ALWAYS_INLINE bool Structure::shouldConvertToPolyProto(const Structure* a, const Structure* b)
 {
     if (!a || !b)
index a991386..498e9e8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #include "GCAssertions.h"
 #include "HandleTypes.h"
+#include "JSCPoison.h"
+#include <type_traits>
+#include <wtf/DumbPtrTraits.h>
+#include <wtf/DumbValueTraits.h>
+#include <wtf/Poisoned.h>
 
 namespace JSC {
 
@@ -38,7 +43,12 @@ class JSCell;
 class VM;
 class JSGlobalObject;
 
-template<class T> class WriteBarrierBase;
+template<class T>
+using WriteBarrierTraitsSelect = typename std::conditional<std::is_same<T, Unknown>::value,
+    DumbValueTraits<T>, DumbPtrTraits<T>
+>::type;
+
+template<class T, typename Traits = WriteBarrierTraitsSelect<T>> class WriteBarrierBase;
 template<> class WriteBarrierBase<JSValue>;
 
 JS_EXPORT_PRIVATE void slowValidateCell(JSCell*);
@@ -66,15 +76,18 @@ template<class T> inline void validateCell(T)
 #endif
 
 // We have a separate base class with no constructors for use in Unions.
-template <typename T> class WriteBarrierBase {
+template <typename T, typename Traits> class WriteBarrierBase {
+    using StorageType = typename Traits::StorageType;
+
 public:
     void set(VM&, const JSCell* owner, T* value);
     
     // This is meant to be used like operator=, but is called copyFrom instead, in
     // order to kindly inform the C++ compiler that its advice is not appreciated.
-    void copyFrom(const WriteBarrierBase<T>& other)
+    void copyFrom(const WriteBarrierBase& other)
     {
-        m_cell = other.m_cell;
+        // FIXME add version with different Traits once needed.
+        Traits::exchange(m_cell, other.m_cell);
     }
 
     void setMayBeNull(VM&, const JSCell* owner, T* value);
@@ -86,31 +99,44 @@ public:
     T* get() const
     {
         // Copy m_cell to a local to avoid multiple-read issues. (See <http://webkit.org/b/110854>)
-        JSCell* cell = m_cell;
+        StorageType cell = m_cell;
         if (cell)
-            validateCell(cell);
-        return reinterpret_cast<T*>(static_cast<void*>(cell));
+            validateCell(reinterpret_cast<JSCell*>(static_cast<void*>(Traits::unwrap(cell))));
+        return Traits::unwrap(cell);
     }
 
     T* operator*() const
     {
-        ASSERT(m_cell);
-        validateCell<T>(static_cast<T*>(m_cell));
-        return static_cast<T*>(m_cell);
+        StorageType cell = m_cell;
+        ASSERT(cell);
+        auto unwrapped = Traits::unwrap(cell);
+        validateCell<T>(unwrapped);
+        return Traits::unwrap(unwrapped);
     }
 
     T* operator->() const
     {
-        ASSERT(m_cell);
-        validateCell(static_cast<T*>(m_cell));
-        return static_cast<T*>(m_cell);
+        StorageType cell = m_cell;
+        ASSERT(cell);
+        auto unwrapped = Traits::unwrap(cell);
+        validateCell(unwrapped);
+        return unwrapped;
     }
 
-    void clear() { m_cell = 0; }
-    
-    T** slot() { return reinterpret_cast<T**>(&m_cell); }
+    void clear() { Traits::exchange(m_cell, nullptr); }
+
+    // Slot cannot be used when pointers aren't stored as-is.
+    template<typename BarrierT, typename BarrierTraits, std::enable_if_t<std::is_same<BarrierTraits, DumbPtrTraits<BarrierT>>::value, void*> = nullptr>
+    struct SlotHelper {
+        static BarrierT** reinterpret(typename BarrierTraits::StorageType* cell) { return reinterpret_cast<T**>(cell); }
+    };
+
+    T** slot()
+    {
+        return SlotHelper<T, Traits>::reinterpret(&m_cell);
+    }
     
-    explicit operator bool() const { return m_cell; }
+    explicit operator bool() const { return !!m_cell; }
     
     bool operator!() const { return !m_cell; }
 
@@ -119,16 +145,16 @@ public:
 #if ENABLE(WRITE_BARRIER_PROFILING)
         WriteBarrierCounters::usesWithoutBarrierFromCpp.count();
 #endif
-        this->m_cell = reinterpret_cast<JSCell*>(value);
+        Traits::exchange(this->m_cell, value);
     }
 
-    T* unvalidatedGet() const { return reinterpret_cast<T*>(static_cast<void*>(m_cell)); }
+    T* unvalidatedGet() const { return Traits::unwrap(m_cell); }
 
 private:
-    JSCell* m_cell;
+    StorageType m_cell;
 };
 
-template <> class WriteBarrierBase<Unknown> {
+template <> class WriteBarrierBase<Unknown, DumbValueTraits<Unknown>> {
 public:
     void set(VM&, const JSCell* owner, JSValue);
     void setWithoutWriteBarrier(JSValue value)
@@ -165,9 +191,12 @@ private:
     EncodedJSValue m_value;
 };
 
-template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
+template <typename T, typename Traits = WriteBarrierTraitsSelect<T>>
+class WriteBarrier : public WriteBarrierBase<T, Traits> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    static constexpr auto poison = Traits::poison;
+
     WriteBarrier()
     {
         this->setWithoutWriteBarrier(0);
@@ -192,9 +221,12 @@ public:
 };
 
 enum UndefinedWriteBarrierTagType { UndefinedWriteBarrierTag };
-template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
+template <>
+class WriteBarrier<Unknown, DumbValueTraits<Unknown>> : public WriteBarrierBase<Unknown, DumbValueTraits<Unknown>> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    static constexpr auto poison = DumbValueTraits<Unknown>::poison;
+
     WriteBarrier()
     {
         this->setWithoutWriteBarrier(JSValue());
@@ -216,9 +248,18 @@ public:
     }
 };
 
-template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs)
+template <typename U, typename V, typename TraitsU, typename TraitsV>
+inline bool operator==(const WriteBarrierBase<U, TraitsU>& lhs, const WriteBarrierBase<V, TraitsV>& rhs)
 {
     return lhs.get() == rhs.get();
 }
 
+template<uint32_t key, class T>
+using PoisonedWriteBarrierTraitsSelect = typename std::conditional<std::is_same<T, Unknown>::value,
+    WTF::ConstExprPoisonedValueTraits<key, T>, WTF::ConstExprPoisonedPtrTraits<key, T>
+>::type;
+
+template <uint32_t key, typename T>
+using PoisonedWriteBarrier = WriteBarrier<T, PoisonedWriteBarrierTraitsSelect<key, T>>;
+
 } // namespace JSC
index 4bd2dd6..9e11351 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,8 +30,8 @@
 
 namespace JSC {
 
-template <typename T>
-inline void WriteBarrierBase<T>::set(VM& vm, const JSCell* owner, T* value)
+template <typename T, typename Traits>
+inline void WriteBarrierBase<T, Traits>::set(VM& vm, const JSCell* owner, T* value)
 {
     ASSERT(value);
     ASSERT(!Options::useConcurrentJIT() || !isCompilationThread());
@@ -39,22 +39,22 @@ inline void WriteBarrierBase<T>::set(VM& vm, const JSCell* owner, T* value)
     setEarlyValue(vm, owner, value);
 }
 
-template <typename T>
-inline void WriteBarrierBase<T>::setMayBeNull(VM& vm, const JSCell* owner, T* value)
+template <typename T, typename Traits>
+inline void WriteBarrierBase<T, Traits>::setMayBeNull(VM& vm, const JSCell* owner, T* value)
 {
     if (value)
         validateCell(value);
     setEarlyValue(vm, owner, value);
 }
 
-template <typename T>
-inline void WriteBarrierBase<T>::setEarlyValue(VM& vm, const JSCell* owner, T* value)
+template <typename T, typename Traits>
+inline void WriteBarrierBase<T, Traits>::setEarlyValue(VM& vm, const JSCell* owner, T* value)
 {
-    this->m_cell = reinterpret_cast<JSCell*>(value);
-    vm.heap.writeBarrier(owner, this->m_cell);
+    Traits::exchange(this->m_cell, value);
+    vm.heap.writeBarrier(owner, static_cast<JSCell*>(value));
 }
 
-inline void WriteBarrierBase<Unknown>::set(VM& vm, const JSCell* owner, JSValue value)
+inline void WriteBarrierBase<Unknown, DumbValueTraits<Unknown>>::set(VM& vm, const JSCell* owner, JSValue value)
 {
     ASSERT(!Options::useConcurrentJIT() || !isCompilationThread());
     m_value = JSValue::encode(value);
index 2c08000..aa9f7cf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -100,7 +100,7 @@ public:
         Instance* targetInstance { nullptr };
         Wasm::WasmEntrypointLoadLocation wasmEntrypoint { nullptr };
         void* wasmToEmbedderStubExecutableAddress { nullptr };
-        void* importFunction { nullptr }; // In a JS embedding, this is a WriteBarrier<JSObject>.
+        void* importFunction { nullptr }; // In a JS embedding, this is a PoisonedBarrier<JSObject>.
     };
     unsigned numImportFunctions() const { return m_numImportFunctions; }
     ImportFunctionInfo* importFunctionInfo(size_t importFunctionNum)
index cbef368..34ac27c 100644 (file)
@@ -54,7 +54,7 @@ JSWebAssemblyInstance::JSWebAssemblyInstance(VM& vm, Structure* structure, Ref<W
     , m_instance(WTFMove(instance))
 {
     for (unsigned i = 0; i < this->instance().numImportFunctions(); ++i)
-        new (this->instance().importFunction<WriteBarrier<JSObject>>(i)) WriteBarrier<JSObject>();
+        new (this->instance().importFunction<PoisonedBarrier<JSObject>>(i)) PoisonedBarrier<JSObject>();
 }
 
 void JSWebAssemblyInstance::finishCreation(VM& vm, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
@@ -65,7 +65,7 @@ void JSWebAssemblyInstance::finishCreation(VM& vm, JSWebAssemblyModule* module,
     m_module.set(vm, this, module);
     m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
     m_callee.set(vm, this, module->callee());
-    
+
     heap()->reportExtraMemoryAllocated(m_instance->extraMemoryAllocated());
 }
 
@@ -88,7 +88,7 @@ void JSWebAssemblyInstance::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(thisObject->m_callee);
     visitor.reportExtraMemoryVisited(thisObject->m_instance->extraMemoryAllocated());
     for (unsigned i = 0; i < thisObject->instance().numImportFunctions(); ++i)
-        visitor.append(*thisObject->instance().importFunction<WriteBarrier<JSObject>>(i)); // This also keeps the functions' JSWebAssemblyInstance alive.
+        visitor.append(*thisObject->instance().importFunction<PoisonedBarrier<JSObject>>(i)); // This also keeps the functions' JSWebAssemblyInstance alive.
 }
 
 void JSWebAssemblyInstance::finalizeCreation(VM& vm, ExecState* exec, Ref<Wasm::CodeBlock>&& wasmCodeBlock)
@@ -236,7 +236,7 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JS
             auto* info = jsInstance->instance().importFunctionInfo(numImportFunctions);
             info->targetInstance = calleeInstance;
             info->wasmEntrypoint = wasmEntrypoint;
-            jsInstance->instance().importFunction<WriteBarrier<JSObject>>(numImportFunctions)->set(vm, jsInstance, function);
+            jsInstance->instance().importFunction<PoisonedBarrier<JSObject>>(numImportFunctions)->set(vm, jsInstance, function);
             ++numImportFunctions;
             // v. Append closure to imports.
             break;
index d25bbcd..1780af2 100644 (file)
@@ -77,7 +77,10 @@ public:
     }
 
     static size_t offsetOfPoisonedInstance() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_instance); }
-    static size_t offsetOfCallee() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_callee); }
+    static size_t offsetOfPoisonedCallee() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_callee); }
+
+    template<typename T>
+    using PoisonedBarrier = PoisonedWriteBarrier<JSWebAssemblyInstancePoison, T>;
 
 protected:
     JSWebAssemblyInstance(VM&, Structure*, Ref<Wasm::Instance>&&);
@@ -90,12 +93,12 @@ private:
 
     PoisonedRef<JSWebAssemblyInstancePoison, Wasm::Instance> m_instance;
 
-    WriteBarrier<JSWebAssemblyModule> m_module;
-    WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlock;
-    WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
-    WriteBarrier<JSWebAssemblyMemory> m_memory;
-    WriteBarrier<JSWebAssemblyTable> m_table;
-    WriteBarrier<WebAssemblyToJSCallee> m_callee;
+    PoisonedBarrier<JSWebAssemblyModule> m_module;
+    PoisonedBarrier<JSWebAssemblyCodeBlock> m_codeBlock;
+    PoisonedBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
+    PoisonedBarrier<JSWebAssemblyMemory> m_memory;
+    PoisonedBarrier<JSWebAssemblyTable> m_table;
+    PoisonedBarrier<WebAssemblyToJSCallee> m_callee;
 };
 
 } // namespace JSC
index 8e12022..86cff99 100644 (file)
@@ -68,7 +68,7 @@ private:
     static void visitChildren(JSCell*, SlotVisitor&);
 
     PoisonedRef<JSWebAssemblyMemoryPoison, Wasm::Memory> m_memory;
-    WriteBarrier<JSArrayBuffer> m_bufferWrapper;
+    PoisonedWriteBarrier<JSWebAssemblyMemoryPoison, JSArrayBuffer> m_bufferWrapper;
     PoisonedRefPtr<JSWebAssemblyMemoryPoison, ArrayBuffer> m_buffer;
 };
 
index 207d03b..089c2fd 100644 (file)
@@ -82,9 +82,13 @@ private:
     static void visitChildren(JSCell*, SlotVisitor&);
 
     PoisonedRef<JSWebAssemblyModulePoison, Wasm::Module> m_module;
-    WriteBarrier<SymbolTable> m_exportSymbolTable;
-    WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::NumberOfMemoryModes];
-    WriteBarrier<WebAssemblyToJSCallee> m_callee;
+
+    template<typename T>
+    using PoisonedBarrier = PoisonedWriteBarrier<JSWebAssemblyModulePoison, T>;
+
+    PoisonedBarrier<SymbolTable> m_exportSymbolTable;
+    PoisonedBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::NumberOfMemoryModes];
+    PoisonedBarrier<WebAssemblyToJSCallee> m_callee;
 };
 
 } // namespace JSC
index 57a12e2..d70abec 100644 (file)
@@ -63,9 +63,9 @@ JSWebAssemblyTable::JSWebAssemblyTable(VM& vm, Structure* structure, Ref<Wasm::T
     // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
     // But for now, we're not doing that.
     // FIXME this over-allocates and could be smarter about not committing all of that memory https://bugs.webkit.org/show_bug.cgi?id=181425
-    m_jsFunctions = MallocPtr<WriteBarrier<JSObject>>::malloc((sizeof(WriteBarrier<JSObject>) * Checked<size_t>(allocatedLength())).unsafeGet());
+    m_jsFunctions = MallocPtr<PoisonedBarrier<JSObject>>::malloc((sizeof(PoisonedBarrier<JSObject>) * Checked<size_t>(allocatedLength())).unsafeGet());
     for (uint32_t i = 0; i < allocatedLength(); ++i)
-        new(&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
+        new(&m_jsFunctions.get()[i]) PoisonedBarrier<JSObject>();
 }
 
 void JSWebAssemblyTable::finishCreation(VM& vm)
@@ -104,10 +104,10 @@ bool JSWebAssemblyTable::grow(uint32_t delta)
     size_t newLength = grew.value();
     if (newLength > m_table->allocatedLength(oldLength))
         // FIXME this over-allocates and could be smarter about not committing all of that memory https://bugs.webkit.org/show_bug.cgi?id=181425
-        m_jsFunctions.realloc((sizeof(WriteBarrier<JSObject>) * Checked<size_t>(m_table->allocatedLength(newLength))).unsafeGet());
+        m_jsFunctions.realloc((sizeof(PoisonedBarrier<JSObject>) * Checked<size_t>(m_table->allocatedLength(newLength))).unsafeGet());
 
     for (size_t i = oldLength; i < m_table->allocatedLength(newLength); ++i)
-        new (&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
+        new (&m_jsFunctions.get()[i]) PoisonedBarrier<JSObject>();
 
     return true;
 }
@@ -121,7 +121,7 @@ JSObject* JSWebAssemblyTable::getFunction(uint32_t index)
 void JSWebAssemblyTable::clearFunction(uint32_t index)
 {
     m_table->clearFunction(index);
-    m_jsFunctions.get()[index & m_table->mask()] = WriteBarrier<JSObject>();
+    m_jsFunctions.get()[index & m_table->mask()] = PoisonedBarrier<JSObject>();
 }
 
 void JSWebAssemblyTable::setFunction(VM& vm, uint32_t index, WebAssemblyFunction* function)
index dc74a8f..c540e76 100644 (file)
@@ -67,7 +67,11 @@ private:
     static void visitChildren(JSCell*, SlotVisitor&);
 
     PoisonedRef<JSWebAssemblyTablePoison, Wasm::Table> m_table;
-    MallocPtr<WriteBarrier<JSObject>> m_jsFunctions;
+
+    template<typename T>
+    using PoisonedBarrier = PoisonedWriteBarrier<JSWebAssemblyTablePoison, T>;
+
+    MallocPtr<PoisonedBarrier<JSObject>> m_jsFunctions;
 };
 
 } // namespace JSC
index e62f8cf..9d3cf39 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -46,13 +46,14 @@ namespace JSC { namespace Wasm {
 
 using JIT = CCallHelpers;
 
-static void materializeImportJSCell(JIT& jit, unsigned importIndex, GPRReg result)
+static void materializeImportJSCell(JIT& jit, unsigned importIndex, GPRReg poison, GPRReg result)
 {
     // We're calling out of the current WebAssembly.Instance. That Instance has a list of all its import functions.
     jit.loadWasmContextInstance(result);
     jit.loadPtr(JIT::Address(result, Instance::offsetOfImportFunction(importIndex)), result);
+    jit.xor64(poison, result);
 }
-    
+
 static Expected<MacroAssemblerCodeRef, BindingFailure> handleBadI64Use(VM* vm, JIT& jit, const Signature& signature, unsigned importIndex)
 {
     unsigned argCount = signature.argumentCount();
@@ -84,9 +85,14 @@ static Expected<MacroAssemblerCodeRef, BindingFailure> handleBadI64Use(VM* vm, J
 
         // Store Callee.
         jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR1, Instance::offsetOfOwner()), GPRInfo::argumentGPR1);
-        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR1, JSWebAssemblyInstance::offsetOfCallee()), GPRInfo::argumentGPR2);
+        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR1, JSWebAssemblyInstance::offsetOfPoisonedCallee()), GPRInfo::argumentGPR2);
+        jit.move(CCallHelpers::TrustedImm64(JSWebAssemblyInstance::PoisonedBarrier<WebAssemblyToJSCallee>::poison), GPRInfo::argumentGPR3);
+        jit.xor64(GPRInfo::argumentGPR3, GPRInfo::argumentGPR2);
         jit.storePtr(GPRInfo::argumentGPR2, JIT::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
 
+        // Let's be paranoid on the exception path and zero out the poison instead of leaving it in an argument GPR.
+        jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::argumentGPR3);
+
         auto call = jit.call();
         jit.jumpToExceptionHandler(*vm);
 
@@ -284,10 +290,16 @@ Expected<MacroAssemblerCodeRef, BindingFailure> wasmToJS(VM* vm, Bag<CallLinkInf
         
         jit.loadWasmContextInstance(GPRInfo::argumentGPR0);
         jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, Instance::offsetOfOwner()), GPRInfo::argumentGPR0);
-        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, JSWebAssemblyInstance::offsetOfCallee()), GPRInfo::argumentGPR0);
+        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, JSWebAssemblyInstance::offsetOfPoisonedCallee()), GPRInfo::argumentGPR0);
+        jit.move(CCallHelpers::TrustedImm64(JSWebAssemblyInstance::PoisonedBarrier<WebAssemblyToJSCallee>::poison), GPRInfo::argumentGPR3);
+        jit.xor64(GPRInfo::argumentGPR3, GPRInfo::argumentGPR0);
         jit.storePtr(GPRInfo::argumentGPR0, JIT::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
         
-        materializeImportJSCell(jit, importIndex, GPRInfo::argumentGPR1);
+        materializeImportJSCell(jit, importIndex, GPRInfo::argumentGPR3, GPRInfo::argumentGPR1);
+        
+        // Let's be paranoid before the call and zero out the poison instead of leaving it in an argument GPR.
+        jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::argumentGPR3);
+
         static_assert(GPRInfo::numberOfArgumentRegisters >= 4, "We rely on this with the call below.");
         jit.setupArgumentsWithExecState(GPRInfo::argumentGPR1, CCallHelpers::TrustedImm32(signatureIndex), CCallHelpers::TrustedImmPtr(buffer));
         auto call = jit.call();
@@ -465,15 +477,24 @@ Expected<MacroAssemblerCodeRef, BindingFailure> wasmToJS(VM* vm, Bag<CallLinkInf
         }
     }
 
+    GPRReg poison = GPRInfo::argumentGPR1;
+    ASSERT(poison != GPRInfo::argumentGPR0); // Both are used at the same time below.
+
     jit.loadWasmContextInstance(GPRInfo::argumentGPR0);
     jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, Instance::offsetOfOwner()), GPRInfo::argumentGPR0);
-    jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, JSWebAssemblyInstance::offsetOfCallee()), GPRInfo::argumentGPR0);
+    jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, JSWebAssemblyInstance::offsetOfPoisonedCallee()), GPRInfo::argumentGPR0);
+    jit.move(CCallHelpers::TrustedImm64(JSWebAssemblyInstance::PoisonedBarrier<WebAssemblyToJSCallee>::poison), poison);
+    jit.xor64(poison, GPRInfo::argumentGPR0);
     jit.storePtr(GPRInfo::argumentGPR0, JIT::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
 
     GPRReg importJSCellGPRReg = GPRInfo::regT0; // Callee needs to be in regT0 for slow path below.
+    ASSERT(poison != importJSCellGPRReg);
+
     ASSERT(!wasmCC.m_calleeSaveRegisters.get(importJSCellGPRReg));
+    materializeImportJSCell(jit, importIndex, poison, importJSCellGPRReg);
 
-    materializeImportJSCell(jit, importIndex, importJSCellGPRReg);
+    // Let's be paranoid zero out the poison instead of leaving it in an argument GPR.
+    jit.move(CCallHelpers::TrustedImm32(0), poison);
 
     jit.store64(importJSCellGPRReg, calleeFrame.withOffset(CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
     jit.store32(JIT::TrustedImm32(numberOfParameters), calleeFrame.withOffset(CallFrameSlot::argumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset));
index 4973e4d..d1719a0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -49,7 +49,8 @@ protected:
     static void visitChildren(JSCell*, SlotVisitor&);
     void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name, JSWebAssemblyInstance*);
     WebAssemblyFunctionBase(VM&, JSGlobalObject*, Structure*);
-    WriteBarrier<JSWebAssemblyInstance> m_instance;
+
+    PoisonedWriteBarrier<WebAssemblyFunctionBasePoison, JSWebAssemblyInstance> m_instance;
 };
 
 } // namespace JSC
index 78baa6b..95db29a 100644 (file)
@@ -110,7 +110,7 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module,
             //   ii. (Note: At most one wrapper is created for any closure, so func is unique, even if there are multiple occurrances in the list. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.)
             if (exp.kindIndex < functionImportCount) {
                 unsigned functionIndex = exp.kindIndex;
-                JSObject* functionImport = instance->instance().importFunction<WriteBarrier<JSObject>>(functionIndex)->get();
+                JSObject* functionImport = instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(functionIndex)->get();
                 if (isWebAssemblyHostFunction(vm, functionImport))
                     exportedValue = functionImport;
                 else {
@@ -191,7 +191,7 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module,
         ASSERT(!signature.argumentCount());
         ASSERT(signature.returnType() == Wasm::Void);
         if (startFunctionIndexSpace < codeBlock->functionImportCount()) {
-            JSObject* startFunction = instance->instance().importFunction<WriteBarrier<JSObject>>(startFunctionIndexSpace)->get();
+            JSObject* startFunction = instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(startFunctionIndexSpace)->get();
             m_startFunction.set(vm, this, startFunction);
         } else {
             Wasm::Callee& embedderEntrypointCallee = codeBlock->embedderEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
@@ -295,7 +295,7 @@ JSValue WebAssemblyModuleRecord::evaluate(ExecState* exec)
             uint32_t functionIndex = element.functionIndices[i];
             Wasm::SignatureIndex signatureIndex = module.signatureIndexFromFunctionIndexSpace(functionIndex);
             if (functionIndex < codeBlock->functionImportCount()) {
-                JSObject* functionImport = m_instance->instance().importFunction<WriteBarrier<JSObject>>(functionIndex)->get();
+                JSObject* functionImport = m_instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(functionIndex)->get();
                 if (isWebAssemblyHostFunction(vm, functionImport)) {
                     WebAssemblyFunction* wasmFunction = jsDynamicCast<WebAssemblyFunction*>(vm, functionImport);
                     // If we ever import a WebAssemblyWrapperFunction, we set the import as the unwrapped value.
index a08ccbc..fc2addd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -59,8 +59,11 @@ private:
 
     static void visitChildren(JSCell*, SlotVisitor&);
 
-    WriteBarrier<JSWebAssemblyInstance> m_instance;
-    WriteBarrier<JSObject> m_startFunction;
+    template<typename T>
+    using PoisonedBarrier = PoisonedWriteBarrier<WebAssemblyModuleRecordPoison, T>;
+
+    PoisonedBarrier<JSWebAssemblyInstance> m_instance;
+    PoisonedBarrier<JSObject> m_startFunction;
 };
 
 } // namespace JSC
index 061d14d..c89a1af 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -51,7 +51,7 @@ private:
     void finishCreation(VM&, JSWebAssemblyModule*);
     WebAssemblyToJSCallee(VM&, Structure*);
 
-    WriteBarrier<JSWebAssemblyModule> m_module;
+    PoisonedWriteBarrier<WebAssemblyToJSCalleePoison, JSWebAssemblyModule> m_module;
 };
 
 } // namespace JSC
index e100f71..ca6c0ca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -56,7 +56,7 @@ protected:
 private:
     WebAssemblyWrapperFunction(VM&, JSGlobalObject*, Structure*, Wasm::CallableFunction);
 
-    WriteBarrier<JSObject> m_function;
+    PoisonedWriteBarrier<WebAssemblyWrapperFunctionPoison, JSObject> m_function;
     // It's safe to just hold the raw CallableFunction because we have a reference
     // to our Instance, which points to the CodeBlock, which points to the Module
     // that exported us, which ensures that the actual Signature/code doesn't get deallocated.
index 9aa46ed..3a89148 100644 (file)
@@ -1,3 +1,26 @@
+2018-01-12  JF Bastien  <jfbastien@apple.com>
+
+        PoisonedWriteBarrier
+        https://bugs.webkit.org/show_bug.cgi?id=181599
+        <rdar://problem/36474351>
+
+        Reviewed by Mark Lam.
+
+        Supporting changes needed to allow poisoning of WriteBarrier
+        objects.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/DumbPtrTraits.h:
+        * wtf/DumbValueTraits.h: Copied from Source/WTF/wtf/DumbPtrTraits.h.
+        (WTF::DumbValueTraits::exchange):
+        (WTF::DumbValueTraits::swap):
+        (WTF::DumbValueTraits::unwrap):
+        * wtf/Forward.h:
+        * wtf/Poisoned.h:
+        (WTF::ConstExprPoisonedValueTraits::exchange):
+        (WTF::ConstExprPoisonedValueTraits::swap):
+        (WTF::ConstExprPoisonedValueTraits::unwrap):
+
 2018-01-11  Basuke Suzuki  <Basuke.Suzuki@sony.com>
 
         Remove noexcept from definition of std::tie()
index f772e76..df96380 100644 (file)
                A8A47372151A825B004123FF /* VMTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMTags.h; sourceTree = "<group>"; };
                A8A4748B151A8264004123FF /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
                A9A4727F151A825A004123FF /* DisallowCType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisallowCType.h; sourceTree = "<group>"; };
+               AD653DA82006B6C200D820D7 /* DumbValueTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DumbValueTraits.h; sourceTree = "<group>"; };
                AD7C434A1DD2A4A70026888B /* Expected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Expected.h; sourceTree = "<group>"; };
                AD89B6B51E6415080090707F /* MemoryPressureHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryPressureHandler.cpp; sourceTree = "<group>"; };
                AD89B6B61E6415080090707F /* MemoryPressureHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryPressureHandler.h; sourceTree = "<group>"; };
                                0F4570421BE5B58F0062A629 /* Dominators.h */,
                                A8A47280151A825A004123FF /* DoublyLinkedList.h */,
                                FE05FAE61FDB214300093230 /* DumbPtrTraits.h */,
+                               AD653DA82006B6C200D820D7 /* DumbValueTraits.h */,
                                A8A47297151A825A004123FF /* dtoa.cpp */,
                                A8A47298151A825A004123FF /* dtoa.h */,
                                1AEA88E11D6BBCF400E5AD64 /* EnumTraits.h */,
index e8425c0..3cece6e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #pragma once
 
+#include <cstdint>
 #include <utility>
 
 namespace WTF {
     
 template<typename T>
 struct DumbPtrTraits {
+    static constexpr uintptr_t poison = 0;
+
     using StorageType = T*;
 
     template<typename U>
@@ -42,3 +45,4 @@ struct DumbPtrTraits {
 
 } // namespace WTF
 
+using WTF::DumbPtrTraits;
diff --git a/Source/WTF/wtf/DumbValueTraits.h b/Source/WTF/wtf/DumbValueTraits.h
new file mode 100644 (file)
index 0000000..8c90ad8
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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 <cstdint>
+#include <utility>
+
+namespace WTF {
+
+template<typename T>
+struct DumbValueTraits {
+    static constexpr uintptr_t poison = 0;
+
+    using StorageType = T;
+
+    template<typename U>
+    static ALWAYS_INLINE T exchange(StorageType& val, U&& newValue) { return std::exchange(val, newValue); }
+
+    static ALWAYS_INLINE void swap(StorageType& a, StorageType& b) { std::swap(a, b); }
+    static ALWAYS_INLINE T unwrap(const StorageType& val) { return val; }
+};
+
+} // namespace WTF
+
+using WTF::DumbValueTraits;
index 3c26d70..42fad81 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006-2017 Apple Inc. All rights reserved.
+ *  Copyright (C) 2006-2018 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -52,6 +52,7 @@ struct FastMalloc;
 
 template<typename> class CompletionHandler;
 template<typename T> struct DumbPtrTraits;
+template<typename T> struct DumbValueTraits;
 template<typename> class Function;
 template<typename> class LazyNeverDestroyed;
 template<typename> class NeverDestroyed;
@@ -84,6 +85,8 @@ using WTF::AtomicStringImpl;
 using WTF::BinarySemaphore;
 using WTF::CString;
 using WTF::CompletionHandler;
+using WTF::DumbPtrTraits;
+using WTF::DumbValueTraits;
 using WTF::Function;
 using WTF::FunctionDispatcher;
 using WTF::HashCountedSet;
index ba5b6a8..4154b3b 100644 (file)
@@ -262,6 +262,8 @@ using ConstExprPoisoned = PoisonedImpl<uintptr_t, makeConstExprPoison(key), T>;
 
 template<uint32_t key, typename T>
 struct ConstExprPoisonedPtrTraits {
+    static constexpr auto poison = makeConstExprPoison(key);
+
     using StorageType = ConstExprPoisoned<key, T*>;
 
     template<class U> static ALWAYS_INLINE T* exchange(StorageType& ptr, U&& newValue) { return ptr.exchange(newValue); }
@@ -275,6 +277,23 @@ struct ConstExprPoisonedPtrTraits {
     static ALWAYS_INLINE T* unwrap(const StorageType& ptr) { return ptr.unpoisoned(); }
 };
 
+template<uint32_t key, typename T>
+struct ConstExprPoisonedValueTraits {
+    static constexpr auto poison = makeConstExprPoison(key);
+
+    using StorageType = ConstExprPoisoned<key, T>;
+
+    template<class U> static ALWAYS_INLINE T exchange(StorageType& val, U&& newValue) { return val.exchange(newValue); }
+
+    template<typename K1, K1 k1, typename T1>
+    static ALWAYS_INLINE void swap(PoisonedImpl<K1, k1, T1>& a, T1& b) { a.swap(b); }
+
+    template<typename K1, K1 k1, typename T1, typename K2, K2 k2, typename T2>
+    static ALWAYS_INLINE void swap(PoisonedImpl<K1, k1, T1>& a, PoisonedImpl<K2, k2, T2>& b) { a.swap(b); }
+
+    static ALWAYS_INLINE T unwrap(const StorageType& val) { return val.unpoisoned(); }
+};
+
 } // namespace WTF
 
 using WTF::ConstExprPoisoned;