+2008-03-05 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Darin.
+
+ Move JNI specific code from runtime_root over to jni_jsobject, where it is used.
+
+ * bridge/jni/jni_jsobject.cpp:
+ (completedJavaScriptAccess):
+ (initializeJavaScriptAccessLock):
+ (lockJavaScriptAccess):
+ (unlockJavaScriptAccess):
+ (dispatchToJavaScriptThread):
+ (performJavaScriptAccess):
+ (JavaJSObject::initializeJNIThreading):
+ (isJavaScriptThread):
+ (JavaJSObject::invoke):
+ * bridge/jni/jni_jsobject.h:
+ * bridge/runtime_root.cpp:
+ * bridge/runtime_root.h:
+ * page/mac/WebCoreFrameBridge.mm:
+ (-[WebCoreFrameBridge init]):
+
2008-03-05 Darin Adler <darin@apple.com>
Reviewed by Sam.
#define JS_LOG(formatAndArgs...) ((void)0)
#else
#define JS_LOG(formatAndArgs...) { \
- fprintf (stderr, "%s(%p,%p): ", __PRETTY_FUNCTION__, RootObject::runLoop(), CFRunLoopGetCurrent()); \
+ fprintf (stderr, "%s(%p,%p): ", __PRETTY_FUNCTION__, _performJavaScriptRunLoop, CFRunLoopGetCurrent()); \
fprintf(stderr, formatAndArgs); \
}
#endif
#define UndefinedHandle 1
+static CFRunLoopSourceRef _performJavaScriptSource;
+static CFRunLoopRef _performJavaScriptRunLoop;
+
+// May only be set by dispatchToJavaScriptThread().
+static CFRunLoopSourceRef completionSource;
+
+static void completedJavaScriptAccess (void *i)
+{
+ assert (CFRunLoopGetCurrent() != _performJavaScriptRunLoop);
+
+ JSObjectCallContext *callContext = (JSObjectCallContext *)i;
+ CFRunLoopRef runLoop = (CFRunLoopRef)callContext->originatingLoop;
+
+ assert (CFRunLoopGetCurrent() == runLoop);
+
+ CFRunLoopStop(runLoop);
+}
+
+static pthread_once_t javaScriptAccessLockOnce = PTHREAD_ONCE_INIT;
+static pthread_mutex_t javaScriptAccessLock;
+static int javaScriptAccessLockCount = 0;
+
+static void initializeJavaScriptAccessLock()
+{
+ pthread_mutexattr_t attr;
+
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+
+ pthread_mutex_init(&javaScriptAccessLock, &attr);
+}
+
+static inline void lockJavaScriptAccess()
+{
+ // Perhaps add deadlock detection?
+ pthread_once(&javaScriptAccessLockOnce, initializeJavaScriptAccessLock);
+ pthread_mutex_lock(&javaScriptAccessLock);
+ javaScriptAccessLockCount++;
+}
+
+static inline void unlockJavaScriptAccess()
+{
+ javaScriptAccessLockCount--;
+ pthread_mutex_unlock(&javaScriptAccessLock);
+}
+
+static void dispatchToJavaScriptThread(JSObjectCallContext *context)
+{
+ // This lock guarantees that only one thread can invoke
+ // at a time, and also guarantees that completionSource;
+ // won't get clobbered.
+ lockJavaScriptAccess();
+
+ CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
+
+ assert (currentRunLoop != _performJavaScriptRunLoop);
+
+ // Setup a source to signal once the invocation of the JavaScript
+ // call completes.
+ //
+ // FIXME: This could be a potential performance issue. Creating and
+ // adding run loop sources is expensive. We could create one source
+ // per thread, as needed, instead.
+ context->originatingLoop = currentRunLoop;
+ CFRunLoopSourceContext sourceContext = {0, context, NULL, NULL, NULL, NULL, NULL, NULL, NULL, completedJavaScriptAccess};
+ completionSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
+ CFRunLoopAddSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
+
+ // Wakeup JavaScript access thread and make it do it's work.
+ CFRunLoopSourceSignal(_performJavaScriptSource);
+ if (CFRunLoopIsWaiting(_performJavaScriptRunLoop))
+ CFRunLoopWakeUp(_performJavaScriptRunLoop);
+
+ // Wait until the JavaScript access thread is done.
+ CFRunLoopRun ();
+
+ CFRunLoopRemoveSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
+ CFRelease (completionSource);
+
+ unlockJavaScriptAccess();
+}
+
+static void performJavaScriptAccess(void*)
+{
+ assert (CFRunLoopGetCurrent() == _performJavaScriptRunLoop);
+
+ // Dispatch JavaScript calls here.
+ CFRunLoopSourceContext sourceContext;
+ CFRunLoopSourceGetContext (completionSource, &sourceContext);
+ JSObjectCallContext *callContext = (JSObjectCallContext *)sourceContext.info;
+ CFRunLoopRef originatingLoop = callContext->originatingLoop;
+
+ JavaJSObject::invoke (callContext);
+
+ // Signal the originating thread that we're done.
+ CFRunLoopSourceSignal (completionSource);
+ if (CFRunLoopIsWaiting(originatingLoop))
+ CFRunLoopWakeUp(originatingLoop);
+}
+
+// Must be called from the thread that will be used to access JavaScript.
+void JavaJSObject::initializeJNIThreading() {
+ // Should only be called once.
+ ASSERT(!_performJavaScriptRunLoop);
+
+ // Assume that we can retain this run loop forever. It'll most
+ // likely (always?) be the main loop.
+ _performJavaScriptRunLoop = (CFRunLoopRef)CFRetain(CFRunLoopGetCurrent());
+
+ // Setup a source the other threads can use to signal the _runLoop
+ // thread that a JavaScript call needs to be invoked.
+ CFRunLoopSourceContext sourceContext = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, performJavaScriptAccess};
+ _performJavaScriptSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
+ CFRunLoopAddSource(_performJavaScriptRunLoop, _performJavaScriptSource, kCFRunLoopDefaultMode);
+}
+
static bool isJavaScriptThread()
{
- return (RootObject::runLoop() == CFRunLoopGetCurrent());
+ return (_performJavaScriptRunLoop == CFRunLoopGetCurrent());
}
-jvalue JavaJSObject::invoke (JSObjectCallContext *context)
+jvalue JavaJSObject::invoke(JSObjectCallContext *context)
{
jvalue result;
if (!isJavaScriptThread()) {
// Send the call context to the thread that is allowed to
// call JavaScript.
- RootObject::dispatchToJavaScriptThread(context);
+ dispatchToJavaScriptThread(context);
result = context->result;
}
else {
RootObject* rootObject() const;
+ // Must be called from the thread that will be used to access JavaScript.
+ static void initializeJNIThreading();
private:
RefPtr<RootObject> _rootObject;
JSObject* _imp;
return 0;
}
-#if PLATFORM(MAC)
-
-static CFRunLoopSourceRef _performJavaScriptSource;
-static CFRunLoopRef _runLoop;
-
-// May only be set by dispatchToJavaScriptThread().
-static CFRunLoopSourceRef completionSource;
-
-static void completedJavaScriptAccess (void *i)
-{
- assert (CFRunLoopGetCurrent() != _runLoop);
-
- JSObjectCallContext *callContext = (JSObjectCallContext *)i;
- CFRunLoopRef runLoop = (CFRunLoopRef)callContext->originatingLoop;
-
- assert (CFRunLoopGetCurrent() == runLoop);
-
- CFRunLoopStop(runLoop);
-}
-
-static pthread_once_t javaScriptAccessLockOnce = PTHREAD_ONCE_INIT;
-static pthread_mutex_t javaScriptAccessLock;
-static int javaScriptAccessLockCount = 0;
-
-static void initializeJavaScriptAccessLock()
-{
- pthread_mutexattr_t attr;
-
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
-
- pthread_mutex_init(&javaScriptAccessLock, &attr);
-}
-
-static inline void lockJavaScriptAccess()
-{
- // Perhaps add deadlock detection?
- pthread_once(&javaScriptAccessLockOnce, initializeJavaScriptAccessLock);
- pthread_mutex_lock(&javaScriptAccessLock);
- javaScriptAccessLockCount++;
-}
-
-static inline void unlockJavaScriptAccess()
-{
- javaScriptAccessLockCount--;
- pthread_mutex_unlock(&javaScriptAccessLock);
-}
-
-void RootObject::dispatchToJavaScriptThread(JSObjectCallContext *context)
-{
- // This lock guarantees that only one thread can invoke
- // at a time, and also guarantees that completionSource;
- // won't get clobbered.
- lockJavaScriptAccess();
-
- CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
-
- assert (currentRunLoop != _runLoop);
-
- // Setup a source to signal once the invocation of the JavaScript
- // call completes.
- //
- // FIXME: This could be a potential performance issue. Creating and
- // adding run loop sources is expensive. We could create one source
- // per thread, as needed, instead.
- context->originatingLoop = currentRunLoop;
- CFRunLoopSourceContext sourceContext = {0, context, NULL, NULL, NULL, NULL, NULL, NULL, NULL, completedJavaScriptAccess};
- completionSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
- CFRunLoopAddSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
-
- // Wakeup JavaScript access thread and make it do it's work.
- CFRunLoopSourceSignal(_performJavaScriptSource);
- if (CFRunLoopIsWaiting(_runLoop))
- CFRunLoopWakeUp(_runLoop);
-
- // Wait until the JavaScript access thread is done.
- CFRunLoopRun ();
-
- CFRunLoopRemoveSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
- CFRelease (completionSource);
-
- unlockJavaScriptAccess();
-}
-
-static void performJavaScriptAccess(void*)
-{
- assert (CFRunLoopGetCurrent() == _runLoop);
-
- // Dispatch JavaScript calls here.
- CFRunLoopSourceContext sourceContext;
- CFRunLoopSourceGetContext (completionSource, &sourceContext);
- JSObjectCallContext *callContext = (JSObjectCallContext *)sourceContext.info;
- CFRunLoopRef originatingLoop = callContext->originatingLoop;
-
- JavaJSObject::invoke (callContext);
-
- // Signal the originating thread that we're done.
- CFRunLoopSourceSignal (completionSource);
- if (CFRunLoopIsWaiting(originatingLoop))
- CFRunLoopWakeUp(originatingLoop);
-}
-
-CFRunLoopRef RootObject::runLoop()
-{
- return _runLoop;
-}
-
-// Must be called from the thread that will be used to access JavaScript.
-void RootObject::initializeJNIThreading() {
- // Should only be called once.
- ASSERT(!_runLoop);
-
- // Assume that we can retain this run loop forever. It'll most
- // likely (always?) be the main loop.
- _runLoop = (CFRunLoopRef)CFRetain (CFRunLoopGetCurrent());
-
- // Setup a source the other threads can use to signal the _runLoop
- // thread that a JavaScript call needs to be invoked.
- CFRunLoopSourceContext sourceContext = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, performJavaScriptAccess};
- _performJavaScriptSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
- CFRunLoopAddSource(_runLoop, _performJavaScriptSource, kCFRunLoopDefaultMode);
-}
-
-#endif
-
PassRefPtr<RootObject> RootObject::create(const void* nativeHandle, JSGlobalObject* globalObject)
{
return adoptRef(new RootObject(nativeHandle, globalObject));
const void* nativeHandle() const;
JSGlobalObject* globalObject() const;
-#if PLATFORM(MAC)
- // Must be called from the thread that will be used to access JavaScript.
- static void initializeJNIThreading();
-
- static CFRunLoopRef runLoop();
- static void dispatchToJavaScriptThread(JSObjectCallContext *context);
-#endif
-
void addRuntimeObject(RuntimeObjectImp*);
void removeRuntimeObject(RuntimeObjectImp*);
private:
#import "visible_units.h"
#import <JavaScriptCore/array_instance.h>
#import <JavaScriptCore/date_object.h>
+#import "jni_jsobject.h"
#import "runtime_root.h"
#import "runtime.h"
#import <OpenScripting/ASRegistry.h>
using KJS::UndefinedType;
using KJS::UnspecifiedType;
-using KJS::Bindings::RootObject;
+using KJS::Bindings::JavaJSObject;
static pthread_t mainThread = 0;
initializedKJS = true;
mainThread = pthread_self();
- RootObject::initializeJNIThreading();
+ JavaJSObject::initializeJNIThreading();
KJS::Bindings::Instance::setDidExecuteFunction(updateRenderingForBindings);
}