diff -r 000000000000 -r 6474c204b198 js/src/jsapi-tests/testGCStoreBufferRemoval.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/jsapi-tests/testGCStoreBufferRemoval.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,125 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +* vim: set ts=8 sts=4 et sw=4 tw=99: +*/ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#ifdef JSGC_GENERATIONAL + +#include "gc/Barrier.h" +#include "jsapi-tests/tests.h" + +using namespace JS; +using namespace js; + +struct AutoIgnoreRootingHazards { + // Force a nontrivial destructor so the compiler sees the whole RAII scope + static volatile int depth; + AutoIgnoreRootingHazards() { depth++; } + ~AutoIgnoreRootingHazards() { depth--; } +}; +volatile int AutoIgnoreRootingHazards::depth = 0; + +BEGIN_TEST(testGCStoreBufferRemoval) +{ + // Sanity check - objects start in the nursery and then become tenured. + JS_GC(cx->runtime()); + JS::RootedObject obj(cx, NurseryObject()); + CHECK(js::gc::IsInsideNursery(rt, obj.get())); + JS_GC(cx->runtime()); + CHECK(!js::gc::IsInsideNursery(rt, obj.get())); + JS::RootedObject tenuredObject(cx, obj); + + // Hide the horrors herein from the static rooting analysis. + AutoIgnoreRootingHazards ignore; + + // Test removal of store buffer entries added by RelocatablePtr. + { + JSObject *badObject = reinterpret_cast(1); + JSObject *punnedPtr = nullptr; + RelocatablePtrObject* relocPtr = + reinterpret_cast(&punnedPtr); + new (relocPtr) RelocatablePtrObject; + *relocPtr = NurseryObject(); + relocPtr->~RelocatablePtrObject(); + punnedPtr = badObject; + JS_GC(cx->runtime()); + + new (relocPtr) RelocatablePtrObject; + *relocPtr = NurseryObject(); + *relocPtr = tenuredObject; + relocPtr->~RelocatablePtrObject(); + punnedPtr = badObject; + JS_GC(cx->runtime()); + + new (relocPtr) RelocatablePtrObject; + *relocPtr = NurseryObject(); + *relocPtr = nullptr; + relocPtr->~RelocatablePtrObject(); + punnedPtr = badObject; + JS_GC(cx->runtime()); + } + + // Test removal of store buffer entries added by RelocatableValue. + { + Value punnedValue; + RelocatableValue *relocValue = reinterpret_cast(&punnedValue); + new (relocValue) RelocatableValue; + *relocValue = ObjectValue(*NurseryObject()); + relocValue->~RelocatableValue(); + punnedValue = ObjectValueCrashOnTouch(); + JS_GC(cx->runtime()); + + new (relocValue) RelocatableValue; + *relocValue = ObjectValue(*NurseryObject()); + *relocValue = ObjectValue(*tenuredObject); + relocValue->~RelocatableValue(); + punnedValue = ObjectValueCrashOnTouch(); + JS_GC(cx->runtime()); + + new (relocValue) RelocatableValue; + *relocValue = ObjectValue(*NurseryObject()); + *relocValue = NullValue(); + relocValue->~RelocatableValue(); + punnedValue = ObjectValueCrashOnTouch(); + JS_GC(cx->runtime()); + } + + // Test removal of store buffer entries added by Heap. + { + JSObject *badObject = reinterpret_cast(1); + JSObject *punnedPtr = nullptr; + Heap* heapPtr = + reinterpret_cast*>(&punnedPtr); + new (heapPtr) Heap; + *heapPtr = NurseryObject(); + heapPtr->~Heap(); + punnedPtr = badObject; + JS_GC(cx->runtime()); + + new (heapPtr) Heap; + *heapPtr = NurseryObject(); + *heapPtr = tenuredObject; + heapPtr->~Heap(); + punnedPtr = badObject; + JS_GC(cx->runtime()); + + new (heapPtr) Heap; + *heapPtr = NurseryObject(); + *heapPtr = nullptr; + heapPtr->~Heap(); + punnedPtr = badObject; + JS_GC(cx->runtime()); + } + + return true; +} + +JSObject *NurseryObject() +{ + return JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()); +} +END_TEST(testGCStoreBufferRemoval) + +#endif