Back to index

lightning-sunbird  0.9+nobinonly
jsd_obj.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * JavaScript Debugging support - Object support
00040  */
00041 
00042 #include "jsd.h"
00043 
00044 /*
00045 * #define JSD_TRACE 1
00046 */
00047 
00048 #ifdef JSD_TRACE
00049 #define TRACEOBJ(jsdc, jsdobj, which) _traceObj(jsdc, jsdobj, which)
00050 
00051 static char *
00052 _describeObj(JSDContext* jsdc, JSDObject *jsdobj)
00053 {
00054     return
00055         JS_smprintf("%0x new'd in %s at line %d using ctor %s in %s at line %d",
00056                     (int)jsdobj,
00057                     JSD_GetObjectNewURL(jsdc, jsdobj),
00058                     JSD_GetObjectNewLineNumber(jsdc, jsdobj),
00059                     JSD_GetObjectConstructorName(jsdc, jsdobj),
00060                     JSD_GetObjectConstructorURL(jsdc, jsdobj),
00061                     JSD_GetObjectConstructorLineNumber(jsdc, jsdobj));
00062 }
00063 
00064 static void
00065 _traceObj(JSDContext* jsdc, JSDObject* jsdobj, int which)
00066 {
00067     char* description;
00068 
00069     if( !jsdobj )
00070         return;
00071 
00072     description = _describeObj(jsdc, jsdobj);
00073 
00074     printf("%s : %s\n",
00075            which == 0 ? "new  " :
00076            which == 1 ? "final" :
00077                         "ctor ",
00078            description);
00079     if(description)
00080         free(description);
00081 }
00082 #else
00083 #define TRACEOBJ(jsdc, jsdobj, which) ((void)0)
00084 #endif /* JSD_TRACE */
00085 
00086 #ifdef DEBUG
00087 void JSD_ASSERT_VALID_OBJECT(JSDObject* jsdobj)
00088 {
00089     JS_ASSERT(jsdobj);
00090     JS_ASSERT(!JS_CLIST_IS_EMPTY(&jsdobj->links));
00091     JS_ASSERT(jsdobj->obj);
00092 }
00093 #endif
00094 
00095 
00096 static void
00097 _destroyJSDObject(JSDContext* jsdc, JSDObject* jsdobj)
00098 {
00099     JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
00100 
00101     JS_REMOVE_LINK(&jsdobj->links);
00102     JS_HashTableRemove(jsdc->objectsTable, jsdobj->obj);
00103 
00104     if(jsdobj->newURL)
00105         jsd_DropAtom(jsdc, jsdobj->newURL);
00106     if(jsdobj->ctorURL)
00107         jsd_DropAtom(jsdc, jsdobj->ctorURL);
00108     if(jsdobj->ctorName)
00109         jsd_DropAtom(jsdc, jsdobj->ctorName);
00110     free(jsdobj);
00111 }
00112 
00113 static JSDObject*
00114 _createJSDObject(JSDContext* jsdc, JSContext *cx, JSObject *obj)
00115 {
00116     JSDObject* jsdobj;
00117     JSStackFrame* fp;
00118     JSStackFrame* iter = NULL;
00119     const char* newURL;
00120     jsbytecode* pc;
00121 
00122     JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
00123 
00124     jsdobj = (JSDObject*) calloc(1, sizeof(JSDObject));
00125     if (jsdobj)
00126     {
00127         JS_INIT_CLIST(&jsdobj->links);
00128         JS_APPEND_LINK(&jsdobj->links, &jsdc->objectsList);
00129         jsdobj->obj = obj;
00130         JS_HashTableAdd(jsdc->objectsTable, obj, jsdobj);
00131 
00132         if (jsdc->flags & JSD_DISABLE_OBJECT_TRACE)
00133             return jsdobj;
00134         
00135         /* walk the stack to find js frame (if any) causing creation */
00136         while (NULL != (fp = JS_FrameIterator(cx, &iter)))
00137         {
00138             if( !JS_IsNativeFrame(cx, fp) )
00139             {
00140                 JSScript* script = JS_GetFrameScript(cx, fp);
00141                 if( !script )
00142                     continue;
00143 
00144                 newURL = JS_GetScriptFilename(cx, script);
00145                 if( newURL )
00146                     jsdobj->newURL = jsd_AddAtom(jsdc, newURL);
00147 
00148                 pc = JS_GetFramePC(cx, fp);
00149                 if( pc )
00150                     jsdobj->newLineno = JS_PCToLineNumber(cx, script, pc);
00151 
00152                 break;
00153             }
00154         }
00155     }
00156     return jsdobj;
00157 }
00158 
00159 void JS_DLL_CALLBACK
00160 jsd_ObjectHook(JSContext *cx, JSObject *obj, JSBool isNew, void *closure)
00161 {
00162     JSDObject* jsdobj;
00163     JSDContext* jsdc = (JSDContext*) closure;
00164 
00165     if( ! jsdc || ! jsdc->inited )
00166         return;
00167 
00168     JSD_LOCK_OBJECTS(jsdc);
00169     if(isNew)
00170     {
00171         jsdobj = _createJSDObject(jsdc, cx, obj);
00172         TRACEOBJ(jsdc, jsdobj, 0);
00173     }
00174     else
00175     {
00176         jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
00177         if( jsdobj )
00178         {
00179             TRACEOBJ(jsdc, jsdobj, 1);
00180             _destroyJSDObject(jsdc, jsdobj);
00181         }
00182     }
00183     JSD_UNLOCK_OBJECTS(jsdc);
00184 }
00185 
00186 void
00187 jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
00188                  JSStackFrame *fp)
00189 {
00190     JSDObject* jsdobj;
00191     JSScript* script;
00192     JSDScript* jsdscript;
00193     const char* ctorURL;
00194     const char* ctorName;
00195 
00196     JSD_LOCK_OBJECTS(jsdc);
00197     jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
00198     if( jsdobj && !jsdobj->ctorURL && !JS_IsNativeFrame(cx, fp) )
00199     {
00200         script = JS_GetFrameScript(cx, fp);
00201         if( script )
00202         {
00203             ctorURL = JS_GetScriptFilename(cx, script);
00204             if( ctorURL )
00205                 jsdobj->ctorURL = jsd_AddAtom(jsdc, ctorURL);
00206 
00207             JSD_LOCK_SCRIPTS(jsdc);
00208             jsdscript = jsd_FindJSDScript(jsdc, script);
00209             JSD_UNLOCK_SCRIPTS(jsdc);
00210             if( jsdscript )
00211             {
00212                 ctorName = jsd_GetScriptFunctionName(jsdc, jsdscript);
00213                 if( ctorName )
00214                     jsdobj->ctorName = jsd_AddAtom(jsdc, ctorName);
00215             }
00216             jsdobj->ctorLineno = JS_GetScriptBaseLineNumber(cx, script);
00217         }
00218     }
00219     TRACEOBJ(jsdc, jsdobj, 3);
00220     JSD_UNLOCK_OBJECTS(jsdc);
00221 }
00222 
00223 JS_STATIC_DLL_CALLBACK(JSHashNumber)
00224 _hash_root(const void *key)
00225 {
00226     return ((JSHashNumber) key) >> 2; /* help lame MSVC1.5 on Win16 */
00227 }
00228 
00229 JSBool
00230 jsd_InitObjectManager(JSDContext* jsdc)
00231 {
00232     JS_INIT_CLIST(&jsdc->objectsList);
00233     jsdc->objectsTable = JS_NewHashTable(256, _hash_root,
00234                                          JS_CompareValues, JS_CompareValues,
00235                                          NULL, NULL);
00236     return (JSBool) jsdc->objectsTable;
00237 }
00238 
00239 void
00240 jsd_DestroyObjectManager(JSDContext* jsdc)
00241 {
00242     JSD_LOCK_OBJECTS(jsdc);
00243     while( !JS_CLIST_IS_EMPTY(&jsdc->objectsList) )
00244         _destroyJSDObject(jsdc, (JSDObject*)JS_NEXT_LINK(&jsdc->objectsList));
00245     JS_HashTableDestroy(jsdc->objectsTable);
00246     JSD_UNLOCK_OBJECTS(jsdc);
00247 }
00248 
00249 JSDObject*
00250 jsd_IterateObjects(JSDContext* jsdc, JSDObject** iterp)
00251 {
00252     JSDObject *jsdobj = *iterp;
00253 
00254     JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
00255 
00256     if( !jsdobj )
00257         jsdobj = (JSDObject *)jsdc->objectsList.next;
00258     if( jsdobj == (JSDObject *)&jsdc->objectsList )
00259         return NULL;
00260     *iterp = (JSDObject*) jsdobj->links.next;
00261     return jsdobj;
00262 }
00263 
00264 JSObject*
00265 jsd_GetWrappedObject(JSDContext* jsdc, JSDObject* jsdobj)
00266 {
00267     return jsdobj->obj;
00268 }
00269 
00270 const char*
00271 jsd_GetObjectNewURL(JSDContext* jsdc, JSDObject* jsdobj)
00272 {
00273     if( jsdobj->newURL )
00274         return JSD_ATOM_TO_STRING(jsdobj->newURL);
00275     return NULL;
00276 }
00277 
00278 uintN
00279 jsd_GetObjectNewLineNumber(JSDContext* jsdc, JSDObject* jsdobj)
00280 {
00281     return jsdobj->newLineno;
00282 }
00283 
00284 const char*
00285 jsd_GetObjectConstructorURL(JSDContext* jsdc, JSDObject* jsdobj)
00286 {
00287     if( jsdobj->ctorURL )
00288         return JSD_ATOM_TO_STRING(jsdobj->ctorURL);
00289     return NULL;
00290 }
00291 
00292 uintN
00293 jsd_GetObjectConstructorLineNumber(JSDContext* jsdc, JSDObject* jsdobj)
00294 {
00295     return jsdobj->ctorLineno;
00296 }
00297 
00298 const char*
00299 jsd_GetObjectConstructorName(JSDContext* jsdc, JSDObject* jsdobj)
00300 {
00301     if( jsdobj->ctorName )
00302         return JSD_ATOM_TO_STRING(jsdobj->ctorName);
00303     return NULL;
00304 }
00305 
00306 JSDObject*
00307 jsd_GetJSDObjectForJSObject(JSDContext* jsdc, JSObject* jsobj)
00308 {
00309     JSDObject* jsdobj;
00310 
00311     JSD_LOCK_OBJECTS(jsdc);
00312     jsdobj = (JSDObject*) JS_HashTableLookup(jsdc->objectsTable, jsobj);
00313     JSD_UNLOCK_OBJECTS(jsdc);
00314     return jsdobj;
00315 }
00316 
00317 JSDObject*
00318 jsd_GetObjectForValue(JSDContext* jsdc, JSDValue* jsdval)
00319 {
00320     return jsd_GetJSDObjectForJSObject(jsdc, JSVAL_TO_OBJECT(jsdval->val));
00321 }
00322 
00323 JSDValue*
00324 jsd_GetValueForObject(JSDContext* jsdc, JSDObject* jsdobj)
00325 {
00326     return jsd_NewValue(jsdc, OBJECT_TO_JSVAL(jsdobj->obj));
00327 }
00328 
00329