1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/DebugOnly.h"
#include "jsapi-tests/tests.h"
#include "vm/HelperThreads.h"
BEGIN_TEST(testOOM) {
JS::RootedValue v(cx, JS::Int32Value(9));
JS::RootedString jsstr(cx, JS::ToString(cx, v));
char16_t ch;
if (!JS_GetStringCharAt(cx, jsstr, 0, &ch)) {
return false;
}
MOZ_RELEASE_ASSERT(ch == '9');
return true;
}
virtual JSContext* createContext() override {
JSContext* cx = JS_NewContext(0);
if (!cx) {
return nullptr;
}
JS_SetGCParameter(cx, JSGC_MAX_BYTES, (uint32_t)-1);
setNativeStackQuota(cx);
return cx;
}
END_TEST(testOOM)
#ifdef DEBUG // js::oom functions are only available in debug builds.
const uint32_t maxAllocsPerTest = 100;
# define START_OOM_TEST(name) \
testName = name; \
printf("Test %s: started: ", testName); \
for (oomAfter = 1; oomAfter < maxAllocsPerTest; ++oomAfter) { \
js::oom::simulator.simulateFailureAfter( \
js::oom::FailureSimulator::Kind::OOM, oomAfter, \
js::THREAD_TYPE_MAIN, true)
# define END_OOM_TEST \
if (!js::oom::HadSimulatedOOM()) { \
printf("\nTest %s: finished with %" PRIu64 " allocations\n", testName, \
oomAfter - 1); \
break; \
} \
} \
js::oom::simulator.reset(); \
CHECK(oomAfter != maxAllocsPerTest)
# define MARK_STAR printf("*");
# define MARK_PLUS printf("+");
# define MARK_DOT printf(".");
BEGIN_TEST(testNewContextOOM) {
uninit(); // Get rid of test harness' original JSContext.
const char* testName;
uint64_t oomAfter;
JSContext* cx;
START_OOM_TEST("new context");
cx = JS_NewContext(8L * 1024 * 1024);
if (cx) {
MARK_PLUS;
JS_DestroyContext(cx);
} else {
MARK_DOT;
CHECK(!JSRuntime::hasLiveRuntimes());
}
END_OOM_TEST;
return true;
}
END_TEST(testNewContextOOM)
BEGIN_TEST(testHelperThreadOOM) {
const char* testName;
uint64_t oomAfter;
START_OOM_TEST("helper thread state");
if (js::CreateHelperThreadsState()) {
if (js::EnsureHelperThreadsInitialized()) {
MARK_STAR;
} else {
MARK_PLUS;
}
} else {
MARK_DOT;
}
// Reset the helper threads to ensure they get re-initalised in following
// iterations
js::DestroyHelperThreadsState();
END_OOM_TEST;
return true;
}
bool init() override {
JSAPITest::uninit(); // Discard the just-created JSContext.
js::DestroyHelperThreadsState(); // The test creates this state.
return true;
}
void uninit() override {
// Leave things initialized after this test finishes.
js::CreateHelperThreadsState();
}
END_TEST(testHelperThreadOOM)
#endif
|