tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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)