Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / jsapi-tests / testThreads.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
5 #ifdef JS_THREADSAFE
6
7 #include "tests.h"
8 #include "prthread.h"
9
10 struct ThreadData {
11     JSRuntime *rt;
12     JSObject *obj;
13     const char *code;
14     bool ok;
15 };
16
17 BEGIN_TEST(testThreads_bug561444)
18     {
19         const char *code = "<a><b/></a>.b.@c = '';";
20         EXEC(code);
21
22         jsrefcount rc = JS_SuspendRequest(cx);
23         {
24             ThreadData data = {rt, global, code, false};
25             PRThread *thread = 
26                 PR_CreateThread(PR_USER_THREAD, threadMain, &data,
27                                 PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
28             CHECK(thread);
29             PR_JoinThread(thread);
30             CHECK(data.ok);
31         }
32         JS_ResumeRequest(cx, rc);
33         return true;
34     }
35
36     static void threadMain(void *arg) {
37         ThreadData *d = (ThreadData *) arg;
38
39         JSContext *cx = JS_NewContext(d->rt, 8192);
40         if (!cx)
41             return;
42         JS_BeginRequest(cx);
43         {
44             JSAutoEnterCompartment ac;
45             jsval v;
46             d->ok = ac.enter(cx, d->obj) &&
47                     JS_EvaluateScript(cx, d->obj, d->code, strlen(d->code), __FILE__, __LINE__,
48                                       &v);
49         }
50         JS_DestroyContext(cx);
51     }
52 END_TEST(testThreads_bug561444)
53
54 const PRUint32 NATIVE_STACK_SIZE = 64 * 1024;
55 const PRUint32 NATIVE_STACK_HEADROOM = 8 * 1024;
56
57 template <class T>
58 class Repeat {
59     size_t n;
60     const T &t;
61
62   public:
63     Repeat(size_t n, const T &t) : n(n), t(t) {}
64
65     bool operator()() const {
66         for (size_t i = 0; i < n; i++)
67             if (!t())
68                 return false;
69         return true;
70     }
71 };
72
73 template <class T> Repeat<T> repeat(size_t n, const T &t) { return Repeat<T>(n, t); }
74
75 /* Class of callable that does something in n parallel threads. */
76 template <class T>
77 class Parallel {
78     size_t n;
79     const T &t;
80
81     struct pair { const Parallel *self; bool ok; };
82
83     static void threadMain(void *arg) {
84         pair *p = (pair *) arg;
85         if (!p->self->t())
86             p->ok = false;
87     }
88
89   public:
90     Parallel(size_t n, const T &t) : n(n), t(t) {}
91
92     bool operator()() const {
93         pair p = {this, true};
94
95         PRThread **thread = new PRThread *[n];
96         if (!thread)
97             return false;
98
99         size_t i;
100         for (i = 0; i < n; i++) {
101             thread[i] = PR_CreateThread(PR_USER_THREAD, threadMain, &p, PR_PRIORITY_NORMAL,
102                                         PR_LOCAL_THREAD, PR_JOINABLE_THREAD, NATIVE_STACK_SIZE);
103             if (thread[i] == NULL) {
104                 p.ok = false;
105                 break;
106             }
107         }
108         while (i--)
109             PR_JoinThread(thread[i]);
110
111         delete[] thread;
112         return p.ok;
113     }
114 };
115
116 template <class T> Parallel<T> parallel(size_t n, const T &t) { return Parallel<T>(n, t); }
117
118 /* Class of callable that creates a compartment and runs some code in it. */
119 class eval {
120     JSRuntime *rt;
121     const char *code;
122
123   public:
124     eval(JSRuntime *rt, const char *code) : rt(rt), code(code) {}
125
126     bool operator()() const {
127         JSContext *cx = JS_NewContext(rt, 8192);
128         if (!cx)
129             return false;
130
131         JS_SetNativeStackQuota(cx, NATIVE_STACK_SIZE - NATIVE_STACK_HEADROOM);
132         bool ok = false;
133         {
134             JSAutoRequest ar(cx);
135             JSObject *global =
136                 JS_NewCompartmentAndGlobalObject(cx, JSAPITest::basicGlobalClass(), NULL);
137             if (global) {
138                 JS_SetGlobalObject(cx, global);
139                 jsval rval;
140                 ok = JS_InitStandardClasses(cx, global) &&
141                     JS_EvaluateScript(cx, global, code, strlen(code), "", 0, &rval);
142             }
143         }
144         JS_DestroyContextMaybeGC(cx);
145         return ok;
146     }
147 };
148
149 BEGIN_TEST(testThreads_bug604782)
150 {
151     jsrefcount rc = JS_SuspendRequest(cx);
152     bool ok = repeat(20, parallel(3, eval(rt, "for(i=0;i<1000;i++);")))();
153     JS_ResumeRequest(cx, rc);
154     CHECK(ok);
155     return true;
156 }
157 END_TEST(testThreads_bug604782)
158
159 BEGIN_TEST(testThreads_bug609103)
160 {
161     const char *code = 
162         "var x = {};\n"
163         "for (var i = 0; i < 10000; i++)\n"
164         "    x = {next: x};\n";
165
166     jsrefcount rc = JS_SuspendRequest(cx);
167     bool ok = parallel(2, eval(rt, code))();
168     JS_ResumeRequest(cx, rc);
169     CHECK(ok);
170     return true;
171 }
172 END_TEST(testThreads_bug609103)
173
174 #endif