Changeset 19183 in webkit for trunk/JavaScriptCore
- Timestamp:
- Jan 26, 2007, 8:50:17 PM (18 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r19178 r19183 1 2007-01-25 Geoffrey Garen <[email protected]> 2 3 Reviewed by Maciej Stachowiak. 4 5 Fixed <rdar://problem/4608404> WebScriptObject's _rootObject lack 6 of ownership policy causes crashes (e.g., in Dashcode) 7 8 The old model for RootObject ownership was either to (1) leak them or (2) assign 9 them to a single owner -- the WebCore::Frame -- which would destroy them 10 when it believed that all of its plug-ins had unloaded. 11 12 This model was broken because of (1) and also because plug-ins are not the only 13 RootObject clients. All Bindings clients are RootObjects clients, including 14 applications, which outlive any particular WebCore::Frame. 15 16 The new model for RootObject ownership is to reference-count them, with a 17 throw-back to the old model: The WebCore::Frame tracks the RootObjects 18 it creates, and invalidates them when it believes that all of its plug-ins 19 have unloaded. 20 21 We maintain this throw-back to avoid plug-in leaks, particularly from Java. 22 Java is completely broken when it comes to releasing JavaScript objects. 23 Comments in our code allege that Java does not always call finalize when 24 collecting objects. Moreoever, my own testing reveals that, when Java does 25 notify JavaScript of a finalize, the data it provides is totally bogus. 26 27 This setup is far from ideal, but I don't think we can do better without 28 completely rewriting the bindings code, and possibly part of the Java 29 plug-in / VM. 30 31 Layout tests pass. No additional leaks reported. WebCore/manual-tests/*liveconnect* 32 and a few LiveConnect demos on the web also run without a hitch. 33 34 const RootObject* => RootObject*, since we need to ref/deref 35 36 * bindings/NP_jsobject.cpp: 37 (jsDeallocate): deref our RootObjects. Also unprotect or JSObject, instead 38 of just relying on the RootObject to do it for us when it's invalidated. 39 (_isSafeScript): Check RootObject validity. 40 (_NPN_CreateScriptObject): ditto 41 (_NPN_Invoke): ditto 42 (_NPN_Evaluate): ditto 43 (_NPN_GetProperty): ditto 44 (_NPN_SetProperty): ditto 45 (_NPN_RemoveProperty): ditto 46 (_NPN_HasProperty): ditto 47 (_NPN_HasMethod): ditto 48 (_NPN_SetException): ditto 49 50 * bindings/runtime_root.cpp: 51 Revived bit-rotted LIAR LIAR LIAR comment. 52 53 LOOK: Added support for invalidating RootObjects without deleting them, 54 which is the main goal of this patch. 55 56 Moved protect counting into the RootObject class, to emphasize that 57 the RootObject protects the JSObject, and unprotects it upon being invalidated. 58 addNativeReference => RootObject::gcProtect 59 removeNativeReference => RootObject::gcUnprotect 60 ProtectCountSet::contains => RootObject::gcIsProtected 61 62 I know we'll all be sad to see the word "native" go. 63 64 * bindings/runtime_root.h: Added ref-counting support to RootObject, with 65 all the standard accoutrements. 66 67 * bindings/c/c_utility.cpp: 68 (KJS::Bindings::convertValueToNPVariant): If we can't find a valid RootObject, 69 return void instead of just leaking. 70 71 * bindings/jni/jni_instance.cpp: 72 (JavaInstance::JavaInstance): Don't take a RootObject in our constructor; 73 be like other Instances and require the caller to call setRootObject. This 74 reduces the number of ownership code paths. 75 (JavaInstance::invokeMethod): Check RootObject for validity. 76 * bindings/jni/jni_instance.h: Removed private no-arg constructor. Having 77 an arg constructor accomplishes the same thing. 78 79 * bindings/jni/jni_jsobject.cpp: 80 (JavaJSObject::invoke): No need to call findProtectCountSet, because finalize() 81 checks for RootObject validity. 82 (JavaJSObject::JavaJSObject): check RootObject for validity 83 (JavaJSObject::call): ditto 84 (JavaJSObject::eval): ditto 85 (JavaJSObject::getMember): ditto 86 (JavaJSObject::setMember): ditto 87 (JavaJSObject::removeMember): ditto 88 (JavaJSObject::getSlot): ditto 89 (JavaJSObject::setSlot): ditto 90 (JavaJSObject::toString): ditto 91 (JavaJSObject::finalize): ditto 92 (JavaJSObject::createNative): No need to tell the RootObject to protect 93 the global object, since the RootObject already owns the interpreter. 94 95 * bindings/jni/jni_runtime.cpp: 96 (JavaArray::JavaArray): Removed copy construcutor becaue it was unused. 97 Dead code is dangerous code. 98 99 * bindings/objc/objc_runtime.mm: Added WebUndefined protocol. Previous use 100 of WebScriptObject was bogus, because WebUndefined is not a subclass of 101 WebScriptObject. 102 (convertValueToObjcObject): If we can't find a valid RootObject, 103 return nil instead of just leaking. 104 105 * bindings/objc/objc_utility.mm: 106 (KJS::Bindings::convertValueToObjcValue): If we can't find a valid RootObject, 107 return nil instead of just leaking. 108 1 109 2007-01-27 Andrew Wellington <[email protected]> 2 110 -
trunk/JavaScriptCore/JavaScriptCore.exp
r18837 r19183 101 101 __NPN_SetProperty 102 102 __NPN_UTF8FromIdentifier 103 __Z23_NPN_CreateScriptObjectP4_NPPPN3KJS8JSObjectE PKNS1_8Bindings10RootObjectES7_103 __Z23_NPN_CreateScriptObjectP4_NPPPN3KJS8JSObjectEN3WTF10PassRefPtrINS1_8Bindings10RootObjectEEES8_ 104 104 __Z25_NPN_CreateNoScriptObjectv 105 105 __ZN3KJS10Identifier3addEPKNS_5UCharEi … … 180 180 __ZN3KJS7UStringC1ERKS0_S2_ 181 181 __ZN3KJS7UStringaSEPKc 182 __ZN3KJS8Bindings10RootObject10invalidateEv 183 __ZN3KJS8Bindings10RootObject11gcUnprotectEPNS_8JSObjectE 182 184 __ZN3KJS8Bindings10RootObject17_createRootObjectE 183 __ZN3KJS8Bindings10RootObject19setCreateRootObjectEPFPS1_PvE 184 __ZN3KJS8Bindings10RootObject7destroyEv 185 __ZN3KJS8Bindings10RootObject19setCreateRootObjectEPFN3WTF10PassRefPtrIS1_EEPvE 186 __ZN3KJS8Bindings10RootObject6createEPKvN3WTF10PassRefPtrINS_11InterpreterEEE 187 __ZN3KJS8Bindings10RootObject9gcProtectEPNS_8JSObjectE 188 __ZN3KJS8Bindings10RootObjectD1Ev 185 189 __ZN3KJS8Bindings10throwErrorEPNS_9ExecStateENS_9ErrorTypeEP8NSString 186 __ZN3KJS8Bindings18addNativeReferenceEPKNS0_10RootObjectEPNS_8JSObjectE187 __ZN3KJS8Bindings21removeNativeReferenceEPNS_8JSObjectE188 190 __ZN3KJS8Bindings23convertObjcValueToValueEPNS_9ExecStateEPvNS0_13ObjcValueTypeE 189 191 __ZN3KJS8Bindings23convertValueToObjcValueEPNS_9ExecStateEPNS_7JSValueENS0_13ObjcValueTypeE 190 192 __ZN3KJS8Bindings8Instance18didExecuteFunctionEv 191 193 __ZN3KJS8Bindings8Instance21setDidExecuteFunctionEPFvPNS_9ExecStateEPNS_8JSObjectEE 192 __ZN3KJS8Bindings8Instance32createBindingForLanguageInstanceENS1_15BindingLanguageEPv PKNS0_10RootObjectE194 __ZN3KJS8Bindings8Instance32createBindingForLanguageInstanceENS1_15BindingLanguageEPvN3WTF10PassRefPtrINS0_10RootObjectEEE 193 195 __ZN3KJS8Debugger12sourceUnusedEPNS_9ExecStateEi 194 196 __ZN3KJS8Debugger6attachEPNS_11InterpreterE … … 255 257 __ZNK3KJS7UString6is8BitEv 256 258 __ZNK3KJS7UString8toUInt32EPb 259 __ZNK3KJS8Bindings10RootObject11interpreterEv 257 260 __ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE 258 261 __ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE -
trunk/JavaScriptCore/bindings/NP_jsobject.cpp
r18461 r19183 49 49 } 50 50 51 static void jsDeallocate(NPObject* obj) 52 { 51 static void jsDeallocate(NPObject* npObj) 52 { 53 JavaScriptObject* obj = (JavaScriptObject*)npObj; 54 55 if (obj->rootObject && obj->rootObject->isValid()) 56 obj->rootObject->gcUnprotect(obj->imp); 57 58 if (obj->rootObject) 59 obj->rootObject->deref(); 60 61 if (obj->originRootObject) 62 obj->originRootObject->deref(); 63 53 64 free(obj); 54 65 } … … 62 73 static bool _isSafeScript(JavaScriptObject* obj) 63 74 { 64 if (obj->originRootObject) { 65 Interpreter* originInterpreter = obj->originRootObject->interpreter(); 66 if (originInterpreter) 67 return originInterpreter->isSafeScript(obj->rootObject->interpreter()); 68 } 69 return true; 70 } 71 72 NPObject* _NPN_CreateScriptObject (NPP npp, JSObject* imp, const RootObject* originRootObject, const RootObject* rootObject) 75 if (!obj->originRootObject || !obj->rootObject) 76 return true; 77 78 if (!obj->originRootObject->isValid() || !obj->rootObject->isValid()) 79 return false; 80 81 return obj->originRootObject->interpreter()->isSafeScript(obj->rootObject->interpreter()); 82 } 83 84 NPObject* _NPN_CreateScriptObject(NPP npp, JSObject* imp, PassRefPtr<RootObject> originRootObject, PassRefPtr<RootObject> rootObject) 73 85 { 74 86 JavaScriptObject* obj = (JavaScriptObject*)_NPN_CreateObject(npp, NPScriptObjectClass); 75 87 88 obj->originRootObject = originRootObject.releaseRef(); 89 obj->rootObject = rootObject.releaseRef(); 90 91 if (obj->rootObject) 92 obj->rootObject->gcProtect(imp); 76 93 obj->imp = imp; 77 obj->originRootObject = originRootObject; 78 obj->rootObject = rootObject; 79 80 addNativeReference(rootObject, imp); 81 82 return (NPObject *)obj; 94 95 return (NPObject*)obj; 83 96 } 84 97 … … 120 133 121 134 // Lookup the function object. 122 ExecState* exec = obj->rootObject->interpreter()->globalExec(); 135 RootObject* rootObject = obj->rootObject; 136 if (!rootObject || !rootObject->isValid()) 137 return false; 138 139 ExecState* exec = rootObject->interpreter()->globalExec(); 123 140 JSLock lock; 124 141 JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string)); … … 157 174 return false; 158 175 159 ExecState* exec = obj->rootObject->interpreter()->globalExec(); 176 RootObject* rootObject = obj->rootObject; 177 if (!rootObject || !rootObject->isValid()) 178 return false; 179 180 ExecState* exec = rootObject->interpreter()->globalExec(); 160 181 161 182 JSLock lock; … … 163 184 unsigned int UTF16Length; 164 185 convertNPStringToUTF16(s, &scriptString, &UTF16Length); // requires free() of returned memory 165 Completion completion = obj->rootObject->interpreter()->evaluate(UString(), 0, UString((const UChar*)scriptString,UTF16Length));186 Completion completion = rootObject->interpreter()->evaluate(UString(), 0, UString((const UChar*)scriptString,UTF16Length)); 166 187 ComplType type = completion.complType(); 167 188 … … 192 213 return false; 193 214 194 ExecState* exec = obj->rootObject->interpreter()->globalExec(); 215 RootObject* rootObject = obj->rootObject; 216 if (!rootObject || !rootObject->isValid()) 217 return false; 218 219 ExecState* exec = rootObject->interpreter()->globalExec(); 195 220 PrivateIdentifier* i = (PrivateIdentifier*)propertyName; 196 221 … … 231 256 return false; 232 257 233 ExecState* exec = obj->rootObject->interpreter()->globalExec(); 258 RootObject* rootObject = obj->rootObject; 259 if (!rootObject || !rootObject->isValid()) 260 return false; 261 262 ExecState* exec = rootObject->interpreter()->globalExec(); 234 263 JSLock lock; 235 264 PrivateIdentifier* i = (PrivateIdentifier*)propertyName; … … 254 283 return false; 255 284 256 ExecState* exec = obj->rootObject->interpreter()->globalExec(); 285 RootObject* rootObject = obj->rootObject; 286 if (!rootObject || !rootObject->isValid()) 287 return false; 288 289 ExecState* exec = rootObject->interpreter()->globalExec(); 257 290 PrivateIdentifier* i = (PrivateIdentifier*)propertyName; 258 291 if (i->isString) { … … 282 315 return false; 283 316 284 ExecState* exec = obj->rootObject->interpreter()->globalExec(); 317 RootObject* rootObject = obj->rootObject; 318 if (!rootObject || !rootObject->isValid()) 319 return false; 320 321 ExecState* exec = rootObject->interpreter()->globalExec(); 285 322 PrivateIdentifier* i = (PrivateIdentifier*)propertyName; 286 323 JSLock lock; … … 307 344 return false; 308 345 309 ExecState* exec = obj->rootObject->interpreter()->globalExec(); 346 RootObject* rootObject = obj->rootObject; 347 if (!rootObject || !rootObject->isValid()) 348 return false; 349 350 ExecState* exec = rootObject->interpreter()->globalExec(); 310 351 JSLock lock; 311 352 JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string)); … … 323 364 if (o->_class == NPScriptObjectClass) { 324 365 JavaScriptObject* obj = (JavaScriptObject*)o; 325 ExecState* exec = obj->rootObject->interpreter()->globalExec(); 366 RootObject* rootObject = obj->rootObject; 367 if (!rootObject || !rootObject->isValid()) 368 return; 369 370 ExecState* exec = rootObject->interpreter()->globalExec(); 326 371 JSLock lock; 327 372 throwError(exec, GeneralError, message); -
trunk/JavaScriptCore/bindings/NP_jsobject.h
r18461 r19183 28 28 29 29 #include "npruntime.h" 30 #include <wtf/Forward.h> 30 31 31 32 namespace KJS { … … 42 43 NPObject object; 43 44 KJS::JSObject* imp; 44 constKJS::Bindings::RootObject* originRootObject;45 constKJS::Bindings::RootObject* rootObject;45 KJS::Bindings::RootObject* originRootObject; 46 KJS::Bindings::RootObject* rootObject; 46 47 }; 47 48 48 NPObject* _NPN_CreateScriptObject(NPP npp, KJS::JSObject*, const KJS::Bindings::RootObject* originRootObject, const KJS::Bindings::RootObject*rootObject);49 NPObject* _NPN_CreateScriptObject(NPP npp, KJS::JSObject*, PassRefPtr<KJS::Bindings::RootObject> originRootObject, PassRefPtr<KJS::Bindings::RootObject> rootObject); 49 50 NPObject* _NPN_CreateNoScriptObject(void); 50 51 -
trunk/JavaScriptCore/bindings/c/c_instance.cpp
r18461 r19183 32 32 #include "list.h" 33 33 #include "npruntime_impl.h" 34 #include "runtime_root.h" 35 #include <wtf/StringExtras.h> 34 36 #include <wtf/Vector.h> 35 #include <wtf/StringExtras.h>36 37 37 38 namespace KJS { -
trunk/JavaScriptCore/bindings/c/c_utility.cpp
r18811 r19183 104 104 JSType type = value->type(); 105 105 106 VOID_TO_NPVARIANT(*result); 107 106 108 if (type == StringType) { 107 109 UString ustring = value->toString(exec); … … 126 128 OBJECT_TO_NPVARIANT(obj, *result); 127 129 } else { 128 Interpreter *originInterpreter = exec->dynamicInterpreter();129 const Bindings::RootObject* originRootObject = findRootObject(originInterpreter);130 Interpreter* originInterpreter = exec->dynamicInterpreter(); 131 RootObject* originRootObject = findRootObject(originInterpreter); 130 132 131 Interpreter *interpreter = 0;133 Interpreter* interpreter = 0; 132 134 if (originInterpreter->isGlobalObject(value)) { 133 135 interpreter = originInterpreter->interpreterForGlobalObject(value); … … 137 139 interpreter = originInterpreter; 138 140 139 constRootObject* rootObject = findRootObject(interpreter);140 if ( !rootObject) {141 RootObject* newRootObject = new RootObject(0, interpreter);142 rootObject = newRootObject;141 RootObject* rootObject = findRootObject(interpreter); 142 if (rootObject) { 143 NPObject* npObject = _NPN_CreateScriptObject(0, object, originRootObject, rootObject); 144 OBJECT_TO_NPVARIANT(npObject, *result); 143 145 } 144 145 NPObject* npObject = _NPN_CreateScriptObject(0, object, originRootObject, rootObject);146 OBJECT_TO_NPVARIANT(npObject, *result);147 146 } 148 147 } 149 else150 VOID_TO_NPVARIANT(*result);151 148 } 152 149 -
trunk/JavaScriptCore/bindings/jni/jni_instance.cpp
r18461 r19183 40 40 } 41 41 #endif 42 42 43 43 using namespace KJS::Bindings; 44 44 using namespace KJS; 45 45 46 JavaInstance::JavaInstance (jobject instance , const RootObject *r)46 JavaInstance::JavaInstance (jobject instance) 47 47 { 48 48 _instance = new JObjectWrapper (instance); 49 49 _class = 0; 50 setRootObject(r);51 50 } 52 51 … … 139 138 } 140 139 141 142 140 jvalue result; 143 141 … … 145 143 // nornmal JNI. The JNI dispatch abstraction allows the Java plugin 146 144 // to dispatch the call on the appropriate internal VM thread. 147 const RootObject* rootObject = this->rootObject(); 145 RootObject* rootObject = this->rootObject(); 146 if (!rootObject) 147 return jsUndefined(); 148 148 149 bool handled = false; 149 if (rootObject && rootObject->nativeHandle()) {150 if (rootObject->nativeHandle()) { 150 151 jobject obj = _instance->_instance; 151 152 JSValue *exceptionDescription = NULL; -
trunk/JavaScriptCore/bindings/jni/jni_instance.h
r18657 r19183 67 67 { 68 68 public: 69 JavaInstance (jobject instance, const RootObject *r); 70 71 ~JavaInstance (); 69 JavaInstance(jobject instance); 70 ~JavaInstance(); 72 71 73 72 virtual Class *getClass() const; … … 88 87 89 88 private: 90 JavaInstance (); // prevent default construction91 89 JavaInstance (JavaInstance &); // prevent copying 92 90 JavaInstance &operator=(JavaInstance &); // prevent copying -
trunk/JavaScriptCore/bindings/jni/jni_jsobject.cpp
r18811 r19183 127 127 128 128 case Finalize: { 129 JSObject *imp = jlong_to_impptr(nativeHandle); 130 // We may have received a finalize method call from the VM 131 // AFTER removing our last reference to the Java instance. 132 if (findProtectCountSet(imp)) 133 JavaJSObject(nativeHandle).finalize(); 129 JavaJSObject(nativeHandle).finalize(); 134 130 break; 135 131 } … … 151 147 _imp = jlong_to_impptr(nativeJSObject); 152 148 153 // If we are unable to cast the nativeJSObject to an JSObject something is 154 // terribly wrong. 155 assert (_imp != 0); 156 149 ASSERT(_imp); 157 150 _rootObject = findRootObject(_imp); 158 159 // If we can't find the root for the object something is terribly wrong. 160 assert (_rootObject != 0); 161 } 162 151 ASSERT(_rootObject); 152 } 153 154 RootObject* JavaJSObject::rootObject() const 155 { 156 return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0; 157 } 163 158 164 159 jobject JavaJSObject::call(jstring methodName, jobjectArray args) const … … 166 161 JS_LOG ("methodName = %s\n", JavaString(methodName).UTF8String()); 167 162 163 RootObject* rootObject = this->rootObject(); 164 if (!rootObject) 165 return 0; 166 168 167 // Lookup the function object. 169 ExecState* exec = _rootObject->interpreter()->globalExec();168 ExecState* exec = rootObject->interpreter()->globalExec(); 170 169 JSLock lock; 171 170 172 171 Identifier identifier(JavaString(methodName).ustring()); 173 172 JSValue *func = _imp->get (exec, identifier); 174 if (func->isUndefinedOrNull()) { 175 // Maybe throw an exception here? 176 return 0; 177 } 173 if (func->isUndefinedOrNull()) 174 return 0; 178 175 179 176 // Call the function object. … … 195 192 JSLock lock; 196 193 197 Completion completion = _rootObject->interpreter()->evaluate(UString(), 0, JavaString(script).ustring(),thisObj); 194 RootObject* rootObject = this->rootObject(); 195 if (!rootObject) 196 return 0; 197 198 Completion completion = rootObject->interpreter()->evaluate(UString(), 0, JavaString(script).ustring(),thisObj); 198 199 ComplType type = completion.complType(); 199 200 … … 212 213 JS_LOG ("(%p) memberName = %s\n", _imp, JavaString(memberName).UTF8String()); 213 214 214 ExecState* exec = _rootObject->interpreter()->globalExec(); 215 RootObject* rootObject = this->rootObject(); 216 if (!rootObject) 217 return 0; 218 219 ExecState* exec = rootObject->interpreter()->globalExec(); 215 220 216 221 JSLock lock; … … 223 228 { 224 229 JS_LOG ("memberName = %s, value = %p\n", JavaString(memberName).UTF8String(), value); 225 ExecState* exec = _rootObject->interpreter()->globalExec(); 230 231 RootObject* rootObject = this->rootObject(); 232 if (!rootObject) 233 return; 234 235 ExecState* exec = rootObject->interpreter()->globalExec(); 226 236 JSLock lock; 227 237 _imp->put(exec, Identifier (JavaString(memberName).ustring()), convertJObjectToValue(value)); … … 233 243 JS_LOG ("memberName = %s\n", JavaString(memberName).UTF8String()); 234 244 235 ExecState* exec = _rootObject->interpreter()->globalExec(); 245 RootObject* rootObject = this->rootObject(); 246 if (!rootObject) 247 return; 248 249 ExecState* exec = rootObject->interpreter()->globalExec(); 236 250 JSLock lock; 237 251 _imp->deleteProperty(exec, Identifier (JavaString(memberName).ustring())); … … 247 261 #endif 248 262 249 ExecState* exec = _rootObject->interpreter()->globalExec(); 263 RootObject* rootObject = this->rootObject(); 264 if (!rootObject) 265 return 0; 266 267 ExecState* exec = rootObject->interpreter()->globalExec(); 250 268 251 269 JSLock lock; … … 264 282 #endif 265 283 266 ExecState* exec = _rootObject->interpreter()->globalExec(); 284 RootObject* rootObject = this->rootObject(); 285 if (!rootObject) 286 return; 287 288 ExecState* exec = rootObject->interpreter()->globalExec(); 267 289 JSLock lock; 268 290 _imp->put(exec, (unsigned)index, convertJObjectToValue(value)); … … 274 296 JS_LOG ("\n"); 275 297 298 RootObject* rootObject = this->rootObject(); 299 if (!rootObject) 300 return 0; 301 276 302 JSLock lock; 277 303 JSObject *thisObj = const_cast<JSObject*>(_imp); 278 ExecState* exec = _rootObject->interpreter()->globalExec();304 ExecState* exec = rootObject->interpreter()->globalExec(); 279 305 280 306 return (jstring)convertValueToJValue (exec, thisObj, object_type, "java.lang.String").l; … … 283 309 void JavaJSObject::finalize() const 284 310 { 285 JS_LOG ("\n"); 286 287 removeNativeReference (_imp); 311 if (RootObject* rootObject = this->rootObject()) 312 rootObject->gcUnprotect(_imp); 288 313 } 289 314 … … 304 329 return ptr_to_jlong(0); 305 330 306 RootObject* rootObject = createRootObject(jlong_to_ptr(nativeHandle)); 331 RefPtr<RootObject> rootObject = createRootObject(jlong_to_ptr(nativeHandle)); 332 307 333 // If rootObject is !NULL We must have been called via netscape.javascript.JavaJSObject.getWindow(), 308 334 // otherwise we are being called after creating a JavaJSObject in 309 335 // JavaJSObject::convertValueToJObject(). 310 if (rootObject) { 311 JSObject* globalObject = rootObject->interpreter()->globalObject(); 312 addNativeReference(rootObject, globalObject); 313 return ptr_to_jlong(globalObject); 314 } 336 if (rootObject) 337 return ptr_to_jlong(rootObject->interpreter()->globalObject()); 315 338 316 339 return nativeHandle; … … 319 342 jobject JavaJSObject::convertValueToJObject (JSValue *value) const 320 343 { 321 ExecState* exec = _rootObject->interpreter()->globalExec(); 344 RootObject* rootObject = this->rootObject(); 345 if (!rootObject) 346 return 0; 347 348 ExecState* exec = rootObject->interpreter()->globalExec(); 322 349 JNIEnv *env = getJNIEnv(); 323 350 jobject result = 0; … … 369 396 else { 370 397 nativeHandle = ptr_to_jlong(imp); 371 372 // Bump our 'meta' reference count for the imp. We maintain the reference 373 // until either finalize is called or the applet shuts down. 374 addNativeReference(_rootObject, imp); 398 rootObject->gcProtect(imp); 375 399 } 376 400 } … … 430 454 431 455 JSLock lock; 432 RuntimeObjectImp* newImp = new RuntimeObjectImp(new JavaInstance(theObject, _rootObject)); 456 JavaInstance* javaInstance = new JavaInstance(theObject); 457 javaInstance->setRootObject(rootObject()); 458 RuntimeObjectImp* newImp = new RuntimeObjectImp(javaInstance); 433 459 434 460 return newImp; -
trunk/JavaScriptCore/bindings/jni/jni_jsobject.h
r18795 r19183 92 92 List listFromJArray(jobjectArray) const; 93 93 94 RootObject* rootObject() const; 95 94 96 private: 95 const RootObject*_rootObject;96 JSObject *_imp;97 RefPtr<RootObject> _rootObject; 98 JSObject* _imp; 97 99 }; 98 100 -
trunk/JavaScriptCore/bindings/jni/jni_runtime.cpp
r18461 r19183 66 66 _name = JavaString(env, fieldName); 67 67 68 _field = new JavaInstance(aField , 0);69 } 70 71 JSValue* JavaArray::convertJObjectToArray(ExecState* exec, jobject anObject, const char* type, const RootObject* r)68 _field = new JavaInstance(aField); 69 } 70 71 JSValue* JavaArray::convertJObjectToArray(ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject> rootObject) 72 72 { 73 73 if (type[0] != '[') 74 74 return jsUndefined(); 75 75 76 return new RuntimeArray(exec, new JavaArray((jobject)anObject, type, r ));76 return new RuntimeArray(exec, new JavaArray((jobject)anObject, type, rootObject)); 77 77 } 78 78 … … 90 90 if ( mid != NULL ) 91 91 { 92 constRootObject* rootObject = instance->rootObject();92 RootObject* rootObject = instance->rootObject(); 93 93 if (rootObject && rootObject->nativeHandle()) { 94 94 JSValue *exceptionDescription = NULL; … … 171 171 if ( mid != NULL ) 172 172 { 173 constRootObject* rootObject = instance->rootObject();173 RootObject* rootObject = instance->rootObject(); 174 174 if (rootObject && rootObject->nativeHandle()) { 175 175 JSValue *exceptionDescription = NULL; … … 365 365 366 366 367 JavaArray::JavaArray (jobject a, const char *t, const RootObject *r)368 { 369 _array = new JObjectWrapper (a);367 JavaArray::JavaArray(jobject array, const char* type, PassRefPtr<RootObject> rootObject) 368 { 369 _array = new JObjectWrapper(array); 370 370 // Java array are fixed length, so we can cache length. 371 371 JNIEnv *env = getJNIEnv(); 372 372 _length = env->GetArrayLength((jarray)_array->_instance); 373 _type = strdup(t );374 _rootObject = r ;373 _type = strdup(type); 374 _rootObject = rootObject; 375 375 } 376 376 … … 380 380 } 381 381 382 383 JavaArray::JavaArray (const JavaArray &other) : Array() 384 { 385 _array = other._array; 386 _type = strdup(other._type); 382 RootObject* JavaArray::rootObject() const 383 { 384 return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0; 387 385 } 388 386 -
trunk/JavaScriptCore/bindings/jni/jni_runtime.h
r18461 r19183 267 267 { 268 268 public: 269 JavaArray (jobject a, const char *type, const RootObject *r); 270 271 JavaArray (const JavaArray &other); 272 273 JavaArray &operator=(const JavaArray &other){ 274 if (this == &other) 275 return *this; 276 277 free ((void *)_type); 278 _type = strdup(other._type); 279 _rootObject = other._rootObject; 280 _array = other._array; 281 282 return *this; 283 }; 269 JavaArray(jobject array, const char* type, PassRefPtr<RootObject>); 270 virtual ~JavaArray(); 271 272 RootObject* rootObject() const; 284 273 285 274 virtual void setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const; … … 287 276 virtual unsigned int getLength() const; 288 277 289 virtual ~JavaArray();290 291 278 jobject javaArray() const { return _array->_instance; } 292 279 293 static JSValue *convertJObjectToArray (ExecState *exec, jobject anObject, const char *type, const RootObject *r); 294 295 const RootObject* rootObject() const { return _rootObject; } 296 297 private: 280 static JSValue* convertJObjectToArray (ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject>); 281 282 private: 283 JavaArray(const JavaArray&); 284 JavaArray& operator=(const JavaArray&); 285 298 286 RefPtr<JObjectWrapper> _array; 299 287 unsigned int _length; 300 288 const char *_type; 301 const RootObject *_rootObject;289 RefPtr<RootObject> _rootObject; 302 290 }; 303 291 -
trunk/JavaScriptCore/bindings/objc/WebScriptObject.h
r18461 r19183 29 29 #include "runtime_root.h" 30 30 31 @class WebUndefined; 32 31 33 @protocol WebScriptObject 32 34 + (NSString *)webScriptNameForSelector:(SEL)aSelector; … … 35 37 + (BOOL)isKeyExcludedFromWebScript:(const char *)name; 36 38 37 + (id)_convertValueToObjcValue:(KJS::JSValue *)value originRootObject:( const KJS::Bindings::RootObject*)originRootObject rootObject:(const KJS::Bindings::RootObject*)rootObject;38 - _initWithJSObject:(KJS::JSObject *)imp originRootObject:(const KJS::Bindings::RootObject*)originRootObject rootObject:(const KJS::Bindings::RootObject*)rootObject;39 + (id)_convertValueToObjcValue:(KJS::JSValue *)value originRootObject:(KJS::Bindings::RootObject*)originRootObject rootObject:(KJS::Bindings::RootObject*)rootObject; 40 - _initWithJSObject:(KJS::JSObject*)imp originRootObject:(PassRefPtr<KJS::Bindings::RootObject>)originRootObject rootObject:(PassRefPtr<KJS::Bindings::RootObject>)rootObject; 39 41 - (KJS::JSObject *)_imp; 40 42 @end 43 44 @protocol WebUndefined 45 + (WebUndefined *)undefined; 46 @end -
trunk/JavaScriptCore/bindings/objc/objc_runtime.mm
r18811 r19183 43 43 extern ClassStructPtr KJS::Bindings::webUndefinedClass() 44 44 { 45 static ClassStructPtr<Web ScriptObject> webUndefinedClass = NSClassFromString(@"WebUndefined");45 static ClassStructPtr<WebUndefined> webUndefinedClass = NSClassFromString(@"WebUndefined"); 46 46 return webUndefinedClass; 47 47 } … … 142 142 static id convertValueToObjcObject(ExecState* exec, JSValue* value) 143 143 { 144 const RootObject* rootObject = findRootObject(exec->dynamicInterpreter()); 145 if (!rootObject) { 146 RootObject* newRootObject = new RootObject(0, exec->dynamicInterpreter()); 147 rootObject = newRootObject; 148 } 149 return [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:rootObject rootObject:rootObject ]; 144 RefPtr<RootObject> rootObject = findRootObject(exec->dynamicInterpreter()); 145 if (!rootObject) 146 return nil; 147 return [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:rootObject.get() rootObject:rootObject.get()]; 150 148 } 151 149 -
trunk/JavaScriptCore/bindings/objc/objc_utility.mm
r18811 r19183 137 137 case ObjcObjectType: { 138 138 Interpreter *originInterpreter = exec->dynamicInterpreter(); 139 constRootObject* originRootObject = findRootObject(originInterpreter);139 RootObject* originRootObject = findRootObject(originInterpreter); 140 140 141 141 Interpreter *interpreter = 0; … … 146 146 interpreter = originInterpreter; 147 147 148 const RootObject* rootObject = findRootObject(interpreter); 149 if (!rootObject) { 150 RootObject* newRootObject = new RootObject(0, interpreter); 151 rootObject = newRootObject; 152 } 153 154 result.objectValue = [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:originRootObject rootObject:rootObject]; 148 RootObject* rootObject = findRootObject(interpreter); 149 result.objectValue = rootObject 150 ? [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:originRootObject rootObject:rootObject] 151 : nil; 155 152 } 156 153 break; -
trunk/JavaScriptCore/bindings/runtime.cpp
r18657 r19183 30 30 #include "NP_jsobject.h" 31 31 #include "c_instance.h" 32 #include "runtime_object.h" 33 #include "runtime_root.h" 34 32 35 #if HAVE(JNI) 33 36 #include "jni_instance.h" … … 39 42 #include "qt_instance.h" 40 43 #endif 41 #include "runtime_object.h"42 44 43 45 namespace KJS { namespace Bindings { … … 95 97 96 98 Instance::Instance() 97 : _rootObject(0) 98 , _refCount(0) 99 : _refCount(0) 100 { 101 } 102 103 Instance::~Instance() 99 104 { 100 105 } … … 115 120 } 116 121 117 Instance* Instance::createBindingForLanguageInstance(BindingLanguage language, void* nativeInstance, const RootObject*rootObject)122 Instance* Instance::createBindingForLanguageInstance(BindingLanguage language, void* nativeInstance, PassRefPtr<RootObject> rootObject) 118 123 { 119 124 Instance *newInstance = 0; … … 122 127 #if HAVE(JNI) 123 128 case Instance::JavaLanguage: { 124 newInstance = new Bindings::JavaInstance((jobject)nativeInstance , rootObject);129 newInstance = new Bindings::JavaInstance((jobject)nativeInstance); 125 130 break; 126 131 } … … 152 157 } 153 158 154 JSObject* Instance::createRuntimeObject(BindingLanguage language, void* nativeInstance, const RootObject*rootObject)159 JSObject* Instance::createRuntimeObject(BindingLanguage language, void* nativeInstance, PassRefPtr<RootObject> rootObject) 155 160 { 156 Instance* in terfaceObject= Instance::createBindingForLanguageInstance(language, nativeInstance, rootObject);161 Instance* instance = Instance::createBindingForLanguageInstance(language, nativeInstance, rootObject); 157 162 158 163 JSLock lock; 159 return new RuntimeObjectImp(interfaceObject); 164 return new RuntimeObjectImp(instance); 165 } 166 167 void Instance::setRootObject(PassRefPtr<RootObject> rootObject) 168 { 169 _rootObject = rootObject; 170 } 171 172 RootObject* Instance::rootObject() const 173 { 174 return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0; 160 175 } 161 176 -
trunk/JavaScriptCore/bindings/runtime.h
r18461 r19183 142 142 static KJSDidExecuteFunctionPtr didExecuteFunction(); 143 143 144 static Instance* createBindingForLanguageInstance(BindingLanguage, void* nativeInstance, const RootObject*= 0);145 static JSObject* createRuntimeObject(BindingLanguage, void* nativeInstance, const RootObject*= 0);144 static Instance* createBindingForLanguageInstance(BindingLanguage, void* nativeInstance, PassRefPtr<RootObject> = 0); 145 static JSObject* createRuntimeObject(BindingLanguage, void* nativeInstance, PassRefPtr<RootObject> = 0); 146 146 147 147 void ref() { _refCount++; } … … 175 175 virtual JSValue* valueOf() const { return jsString(getClass()->name()); } 176 176 177 void setRootObject( const RootObject* r) { _rootObject = r; }178 const RootObject* rootObject() const { return _rootObject; }179 180 virtual ~Instance() {}177 void setRootObject(PassRefPtr<RootObject>); 178 RootObject* rootObject() const; 179 180 virtual ~Instance(); 181 181 182 182 protected: 183 const RootObject*_rootObject;183 RefPtr<RootObject> _rootObject; 184 184 unsigned _refCount; 185 185 -
trunk/JavaScriptCore/bindings/runtime_root.cpp
r18811 r19183 28 28 #include "runtime_root.h" 29 29 #include <wtf/HashCountedSet.h> 30 #include <wtf/HashSet.h> 30 31 31 32 namespace KJS { namespace Bindings { 32 33 33 // Java does NOT always call finalize (and thus KJS_JSObject_JSFinalize) when 34 // it collects an objects. This presents some difficulties. We must ensure 35 // the a JavaJSObject's corresponding JavaScript object doesn't get collected. We 36 // do this by incrementing the JavaScript's reference count the first time we 37 // create a JavaJSObject for it, and decrementing the JavaScript reference count when 38 // the last JavaJSObject that refers to it is finalized, or when the applet is 39 // shutdown. 40 // 41 // To do this we keep a map that maps each applet instance 42 // to the JavaScript objects it is referencing. For each JavaScript instance 43 // we also maintain a secondary reference count. When that reference count reaches 44 // 1 OR the applet is shutdown we deref the JavaScript instance. Applet instances 45 // are represented by a jlong. 46 47 typedef HashMap<const RootObject*, ProtectCountSet*> RootObjectMap; 48 49 static RootObjectMap* rootObjectMap() 50 { 51 static RootObjectMap staticRootObjectMap; 52 return &staticRootObjectMap; 53 } 54 55 static ProtectCountSet* getProtectCountSet(const RootObject* rootObject) 56 { 57 ProtectCountSet* protectCountSet = rootObjectMap()->get(rootObject); 58 59 if (!protectCountSet) { 60 protectCountSet = new ProtectCountSet; 61 rootObjectMap()->add(rootObject, protectCountSet); 62 } 63 return protectCountSet; 64 } 65 66 static void destroyProtectCountSet(const RootObject* rootObject, ProtectCountSet* protectCountSet) 67 { 68 rootObjectMap()->remove(rootObject); 69 delete protectCountSet; 34 // This code attempts to solve two problems: (1) plug-ins leaking references to 35 // JS and the DOM; (2) plug-ins holding stale references to JS and the DOM. Previous 36 // comments in this file claimed that problem #1 was an issue in Java, in particular, 37 // because Java, allegedly, didn't always call finalize when collecting an object. 38 39 typedef HashSet<RootObject*> RootObjectSet; 40 41 static RootObjectSet* rootObjectSet() 42 { 43 static RootObjectSet staticRootObjectSet; 44 return &staticRootObjectSet; 70 45 } 71 46 … … 73 48 // fix them by adding a JSObject to RootObject dictionary. 74 49 75 ProtectCountSet* findProtectCountSet(JSObject* jsObject) 76 { 77 const RootObject* rootObject = findRootObject(jsObject); 78 return rootObject ? getProtectCountSet(rootObject) : 0; 79 } 80 81 const RootObject* findRootObject(JSObject* jsObject) 82 { 83 RootObjectMap::const_iterator end = rootObjectMap()->end(); 84 for (RootObjectMap::const_iterator it = rootObjectMap()->begin(); it != end; ++it) { 85 ProtectCountSet* set = it->second; 86 if (set->contains(jsObject)) 87 return it->first; 88 } 89 50 RootObject* findRootObject(JSObject* jsObject) 51 { 52 RootObjectSet::const_iterator end = rootObjectSet()->end(); 53 for (RootObjectSet::const_iterator it = rootObjectSet()->begin(); it != end; ++it) { 54 if ((*it)->gcIsProtected(jsObject)) 55 return *it; 56 } 90 57 return 0; 91 58 } 92 59 93 const RootObject* findRootObject(Interpreter* interpreter) 94 { 95 RootObjectMap::const_iterator end = rootObjectMap()->end(); 96 for (RootObjectMap::const_iterator it = rootObjectMap()->begin(); it != end; ++it) { 97 const RootObject* aRootObject = it->first; 98 99 if (aRootObject->interpreter() == interpreter) 100 return aRootObject; 101 } 102 60 RootObject* findRootObject(Interpreter* interpreter) 61 { 62 RootObjectSet::const_iterator end = rootObjectSet()->end(); 63 for (RootObjectSet::const_iterator it = rootObjectSet()->begin(); it != end; ++it) { 64 if ((*it)->interpreter() == interpreter) 65 return *it; 66 } 103 67 return 0; 104 }105 106 void addNativeReference(const RootObject* rootObject, JSObject* jsObject)107 {108 if (!rootObject)109 return;110 111 ProtectCountSet* protectCountSet = getProtectCountSet(rootObject);112 if (!protectCountSet->contains(jsObject)) {113 JSLock lock;114 gcProtect(jsObject);115 }116 protectCountSet->add(jsObject);117 }118 119 void removeNativeReference(JSObject* jsObject)120 {121 if (!jsObject)122 return;123 124 // We might have manually detroyed the root object and its protect set already125 ProtectCountSet* protectCountSet = findProtectCountSet(jsObject);126 if (!protectCountSet)127 return;128 129 if (protectCountSet->count(jsObject) == 1) {130 JSLock lock;131 gcUnprotect(jsObject);132 }133 protectCountSet->remove(jsObject);134 68 } 135 69 … … 256 190 CFRunLoopAddSource(RootObject::_runLoop, RootObject::_performJavaScriptSource, kCFRunLoopDefaultMode); 257 191 } 192 258 193 #endif 259 194 260 // Destroys the RootObject and unprotects all JSObjects associated with it. 261 void RootObject::destroy() 262 { 263 ProtectCountSet* protectCountSet = getProtectCountSet(this); 264 265 if (protectCountSet) { 266 ProtectCountSet::iterator end = protectCountSet->end(); 267 for (ProtectCountSet::iterator it = protectCountSet->begin(); it != end; ++it) { 268 JSLock lock; 269 gcUnprotect(it->first); 270 } 271 272 destroyProtectCountSet(this, protectCountSet); 273 } 274 275 delete this; 195 PassRefPtr<RootObject> RootObject::create(const void* nativeHandle, PassRefPtr<Interpreter> interpreter) 196 { 197 return new RootObject(nativeHandle, interpreter); 198 } 199 200 RootObject::RootObject(const void* nativeHandle, PassRefPtr<Interpreter> interpreter) 201 : m_refCount(0) 202 , m_isValid(true) 203 , m_nativeHandle(nativeHandle) 204 , m_interpreter(interpreter) 205 { 206 ASSERT(m_interpreter); 207 rootObjectSet()->add(this); 208 } 209 210 RootObject::~RootObject() 211 { 212 if (m_isValid) 213 invalidate(); 214 } 215 216 void RootObject::invalidate() 217 { 218 if (!m_isValid) 219 return; 220 221 m_isValid = false; 222 223 m_nativeHandle = 0; 224 m_interpreter = 0; 225 226 ProtectCountSet::iterator end = m_protectCountSet.end(); 227 for (ProtectCountSet::iterator it = m_protectCountSet.begin(); it != end; ++it) { 228 JSLock lock; 229 KJS::gcUnprotect(it->first); 230 } 231 m_protectCountSet.clear(); 232 233 rootObjectSet()->remove(this); 234 } 235 236 void RootObject::gcProtect(JSObject* jsObject) 237 { 238 ASSERT(m_isValid); 239 240 if (!m_protectCountSet.contains(jsObject)) { 241 JSLock lock; 242 KJS::gcProtect(jsObject); 243 } 244 m_protectCountSet.add(jsObject); 245 } 246 247 void RootObject::gcUnprotect(JSObject* jsObject) 248 { 249 ASSERT(m_isValid); 250 251 if (!jsObject) 252 return; 253 254 if (m_protectCountSet.count(jsObject) == 1) { 255 JSLock lock; 256 KJS::gcUnprotect(jsObject); 257 } 258 m_protectCountSet.remove(jsObject); 259 } 260 261 bool RootObject::gcIsProtected(JSObject* jsObject) 262 { 263 ASSERT(m_isValid); 264 return m_protectCountSet.contains(jsObject); 265 } 266 267 const void* RootObject::nativeHandle() const 268 { 269 ASSERT(m_isValid); 270 return m_nativeHandle; 271 } 272 273 Interpreter* RootObject::interpreter() const 274 { 275 ASSERT(m_isValid); 276 return m_interpreter.get(); 276 277 } 277 278 -
trunk/JavaScriptCore/bindings/runtime_root.h
r18811 r19183 39 39 class RootObject; 40 40 41 typedef RootObject*(*CreateRootObjectFunction)(void* nativeHandle);41 typedef PassRefPtr<RootObject> (*CreateRootObjectFunction)(void* nativeHandle); 42 42 typedef HashCountedSet<JSObject*> ProtectCountSet; 43 43 44 extern ProtectCountSet* findProtectCountSet(JSObject*); 45 extern const RootObject* findRootObject(JSObject*); 46 extern const RootObject* findRootObject(Interpreter*); 47 extern void addNativeReference(const RootObject*, JSObject*); 48 extern void removeNativeReference(JSObject*); 44 extern RootObject* findRootObject(JSObject*); 45 extern RootObject* findRootObject(Interpreter*); 49 46 50 47 class RootObject … … 52 49 friend class JavaJSObject; 53 50 public: 54 RootObject(const void* nativeHandle, PassRefPtr<Interpreter> interpreter) 55 : m_nativeHandle(nativeHandle) 56 , m_interpreter(interpreter) 51 static PassRefPtr<RootObject> create(const void* nativeHandle, PassRefPtr<Interpreter> interpreter); 52 53 void ref() { m_refCount++; } 54 void deref() 57 55 { 56 if (--m_refCount == 0) 57 delete this; 58 58 } 59 60 bool isValid() { return m_isValid; } 61 void invalidate(); 59 62 60 const void *nativeHandle() const { return m_nativeHandle; } 61 Interpreter *interpreter() const { return m_interpreter.get(); } 63 void gcProtect(JSObject*); 64 void gcUnprotect(JSObject*); 65 bool gcIsProtected(JSObject*); 62 66 63 void destroy(); 67 const void* nativeHandle() const; 68 Interpreter* interpreter() const; 64 69 65 70 #if PLATFORM(MAC) … … 77 82 78 83 private: 84 RootObject(const void* nativeHandle, PassRefPtr<Interpreter> interpreter); 85 ~RootObject(); 86 87 // Uncopyable 88 RootObject(const RootObject&); 89 RootObject& operator=(const RootObject&); 90 91 unsigned m_refCount; 92 bool m_isValid; 93 79 94 const void* m_nativeHandle; 80 95 RefPtr<Interpreter> m_interpreter; 96 ProtectCountSet m_protectCountSet; 81 97 82 98 #if PLATFORM(MAC)
Note:
See TracChangeset
for help on using the changeset viewer.