Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 0babc1c

Browse files
committed
Bug 1669306 - Allow JSAPI tests to opt-in to reuse a global and cx instead of tearing everything down and starting up every time. r=nbp
Cons: (1) messy, (2) may be unnecessary once Stencil allows better caching of self-hosted code. Pros: 322x faster for testJitABIcalls. Differential Revision: https://phabricator.services.mozilla.com/D92475
1 parent 88e9eb0 commit 0babc1c

4 files changed

Lines changed: 74 additions & 22 deletions

File tree

js/src/jsapi-tests/testGCOutOfMemory.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,4 @@ virtual JSContext* createContext() override {
7373
return cx;
7474
}
7575

76-
virtual void destroyContext() override { JS_DestroyContext(cx); }
77-
7876
END_TEST(testGCOutOfMemory)

js/src/jsapi-tests/testOOM.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,14 @@ BEGIN_TEST(testHelperThreadOOM) {
101101
}
102102

103103
bool init() override {
104-
js::DestroyHelperThreadsState();
104+
JSAPITest::uninit(); // Discard the just-created JSContext.
105+
js::DestroyHelperThreadsState(); // The test creates this state.
105106
return true;
106107
}
107-
void uninit() override { js::CreateHelperThreadsState(); }
108+
void uninit() override {
109+
// Leave things initialized after this test finishes.
110+
js::CreateHelperThreadsState();
111+
}
108112

109113
END_TEST(testHelperThreadOOM)
110114

js/src/jsapi-tests/tests.cpp

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,15 @@
1717

1818
JSAPITest* JSAPITest::list;
1919

20-
bool JSAPITest::init() {
20+
bool JSAPITest::init(JSContext* maybeReusableContext) {
21+
if (maybeReusableContext && reuseGlobal) {
22+
cx = maybeReusableContext;
23+
global.init(cx, cx->global());
24+
return init();
25+
}
26+
27+
MaybeFreeContext(maybeReusableContext);
28+
2129
cx = createContext();
2230
if (!cx) {
2331
return false;
@@ -32,18 +40,32 @@ bool JSAPITest::init() {
3240
return false;
3341
}
3442
JS::EnterRealm(cx, global);
35-
return true;
43+
return init();
3644
}
3745

38-
void JSAPITest::uninit() {
39-
if (global) {
40-
JS::LeaveRealm(cx, nullptr);
41-
global = nullptr;
46+
JSContext* JSAPITest::maybeForgetContext() {
47+
if (!reuseGlobal) {
48+
return nullptr;
4249
}
43-
if (cx) {
44-
destroyContext();
45-
cx = nullptr;
50+
51+
JSContext* reusableCx = cx;
52+
global.reset();
53+
cx = nullptr;
54+
return reusableCx;
55+
}
56+
57+
/* static */
58+
void JSAPITest::MaybeFreeContext(JSContext* maybeCx) {
59+
if (maybeCx) {
60+
JS::LeaveRealm(maybeCx, nullptr);
61+
JS_DestroyContext(maybeCx);
4662
}
63+
}
64+
65+
void JSAPITest::uninit() {
66+
global.reset();
67+
MaybeFreeContext(cx);
68+
cx = nullptr;
4769
msgs.clear();
4870
}
4971

@@ -112,6 +134,17 @@ int main(int argc, char* argv[]) {
112134
return 1;
113135
}
114136

137+
if (filter && strcmp(filter, "--list") == 0) {
138+
for (JSAPITest* test = JSAPITest::list; test; test = test->next) {
139+
printf("%s\n", test->name());
140+
}
141+
return 0;
142+
}
143+
144+
// Reinitializing the global for every test is quite slow, due to having to
145+
// recompile all self-hosted builtins. Allow tests to opt-in to reusing the
146+
// global.
147+
JSContext* maybeReusedContext = nullptr;
115148
for (JSAPITest* test = JSAPITest::list; test; test = test->next) {
116149
const char* name = test->name();
117150
if (filter && strstr(name, filter) == nullptr) {
@@ -121,7 +154,7 @@ int main(int argc, char* argv[]) {
121154
total += 1;
122155

123156
printf("%s\n", name);
124-
if (!test->init()) {
157+
if (!test->init(maybeReusedContext)) {
125158
printf("TEST-UNEXPECTED-FAIL | %s | Failed to initialize.\n", name);
126159
failures++;
127160
test->uninit();
@@ -139,8 +172,13 @@ int main(int argc, char* argv[]) {
139172
failures++;
140173
}
141174
}
175+
176+
// Return a non-nullptr pointer if the context & global can safely be
177+
// reused for the next test.
178+
maybeReusedContext = test->maybeForgetContext();
142179
test->uninit();
143180
}
181+
JSAPITest::MaybeFreeContext(maybeReusedContext);
144182

145183
MOZ_RELEASE_ASSERT(!JSRuntime::hasLiveRuntimes());
146184
JS_ShutDown();

js/src/jsapi-tests/tests.h

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,13 @@ class JSAPITest {
7777
bool knownFail;
7878
JSAPITestString msgs;
7979

80-
JSAPITest() : cx(nullptr), knownFail(false) {
80+
// Whether this test is willing to skip its init() and reuse a global (and
81+
// JSContext etc.) from a previous test that also has reuseGlobal=true. It
82+
// also means this test is willing to skip its uninit() if it is followed by
83+
// another reuseGlobal test.
84+
bool reuseGlobal;
85+
86+
JSAPITest() : cx(nullptr), knownFail(false), reuseGlobal(false) {
8187
next = list;
8288
list = this;
8389
}
@@ -87,7 +93,19 @@ class JSAPITest {
8793
MOZ_RELEASE_ASSERT(!global);
8894
}
8995

90-
virtual bool init();
96+
// Initialize this test, possibly with the cx from a previously run test.
97+
bool init(JSContext* maybeReusedContext);
98+
99+
// If this test is ok with its cx and global being reused, release this
100+
// test's cx to be reused by another test.
101+
JSContext* maybeForgetContext();
102+
103+
static void MaybeFreeContext(JSContext* maybeCx);
104+
105+
// The real initialization happens in init(JSContext*), above, but this
106+
// method may be overridden to perform additional initialization after the
107+
// JSContext and global have been created.
108+
virtual bool init() { return true; }
91109
virtual void uninit();
92110

93111
virtual const char* name() = 0;
@@ -353,12 +371,6 @@ class JSAPITest {
353371
return cx;
354372
}
355373

356-
virtual void destroyContext() {
357-
MOZ_RELEASE_ASSERT(cx);
358-
JS_DestroyContext(cx);
359-
cx = nullptr;
360-
}
361-
362374
static void reportWarning(JSContext* cx, JSErrorReport* report) {
363375
MOZ_RELEASE_ASSERT(report->isWarning());
364376

0 commit comments

Comments
 (0)