tor-browser

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

testGCOutOfMemory.cpp (2557B)


      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 * Any copyright is dedicated to the Public Domain.
      5 * http://creativecommons.org/licenses/publicdomain/
      6 * Contributor: Igor Bukanov
      7 */
      8 
      9 #include "mozilla/Utf8.h"  // mozilla::Utf8Unit
     10 
     11 #include "gc/GCEnum.h"                    // js::gc::ZealMode
     12 #include "js/CompilationAndEvaluation.h"  // JS::Evaluate
     13 #include "js/SourceText.h"                // JS::Source{Ownership,Text}
     14 #include "jsapi-tests/tests.h"
     15 
     16 BEGIN_TEST(testGCOutOfMemory) {
     17  // Count the number of allocations until we hit OOM, and store it in 'max'.
     18  static const char source[] =
     19      "var max = 0; (function() {"
     20      "    var array = [];"
     21      "    for (; ; ++max)"
     22      "        array.push({});"
     23      "    array = []; array.push(0);"
     24      "})();";
     25 
     26  JS::CompileOptions opts(cx);
     27 
     28  JS::SourceText<mozilla::Utf8Unit> srcBuf;
     29  CHECK(srcBuf.init(cx, source, strlen(source), JS::SourceOwnership::Borrowed));
     30 
     31  JS::RootedValue root(cx);
     32  bool ok = JS::Evaluate(cx, opts, srcBuf, &root);
     33 
     34  /* Check that we get OOM. */
     35  CHECK(!ok);
     36  CHECK(JS_GetPendingException(cx, &root));
     37  CHECK(root.isString());
     38  bool match = false;
     39  CHECK(JS_StringEqualsLiteral(cx, root.toString(), "out of memory", &match));
     40  CHECK(match);
     41  JS_ClearPendingException(cx);
     42 
     43  JS_GC(cx);
     44 
     45  // The above GC should have discarded everything. Verify that we can now
     46  // allocate half as many objects without OOMing.
     47  EVAL(
     48      "(function() {"
     49      "    var array = [];"
     50      "    for (var i = max >> 2; i != 0;) {"
     51      "        --i;"
     52      "        array.push({});"
     53      "    }"
     54      "})();",
     55      &root);
     56  CHECK(!JS_IsExceptionPending(cx));
     57  return true;
     58 }
     59 
     60 virtual JSContext* createContext() override {
     61  // Note that the max nursery size must be less than the whole heap size, or
     62  // the test will fail because 'max' (the number of allocations required for
     63  // OOM) will be based on the nursery size, and that will overflow the
     64  // tenured heap, which will cause the second pass with max/4 allocations to
     65  // OOM. (Actually, this only happens with nursery zeal, because normally
     66  // the nursery will start out with only a single chunk before triggering a
     67  // major GC.)
     68  JSContext* cx = JS_NewContext(4 * 1024 * 1024);
     69  if (!cx) {
     70    return nullptr;
     71  }
     72  JS_SetGCParameter(cx, JSGC_MAX_NURSERY_BYTES, js::gc::ChunkSize);
     73 #ifdef JS_GC_ZEAL
     74  JS::UnsetGCZeal(cx, uint8_t(js::gc::ZealMode::GenerationalGC));
     75 #endif
     76  return cx;
     77 }
     78 
     79 END_TEST(testGCOutOfMemory)