testIsInsideNursery.cpp (4087B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "jsapi-tests/tests.h" 9 10 #include "vm/JSContext-inl.h" 11 12 using namespace js; 13 14 BEGIN_TEST(testIsInsideNursery) { 15 /* Non-GC things are never inside the nursery. */ 16 CHECK(!cx->nursery().isInside(cx)); 17 CHECK(!cx->nursery().isInside((void*)nullptr)); 18 19 // Skip test if some part of the nursery is disabled (via env var, for 20 // example.) 21 if (!cx->zone()->allocNurseryObjects() || 22 !cx->zone()->allocNurseryStrings()) { 23 return true; 24 } 25 26 JS_GC(cx); 27 28 JS::Rooted<JSObject*> object(cx, JS_NewPlainObject(cx)); 29 const char oolstr[] = 30 "my hands are floppy dark red pieces of liver, large " 31 "enough to exceed the space of an inline string"; 32 JS::Rooted<JSString*> string(cx, JS_NewStringCopyZ(cx, oolstr)); 33 34 /* Objects are initially allocated in the nursery. */ 35 CHECK(gc::IsInsideNursery(object)); 36 /* As are strings. */ 37 CHECK(gc::IsInsideNursery(string)); 38 /* And their contents. */ 39 { 40 JS::AutoCheckCannotGC nogc; 41 const JS::Latin1Char* strdata = 42 string->asLinear().nonInlineLatin1Chars(nogc); 43 CHECK(cx->nursery().isInside(strdata)); 44 } 45 46 JS_GC(cx); 47 48 /* And are tenured if still live after a GC. */ 49 CHECK(!gc::IsInsideNursery(object)); 50 CHECK(!gc::IsInsideNursery(string)); 51 { 52 JS::AutoCheckCannotGC nogc; 53 const JS::Latin1Char* strdata = 54 string->asLinear().nonInlineLatin1Chars(nogc); 55 CHECK(!cx->nursery().isInside(strdata)); 56 } 57 58 return true; 59 } 60 END_TEST(testIsInsideNursery) 61 62 BEGIN_TEST(testSemispaceNursery) { 63 AutoGCParameter enableSemispace(cx, JSGC_SEMISPACE_NURSERY_ENABLED, 1); 64 65 JS_GC(cx); 66 67 /* Objects are initially allocated in the nursery. */ 68 RootedObject object(cx, JS_NewPlainObject(cx)); 69 CHECK(gc::IsInsideNursery(object)); 70 71 /* Minor GC with the evict reason tenures them. */ 72 cx->minorGC(JS::GCReason::EVICT_NURSERY); 73 CHECK(!gc::IsInsideNursery(object)); 74 75 /* Minor GC with other reasons gives them a second chance. */ 76 object = JS_NewPlainObject(cx); 77 void* ptr = object; 78 CHECK(gc::IsInsideNursery(object)); 79 cx->minorGC(JS::GCReason::API); 80 CHECK(ptr != object); 81 CHECK(gc::IsInsideNursery(object)); 82 ptr = object; 83 cx->minorGC(JS::GCReason::API); 84 CHECK(!gc::IsInsideNursery(object)); 85 CHECK(ptr != object); 86 87 CHECK(testReferencesBetweenGenerations(0)); 88 CHECK(testReferencesBetweenGenerations(1)); 89 CHECK(testReferencesBetweenGenerations(2)); 90 91 return true; 92 } 93 94 bool testReferencesBetweenGenerations(size_t referrerGeneration) { 95 MOZ_ASSERT(referrerGeneration <= 2); 96 97 RootedObject referrer(cx, JS_NewPlainObject(cx)); 98 CHECK(referrer); 99 CHECK(gc::IsInsideNursery(referrer)); 100 101 for (size_t i = 0; i < referrerGeneration; i++) { 102 cx->minorGC(JS::GCReason::API); 103 } 104 MOZ_ASSERT(IsInsideNursery(referrer) == (referrerGeneration < 2)); 105 106 RootedObject object(cx, JS_NewPlainObject(cx)); 107 CHECK(gc::IsInsideNursery(object)); 108 RootedValue value(cx, JS::ObjectValue(*object)); 109 CHECK(JS_DefineProperty(cx, referrer, "prop", value, 0)); 110 CHECK(JS_GetProperty(cx, referrer, "prop", &value)); 111 CHECK(&value.toObject() == object); 112 CHECK(JS_SetElement(cx, referrer, 0, value)); 113 CHECK(JS_GetElement(cx, referrer, 0, &value)); 114 CHECK(&value.toObject() == object); 115 116 cx->minorGC(JS::GCReason::API); 117 CHECK(gc::IsInsideNursery(object)); 118 CHECK(JS_GetProperty(cx, referrer, "prop", &value)); 119 CHECK(&value.toObject() == object); 120 CHECK(JS_GetElement(cx, referrer, 0, &value)); 121 CHECK(&value.toObject() == object); 122 123 cx->minorGC(JS::GCReason::API); 124 CHECK(!gc::IsInsideNursery(object)); 125 CHECK(JS_GetProperty(cx, referrer, "prop", &value)); 126 CHECK(&value.toObject() == object); 127 CHECK(JS_GetElement(cx, referrer, 0, &value)); 128 CHECK(&value.toObject() == object); 129 130 return true; 131 } 132 133 END_TEST(testSemispaceNursery)