static void TraceArray(JSTracer* trc, void* data) { ArrayT* array = static_cast<ArrayT *>(data); for (unsigned i = 0; i < array->Length(); ++i) JS_CallHeapObjectTracer(trc, &array->ElementAt(i), "array-element"); }
static void RunTest(JSRuntime* rt, JSContext* cx) { JS_GC(rt); /* * Create an array with space for half the final number of elements to test * that moving Heap<T> elements works correctly. */ const int elements = 100; ArrayT* array = new ArrayT(elements / 2); ASSERT_TRUE(array != nullptr); JS_AddExtraGCRootsTracer(rt, TraceArray, array); /* * Create the array and fill it with new JS objects. With GGC these will be * allocated in the nursery. */ RootedValue value(cx); const char* property = "foo"; JS::shadow::Runtime* srt = reinterpret_cast<JS::shadow::Runtime*>(rt); for (int i = 0; i < elements; ++i) { RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr())); #ifdef JSGC_GENERATIONAL ASSERT_TRUE(js::gc::IsInsideNursery(srt, obj)); #else ASSERT_FALSE(js::gc::IsInsideNursery(srt, obj)); #endif value = Int32Value(i); ASSERT_TRUE(JS_SetProperty(cx, obj, property, value)); array->AppendElement(obj); } /* * If postbarriers are not working, we will crash here when we try to mark * objects that have been moved to the tenured heap. */ JS_GC(rt); /* * Sanity check that our array contains what we expect. */ for (int i = 0; i < elements; ++i) { RootedObject obj(cx, array->ElementAt(i)); ASSERT_FALSE(js::gc::IsInsideNursery(srt, obj)); ASSERT_TRUE(JS_GetProperty(cx, obj, property, &value)); ASSERT_TRUE(value.isInt32()); ASSERT_EQ(i, value.toInt32()); } JS_RemoveExtraGCRootsTracer(rt, TraceArray, array); }