1563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/* 2563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. 3563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * (C) 2007 Graham Dennis (graham.dennis@gmail.com) 4563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * (C) 2007 Eric Seidel <eric@webkit.org> 5563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 6563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Redistribution and use in source and binary forms, with or without 7563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * modification, are permitted provided that the following conditions 8563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * are met: 9563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 10563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 1. Redistributions of source code must retain the above copyright 11563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * notice, this list of conditions and the following disclaimer. 12563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 2. Redistributions in binary form must reproduce the above copyright 13563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * notice, this list of conditions and the following disclaimer in the 14563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * documentation and/or other materials provided with the distribution. 15563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 16563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * its contributors may be used to endorse or promote products derived 17563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * from this software without specific prior written permission. 18563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 19563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */ 30563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 31643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "config.h" 32563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#include "JavaScriptThreading.h" 33563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 34563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#include <CoreFoundation/CoreFoundation.h> 35563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#include <JavaScriptCore/JavaScriptCore.h> 36563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#include <pthread.h> 37563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#include <wtf/Assertions.h> 38563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#include <wtf/HashSet.h> 39563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 402fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic JSContextGroupRef javaScriptThreadsGroup; 412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 42563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkstatic pthread_mutex_t javaScriptThreadsMutex = PTHREAD_MUTEX_INITIALIZER; 43563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkstatic bool javaScriptThreadsShouldTerminate; 44563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 45563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkstatic const int javaScriptThreadsCount = 4; 46563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 47563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarktypedef HashSet<pthread_t> ThreadSet; 48563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 49563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkstatic ThreadSet* javaScriptThreads() 50563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{ 51563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark ASSERT(pthread_mutex_trylock(&javaScriptThreadsMutex) == EBUSY); 52563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark static ThreadSet staticJavaScriptThreads; 53563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return &staticJavaScriptThreads; 54563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 55563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// This function exercises JSC in a loop until javaScriptThreadsShouldTerminate 572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// becomes true or it probabilistically decides to spawn a replacement thread and exit. 58563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvoid* runJavaScriptThread(void* arg) 59563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{ 602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block static const char* const script = 61563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark "var array = [];" 622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block "for (var i = 0; i < 1024; i++) {" 63563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark " array.push(String(i));" 64563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark "}"; 65563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block pthread_mutex_lock(&javaScriptThreadsMutex); 672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block JSGlobalContextRef ctx = JSGlobalContextCreateInGroup(javaScriptThreadsGroup, 0); 682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block pthread_mutex_unlock(&javaScriptThreadsMutex); 692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block pthread_mutex_lock(&javaScriptThreadsMutex); 712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block JSStringRef scriptRef = JSStringCreateWithUTF8CString(script); 722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block pthread_mutex_unlock(&javaScriptThreadsMutex); 73563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block while (1) { 752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block pthread_mutex_lock(&javaScriptThreadsMutex); 76563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark JSValueRef exception = 0; 77563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark JSEvaluateScript(ctx, scriptRef, 0, 0, 1, &exception); 78563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark ASSERT(!exception); 792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block pthread_mutex_unlock(&javaScriptThreadsMutex); 80563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 81563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_mutex_lock(&javaScriptThreadsMutex); 822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block size_t valuesCount = 1024; 832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block JSValueRef values[valuesCount]; 842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for (size_t i = 0; i < valuesCount; ++i) 852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block values[i] = JSObjectMake(ctx, 0, 0); 862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block pthread_mutex_unlock(&javaScriptThreadsMutex); 87563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 88563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark // Check for cancellation. 892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (javaScriptThreadsShouldTerminate) 902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block goto done; 91563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 92563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark // Respawn probabilistically. 93563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (random() % 5 == 0) { 942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block pthread_mutex_lock(&javaScriptThreadsMutex); 95563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_t pthread; 96563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_create(&pthread, 0, &runJavaScriptThread, 0); 97563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_detach(pthread); 98563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark javaScriptThreads()->add(pthread); 99563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_mutex_unlock(&javaScriptThreadsMutex); 1002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block goto done; 101563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 102563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 1032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1042fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockdone: 1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block pthread_mutex_lock(&javaScriptThreadsMutex); 1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block JSStringRelease(scriptRef); 1072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block JSGarbageCollect(ctx); 1082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block JSGlobalContextRelease(ctx); 1092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block javaScriptThreads()->remove(pthread_self()); 1102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block pthread_mutex_unlock(&javaScriptThreadsMutex); 1112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return 0; 112563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 113563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 114563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvoid startJavaScriptThreads() 115563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{ 1162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block javaScriptThreadsGroup = JSContextGroupCreate(); 1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 118563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_mutex_lock(&javaScriptThreadsMutex); 119563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 120563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark for (int i = 0; i < javaScriptThreadsCount; i++) { 121563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_t pthread; 122563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_create(&pthread, 0, &runJavaScriptThread, 0); 123563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_detach(pthread); 124563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark javaScriptThreads()->add(pthread); 125563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 126563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 127563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_mutex_unlock(&javaScriptThreadsMutex); 128563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 129563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 130563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvoid stopJavaScriptThreads() 131563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{ 132563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_mutex_lock(&javaScriptThreadsMutex); 133563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 134563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark javaScriptThreadsShouldTerminate = true; 135563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 136563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_mutex_unlock(&javaScriptThreadsMutex); 137563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 138563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark while (true) { 139563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_mutex_lock(&javaScriptThreadsMutex); 140563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark int threadCount = javaScriptThreads()->size(); 141563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark pthread_mutex_unlock(&javaScriptThreadsMutex); 142563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 143563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (!threadCount) 144563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark break; 145563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark 146563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark usleep(1000); 147563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark } 148563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark} 149