| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
| * vim: set ts=8 sts=4 et sw=4 tw=99: |
| * |
| * Any copyright is dedicated to the Public Domain. |
| * http://creativecommons.org/licenses/publicdomain/ |
| * Contributor: Igor Bukanov |
| */ |
| |
| #include "jsapi-tests/tests.h" |
| |
| static unsigned errorCount = 0; |
| |
| static void |
| ErrorCounter(JSContext* cx, const char* message, JSErrorReport* report) |
| { |
| ++errorCount; |
| } |
| |
| BEGIN_TEST(testGCOutOfMemory) |
| { |
| JS_SetErrorReporter(rt, ErrorCounter); |
| |
| JS::RootedValue root(cx); |
| |
| // Count the number of allocations until we hit OOM, and store it in 'max'. |
| static const char source[] = |
| "var max = 0; (function() {" |
| " var array = [];" |
| " for (; ; ++max)" |
| " array.push({});" |
| " array = []; array.push(0);" |
| "})();"; |
| JS::CompileOptions opts(cx); |
| bool ok = JS::Evaluate(cx, opts, source, strlen(source), &root); |
| |
| /* Check that we get OOM. */ |
| CHECK(!ok); |
| CHECK(!JS_IsExceptionPending(cx)); |
| CHECK_EQUAL(errorCount, 1u); |
| JS_GC(rt); |
| |
| // The above GC should have discarded everything. Verify that we can now |
| // allocate half as many objects without OOMing. |
| EVAL("(function() {" |
| " var array = [];" |
| " for (var i = max >> 2; i != 0;) {" |
| " --i;" |
| " array.push({});" |
| " }" |
| "})();", &root); |
| CHECK_EQUAL(errorCount, 1u); |
| return true; |
| } |
| |
| virtual JSRuntime * createRuntime() override { |
| // Note that the max nursery size must be less than the whole heap size, or |
| // the test will fail because 'max' (the number of allocations required for |
| // OOM) will be based on the nursery size, and that will overflow the |
| // tenured heap, which will cause the second pass with max/4 allocations to |
| // OOM. (Actually, this only happens with nursery zeal, because normally |
| // the nursery will start out with only a single chunk before triggering a |
| // major GC.) |
| JSRuntime* rt = JS_NewRuntime(768 * 1024, 128 * 1024); |
| if (!rt) |
| return nullptr; |
| setNativeStackQuota(rt); |
| return rt; |
| } |
| |
| virtual void destroyRuntime() override { |
| JS_DestroyRuntime(rt); |
| } |
| |
| END_TEST(testGCOutOfMemory) |