summaryrefslogtreecommitdiff
path: root/js/src
diff options
context:
space:
mode:
authorJeremy Andrews <athenian200@outlook.com>2022-05-26 18:57:18 -0500
committerJeremy Andrews <athenian200@outlook.com>2022-05-27 07:21:59 -0500
commit64ea1e09c2dfd09bf71738f08e15ec3d7d80e33b (patch)
treeea35d0e6ea0d4e4a20a131224c48e8d3bf844f97 /js/src
parentcd55d0fbe4e5dddfc7e0bcc97ffa8a5a9febaff2 (diff)
downloaduxp-64ea1e09c2dfd09bf71738f08e15ec3d7d80e33b.tar.gz
Issue #1742 - Part 4: Don't trigger read barriers when comparing wrapped pointers types
This is actually an undocumented dependency of Bug 1325406 for Linux and SunOS. Ref: BZ 1308236
Diffstat (limited to 'js/src')
-rw-r--r--js/src/gc/Barrier.h46
-rw-r--r--js/src/jsapi-tests/testGCHeapPostBarriers.cpp108
-rw-r--r--js/src/vm/SharedMem.h4
3 files changed, 148 insertions, 10 deletions
diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h
index 25f153207f..1ec269abf3 100644
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -356,7 +356,8 @@ class WriteBarrieredBase : public BarrieredBase<T>,
explicit WriteBarrieredBase(const T& v) : BarrieredBase<T>(v) {}
public:
- DECLARE_POINTER_COMPARISON_OPS(T);
+ using ElementType = T;
+
DECLARE_POINTER_CONSTREF_OPS(T);
// Use this if the automatic coercion to T isn't working.
@@ -611,14 +612,13 @@ class ReadBarriered : public ReadBarrieredBase<T>,
return *this;
}
- const T get() const {
- if (!InternalBarrierMethods<T>::isMarkable(this->value))
- return JS::GCPolicy<T>::initial();
- this->read();
+ const T& get() const {
+ if (InternalBarrierMethods<T>::isMarkable(this->value))
+ this->read();
return this->value;
}
- const T unbarrieredGet() const {
+ const T& unbarrieredGet() const {
return this->value;
}
@@ -626,9 +626,9 @@ class ReadBarriered : public ReadBarrieredBase<T>,
return bool(this->value);
}
- operator const T() const { return get(); }
+ operator const T&() const { return get(); }
- const T operator->() const { return get(); }
+ const T& operator->() const { return get(); }
T* unsafeGet() { return &this->value; }
T const* unsafeGet() const { return &this->value; }
@@ -934,6 +934,36 @@ typedef ReadBarriered<WasmTableObject*> ReadBarrieredWasmTableObject;
typedef ReadBarriered<Value> ReadBarrieredValue;
+namespace detail {
+
+template <typename T>
+struct DefineComparisonOps<PreBarriered<T>> : mozilla::TrueType {
+ static const T& get(const PreBarriered<T>& v) { return v.get(); }
+};
+
+template <typename T>
+struct DefineComparisonOps<GCPtr<T>> : mozilla::TrueType {
+ static const T& get(const GCPtr<T>& v) { return v.get(); }
+};
+
+template <typename T>
+struct DefineComparisonOps<HeapPtr<T>> : mozilla::TrueType {
+ static const T& get(const HeapPtr<T>& v) { return v.get(); }
+};
+
+template <typename T>
+struct DefineComparisonOps<ReadBarriered<T>> : mozilla::TrueType {
+ static const T& get(const ReadBarriered<T>& v) { return v.unbarrieredGet(); }
+};
+
+template <>
+struct DefineComparisonOps<HeapSlot> : mozilla::TrueType {
+ static const Value& get(const HeapSlot& v) { return v.get(); }
+};
+
+} /* namespace detail */
+
+
} /* namespace js */
#endif /* gc_Barrier_h */
diff --git a/js/src/jsapi-tests/testGCHeapPostBarriers.cpp b/js/src/jsapi-tests/testGCHeapPostBarriers.cpp
index ccc9869724..2353f9ae46 100644
--- a/js/src/jsapi-tests/testGCHeapPostBarriers.cpp
+++ b/js/src/jsapi-tests/testGCHeapPostBarriers.cpp
@@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "mozilla/TypeTraits.h"
#include "mozilla/UniquePtr.h"
#include "js/RootingAPI.h"
@@ -146,3 +147,110 @@ TestHeapPostBarrierInitFailure()
}
END_TEST(testGCHeapPostBarriers)
+
+BEGIN_TEST(testUnbarrieredEquality)
+{
+ // Use ArrayBuffers because they have finalizers, which allows using them
+ // in ObjectPtr without awkward conversations about nursery allocatability.
+ JS::RootedObject robj(cx, JS_NewArrayBuffer(cx, 20));
+ JS::RootedObject robj2(cx, JS_NewArrayBuffer(cx, 30));
+ cx->gc.evictNursery(); // Need tenured objects
+
+ // Need some bare pointers to compare against.
+ JSObject* obj = robj;
+ JSObject* obj2 = robj2;
+ const JSObject* constobj = robj;
+ const JSObject* constobj2 = robj2;
+
+ // Make them gray. We will make sure they stay gray. (For most reads, the
+ // barrier will unmark gray.)
+ using namespace js::gc;
+ TenuredCell* cell = &obj->asTenured();
+ TenuredCell* cell2 = &obj2->asTenured();
+ cell->markIfUnmarked(GRAY);
+ cell2->markIfUnmarked(GRAY);
+ MOZ_ASSERT(cell->isMarked(GRAY));
+ MOZ_ASSERT(cell2->isMarked(GRAY));
+
+ {
+ JS::Heap<JSObject*> heap(obj);
+ JS::Heap<JSObject*> heap2(obj2);
+ CHECK(TestWrapper(obj, obj2, heap, heap2));
+ CHECK(TestWrapper(constobj, constobj2, heap, heap2));
+ }
+
+ {
+ JS::TenuredHeap<JSObject*> heap(obj);
+ JS::TenuredHeap<JSObject*> heap2(obj2);
+ CHECK(TestWrapper(obj, obj2, heap, heap2));
+ CHECK(TestWrapper(constobj, constobj2, heap, heap2));
+ }
+
+ {
+ JS::ObjectPtr objptr(obj);
+ JS::ObjectPtr objptr2(obj2);
+ CHECK(TestWrapper(obj, obj2, objptr, objptr2));
+ CHECK(TestWrapper(constobj, constobj2, objptr, objptr2));
+ objptr.finalize(cx);
+ objptr2.finalize(cx);
+ }
+ // Sanity check that the barriers normally mark things black.
+ {
+ JS::Heap<JSObject*> heap(obj);
+ JS::Heap<JSObject*> heap2(obj2);
+ heap.get();
+ heap2.get();
+ CHECK(cell->isMarked(BLACK));
+ CHECK(cell2->isMarked(BLACK));
+ }
+
+ return true;
+}
+
+template <typename ObjectT, typename WrapperT>
+bool
+TestWrapper(ObjectT obj, ObjectT obj2, WrapperT& wrapper, WrapperT& wrapper2)
+{
+ using namespace js::gc;
+
+ const TenuredCell& cell = obj->asTenured();
+ const TenuredCell& cell2 = obj2->asTenured();
+
+ int x = 0;
+
+ CHECK(cell.isMarked(GRAY));
+ CHECK(cell2.isMarked(GRAY));
+ x += obj == obj2;
+ CHECK(cell.isMarked(GRAY));
+ CHECK(cell2.isMarked(GRAY));
+ x += obj == wrapper2;
+ CHECK(cell.isMarked(GRAY));
+ CHECK(cell2.isMarked(GRAY));
+ x += wrapper == obj2;
+ CHECK(cell.isMarked(GRAY));
+ CHECK(cell2.isMarked(GRAY));
+ x += wrapper == wrapper2;
+ CHECK(cell.isMarked(GRAY));
+ CHECK(cell2.isMarked(GRAY));
+
+ CHECK(x == 0);
+
+ x += obj != obj2;
+ CHECK(cell.isMarked(GRAY));
+ CHECK(cell2.isMarked(GRAY));
+ x += obj != wrapper2;
+ CHECK(cell.isMarked(GRAY));
+ CHECK(cell2.isMarked(GRAY));
+ x += wrapper != obj2;
+ CHECK(cell.isMarked(GRAY));
+ CHECK(cell2.isMarked(GRAY));
+ x += wrapper != wrapper2;
+ CHECK(cell.isMarked(GRAY));
+ CHECK(cell2.isMarked(GRAY));
+
+ CHECK(x == 4);
+
+ return true;
+}
+
+END_TEST(testUnbarrieredEquality)
diff --git a/js/src/vm/SharedMem.h b/js/src/vm/SharedMem.h
index fe8dad304d..8e5bae492a 100644
--- a/js/src/vm/SharedMem.h
+++ b/js/src/vm/SharedMem.h
@@ -11,8 +11,8 @@
template<typename T>
class SharedMem
{
- static_assert(mozilla::IsPointer<T>::value,
- "SharedMem encapsulates pointer types");
+ // static_assert(mozilla::IsPointer<T>::value,
+ // "SharedMem encapsulates pointer types");
enum Sharedness {
IsUnshared,