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:
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/. */
12 #include "js/RootingAPI.h"
13 #include "js/StableStringChars.h"
14 #include "js/String.h" // JS::StringToLinearString
16 #include "jsapi-tests/tests.h"
18 #include "vm/JSContext.h"
19 #include "vm/StringType.h"
21 #include "vm/JSContext-inl.h"
23 static bool SameChars(JSContext
* cx
, JSString
* str1
, JSString
* str2
,
25 JS::AutoCheckCannotGC
nogc(cx
);
27 const JS::Latin1Char
* chars1
=
28 JS::StringToLinearString(cx
, str1
)->latin1Chars(nogc
);
29 const JS::Latin1Char
* chars2
=
30 JS::StringToLinearString(cx
, str2
)->latin1Chars(nogc
);
32 return chars1
== chars2
+ offset
;
35 BEGIN_TEST(testDeduplication_ASSC
) {
36 // Test with a long enough string to avoid inline chars allocation.
38 "Andthebeastshallcomeforthsurroundedbyaroilingcloudofvengeance."
39 "Thehouseoftheunbelieversshallberazedandtheyshallbescorchedtoth"
40 "eearth.Theirtagsshallblinkuntiltheendofdays.";
42 // Create a string to deduplicate later strings to.
43 JS::RootedString
original(cx
);
44 JS::RootedString
str(cx
);
45 JS::RootedString
dep(cx
);
46 JS::RootedString
depdep(cx
);
47 JS::RootedString
str2(cx
);
48 JS::RootedString
dep2(cx
);
49 JS::RootedString
depdep2(cx
);
52 // This test checks the behavior when GC is performed after allocating
53 // all the following strings.
54 // GC shouldn't happen in between them, even in compacting jobs.
55 js::gc::AutoSuppressGC
suppress(cx
);
57 original
= JS_NewStringCopyZ(cx
, text
);
60 // Create a chain of dependent strings, with a base string whose contents
61 // match `original`'s.
62 str
= JS_NewStringCopyZ(cx
, text
);
65 dep
= JS_NewDependentString(cx
, str
, 10, 100);
68 depdep
= JS_NewDependentString(cx
, dep
, 10, 80);
71 // Repeat. This one will not be prevented from deduplication.
72 str2
= JS_NewStringCopyZ(cx
, text
);
75 dep2
= JS_NewDependentString(cx
, str2
, 10, 100);
78 depdep2
= JS_NewDependentString(cx
, dep2
, 10, 80);
82 // Initializing an AutoStableStringChars with `depdep` should prevent the
83 // owner of its chars (`str`) from deduplication.
84 JS::AutoStableStringChars
stable(cx
);
85 CHECK(stable
.init(cx
, depdep
));
87 const JS::Latin1Char
* chars
= stable
.latin1Chars();
88 CHECK(memcmp(chars
, text
+ 20, 80 * sizeof(JS::Latin1Char
)) == 0);
90 // `depdep` should share chars with `str` but not with `original`.
91 CHECK(SameChars(cx
, depdep
, str
, 20));
92 CHECK(!SameChars(cx
, depdep
, original
, 20));
94 // Same for `depdep2`.
95 CHECK(SameChars(cx
, depdep2
, str2
, 20));
96 CHECK(!SameChars(cx
, depdep2
, original
, 20));
98 // Do a minor GC that will deduplicate `str2` to `original`, and would have
99 // deduplicated `str` as well if it weren't prevented by the
100 // AutoStableStringChars.
101 cx
->minorGC(JS::GCReason::API
);
103 // `depdep` should still share chars with `str` but not with `original`.
104 CHECK(SameChars(cx
, depdep
, str
, 20));
105 CHECK(!SameChars(cx
, depdep
, original
, 20));
107 // `depdep2` should now share chars with both `str` and `original`.
108 CHECK(SameChars(cx
, depdep2
, str2
, 20));
109 CHECK(SameChars(cx
, depdep2
, original
, 20));
113 END_TEST(testDeduplication_ASSC
)