Initialize CPPGC heap with kNoConservativeStack.
Otherwise, we might encounter a partially-constructed object,
which is conservatively scanned, rather than Traced. This works
fine so long as all the pointers are inline, but not with
std::list<> etc. where they may be out of line.
Roll back the protections introduced earlier, as tracing such
an object was in fact a v8 bug.
Change-Id: If8d2373b3c91acebe7697ff4760eed97f3efb109
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/73254
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/fxjs/gc/container_trace.h b/fxjs/gc/container_trace.h
index c615a2a..23a03b9 100644
--- a/fxjs/gc/container_trace.h
+++ b/fxjs/gc/container_trace.h
@@ -17,10 +17,6 @@
template <typename T, typename V = cppgc::Visitor>
void ContainerTrace(V* visitor, const std::list<cppgc::Member<T>>& container) {
- // Defend against CPPGC invoking Trace() on zero-initialized memory.
- if (container.empty())
- return;
-
for (const auto& item : container)
visitor->Trace(item);
}
@@ -28,20 +24,12 @@
template <typename T, typename U, typename V = cppgc::Visitor>
void ContainerTrace(V* visitor,
const std::map<U, cppgc::Member<T>>& container) {
- // Defend against CPPGC invoking Trace() on zero-initialized memory.
- if (container.empty())
- return;
-
for (const auto& item : container)
visitor->Trace(item.second);
}
template <typename T, typename V = cppgc::Visitor>
void ContainerTrace(V* visitor, const std::set<cppgc::Member<T>>& container) {
- // Defend against CPPGC invoking Trace() on zero-initialized memory.
- if (container.empty())
- return;
-
for (const auto& item : container)
visitor->Trace(item);
}
diff --git a/fxjs/gc/container_trace_unittest.cpp b/fxjs/gc/container_trace_unittest.cpp
index 6133a0c..b02136a 100644
--- a/fxjs/gc/container_trace_unittest.cpp
+++ b/fxjs/gc/container_trace_unittest.cpp
@@ -34,107 +34,6 @@
} // namespace
-TEST(ContainerTrace, ZeroedListQuirk) {
- using Type = std::list<cppgc::Member<Thing>>;
- uint8_t buffer[sizeof(Type)];
- memset(&buffer, 0, sizeof(buffer));
-
- auto* thing = reinterpret_cast<Type*>(buffer);
-
- // Can't trust iterators.
- // EXPECT_NE(thing->begin(), thing->end());
-
- // But we can trust empty() and guard with it.
- EXPECT_TRUE(thing->empty());
-}
-
-TEST(ContainerTrace, ZeroedMapQuirk) {
- using Type = std::map<int, cppgc::Member<Thing>>;
- uint8_t buffer[sizeof(Type)];
- memset(&buffer, 0, sizeof(buffer));
-
- auto* thing = reinterpret_cast<Type*>(buffer);
-
- // Can't trust iterators.
- // EXPECT_NE(thing->begin(), thing->end());
-
- // But we can trust empty() and guard with it.
- EXPECT_TRUE(thing->empty());
-}
-
-TEST(ContainerTrace, ZeroedSetQuirk) {
- using Type = std::set<cppgc::Member<Thing>>;
- uint8_t buffer[sizeof(Type)];
- memset(&buffer, 0, sizeof(buffer));
-
- auto* thing = reinterpret_cast<Type*>(buffer);
-
- // Can't trust iterators.
- // EXPECT_NE(thing->begin(), thing->end());
-
- // But we can trust empty() and guard with it.
- EXPECT_TRUE(thing->empty());
-}
-
-TEST(ContainerTrace, ZeroedVectorQuirk) {
- using Type = std::vector<cppgc::Member<Thing>>;
- uint8_t buffer[sizeof(Type)];
- memset(&buffer, 0, sizeof(buffer));
-
- auto* thing = reinterpret_cast<Type*>(buffer);
-
- // Can trust iterators, no guard required.
- EXPECT_EQ(thing->begin(), thing->end());
-}
-
-TEST(ContainerTrace, ZeroedListTrace) {
- using Type = std::list<cppgc::Member<Thing>>;
- uint8_t buffer[sizeof(Type)];
- memset(&buffer, 0, sizeof(buffer));
-
- auto* thing = reinterpret_cast<Type*>(buffer);
-
- CountingVisitor cv;
- ContainerTrace(&cv, *thing);
- EXPECT_EQ(0, cv.call_count());
-}
-
-TEST(ContainerTrace, ZeroedMapTrace) {
- using Type = std::map<int, cppgc::Member<Thing>>;
- uint8_t buffer[sizeof(Type)];
- memset(&buffer, 0, sizeof(buffer));
-
- auto* thing = reinterpret_cast<Type*>(buffer);
-
- CountingVisitor cv;
- ContainerTrace(&cv, *thing);
- EXPECT_EQ(0, cv.call_count());
-}
-
-TEST(ContainerTrace, ZeroedSetTrace) {
- using Type = std::set<cppgc::Member<Thing>>;
- uint8_t buffer[sizeof(Type)];
- memset(&buffer, 0, sizeof(buffer));
-
- auto* thing = reinterpret_cast<Type*>(buffer);
-
- CountingVisitor cv;
- ContainerTrace(&cv, *thing);
- EXPECT_EQ(0, cv.call_count());
-}
-
-TEST(ContainerTrace, ZeroedVectorTrace) {
- using Type = std::vector<cppgc::Member<Thing>>;
- uint8_t buffer[sizeof(Type)];
- memset(&buffer, 0, sizeof(buffer));
-
- auto* thing = reinterpret_cast<Type*>(buffer);
-
- CountingVisitor cv;
- ContainerTrace(&cv, *thing);
- EXPECT_EQ(0, cv.call_count());
-}
-
TEST(ContainerTrace, ActualListTrace) {
std::list<cppgc::Member<Thing>> thing;
thing.emplace_back(nullptr);
diff --git a/fxjs/gc/heap.cpp b/fxjs/gc/heap.cpp
index 4663763..2c02752 100644
--- a/fxjs/gc/heap.cpp
+++ b/fxjs/gc/heap.cpp
@@ -71,7 +71,10 @@
return nullptr;
++g_platform_ref_count;
- auto heap = cppgc::Heap::Create(std::make_shared<CFXGC_Platform>());
+ auto heap = cppgc::Heap::Create(
+ std::make_shared<CFXGC_Platform>(),
+ {{}, cppgc::Heap::StackSupport::kNoConservativeStackScan, {}});
+
return FXGCScopedHeap(heap.release());
}