JavaScriptCore:
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Mar 2008 01:00:15 +0000 (01:00 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Mar 2008 01:00:15 +0000 (01:00 +0000)
2008-03-19  Sam Weinig  <sam@webkit.org>

        Reviewed by Anders Carlsson.

        Fix for <rdar://problem/5785694>
        Crash occurs at KJS::Collector::collect() when loading web clip widgets with a PAC file

        Make the activeExecStates stack per JSGlobalObject instead of static to ensure
        thread safety.

        * JavaScriptCore.exp:
        * kjs/ExecState.cpp:
        (KJS::InterpreterExecState::InterpreterExecState):
        (KJS::InterpreterExecState::~InterpreterExecState):
        (KJS::EvalExecState::EvalExecState):
        (KJS::EvalExecState::~EvalExecState):
        (KJS::FunctionExecState::FunctionExecState):
        (KJS::FunctionExecState::~FunctionExecState):
        * kjs/ExecState.h:
        (KJS::):
        * kjs/JSGlobalObject.cpp:
        (KJS::JSGlobalObject::mark):
        * kjs/JSGlobalObject.h:
        (KJS::JSGlobalObject::activeExecStates):
        * kjs/collector.cpp:
        (KJS::Collector::collect):
        (KJS::Collector::reportOutOfMemoryToAllExecStates): Iterate all JSGlobalObjects and report
        the OutOfMemory condition to all the ExecStates in each.

WebCore:

2008-03-19  Sam Weinig  <sam@webkit.org>

        Reviewed by Anders Carlsson.

        Fix for <rdar://problem/5785694>
        Crash occurs at KJS::Collector::collect() when loading web clip widgets with a PAC file

        Make the activeExecStates stack per JSGlobalObject instead of static to ensure
        thread safety.

        * bindings/objc/WebScriptObject.mm:
        (+[WebScriptObject throwException:]): Change to throw an exception on the current
        GlobalObject instead of the top of the static activeExecStates stack.
        (-[WebScriptObject setException:]): Change to use the top of the rootObjects GlobalObject
        instead of the top of the static activeExecStates stack.

        * bridge/c/c_instance.cpp:
        * bridge/c/c_instance.h:
        * bridge/jni/jni_instance.cpp:
        (JavaInstance::virtualBegin):
        (JavaInstance::virtualEnd):
        * bridge/jni/jni_instance.h:
        * bridge/objc/objc_instance.h:
        * bridge/objc/objc_instance.mm:
        (ObjcInstance::~ObjcInstance):
        (ObjcInstance::virtualBegin):
        (ObjcInstance::virtualEnd):
        * bridge/runtime.cpp:
        (KJS::Bindings::Instance::setDidExecuteFunction):
        (KJS::Bindings::Instance::didExecuteFunction):
        (KJS::Bindings::Instance::setCurrentGlobalObject): Added.
        (KJS::Bindings::Instance::currentGlobalObject): Added.
        (KJS::Bindings::Instance::begin):
        (KJS::Bindings::Instance::end):
        * bridge/runtime.h:
        (KJS::Bindings::Instance::virtualBegin): Renamed from begin().
        (KJS::Bindings::Instance::virtualEnd): Renamed from end().
        We now store the currently active globalObject everytime we cross the runtime
        object boundary.  To do this, we take advantage of the existing begin/end
        methods that are called when crossing this boundary, making begin set the current
        globalObject and then call the old begin, now called virtualBegin.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@31167 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/kjs/ExecState.cpp
JavaScriptCore/kjs/ExecState.h
JavaScriptCore/kjs/JSGlobalObject.cpp
JavaScriptCore/kjs/JSGlobalObject.h
JavaScriptCore/kjs/collector.cpp
WebCore/ChangeLog
WebCore/bindings/objc/WebScriptObject.mm
WebCore/bridge/c/c_instance.cpp
WebCore/bridge/c/c_instance.h
WebCore/bridge/jni/jni_instance.cpp
WebCore/bridge/jni/jni_instance.h
WebCore/bridge/objc/objc_instance.h
WebCore/bridge/objc/objc_instance.mm
WebCore/bridge/runtime.cpp
WebCore/bridge/runtime.h

index cf4c0bcc78a57f87cb5dd0cb7c8e3e46866866fe..1fcfe326beebcb3be987a7666ddbf44748d96475 100644 (file)
@@ -1,3 +1,32 @@
+2008-03-19  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Anders Carlsson.
+
+        Fix for <rdar://problem/5785694>
+        Crash occurs at KJS::Collector::collect() when loading web clip widgets with a PAC file
+
+        Make the activeExecStates stack per JSGlobalObject instead of static to ensure
+        thread safety.
+
+        * JavaScriptCore.exp:
+        * kjs/ExecState.cpp:
+        (KJS::InterpreterExecState::InterpreterExecState):
+        (KJS::InterpreterExecState::~InterpreterExecState):
+        (KJS::EvalExecState::EvalExecState):
+        (KJS::EvalExecState::~EvalExecState):
+        (KJS::FunctionExecState::FunctionExecState):
+        (KJS::FunctionExecState::~FunctionExecState):
+        * kjs/ExecState.h:
+        (KJS::):
+        * kjs/JSGlobalObject.cpp:
+        (KJS::JSGlobalObject::mark):
+        * kjs/JSGlobalObject.h:
+        (KJS::JSGlobalObject::activeExecStates):
+        * kjs/collector.cpp:
+        (KJS::Collector::collect):
+        (KJS::Collector::reportOutOfMemoryToAllExecStates): Iterate all JSGlobalObjects and report
+        the OutOfMemory condition to all the ExecStates in each.
+
 2008-03-19  Jasper Bryant-Greene  <jasper@unix.geek.nz>
 
         Reviewed by Maciej Stachowiak.
index 3f99280e03fcd478fa639cd87254298374749bf1..4d8d43495e4b001103039601ac2d19822a8563a4 100644 (file)
@@ -197,7 +197,6 @@ __ZN3KJS9Collector4sizeEv
 __ZN3KJS9Collector7collectEv
 __ZN3KJS9Collector7protectEPNS_7JSValueE
 __ZN3KJS9Collector9unprotectEPNS_7JSValueE
-__ZN3KJS9ExecState16activeExecStatesEv
 __ZN3KJSeqERKNS_7UStringEPKc
 __ZN3WTF10fastCallocEmm
 __ZN3WTF10fastMallocEm
index 9ae6ecc2c9c32aa0c7a7b9f8a33143053c863c3d..3a7a5e90519bd3f5076108a06de7b6f8069164ef 100644 (file)
@@ -144,24 +144,6 @@ JSGlobalObject* ExecState::lexicalGlobalObject() const
     return m_globalObject;
 }
 
