Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / jsapi-tests / testGCChunkAlloc.cpp
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sw=4 et tw=99:
3  *
4  * Any copyright is dedicated to the Public Domain.
5  * http://creativecommons.org/licenses/publicdomain/
6  * Contributor: Igor Bukanov
7  */
8
9 #include "tests.h"
10 #include "jsgcchunk.h"
11 #include "jscntxt.h"
12
13 /* We allow to allocate only single chunk. */
14
15 class CustomGCChunkAllocator: public js::GCChunkAllocator {
16   public:
17     CustomGCChunkAllocator() : pool(NULL) {}
18     void *pool;
19     
20   private:
21
22     virtual void *doAlloc() {
23         if (!pool)
24             return NULL;
25         void *chunk = pool;
26         pool = NULL;
27         return chunk;
28     }
29         
30     virtual void doFree(void *chunk) {
31         JS_ASSERT(!pool);
32         pool = chunk;
33     }
34 };
35
36 static CustomGCChunkAllocator customGCChunkAllocator;
37
38 static unsigned errorCount = 0;
39
40 static void
41 ErrorCounter(JSContext *cx, const char *message, JSErrorReport *report)
42 {
43     ++errorCount;
44 }
45
46 BEGIN_TEST(testGCChunkAlloc)
47 {
48     JS_SetErrorReporter(cx, ErrorCounter);
49
50     jsvalRoot root(cx);
51
52     /*
53      * We loop until out-of-memory happens during the chunk allocation. But
54      * we have to disable the jit since it cannot tolerate OOM during the
55      * chunk allocation.
56      */
57     JS_ToggleOptions(cx, JSOPTION_JIT);
58
59     static const char source[] =
60         "var max = 0; (function() {"
61         "    var array = [];"
62         "    for (; ; ++max)"
63         "        array.push({});"
64         "})();";
65     JSBool ok = JS_EvaluateScript(cx, global, source, strlen(source), "", 1,
66                                   root.addr());
67
68     /* Check that we get OOM. */
69     CHECK(!ok);
70     CHECK(!JS_IsExceptionPending(cx));
71     CHECK(errorCount == 1);
72     CHECK(!customGCChunkAllocator.pool);
73     JS_GC(cx);
74     JS_ToggleOptions(cx, JSOPTION_JIT);
75     EVAL("(function() {"
76          "    var array = [];"
77          "    for (var i = max >> 1; i != 0;) {"
78          "        --i;"
79          "        array.push({});"
80          "    }"
81          "})();", root.addr());
82     CHECK(errorCount == 1);
83     return true;
84 }
85
86 virtual JSRuntime * createRuntime() {
87     /*
88      * To test failure of chunk allocation allow to use GC twice the memory
89      * the single chunk contains.
90      */
91     JSRuntime *rt = JS_NewRuntime(2 * js::GC_CHUNK_SIZE);
92     if (!rt)
93         return NULL;
94
95     customGCChunkAllocator.pool = js::AllocGCChunk();
96     JS_ASSERT(customGCChunkAllocator.pool);
97
98     rt->setCustomGCChunkAllocator(&customGCChunkAllocator);
99     return rt;
100 }
101
102 virtual void destroyRuntime() {
103     JS_DestroyRuntime(rt);
104
105     /* We should get the initial chunk back at this point. */
106     JS_ASSERT(customGCChunkAllocator.pool);
107     js::FreeGCChunk(customGCChunkAllocator.pool);
108     customGCChunkAllocator.pool = NULL;
109 }
110
111 END_TEST(testGCChunkAlloc)