blob: af3b2e1fca36b2ff421c5c1ef41e06a89911344e [file] [log] [blame]
paroga@webkit.org332bfe02013-05-09 21:35:01 +00001/*
darin@apple.com8f723292017-07-25 04:29:08 +00002 * Copyright (C) 2005-2017 Apple Inc. All rights reserved.
paroga@webkit.org332bfe02013-05-09 21:35:01 +00003 * (C) 2007 Graham Dennis (graham.dennis@gmail.com)
4 * (C) 2007 Eric Seidel <eric@webkit.org>
5 * (C) 2012 Patrick Ganstere <paroga@paroga.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
mjs@apple.com92047332014-03-15 04:08:27 +000016 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
paroga@webkit.org332bfe02013-05-09 21:35:01 +000017 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "config.h"
33#include "JavaScriptThreading.h"
34
35#include <JavaScriptCore/JavaScriptCore.h>
36#include <stdlib.h>
37#include <wtf/Assertions.h>
38#include <wtf/HashSet.h>
fpizlo@apple.com73985982015-08-18 19:31:28 +000039#include <wtf/Lock.h>
darin@apple.com8f723292017-07-25 04:29:08 +000040#include <wtf/NeverDestroyed.h>
andersca@apple.com5d79e752014-01-25 19:24:14 +000041#include <wtf/Threading.h>
42#include <wtf/ThreadingPrimitives.h>
paroga@webkit.org332bfe02013-05-09 21:35:01 +000043#include <wtf/Vector.h>
44
45static const size_t javaScriptThreadsCount = 4;
46static bool javaScriptThreadsShouldTerminate;
47static JSContextGroupRef javaScriptThreadsGroup;
utatane.tea@gmail.come71a8722018-04-05 17:22:21 +000048static Lock javaScriptThreadsLock;
paroga@webkit.org332bfe02013-05-09 21:35:01 +000049
utatane.tea@gmail.com1e94a262017-04-12 12:08:29 +000050typedef HashSet<RefPtr<Thread>> ThreadSet;
paroga@webkit.org332bfe02013-05-09 21:35:01 +000051static ThreadSet& javaScriptThreads()
52{
darin@apple.com8f723292017-07-25 04:29:08 +000053 static NeverDestroyed<ThreadSet> staticJavaScriptThreads;
utatane.tea@gmail.comd4c4a512017-12-08 01:31:10 +000054 ASSERT(!javaScriptThreadsLock.tryLock());
paroga@webkit.org332bfe02013-05-09 21:35:01 +000055 return staticJavaScriptThreads;
56}
57
58// This function exercises JSC in a loop until javaScriptThreadsShouldTerminate
59// becomes true or it probabilistically decides to spawn a replacement thread and exit.
utatane.tea@gmail.com573f09c2017-06-26 18:19:36 +000060void runJavaScriptThread()
paroga@webkit.org332bfe02013-05-09 21:35:01 +000061{
62 static const char* const script =
63 "var array = [];"
64 "for (var i = 0; i < 1024; i++) {"
65 " array.push(String(i));"
66 "}";
67
68 JSGlobalContextRef ctx;
69 {
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +000070 Locker locker { javaScriptThreadsLock };
paroga@webkit.org332bfe02013-05-09 21:35:01 +000071 ctx = JSGlobalContextCreateInGroup(javaScriptThreadsGroup, 0);
72 }
73
74 JSStringRef scriptRef;
75 {
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +000076 Locker locker { javaScriptThreadsLock };
paroga@webkit.org332bfe02013-05-09 21:35:01 +000077 scriptRef = JSStringCreateWithUTF8CString(script);
78 }
79
80 while (true) {
81 {
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +000082 Locker locker { javaScriptThreadsLock };
paroga@webkit.org332bfe02013-05-09 21:35:01 +000083 JSValueRef exception = 0;
84 JSEvaluateScript(ctx, scriptRef, 0, 0, 1, &exception);
85 ASSERT(!exception);
86 }
87
88 {
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +000089 Locker locker { javaScriptThreadsLock };
paroga@webkit.org332bfe02013-05-09 21:35:01 +000090 const size_t valuesCount = 1024;
91 JSValueRef values[valuesCount];
92 for (size_t i = 0; i < valuesCount; ++i)
93 values[i] = JSObjectMake(ctx, 0, 0);
94 }
95
96 {
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +000097 Locker locker { javaScriptThreadsLock };
paroga@webkit.org332bfe02013-05-09 21:35:01 +000098 if (javaScriptThreadsShouldTerminate)
99 break;
100 }
101
102 // Respawn probabilistically.
103 if (rand() % 5)
104 continue;
105
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +0000106 Locker locker { javaScriptThreadsLock };
utatane.tea@gmail.com1e94a262017-04-12 12:08:29 +0000107 Thread& thread = Thread::current();
108 thread.detach();
109 javaScriptThreads().remove(&thread);
utatane.tea@gmail.com573f09c2017-06-26 18:19:36 +0000110 javaScriptThreads().add(Thread::create("JavaScript Thread", &runJavaScriptThread));
paroga@webkit.org332bfe02013-05-09 21:35:01 +0000111 break;
112 }
113
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +0000114 Locker locker { javaScriptThreadsLock };
paroga@webkit.org332bfe02013-05-09 21:35:01 +0000115 JSStringRelease(scriptRef);
116 JSGarbageCollect(ctx);
117 JSGlobalContextRelease(ctx);
118}
119
120void startJavaScriptThreads()
121{
122 javaScriptThreadsGroup = JSContextGroupCreate();
123
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +0000124 Locker locker { javaScriptThreadsLock };
paroga@webkit.org332bfe02013-05-09 21:35:01 +0000125
126 for (size_t i = 0; i < javaScriptThreadsCount; ++i)
utatane.tea@gmail.com573f09c2017-06-26 18:19:36 +0000127 javaScriptThreads().add(Thread::create("JavaScript Thread", &runJavaScriptThread));
paroga@webkit.org332bfe02013-05-09 21:35:01 +0000128}
129
130void stopJavaScriptThreads()
131{
132 {
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +0000133 Locker locker { javaScriptThreadsLock };
paroga@webkit.org332bfe02013-05-09 21:35:01 +0000134 javaScriptThreadsShouldTerminate = true;
135 }
136
utatane.tea@gmail.com1e94a262017-04-12 12:08:29 +0000137 Vector<RefPtr<Thread>, javaScriptThreadsCount> threads;
paroga@webkit.org332bfe02013-05-09 21:35:01 +0000138 {
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +0000139 Locker locker { javaScriptThreadsLock };
weinig@apple.comb6e19c52017-10-12 15:38:42 +0000140 threads = copyToVector(javaScriptThreads());
paroga@webkit.org332bfe02013-05-09 21:35:01 +0000141 ASSERT(threads.size() == javaScriptThreadsCount);
142 }
143
144 for (size_t i = 0; i < javaScriptThreadsCount; ++i)
utatane.tea@gmail.com1e94a262017-04-12 12:08:29 +0000145 threads[i]->waitForCompletion();
paroga@webkit.org332bfe02013-05-09 21:35:01 +0000146
ggaren@apple.com96fea772015-01-29 00:58:13 +0000147 {
cdumez@apple.com8c8c0bd2021-05-22 04:34:08 +0000148 Locker locker { javaScriptThreadsLock };
ggaren@apple.com96fea772015-01-29 00:58:13 +0000149 javaScriptThreads().clear();
150 }
paroga@webkit.org332bfe02013-05-09 21:35:01 +0000151
152 JSContextGroupRelease(javaScriptThreadsGroup);
153}