tor-browser

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

testDeduplication.cpp (4999B)


      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 <string.h>
      9 
     10 #include "gc/GC.h"
     11 
     12 #include "js/RootingAPI.h"
     13 #include "js/StableStringChars.h"
     14 #include "js/String.h"  // JS::StringToLinearString
     15 
     16 #include "jsapi-tests/tests.h"
     17 
     18 #include "vm/JSContext.h"
     19 #include "vm/StringType.h"
     20 
     21 #include "vm/JSContext-inl.h"
     22 
     23 static bool SameChars(JSContext* cx, JSString* str1, JSString* str2,
     24                      size_t offset) {
     25  JS::AutoCheckCannotGC nogc(cx);
     26 
     27  const JS::Latin1Char* chars1 =
     28      JS::StringToLinearString(cx, str1)->latin1Chars(nogc);
     29  const JS::Latin1Char* chars2 =
     30      JS::StringToLinearString(cx, str2)->latin1Chars(nogc);
     31 
     32  return chars1 == chars2 + offset;
     33 }
     34 
     35 BEGIN_TEST(testDeduplication_ASSC) {
     36  AutoGCParameter disableSemispace(cx, JSGC_SEMISPACE_NURSERY_ENABLED, 0);
     37 
     38  // Test with a long enough string to avoid inline chars allocation.
     39  const char text[] =
     40      "Andthebeastshallcomeforthsurroundedbyaroilingcloudofvengeance."
     41      "Thehouseoftheunbelieversshallberazedandtheyshallbescorchedtoth"
     42      "eearth.Theirtagsshallblinkuntiltheendofdays.";
     43 
     44  // Create a string to deduplicate later strings to.
     45  JS::RootedString original(cx);
     46  JS::RootedString str(cx);
     47  JS::RootedString dep(cx);
     48  JS::RootedString depdep(cx);
     49  JS::RootedString str2(cx);
     50  JS::RootedString dep2(cx);
     51  JS::RootedString depdep2(cx);
     52 
     53  if (!cx->zone()->allocNurseryStrings()) {
     54    // This test requires nursery-allocated strings, so that they will go
     55    // through the deduplication pass during minor GC.
     56    return true;
     57  }
     58 
     59  {
     60    // This test checks the behavior when GC is performed after allocating
     61    // all the following strings.
     62    // GC shouldn't happen in between them, even in compacting jobs.
     63    js::gc::AutoSuppressGC suppress(cx);
     64 
     65    original = JS_NewStringCopyZ(cx, text);
     66    CHECK(original);
     67 
     68    // Create a chain of dependent strings, with a base string whose contents
     69    // match `original`'s.
     70    str = JS_NewStringCopyZ(cx, text);
     71    CHECK(str && !str->isTenured());
     72 
     73    dep = JS_NewDependentString(cx, str, 10, 100);
     74    CHECK(dep && !dep->isTenured());
     75 
     76    depdep = JS_NewDependentString(cx, dep, 10, 80);
     77    CHECK(depdep && !depdep->isTenured());
     78 
     79    // Repeat. This one will not be prevented from deduplication.
     80    str2 = JS_NewStringCopyZ(cx, text);
     81    CHECK(str2 && !str2->isTenured());
     82 
     83    dep2 = JS_NewDependentString(cx, str2, 10, 100);
     84    CHECK(dep2 && !dep2->isTenured());
     85 
     86    depdep2 = JS_NewDependentString(cx, dep2, 10, 80);
     87    CHECK(depdep2 && !depdep2->isTenured());
     88  }
     89 
     90  // Initializing an AutoStableStringChars with `depdep` will prevent the
     91  // owner of its chars (`str`) from being deduplicated, but only if the
     92  // chars are stored in the malloc heap. Force `str` to be nondeduplicatable
     93  // unconditionally to avoid depending on the exact set of things that are
     94  // enabled.
     95  str->setNonDeduplicatable();
     96  JS::AutoStableStringChars stable(cx);
     97  CHECK(stable.init(cx, depdep));
     98 
     99  CHECK(stable.latin1Range().length() == 80);
    100 
    101  const JS::Latin1Char* chars = stable.latin1Chars();
    102  CHECK(memcmp(chars, text + 20, 80 * sizeof(JS::Latin1Char)) == 0);
    103 
    104  // `depdep` should share chars with `str` but not with `original`.
    105  CHECK(SameChars(cx, depdep, str, 20));
    106  CHECK(!SameChars(cx, depdep, original, 20));
    107 
    108  // Same for `depdep2`.
    109  CHECK(SameChars(cx, depdep2, str2, 20));
    110  CHECK(!SameChars(cx, depdep2, original, 20));
    111 
    112  // Do a minor GC that will deduplicate `str2` to `original`, and would have
    113  // deduplicated `str` as well if it weren't prevented by the
    114  // AutoStableStringChars.
    115  cx->minorGC(JS::GCReason::API);
    116 
    117  // `depdep` should still share chars with `str` but not with `original`.
    118  CHECK(SameChars(cx, depdep, str, 20));
    119  CHECK(!SameChars(cx, depdep, original, 20));
    120 
    121  // `depdep2` should now share chars with both `str2` and `original`. Or with
    122  // `str`, since it could legitimately have been detected to be identical to
    123  // the tenured `depdep` and deduplicated to that.
    124  CHECK(SameChars(cx, depdep2, str2, 20) || SameChars(cx, depdep2, str, 20));
    125 
    126  // TODO: this currently breaks because we are more conservative than we need
    127  // to be with handling the DEPENDED_ON_BIT and deduplication. This will be
    128  // fixed in bug 1900142
    129  // CHECK(SameChars(cx, depdep2, original, 20) ||
    130  //       SameChars(cx, depdep2, str, 20));
    131 
    132  // Make sure AutoStableStringChars uses the correct length when strings are
    133  // tenured.
    134  JS::AutoStableStringChars stable2(cx);
    135  CHECK(stable2.init(cx, depdep));
    136  // This should get the length from the dependent string, not the string that
    137  // owns its data.
    138  CHECK(stable2.latin1Range().length() == 80);
    139 
    140  return true;
    141 }
    142 END_TEST(testDeduplication_ASSC)