diff options
Diffstat (limited to 'Tools/DumpRenderTree/JavaScriptThreading.cpp')
-rw-r--r-- | Tools/DumpRenderTree/JavaScriptThreading.cpp | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/Tools/DumpRenderTree/JavaScriptThreading.cpp b/Tools/DumpRenderTree/JavaScriptThreading.cpp new file mode 100644 index 000000000..e2f9bade6 --- /dev/null +++ b/Tools/DumpRenderTree/JavaScriptThreading.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * (C) 2012 Patrick Ganstere <paroga@paroga.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JavaScriptThreading.h" + +#include <JavaScriptCore/JavaScriptCore.h> +#include <stdlib.h> +#include <wtf/Assertions.h> +#include <wtf/HashSet.h> +#include <wtf/Lock.h> +#include <wtf/Threading.h> +#include <wtf/ThreadingPrimitives.h> +#include <wtf/Vector.h> + +static const size_t javaScriptThreadsCount = 4; +static bool javaScriptThreadsShouldTerminate; +static JSContextGroupRef javaScriptThreadsGroup; + +static Lock& javaScriptThreadsMutex() +{ + DEPRECATED_DEFINE_STATIC_LOCAL(Lock, staticMutex, ()); + return staticMutex; +} + +typedef HashSet<ThreadIdentifier> ThreadSet; +static ThreadSet& javaScriptThreads() +{ + DEPRECATED_DEFINE_STATIC_LOCAL(ThreadSet, staticJavaScriptThreads, ()); + ASSERT(!javaScriptThreadsMutex().tryLock()); + return staticJavaScriptThreads; +} + +// This function exercises JSC in a loop until javaScriptThreadsShouldTerminate +// becomes true or it probabilistically decides to spawn a replacement thread and exit. +void runJavaScriptThread(void*) +{ + static const char* const script = + "var array = [];" + "for (var i = 0; i < 1024; i++) {" + " array.push(String(i));" + "}"; + + JSGlobalContextRef ctx; + { + LockHolder locker(javaScriptThreadsMutex()); + ctx = JSGlobalContextCreateInGroup(javaScriptThreadsGroup, 0); + } + + JSStringRef scriptRef; + { + LockHolder locker(javaScriptThreadsMutex()); + scriptRef = JSStringCreateWithUTF8CString(script); + } + + while (true) { + { + LockHolder locker(javaScriptThreadsMutex()); + JSValueRef exception = 0; + JSEvaluateScript(ctx, scriptRef, 0, 0, 1, &exception); + ASSERT(!exception); + } + + { + LockHolder locker(javaScriptThreadsMutex()); + const size_t valuesCount = 1024; + JSValueRef values[valuesCount]; + for (size_t i = 0; i < valuesCount; ++i) + values[i] = JSObjectMake(ctx, 0, 0); + } + + { + LockHolder locker(javaScriptThreadsMutex()); + if (javaScriptThreadsShouldTerminate) + break; + } + + // Respawn probabilistically. + if (rand() % 5) + continue; + + LockHolder locker(javaScriptThreadsMutex()); + ThreadIdentifier thread = currentThread(); + detachThread(thread); + javaScriptThreads().remove(thread); + javaScriptThreads().add(createThread(&runJavaScriptThread, 0, 0)); + break; + } + + LockHolder locker(javaScriptThreadsMutex()); + JSStringRelease(scriptRef); + JSGarbageCollect(ctx); + JSGlobalContextRelease(ctx); +} + +void startJavaScriptThreads() +{ + javaScriptThreadsGroup = JSContextGroupCreate(); + + LockHolder locker(javaScriptThreadsMutex()); + + for (size_t i = 0; i < javaScriptThreadsCount; ++i) + javaScriptThreads().add(createThread(&runJavaScriptThread, 0, 0)); +} + +void stopJavaScriptThreads() +{ + { + LockHolder locker(javaScriptThreadsMutex()); + javaScriptThreadsShouldTerminate = true; + } + + Vector<ThreadIdentifier, javaScriptThreadsCount> threads; + { + LockHolder locker(javaScriptThreadsMutex()); + copyToVector(javaScriptThreads(), threads); + ASSERT(threads.size() == javaScriptThreadsCount); + } + + for (size_t i = 0; i < javaScriptThreadsCount; ++i) + waitForThreadCompletion(threads[i]); + + { + LockHolder locker(javaScriptThreadsMutex()); + javaScriptThreads().clear(); + } + + JSContextGroupRelease(javaScriptThreadsGroup); +} |