-void ExecState::markActiveExecStates() 
-{
-    ExecStateStack::const_iterator end = activeExecStates().end();
-    for (ExecStateStack::const_iterator it = activeExecStates().begin(); it != end; ++it)
-        (*it)->m_scopeChain.mark();
-}
-
-static inline ExecStateStack& inlineActiveExecStates()
-{
-    static ExecStateStack staticActiveExecStates;
-    return staticActiveExecStates;
-}
-
-ExecStateStack& ExecState::activeExecStates()
-{
-    return inlineActiveExecStates();
-}
-
 GlobalExecState::GlobalExecState(JSGlobalObject* globalObject)
     : ExecState(globalObject)
 {
@@ -174,25 +156,25 @@ GlobalExecState::~GlobalExecState()
 InterpreterExecState::InterpreterExecState(JSGlobalObject* globalObject, JSObject* thisObject, ProgramNode* programNode)
     : ExecState(globalObject, thisObject, programNode)
 {
-    inlineActiveExecStates().append(this);
+    m_globalObject->activeExecStates().append(this);
 }
 
 InterpreterExecState::~InterpreterExecState()
 {
-    ASSERT(inlineActiveExecStates().last() == this);
-    inlineActiveExecStates().removeLast();
+    ASSERT(m_globalObject->activeExecStates().last() == this);
+    m_globalObject->activeExecStates().removeLast();
 }
 
 EvalExecState::EvalExecState(JSGlobalObject* globalObject, JSObject* thisObj, EvalNode* evalNode, ExecState* callingExec, const ScopeChain& scopeChain, JSVariableObject* variableObject)
     : ExecState(globalObject, thisObj, evalNode, callingExec, scopeChain, variableObject)
 {
-    inlineActiveExecStates().append(this);
+    m_globalObject->activeExecStates().append(this);
 }
 
 EvalExecState::~EvalExecState()
 {
-    ASSERT(inlineActiveExecStates().last() == this);
-    inlineActiveExecStates().removeLast();
+    ASSERT(m_globalObject->activeExecStates().last() == this);
+    m_globalObject->activeExecStates().removeLast();
 }
 
 FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thisObject, 
@@ -200,13 +182,13 @@ FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thi
          FunctionImp* func, const List& args)
     : ExecState(globalObject, thisObject, functionBodyNode, callingExec, func, args)
 {
-    inlineActiveExecStates().append(this);
+    m_globalObject->activeExecStates().append(this);
 }
 
 FunctionExecState::~FunctionExecState()
 {
-    ASSERT(inlineActiveExecStates().last() == this);
-    inlineActiveExecStates().removeLast();
+    ASSERT(m_globalObject->activeExecStates().last() == this);
+    m_globalObject->activeExecStates().removeLast();
 
     if (m_activation->needsPop())
         m_globalObject->popActivation();
index 144aebfc018d3079930ab627b2c050593345fcd1..4220a21b5d9cf9ca8df66e217692a384a7fb9283 100644 (file)
@@ -45,12 +45,11 @@ namespace KJS  {
     class ScopeNode;
     
     enum CodeType { GlobalCode, EvalCode, FunctionCode };
-    
-    typedef Vector<ExecState*, 16> ExecStateStack;
 
     // Represents the current state of script execution.
     // Passed as the first argument to most functions.
     class ExecState : Noncopyable {
+        friend class JSGlobalObject;
     public:
         // Global object that was in scope when the current script started executing.
         JSGlobalObject* dynamicGlobalObject() const { return m_globalObject; }
@@ -164,9 +163,6 @@ namespace KJS  {
             return 0;
         }
 
-        static void markActiveExecStates();
-        static ExecStateStack& activeExecStates();
-
     protected:
         ExecState(JSGlobalObject*);
         ExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
index 9fb71bfa98c9e65f4638bce9c0e9cdb48a29e8e9..03765efb590fdb899fbcead62ad15d25324a80d5 100644 (file)
@@ -483,6 +483,10 @@ void JSGlobalObject::mark()
 {
     JSVariableObject::mark();
 
+    ExecStateStack::const_iterator end = d()->activeExecStates.end();
+    for (ExecStateStack::const_iterator it = d()->activeExecStates.begin(); it != end; ++it)
+        (*it)->m_scopeChain.mark();
+
     markIfNeeded(d()->globalExec.exception());
 
     markIfNeeded(d()->objectConstructor);
index 0c0ece60e1fa18ea0f921f0fd38cc6938a2afce6..b421bcd6e83f484075603db3dbd18af0bc2b0698 100644 (file)
@@ -68,6 +68,8 @@ namespace KJS {
     class UriErrorPrototype;
     struct ActivationStackNode;
 
+    typedef Vector<ExecState*, 16> ExecStateStack;
+
     class JSGlobalObject : public JSVariableObject {
     protected:
         using JSVariableObject::JSVariableObjectData;
@@ -130,6 +132,8 @@ namespace KJS {
             
             SymbolTable inlineSymbolTable;
 
+            ExecStateStack activeExecStates;
+
             ActivationStackNode* activations;
             size_t activationCount;
         };
@@ -233,6 +237,8 @@ namespace KJS {
 
         virtual bool isDynamicScope() const;
 
+        ExecStateStack& activeExecStates() const { return d()->activeExecStates; }
+
     private:
         void init();
         
index 23b93dfab51dce26354007f25b9e8992857a2bef..6466de19f4ce62d12eb2eeb71645a7b97d85b2ad 100644 (file)
@@ -935,7 +935,6 @@ bool Collector::collect()
 
   markStackObjectsConservatively();
   markProtectedObjects();
-  ExecState::markActiveExecStates();
   List::markProtectedLists();
 #if USE(MULTIPLE_THREADS)
   if (!currentThreadIsMainThread)
@@ -1045,10 +1044,16 @@ bool Collector::isBusy()
 
 void Collector::reportOutOfMemoryToAllExecStates()
 {
-    ExecStateStack::const_iterator end = ExecState::activeExecStates().end();
-    for (ExecStateStack::const_iterator it = ExecState::activeExecStates().begin(); it != end; ++it) {
-        (*it)->setException(Error::create(*it, GeneralError, "Out of memory"));
-    }
+    if (!JSGlobalObject::head())
+        return;
+
+    JSGlobalObject* globalObject = JSGlobalObject::head();
+    do {
+        ExecStateStack::const_iterator end = globalObject->activeExecStates().end();
+        for (ExecStateStack::const_iterator it = globalObject->activeExecStates().begin(); it != end; ++it)
+            (*it)->setException(Error::create(*it, GeneralError, "Out of memory"));
+        globalObject = globalObject->next();
+    } while (globalObject != JSGlobalObject::head());
 }
 
 } // namespace KJS
index 4be6c0cad0e187f0111a40d9da54e519b8fda563..b832b034a20ca949d2b0a038830008693e121042 100644 (file)
@@ -1,3 +1,45 @@
+2008-03-19  Sam Weinig  <sam@webkit.org>
+
+        Reviewed by Anders Carlsson.
+
+        Fix for <rdar://problem/5785694>
+        Crash occurs at KJS::Collector::collect() when loading web clip widgets with a PAC file
+
+        Make the activeExecStates stack per JSGlobalObject instead of static to ensure
+        thread safety.
+
+        * bindings/objc/WebScriptObject.mm:
+        (+[WebScriptObject throwException:]): Change to throw an exception on the current
+        GlobalObject instead of the top of the static activeExecStates stack.
+        (-[WebScriptObject setException:]): Change to use the top of the rootObjects GlobalObject
+        instead of the top of the static activeExecStates stack.
+
+        * bridge/c/c_instance.cpp:
+        * bridge/c/c_instance.h:
+        * bridge/jni/jni_instance.cpp:
+        (JavaInstance::virtualBegin):
+        (JavaInstance::virtualEnd):
+        * bridge/jni/jni_instance.h:
+        * bridge/objc/objc_instance.h:
+        * bridge/objc/objc_instance.mm:
+        (ObjcInstance::~ObjcInstance):
+        (ObjcInstance::virtualBegin):
+        (ObjcInstance::virtualEnd):
+        * bridge/runtime.cpp:
+        (KJS::Bindings::Instance::setDidExecuteFunction):
+        (KJS::Bindings::Instance::didExecuteFunction):
+        (KJS::Bindings::Instance::setCurrentGlobalObject): Added.
+        (KJS::Bindings::Instance::currentGlobalObject): Added.
+        (KJS::Bindings::Instance::begin):
+        (KJS::Bindings::Instance::end):
+        * bridge/runtime.h:
+        (KJS::Bindings::Instance::virtualBegin): Renamed from begin().
+        (KJS::Bindings::Instance::virtualEnd): Renamed from end().
+        We now store the currently active globalObject everytime we cross the runtime
+        object boundary.  To do this, we take advantage of the existing begin/end
+        methods that are called when crossing this boundary, making begin set the current
+        globalObject and then call the old begin, now called virtualBegin.
+
 2008-03-19  Brady Eidson  <beidson@apple.com>
 
         Reviewed by Anders
index ffeac8360daf1a194c696855c7e174dd25c19f1c..b39cb398d2b866d5a1831fd1411558e75fbf9345 100644 (file)
@@ -250,17 +250,16 @@ static void _didExecute(WebScriptObject *obj)
 + (BOOL)throwException:(NSString *)exceptionMessage
 {
     JSLock lock;
-    
-    // This code assumes that we only ever have one running interpreter.  A
-    // good assumption for now, as we depend on that elsewhere.  However,
-    // in the future we may have the ability to run multiple interpreters,
-    // in which case this will have to change.
-    
-    if (ExecState::activeExecStates().size()) {
-        throwError(ExecState::activeExecStates().last(), GeneralError, exceptionMessage);
+
+    JSGlobalObject* globalObject = Instance::currentGlobalObject();
+    if (!globalObject)
+        return NO;
+
+    if (globalObject->activeExecStates().size()) {
+        throwError(globalObject->activeExecStates().last(), GeneralError, exceptionMessage);
         return YES;
     }
-    
+
     return NO;
 }
 
@@ -498,12 +497,13 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root
     JSLock lock;
 
     ExecState* exec = 0;
-    JSObject* globalObject = [self _rootObject]->globalObject();
-    ExecStateStack::const_iterator end = ExecState::activeExecStates().end();
-    for (ExecStateStack::const_iterator it = ExecState::activeExecStates().begin(); it != end; ++it)
+    JSGlobalObject* globalObject = [self _rootObject]->globalObject();
+    ExecStateStack::const_iterator end = globalObject->activeExecStates().end();
+    for (ExecStateStack::const_iterator it = globalObject->activeExecStates().begin(); it != end; ++it) {
         if ((*it)->dynamicGlobalObject() == globalObject)
             exec = *it;
-            
+    }
+
     if (exec)
         throwError(exec, GeneralError, description);
 }
index abcc090e772b535086ed4cf98268cc3dcc9ff5b0..3907f67ff17f0b2ec2f894d49f8ee1037236e228 100644 (file)
@@ -62,16 +62,6 @@ Class *CInstance::getClass() const
     return _class;
 }
 
-void CInstance::begin()
-{
-    // Do nothing.
-}
-
-void CInstance::end()
-{
-    // Do nothing.
-}
-
 bool CInstance::implementsCall() const
 {
     return (_object->_class->invokeDefault != 0);
index 4b1614f0ecc399eb8a4210649c1fb4c9be57b2b1..0397a934e6945dc5a05ef9c39aee93ec5e48b82d 100644 (file)
@@ -49,10 +49,7 @@ public:
     ~CInstance ();
     
     virtual Class *getClass() const;
-    
-    virtual void begin();
-    virtual void end();
-    
+
     virtual JSValue *valueOf() const;
     virtual JSValue *defaultValue (JSType hint) const;
 
index db1847c3105c2f738f70e9398ffbe0282d7f9deb..a198c5dadbbc0c462e2b291a1592c7bb813bd618 100644 (file)
@@ -60,12 +60,12 @@ JavaInstance::~JavaInstance ()
 
 #define NUM_LOCAL_REFS 64
 
-void JavaInstance::begin()
+void JavaInstance::virtualBegin()
 {
     getJNIEnv()->PushLocalFrame (NUM_LOCAL_REFS);
 }
 
-void JavaInstance::end()
+void JavaInstance::virtualEnd()
 {
     getJNIEnv()->PopLocalFrame (NULL);
 }
index cf8864f7d05526ddf25962c1641e27416419790f..366adcdeb19455bebcd3a420efc5a0b825758b80 100644 (file)
@@ -77,9 +77,6 @@ public:
     
     virtual Class *getClass() const;
     
-    virtual void begin();
-    virtual void end();
-    
     virtual JSValue *valueOf() const;
     virtual JSValue *defaultValue (JSType hint) const;
 
@@ -93,9 +90,13 @@ public:
 
     virtual BindingLanguage getBindingLanguage() const { return JavaLanguage; }
 
+protected:
+    virtual void virtualBegin();
+    virtual void virtualEnd();
+
 private:
     JavaInstance(jobject instance, PassRefPtr<RootObject>);
-    
+
     RefPtr<JObjectWrapper> _instance;
     mutable JavaClass *_class;
 };
index ec66004aa221dd31627d06a3c30818d8aac2ea78..6039232af3da5e5cd27defcce4c0ffe7e1b4d454 100644 (file)
@@ -45,10 +45,7 @@ public:
     ~ObjcInstance();
     
     virtual Class *getClass() const;
-    
-    virtual void begin();
-    virtual void end();
-    
+        
     virtual JSValue *valueOf() const;
     virtual JSValue *defaultValue(JSType hint) const;
 
@@ -70,6 +67,10 @@ public:
 
     virtual BindingLanguage getBindingLanguage() const { return ObjectiveCLanguage; }
 
+protected:
+    virtual void virtualBegin();
+    virtual void virtualEnd();
+
 private:
     ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject>);
     
index 57ebfe81d2cc4debff7760d1581ee968c8735d54..589b935060cc13912f3072d85f36af79cab1d7ed 100644 (file)
@@ -52,21 +52,22 @@ ObjcInstance::ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject> root
 
 ObjcInstance::~ObjcInstance() 
 {
-    begin(); // -finalizeForWebScript and -dealloc/-finalize may require autorelease pools.
+    // -finalizeForWebScript and -dealloc/-finalize may require autorelease pools.
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
     if ([_instance.get() respondsToSelector:@selector(finalizeForWebScript)])
         [_instance.get() performSelector:@selector(finalizeForWebScript)];
     _instance = 0;
-    end();
+    [pool drain];
 }
 
-void ObjcInstance::begin()
+void ObjcInstance::virtualBegin()
 {
     if (!_pool)
         _pool = [[NSAutoreleasePool alloc] init];
     _beginCount++;
 }
 
-void ObjcInstance::end()
+void ObjcInstance::virtualEnd()
 {
     _beginCount--;
     ASSERT(_beginCount >= 0);
index 5abcc6eec06678e5a1776d8b9e477885cb3bad55..c75199e09d34571f04e2ec3fc02ca60c1219ee1d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003, 2006 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -55,10 +55,40 @@ Instance::~Instance()
 {
 }
 
-static KJSDidExecuteFunctionPtr _DidExecuteFunction;
+static KJSDidExecuteFunctionPtr s_didExecuteFunction;
 
-void Instance::setDidExecuteFunction(KJSDidExecuteFunctionPtr func) { _DidExecuteFunction = func; }
-KJSDidExecuteFunctionPtr Instance::didExecuteFunction() { return _DidExecuteFunction; }
+void Instance::setDidExecuteFunction(KJSDidExecuteFunctionPtr func)
+{
+    s_didExecuteFunction = func;
+}
+
+KJSDidExecuteFunctionPtr Instance::didExecuteFunction()
+{
+    return s_didExecuteFunction;
+}
+
+static JSGlobalObject* s_currentGlobalObject;
+
+void Instance::setCurrentGlobalObject(JSGlobalObject* globalObject)
+{
+    s_currentGlobalObject = globalObject;
+}
+
+JSGlobalObject* Instance::currentGlobalObject()
+{
+    return s_currentGlobalObject;
+}
+
+void Instance::begin()
+{
+    setCurrentGlobalObject(_rootObject && _rootObject->isValid() ? _rootObject->globalObject() : 0);
+    virtualBegin();
+}
+
+void Instance::end()
+{
+    virtualEnd();
+}
 
 JSValue *Instance::getValueOfField(ExecState *exec, const Field *aField) const
 {
index 8df88bc3f757538c15505fb57c3f83865abca107..8a85f915fb77e720467a101efc15bf8c867db7d9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,6 +35,7 @@
 namespace KJS  {
 
 class Identifier;
+class JSGlobalObject;
 class List;
 class PropertyNameArray;
 
@@ -102,15 +103,18 @@ public:
 
     static void setDidExecuteFunction(KJSDidExecuteFunctionPtr func);
     static KJSDidExecuteFunctionPtr didExecuteFunction();
-    
+
+    static void setCurrentGlobalObject(JSGlobalObject*);
+    static JSGlobalObject* currentGlobalObject();
+
     static JSObject* createRuntimeObject(PassRefPtr<Instance>);
     static Instance* getInstance(JSObject*, BindingLanguage);
 
     // These functions are called before and after the main entry points into
     // the native implementations.  They can be used to establish and cleanup
     // any needed state.
-    virtual void begin() {}
-    virtual void end() {}
+    void begin();
+    void end();
     
     virtual Class *getClass() const = 0;
     
@@ -138,6 +142,9 @@ public:
     virtual BindingLanguage getBindingLanguage() const = 0;
 
 protected:
+    virtual void virtualBegin() { }
+    virtual void virtualEnd() { }
+
     RefPtr<RootObject> _rootObject;
 };