michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifdef JSGC_GENERATIONAL michael@0: michael@0: #include "gc/Barrier.h" michael@0: #include "jsapi-tests/tests.h" michael@0: michael@0: using namespace JS; michael@0: using namespace js; michael@0: michael@0: struct AutoIgnoreRootingHazards { michael@0: // Force a nontrivial destructor so the compiler sees the whole RAII scope michael@0: static volatile int depth; michael@0: AutoIgnoreRootingHazards() { depth++; } michael@0: ~AutoIgnoreRootingHazards() { depth--; } michael@0: }; michael@0: volatile int AutoIgnoreRootingHazards::depth = 0; michael@0: michael@0: BEGIN_TEST(testGCStoreBufferRemoval) michael@0: { michael@0: // Sanity check - objects start in the nursery and then become tenured. michael@0: JS_GC(cx->runtime()); michael@0: JS::RootedObject obj(cx, NurseryObject()); michael@0: CHECK(js::gc::IsInsideNursery(rt, obj.get())); michael@0: JS_GC(cx->runtime()); michael@0: CHECK(!js::gc::IsInsideNursery(rt, obj.get())); michael@0: JS::RootedObject tenuredObject(cx, obj); michael@0: michael@0: // Hide the horrors herein from the static rooting analysis. michael@0: AutoIgnoreRootingHazards ignore; michael@0: michael@0: // Test removal of store buffer entries added by RelocatablePtr. michael@0: { michael@0: JSObject *badObject = reinterpret_cast(1); michael@0: JSObject *punnedPtr = nullptr; michael@0: RelocatablePtrObject* relocPtr = michael@0: reinterpret_cast(&punnedPtr); michael@0: new (relocPtr) RelocatablePtrObject; michael@0: *relocPtr = NurseryObject(); michael@0: relocPtr->~RelocatablePtrObject(); michael@0: punnedPtr = badObject; michael@0: JS_GC(cx->runtime()); michael@0: michael@0: new (relocPtr) RelocatablePtrObject; michael@0: *relocPtr = NurseryObject(); michael@0: *relocPtr = tenuredObject; michael@0: relocPtr->~RelocatablePtrObject(); michael@0: punnedPtr = badObject; michael@0: JS_GC(cx->runtime()); michael@0: michael@0: new (relocPtr) RelocatablePtrObject; michael@0: *relocPtr = NurseryObject(); michael@0: *relocPtr = nullptr; michael@0: relocPtr->~RelocatablePtrObject(); michael@0: punnedPtr = badObject; michael@0: JS_GC(cx->runtime()); michael@0: } michael@0: michael@0: // Test removal of store buffer entries added by RelocatableValue. michael@0: { michael@0: Value punnedValue; michael@0: RelocatableValue *relocValue = reinterpret_cast(&punnedValue); michael@0: new (relocValue) RelocatableValue; michael@0: *relocValue = ObjectValue(*NurseryObject()); michael@0: relocValue->~RelocatableValue(); michael@0: punnedValue = ObjectValueCrashOnTouch(); michael@0: JS_GC(cx->runtime()); michael@0: michael@0: new (relocValue) RelocatableValue; michael@0: *relocValue = ObjectValue(*NurseryObject()); michael@0: *relocValue = ObjectValue(*tenuredObject); michael@0: relocValue->~RelocatableValue(); michael@0: punnedValue = ObjectValueCrashOnTouch(); michael@0: JS_GC(cx->runtime()); michael@0: michael@0: new (relocValue) RelocatableValue; michael@0: *relocValue = ObjectValue(*NurseryObject()); michael@0: *relocValue = NullValue(); michael@0: relocValue->~RelocatableValue(); michael@0: punnedValue = ObjectValueCrashOnTouch(); michael@0: JS_GC(cx->runtime()); michael@0: } michael@0: michael@0: // Test removal of store buffer entries added by Heap. michael@0: { michael@0: JSObject *badObject = reinterpret_cast(1); michael@0: JSObject *punnedPtr = nullptr; michael@0: Heap* heapPtr = michael@0: reinterpret_cast*>(&punnedPtr); michael@0: new (heapPtr) Heap; michael@0: *heapPtr = NurseryObject(); michael@0: heapPtr->~Heap(); michael@0: punnedPtr = badObject; michael@0: JS_GC(cx->runtime()); michael@0: michael@0: new (heapPtr) Heap; michael@0: *heapPtr = NurseryObject(); michael@0: *heapPtr = tenuredObject; michael@0: heapPtr->~Heap(); michael@0: punnedPtr = badObject; michael@0: JS_GC(cx->runtime()); michael@0: michael@0: new (heapPtr) Heap; michael@0: *heapPtr = NurseryObject(); michael@0: *heapPtr = nullptr; michael@0: heapPtr->~Heap(); michael@0: punnedPtr = badObject; michael@0: JS_GC(cx->runtime()); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: JSObject *NurseryObject() michael@0: { michael@0: return JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()); michael@0: } michael@0: END_TEST(testGCStoreBufferRemoval) michael@0: michael@0: #endif