LCOV - code coverage report
Current view: directory - js/jsd - jsd_scpt.c (source / functions) Found Hit Coverage
Test: app.info Lines: 370 204 55.1 %
Date: 2012-06-02 Functions: 52 30 57.7 %

       1                 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : /*
      39                 :  * JavaScript Debugging support - Script support
      40                 :  */
      41                 : 
      42                 : #include "jsd.h"
      43                 : #include "jsfriendapi.h"
      44                 : 
      45                 : /* Comment this out to disable (NT specific) dumping as we go */
      46                 : /*
      47                 : ** #ifdef DEBUG      
      48                 : ** #define JSD_DUMP 1
      49                 : ** #endif            
      50                 : */
      51                 : 
      52                 : #define NOT_SET_YET -1
      53                 : 
      54                 : /***************************************************************************/
      55                 : 
      56                 : #ifdef DEBUG
      57          206634 : void JSD_ASSERT_VALID_SCRIPT(JSDScript* jsdscript)
      58                 : {
      59          206634 :     JS_ASSERT(jsdscript);
      60          206634 :     JS_ASSERT(jsdscript->script);
      61          206634 : }
      62               5 : void JSD_ASSERT_VALID_EXEC_HOOK(JSDExecHook* jsdhook)
      63                 : {
      64               5 :     JS_ASSERT(jsdhook);
      65               5 :     JS_ASSERT(jsdhook->hook);
      66               5 : }
      67                 : #endif
      68                 : 
      69                 : #ifdef LIVEWIRE
      70                 : static JSBool
      71                 : HasFileExtention(const char* name, const char* ext)
      72                 : {
      73                 :     int i;
      74                 :     int len = strlen(ext);
      75                 :     const char* p = strrchr(name,'.');
      76                 :     if( !p )
      77                 :         return JS_FALSE;
      78                 :     p++;
      79                 :     for(i = 0; i < len; i++ )
      80                 :     {
      81                 :         JS_ASSERT(islower(ext[i]));
      82                 :         if( 0 == p[i] || tolower(p[i]) != ext[i] )
      83                 :             return JS_FALSE;
      84                 :     }
      85                 :     if( 0 != p[i] )
      86                 :         return JS_FALSE;
      87                 :     return JS_TRUE;
      88                 : }    
      89                 : #endif /* LIVEWIRE */
      90                 : 
      91                 : static JSDScript*
      92          210393 : _newJSDScript(JSDContext*  jsdc,
      93                 :               JSContext    *cx,
      94                 :               JSScript     *script)
      95                 : {
      96                 :     JSDScript*  jsdscript;
      97                 :     unsigned     lineno;
      98                 :     const char* raw_filename;
      99                 : 
     100          210393 :     JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
     101                 : 
     102                 :     /* these are inlined javascript: urls and we can't handle them now */
     103          210393 :     lineno = (unsigned) JS_GetScriptBaseLineNumber(cx, script);
     104          210393 :     if( lineno == 0 )
     105            3820 :         return NULL;
     106                 : 
     107          206573 :     jsdscript = (JSDScript*) calloc(1, sizeof(JSDScript));
     108          206573 :     if( ! jsdscript )
     109               0 :         return NULL;
     110                 : 
     111          206573 :     raw_filename = JS_GetScriptFilename(cx,script);
     112                 : 
     113          206573 :     JS_HashTableAdd(jsdc->scriptsTable, (void *)script, (void *)jsdscript);
     114          206573 :     JS_APPEND_LINK(&jsdscript->links, &jsdc->scripts);
     115          206573 :     jsdscript->jsdc         = jsdc;
     116          206573 :     jsdscript->script       = script;  
     117          206573 :     jsdscript->lineBase     = lineno;
     118          206573 :     jsdscript->lineExtent   = (unsigned)NOT_SET_YET;
     119          206573 :     jsdscript->data         = NULL;
     120                 : #ifndef LIVEWIRE
     121          206573 :     jsdscript->url          = (char*) jsd_BuildNormalizedURL(raw_filename);
     122                 : #else
     123                 :     jsdscript->app = LWDBG_GetCurrentApp();    
     124                 :     if( jsdscript->app && raw_filename )
     125                 :     {
     126                 :         jsdscript->url = jsdlw_BuildAppRelativeFilename(jsdscript->app, raw_filename);
     127                 :         if( function )
     128                 :         {
     129                 :             JSString* funid = JS_GetFunctionId(function);
     130                 :             char* funbytes;
     131                 :             const char* funnanme;
     132                 :             if( fuinid )
     133                 :             {
     134                 :                 funbytes = JS_EncodeString(cx, funid);
     135                 :                 funname = funbytes ? funbytes : "";
     136                 :             }
     137                 :             else
     138                 :             {
     139                 :                 funbytes = NULL;
     140                 :                 funname = "anonymous";
     141                 :             }
     142                 :             jsdscript->lwscript = 
     143                 :                 LWDBG_GetScriptOfFunction(jsdscript->app,funname);
     144                 :             JS_Free(cx, funbytes);
     145                 :     
     146                 :             /* also, make sure this file is added to filelist if is .js file */
     147                 :             if( HasFileExtention(raw_filename,"js") || 
     148                 :                 HasFileExtention(raw_filename,"sjs") )
     149                 :             {
     150                 :                 jsdlw_PreLoadSource(jsdc, jsdscript->app, raw_filename, JS_FALSE);
     151                 :             }
     152                 :         }
     153                 :         else
     154                 :         {
     155                 :             jsdscript->lwscript = LWDBG_GetCurrentTopLevelScript();
     156                 :         }
     157                 :     }
     158                 : #endif
     159                 : 
     160          206573 :     JS_INIT_CLIST(&jsdscript->hooks);
     161                 :     
     162          206573 :     return jsdscript;
     163                 : }           
     164                 : 
     165                 : static void 
     166          206573 : _destroyJSDScript(JSDContext*  jsdc,
     167                 :                   JSDScript*   jsdscript)
     168                 : {
     169          206573 :     JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
     170                 : 
     171                 :     /* destroy all hooks */
     172          206573 :     jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
     173                 : 
     174          206573 :     JS_REMOVE_LINK(&jsdscript->links);
     175          206573 :     if(jsdscript->url)
     176          206573 :         free(jsdscript->url);
     177                 : 
     178          206573 :     if (jsdscript->profileData)
     179               0 :         free(jsdscript->profileData);
     180                 :     
     181          206573 :     free(jsdscript);
     182          206573 : }
     183                 : 
     184                 : /***************************************************************************/
     185                 : 
     186                 : #ifdef JSD_DUMP
     187                 : #ifndef XP_WIN
     188                 : void
     189                 : OutputDebugString (char *buf)
     190                 : {
     191                 :     fprintf (stderr, "%s", buf);
     192                 : }
     193                 : #endif
     194                 : 
     195                 : static void
     196                 : _dumpJSDScript(JSDContext* jsdc, JSDScript* jsdscript, const char* leadingtext)
     197                 : {
     198                 :     const char* name;
     199                 :     JSString* fun;
     200                 :     unsigned base;
     201                 :     unsigned extent;
     202                 :     char Buf[256];
     203                 :     size_t n;
     204                 : 
     205                 :     name   = jsd_GetScriptFilename(jsdc, jsdscript);
     206                 :     fun    = jsd_GetScriptFunctionId(jsdc, jsdscript);
     207                 :     base   = jsd_GetScriptBaseLineNumber(jsdc, jsdscript);
     208                 :     extent = jsd_GetScriptLineExtent(jsdc, jsdscript);
     209                 :     n = size_t(snprintf(Buf, sizeof(Buf), "%sscript=%08X, %s, ",
     210                 :                         leadingtext, (unsigned) jsdscript->script,
     211                 :                         name ? name : "no URL"));
     212                 :     if (n + 1 < sizeof(Buf)) {
     213                 :         if (fun) {
     214                 :             n += size_t(snprintf(Buf + n, sizeof(Buf) - n, "%s", "no fun"));
     215                 :         } else {
     216                 :             n += JS_PutEscapedFlatString(Buf + n, sizeof(Buf) - n,
     217                 :                                          JS_ASSERT_STRING_IS_FLAT(fun), 0);
     218                 :             Buf[sizeof(Buf) - 1] = '\0';
     219                 :         }
     220                 :         if (n + 1 < sizeof(Buf))
     221                 :             snprintf(Buf + n, sizeof(Buf) - n, ", %d-%d\n", base, base + extent - 1);
     222                 :     }
     223                 :     OutputDebugString( Buf );
     224                 : }
     225                 : 
     226                 : static void
     227                 : _dumpJSDScriptList( JSDContext* jsdc )
     228                 : {
     229                 :     JSDScript* iterp = NULL;
     230                 :     JSDScript* jsdscript = NULL;
     231                 :     
     232                 :     OutputDebugString( "*** JSDScriptDump\n" );
     233                 :     while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
     234                 :         _dumpJSDScript( jsdc, jsdscript, "  script: " );
     235                 : }
     236                 : #endif /* JSD_DUMP */
     237                 : 
     238                 : /***************************************************************************/
     239                 : static JSHashNumber
     240          332911 : jsd_hash_script(const void *key)
     241                 : {
     242          332911 :     return ((JSHashNumber)(ptrdiff_t) key) >> 2; /* help lame MSVC1.5 on Win16 */
     243                 : }
     244                 : 
     245                 : static void *
     246            1244 : jsd_alloc_script_table(void *priv, size_t size)
     247                 : {
     248            1244 :     return malloc(size);
     249                 : }
     250                 : 
     251                 : static void
     252            1244 : jsd_free_script_table(void *priv, void *item, size_t size)
     253                 : {
     254            1244 :     free(item);
     255            1244 : }
     256                 : 
     257                 : static JSHashEntry *
     258          206573 : jsd_alloc_script_entry(void *priv, const void *item)
     259                 : {
     260          206573 :     return (JSHashEntry*) malloc(sizeof(JSHashEntry));
     261                 : }
     262                 : 
     263                 : static void
     264          206573 : jsd_free_script_entry(void *priv, JSHashEntry *he, unsigned flag)
     265                 : {
     266          206573 :     if (flag == HT_FREE_ENTRY)
     267                 :     {
     268          206573 :         _destroyJSDScript((JSDContext*) priv, (JSDScript*) he->value);
     269          206573 :         free(he);
     270                 :     }
     271          206573 : }
     272                 : 
     273                 : static JSHashAllocOps script_alloc_ops = {
     274                 :     jsd_alloc_script_table, jsd_free_script_table,
     275                 :     jsd_alloc_script_entry, jsd_free_script_entry
     276                 : };
     277                 : 
     278                 : #ifndef JSD_SCRIPT_HASH_SIZE
     279                 : #define JSD_SCRIPT_HASH_SIZE 1024
     280                 : #endif
     281                 : 
     282                 : JSBool
     283             280 : jsd_InitScriptManager(JSDContext* jsdc)
     284                 : {
     285             280 :     JS_INIT_CLIST(&jsdc->scripts);
     286             280 :     jsdc->scriptsTable = JS_NewHashTable(JSD_SCRIPT_HASH_SIZE, jsd_hash_script,
     287                 :                                          JS_CompareValues, JS_CompareValues,
     288                 :                                          &script_alloc_ops, (void*) jsdc);
     289             280 :     return !!jsdc->scriptsTable;
     290                 : }
     291                 : 
     292                 : void
     293             280 : jsd_DestroyScriptManager(JSDContext* jsdc)
     294                 : {
     295             280 :     JSD_LOCK_SCRIPTS(jsdc);
     296             280 :     if (jsdc->scriptsTable)
     297             280 :         JS_HashTableDestroy(jsdc->scriptsTable);
     298             280 :     JSD_UNLOCK_SCRIPTS(jsdc);
     299             280 : }
     300                 : 
     301                 : JSDScript*
     302           71112 : jsd_FindJSDScript( JSDContext*  jsdc,
     303                 :                    JSScript     *script )
     304                 : {
     305           71112 :     JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
     306           71112 :     return (JSDScript*) JS_HashTableLookup(jsdc->scriptsTable, (void *)script);
     307                 : }
     308                 : 
     309                 : JSDScript *
     310               0 : jsd_FindOrCreateJSDScript(JSDContext    *jsdc,
     311                 :                           JSContext     *cx,
     312                 :                           JSScript      *script,
     313                 :                           JSStackFrame  *fp)
     314                 : {
     315                 :     JSDScript *jsdscript;
     316               0 :     JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
     317                 : 
     318               0 :     jsdscript = jsd_FindJSDScript(jsdc, script);
     319               0 :     if (jsdscript)
     320               0 :         return jsdscript;
     321                 : 
     322                 :     /* Fallback for unknown scripts: create a new script. */
     323               0 :     if (!fp)
     324               0 :         JS_FrameIterator(cx, &fp);
     325               0 :     if (fp)
     326               0 :         jsdscript = _newJSDScript(jsdc, cx, script);
     327                 : 
     328               0 :     return jsdscript;
     329                 : }
     330                 : 
     331                 : JSDProfileData*
     332               0 : jsd_GetScriptProfileData(JSDContext* jsdc, JSDScript *script)
     333                 : {
     334               0 :     if (!script->profileData)
     335               0 :         script->profileData = (JSDProfileData*)calloc(1, sizeof(JSDProfileData));
     336                 : 
     337               0 :     return script->profileData;
     338                 : }
     339                 : 
     340                 : uint32_t
     341               0 : jsd_GetScriptFlags(JSDContext *jsdc, JSDScript *script)
     342                 : {
     343               0 :     return script->flags;
     344                 : }
     345                 : 
     346                 : void
     347               0 : jsd_SetScriptFlags(JSDContext *jsdc, JSDScript *script, uint32_t flags)
     348                 : {
     349               0 :     script->flags = flags;
     350               0 : }
     351                 : 
     352                 : unsigned
     353               0 : jsd_GetScriptCallCount(JSDContext* jsdc, JSDScript *script)
     354                 : {
     355               0 :     if (script->profileData)
     356               0 :         return script->profileData->callCount;
     357                 : 
     358               0 :     return 0;
     359                 : }
     360                 : 
     361                 : unsigned
     362               0 : jsd_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script)
     363                 : {
     364               0 :     if (script->profileData)
     365               0 :         return script->profileData->maxRecurseDepth;
     366                 : 
     367               0 :     return 0;
     368                 : }
     369                 : 
     370                 : double
     371               0 : jsd_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script)
     372                 : {
     373               0 :     if (script->profileData)
     374               0 :         return script->profileData->minExecutionTime;
     375                 : 
     376               0 :     return 0.0;
     377                 : }
     378                 : 
     379                 : double
     380               0 : jsd_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script)
     381                 : {
     382               0 :     if (script->profileData)
     383               0 :         return script->profileData->maxExecutionTime;
     384                 : 
     385               0 :     return 0.0;
     386                 : }
     387                 : 
     388                 : double
     389               0 : jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script)
     390                 : {
     391               0 :     if (script->profileData)
     392               0 :         return script->profileData->totalExecutionTime;
     393                 : 
     394               0 :     return 0.0;
     395                 : }
     396                 : 
     397                 : double
     398               0 : jsd_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
     399                 : {
     400               0 :     if (script->profileData)
     401               0 :         return script->profileData->minOwnExecutionTime;
     402                 : 
     403               0 :     return 0.0;
     404                 : }
     405                 : 
     406                 : double
     407               0 : jsd_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
     408                 : {
     409               0 :     if (script->profileData)
     410               0 :         return script->profileData->maxOwnExecutionTime;
     411                 : 
     412               0 :     return 0.0;
     413                 : }
     414                 : 
     415                 : double
     416               0 : jsd_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
     417                 : {
     418               0 :     if (script->profileData)
     419               0 :         return script->profileData->totalOwnExecutionTime;
     420                 : 
     421               0 :     return 0.0;
     422                 : }
     423                 : 
     424                 : void
     425               0 : jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script)
     426                 : {
     427               0 :     if (script->profileData)
     428                 :     {
     429               0 :         free(script->profileData);
     430               0 :         script->profileData = NULL;
     431                 :     }
     432               0 : }    
     433                 : 
     434                 : JSScript *
     435               0 : jsd_GetJSScript (JSDContext *jsdc, JSDScript *script)
     436                 : {
     437               0 :     return script->script;
     438                 : }
     439                 : 
     440                 : JSFunction *
     441               6 : jsd_GetJSFunction (JSDContext *jsdc, JSDScript *script)
     442                 : {
     443               6 :     return JS_GetScriptFunction(jsdc->dumbContext, script->script);
     444                 : }
     445                 : 
     446                 : JSDScript*
     447          303261 : jsd_IterateScripts(JSDContext* jsdc, JSDScript **iterp)
     448                 : {
     449          303261 :     JSDScript *jsdscript = *iterp;
     450                 :     
     451          303261 :     JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
     452                 : 
     453          303261 :     if( !jsdscript )
     454             561 :         jsdscript = (JSDScript *)jsdc->scripts.next;
     455          303261 :     if( jsdscript == (JSDScript *)&jsdc->scripts )
     456             561 :         return NULL;
     457          302700 :     *iterp = (JSDScript*) jsdscript->links.next;
     458          302700 :     return jsdscript;
     459                 : }
     460                 : 
     461                 : void *
     462              12 : jsd_SetScriptPrivate(JSDScript *jsdscript, void *data)
     463                 : {
     464              12 :     void *rval = jsdscript->data;
     465              12 :     jsdscript->data = data;
     466              12 :     return rval;
     467                 : }
     468                 : 
     469                 : void *
     470          206585 : jsd_GetScriptPrivate(JSDScript *jsdscript)
     471                 : {
     472          206585 :     return jsdscript->data;
     473                 : }
     474                 : 
     475                 : JSBool
     476               0 : jsd_IsActiveScript(JSDContext* jsdc, JSDScript *jsdscript)
     477                 : {
     478                 :     JSDScript *current;
     479                 : 
     480               0 :     JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
     481                 : 
     482               0 :     for( current = (JSDScript *)jsdc->scripts.next;
     483               0 :          current != (JSDScript *)&jsdc->scripts;
     484               0 :          current = (JSDScript *)current->links.next )
     485                 :     {
     486               0 :         if(jsdscript == current)
     487               0 :             return JS_TRUE;
     488                 :     }
     489               0 :     return JS_FALSE;
     490                 : }        
     491                 : 
     492                 : const char*
     493               7 : jsd_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript)
     494                 : {
     495               7 :     return jsdscript->url;
     496                 : }
     497                 : 
     498                 : JSString*
     499               6 : jsd_GetScriptFunctionId(JSDContext* jsdc, JSDScript *jsdscript)
     500                 : {
     501                 :     JSString* str;
     502               6 :     JSFunction *fun = jsd_GetJSFunction(jsdc, jsdscript);
     503                 : 
     504               6 :     if( ! fun )
     505               2 :         return NULL;
     506               4 :     str = JS_GetFunctionId(fun);
     507                 : 
     508                 :     /* For compatibility we return "anonymous", not an empty string here. */
     509               4 :     return str ? str : JS_GetAnonymousString(jsdc->jsrt);
     510                 : }
     511                 : 
     512                 : unsigned
     513               6 : jsd_GetScriptBaseLineNumber(JSDContext* jsdc, JSDScript *jsdscript)
     514                 : {
     515               6 :     return jsdscript->lineBase;
     516                 : }
     517                 : 
     518                 : unsigned
     519               6 : jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript)
     520                 : {
     521               6 :     if( NOT_SET_YET == (int)jsdscript->lineExtent )
     522               6 :         jsdscript->lineExtent = JS_GetScriptLineExtent(jsdc->dumbContext, jsdscript->script);
     523               6 :     return jsdscript->lineExtent;
     524                 : }
     525                 : 
     526                 : uintptr_t
     527               6 : jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, unsigned line)
     528                 : {
     529                 :     uintptr_t pc;
     530                 :     JSCrossCompartmentCall *call;
     531                 : 
     532               6 :     if( !jsdscript )
     533               0 :         return 0;
     534                 : #ifdef LIVEWIRE
     535                 :     if( jsdscript->lwscript )
     536                 :     {
     537                 :         unsigned newline;
     538                 :         jsdlw_RawToProcessedLineNumber(jsdc, jsdscript, line, &newline);
     539                 :         if( line != newline )
     540                 :             line = newline;
     541                 :     }
     542                 : #endif
     543                 : 
     544               6 :     call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
     545               6 :     if(!call)
     546               0 :         return 0;
     547               6 :     pc = (uintptr_t) JS_LineNumberToPC(jsdc->dumbContext, jsdscript->script, line );
     548               6 :     JS_LeaveCrossCompartmentCall(call);
     549               6 :     return pc;
     550                 : }
     551                 : 
     552                 : unsigned
     553               0 : jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, uintptr_t pc)
     554                 : {
     555                 :     JSCrossCompartmentCall *call;
     556               0 :     unsigned first = jsdscript->lineBase;
     557               0 :     unsigned last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1;
     558               0 :     unsigned line = 0;
     559                 : 
     560               0 :     call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
     561               0 :     if(!call)
     562               0 :         return 0;
     563               0 :     if (pc)
     564               0 :         line = JS_PCToLineNumber(jsdc->dumbContext, jsdscript->script, (jsbytecode*)pc);
     565               0 :     JS_LeaveCrossCompartmentCall(call);
     566                 : 
     567               0 :     if( line < first )
     568               0 :         return first;
     569               0 :     if( line > last )
     570               0 :         return last;
     571                 : 
     572                 : #ifdef LIVEWIRE
     573                 :     if( jsdscript && jsdscript->lwscript )
     574                 :     {
     575                 :         unsigned newline;
     576                 :         jsdlw_ProcessedToRawLineNumber(jsdc, jsdscript, line, &newline);
     577                 :         line = newline;
     578                 :     }
     579                 : #endif
     580                 : 
     581               0 :     return line;    
     582                 : }
     583                 : 
     584                 : JSBool
     585               0 : jsd_GetLinePCs(JSDContext* jsdc, JSDScript* jsdscript,
     586                 :                unsigned startLine, unsigned maxLines,
     587                 :                unsigned* count, unsigned** retLines, uintptr_t** retPCs)
     588                 : {
     589                 :     JSCrossCompartmentCall *call;
     590               0 :     unsigned first = jsdscript->lineBase;
     591               0 :     unsigned last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1;
     592                 :     JSBool ok;
     593                 :     unsigned *lines;
     594                 :     jsbytecode **pcs;
     595                 :     unsigned i;
     596                 : 
     597               0 :     if (last < startLine)
     598               0 :         return JS_TRUE;
     599                 : 
     600               0 :     call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
     601               0 :     if (!call)
     602               0 :         return JS_FALSE;
     603                 : 
     604               0 :     ok = JS_GetLinePCs(jsdc->dumbContext, jsdscript->script,
     605                 :                        startLine, maxLines,
     606                 :                        count, retLines, &pcs);
     607                 : 
     608               0 :     if (ok) {
     609               0 :         if (retPCs) {
     610               0 :             for (i = 0; i < *count; ++i) {
     611               0 :                 (*retPCs)[i] = (*pcs)[i];
     612                 :             }
     613                 :         }
     614                 : 
     615               0 :         JS_free(jsdc->dumbContext, pcs);
     616                 :     }
     617                 : 
     618               0 :     JS_LeaveCrossCompartmentCall(call);
     619               0 :     return ok;
     620                 : }
     621                 : 
     622                 : JSBool
     623             560 : jsd_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata)
     624                 : {
     625             560 :     JSD_LOCK();
     626             560 :     jsdc->scriptHook = hook;
     627             560 :     jsdc->scriptHookData = callerdata;
     628             560 :     JSD_UNLOCK();
     629             560 :     return JS_TRUE;
     630                 : }
     631                 : 
     632                 : JSBool
     633               0 : jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata)
     634                 : {
     635               0 :     JSD_LOCK();
     636               0 :     if( hook )
     637               0 :         *hook = jsdc->scriptHook;
     638               0 :     if( callerdata )
     639               0 :         *callerdata = jsdc->scriptHookData;
     640               0 :     JSD_UNLOCK();
     641               0 :     return JS_TRUE;
     642                 : }    
     643                 : 
     644                 : JSBool
     645               0 : jsd_EnableSingleStepInterrupts(JSDContext* jsdc, JSDScript* jsdscript, JSBool enable)
     646                 : {
     647                 :     JSCrossCompartmentCall *call;
     648                 :     JSBool rv;
     649               0 :     call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
     650               0 :     if(!call)
     651               0 :         return JS_FALSE;
     652               0 :     JSD_LOCK();
     653               0 :     rv = JS_SetSingleStepMode(jsdc->dumbContext, jsdscript->script, enable);
     654               0 :     JSD_UNLOCK();
     655               0 :     JS_LeaveCrossCompartmentCall(call);
     656               0 :     return rv;
     657                 : }
     658                 : 
     659                 : 
     660                 : /***************************************************************************/
     661                 : 
     662                 : void
     663          210393 : jsd_NewScriptHookProc( 
     664                 :                 JSContext   *cx,
     665                 :                 const char  *filename,      /* URL this script loads from */
     666                 :                 unsigned       lineno,         /* line where this script starts */
     667                 :                 JSScript    *script,
     668                 :                 JSFunction  *fun,                
     669                 :                 void*       callerdata )
     670                 : {
     671          210393 :     JSDScript* jsdscript = NULL;
     672          210393 :     JSDContext* jsdc = (JSDContext*) callerdata;
     673                 :     JSD_ScriptHookProc      hook;
     674                 :     void*                   hookData;
     675                 :     
     676          210393 :     JSD_ASSERT_VALID_CONTEXT(jsdc);
     677                 : 
     678                 :     if( JSD_IS_DANGEROUS_THREAD(jsdc) )
     679                 :         return;
     680                 :     
     681          210393 :     JSD_LOCK_SCRIPTS(jsdc);
     682          210393 :     jsdscript = _newJSDScript(jsdc, cx, script);
     683          210393 :     JSD_UNLOCK_SCRIPTS(jsdc);
     684          210393 :     if( ! jsdscript )
     685            3820 :         return;
     686                 : 
     687                 : #ifdef JSD_DUMP
     688                 :     JSD_LOCK_SCRIPTS(jsdc);
     689                 :     _dumpJSDScript(jsdc, jsdscript, "***NEW Script: ");
     690                 :     _dumpJSDScriptList( jsdc );
     691                 :     JSD_UNLOCK_SCRIPTS(jsdc);
     692                 : #endif /* JSD_DUMP */
     693                 : 
     694                 :     /* local in case jsdc->scriptHook gets cleared on another thread */
     695          206573 :     JSD_LOCK();
     696          206573 :     hook = jsdc->scriptHook;
     697          206573 :     hookData = jsdc->scriptHookData;
     698          206573 :     JSD_UNLOCK();
     699                 : 
     700          206573 :     if( hook )
     701          206573 :         hook(jsdc, jsdscript, JS_TRUE, hookData);
     702                 : }
     703                 : 
     704                 : void
     705           71086 : jsd_DestroyScriptHookProc( 
     706                 :                 JSContext   *cx,
     707                 :                 JSScript    *script,
     708                 :                 void*       callerdata )
     709                 : {
     710           71086 :     JSDScript* jsdscript = NULL;
     711           71086 :     JSDContext* jsdc = (JSDContext*) callerdata;
     712                 :     JSD_ScriptHookProc      hook;
     713                 :     void*                   hookData;
     714                 :     
     715           71086 :     JSD_ASSERT_VALID_CONTEXT(jsdc);
     716                 : 
     717                 :     if( JSD_IS_DANGEROUS_THREAD(jsdc) )
     718                 :         return;
     719                 :     
     720           71086 :     JSD_LOCK_SCRIPTS(jsdc);
     721           71086 :     jsdscript = jsd_FindJSDScript(jsdc, script);
     722           71086 :     JSD_UNLOCK_SCRIPTS(jsdc);
     723                 : 
     724           71086 :     if( ! jsdscript )
     725           15860 :         return;
     726                 : 
     727                 : #ifdef JSD_DUMP
     728                 :     JSD_LOCK_SCRIPTS(jsdc);
     729                 :     _dumpJSDScript(jsdc, jsdscript, "***DESTROY Script: ");
     730                 :     JSD_UNLOCK_SCRIPTS(jsdc);
     731                 : #endif /* JSD_DUMP */
     732                 : 
     733                 :     /* local in case hook gets cleared on another thread */
     734           55226 :     JSD_LOCK();
     735           55226 :     hook = jsdc->scriptHook;
     736           55226 :     hookData = jsdc->scriptHookData;
     737           55226 :     JSD_UNLOCK();
     738                 : 
     739           55226 :     if( hook )
     740           55226 :         hook(jsdc, jsdscript, JS_FALSE, hookData);
     741                 : 
     742           55226 :     JSD_LOCK_SCRIPTS(jsdc);
     743           55226 :     JS_HashTableRemove(jsdc->scriptsTable, (void *)script);
     744           55226 :     JSD_UNLOCK_SCRIPTS(jsdc);
     745                 : 
     746                 : #ifdef JSD_DUMP
     747                 :     JSD_LOCK_SCRIPTS(jsdc);
     748                 :     _dumpJSDScriptList(jsdc);
     749                 :     JSD_UNLOCK_SCRIPTS(jsdc);
     750                 : #endif /* JSD_DUMP */
     751                 : }                
     752                 : 
     753                 : 
     754                 : /***************************************************************************/
     755                 : 
     756                 : static JSDExecHook*
     757               6 : _findHook(JSDContext* jsdc, JSDScript* jsdscript, uintptr_t pc)
     758                 : {
     759                 :     JSDExecHook* jsdhook;
     760               6 :     JSCList* list = &jsdscript->hooks;
     761                 : 
     762              12 :     for( jsdhook = (JSDExecHook*)list->next;
     763               6 :          jsdhook != (JSDExecHook*)list;
     764               0 :          jsdhook = (JSDExecHook*)jsdhook->links.next )
     765                 :     {
     766               0 :         if (jsdhook->pc == pc)
     767               0 :             return jsdhook;
     768                 :     }
     769               6 :     return NULL;
     770                 : }
     771                 : 
     772                 : static JSBool
     773               5 : _isActiveHook(JSDContext* jsdc, JSScript *script, JSDExecHook* jsdhook)
     774                 : {
     775                 :     JSDExecHook* current;
     776                 :     JSCList* list;
     777                 :     JSDScript* jsdscript;
     778                 : 
     779               5 :     JSD_LOCK_SCRIPTS(jsdc);
     780               5 :     jsdscript = jsd_FindJSDScript(jsdc, script);
     781               5 :     if( ! jsdscript)
     782                 :     {
     783               0 :         JSD_UNLOCK_SCRIPTS(jsdc);
     784               0 :         return JS_FALSE;
     785                 :     }
     786                 : 
     787               5 :     list = &jsdscript->hooks;
     788                 : 
     789              10 :     for( current = (JSDExecHook*)list->next;
     790               5 :          current != (JSDExecHook*)list;
     791               0 :          current = (JSDExecHook*)current->links.next )
     792                 :     {
     793               5 :         if(current == jsdhook)
     794                 :         {
     795               5 :             JSD_UNLOCK_SCRIPTS(jsdc);
     796               5 :             return JS_TRUE;
     797                 :         }
     798                 :     }
     799               0 :     JSD_UNLOCK_SCRIPTS(jsdc);
     800               0 :     return JS_FALSE;
     801                 : }
     802                 : 
     803                 : 
     804                 : JSTrapStatus
     805               5 : jsd_TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
     806                 :                 jsval closure)
     807                 : {
     808               5 :     JSDExecHook* jsdhook = (JSDExecHook*) JSVAL_TO_PRIVATE(closure);
     809                 :     JSD_ExecutionHookProc hook;
     810                 :     void* hookData;
     811                 :     JSDContext*  jsdc;
     812                 :     JSDScript* jsdscript;
     813                 : 
     814               5 :     JSD_LOCK();
     815                 : 
     816              10 :     if( NULL == (jsdc = jsd_JSDContextForJSContext(cx)) ||
     817               5 :         ! _isActiveHook(jsdc, script, jsdhook) )
     818                 :     {
     819               0 :         JSD_UNLOCK();
     820               0 :         return JSTRAP_CONTINUE;
     821                 :     }
     822                 : 
     823               5 :     JSD_ASSERT_VALID_EXEC_HOOK(jsdhook);
     824               5 :     JS_ASSERT(!jsdhook->pc || jsdhook->pc == (uintptr_t)pc);
     825               5 :     JS_ASSERT(jsdhook->jsdscript->script == script);
     826               5 :     JS_ASSERT(jsdhook->jsdscript->jsdc == jsdc);
     827                 : 
     828               5 :     hook = jsdhook->hook;
     829               5 :     hookData = jsdhook->callerdata;
     830               5 :     jsdscript = jsdhook->jsdscript;
     831                 : 
     832                 :     /* do not use jsdhook-> after this point */
     833               5 :     JSD_UNLOCK();
     834                 : 
     835               5 :     if( ! jsdc || ! jsdc->inited )
     836               0 :         return JSTRAP_CONTINUE;
     837                 : 
     838                 :     if( JSD_IS_DANGEROUS_THREAD(jsdc) )
     839                 :         return JSTRAP_CONTINUE;
     840                 : 
     841                 : #ifdef LIVEWIRE
     842                 :     if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (uintptr_t)pc) )
     843                 :         return JSTRAP_CONTINUE;
     844                 : #endif
     845                 : 
     846               5 :     return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_BREAKPOINT,
     847                 :                                  hook, hookData, rval);
     848                 : }
     849                 : 
     850                 : 
     851                 : 
     852                 : JSBool
     853               6 : jsd_SetExecutionHook(JSDContext*           jsdc, 
     854                 :                      JSDScript*            jsdscript,
     855                 :                      uintptr_t             pc,
     856                 :                      JSD_ExecutionHookProc hook,
     857                 :                      void*                 callerdata)
     858                 : {
     859                 :     JSDExecHook* jsdhook;
     860                 :     JSBool rv;
     861                 :     JSCrossCompartmentCall *call;
     862                 : 
     863               6 :     JSD_LOCK();
     864               6 :     if( ! hook )
     865                 :     {
     866               0 :         jsd_ClearExecutionHook(jsdc, jsdscript, pc);
     867               0 :         JSD_UNLOCK();
     868               0 :         return JS_TRUE;
     869                 :     }
     870                 : 
     871               6 :     jsdhook = _findHook(jsdc, jsdscript, pc);
     872               6 :     if( jsdhook )
     873                 :     {
     874               0 :         jsdhook->hook       = hook;
     875               0 :         jsdhook->callerdata = callerdata;
     876               0 :         JSD_UNLOCK();
     877               0 :         return JS_TRUE;
     878                 :     }
     879                 :     /* else... */
     880                 : 
     881               6 :     jsdhook = (JSDExecHook*)calloc(1, sizeof(JSDExecHook));
     882               6 :     if( ! jsdhook ) {
     883               0 :         JSD_UNLOCK();
     884               0 :         return JS_FALSE;
     885                 :     }
     886               6 :     jsdhook->jsdscript  = jsdscript;
     887               6 :     jsdhook->pc         = pc;
     888               6 :     jsdhook->hook       = hook;
     889               6 :     jsdhook->callerdata = callerdata;
     890                 : 
     891               6 :     call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
     892               6 :     if(!call) {
     893               0 :         free(jsdhook);
     894               0 :         JSD_UNLOCK();
     895               0 :         return JS_FALSE;
     896                 :     }
     897                 : 
     898               6 :     rv = JS_SetTrap(jsdc->dumbContext, jsdscript->script, 
     899                 :                     (jsbytecode*)pc, jsd_TrapHandler,
     900                 :                     PRIVATE_TO_JSVAL(jsdhook));
     901                 : 
     902               6 :     JS_LeaveCrossCompartmentCall(call);
     903                 : 
     904               6 :     if ( ! rv ) {
     905               0 :         free(jsdhook);
     906               0 :         JSD_UNLOCK();
     907               0 :         return JS_FALSE;
     908                 :     }
     909                 : 
     910               6 :     JS_APPEND_LINK(&jsdhook->links, &jsdscript->hooks);
     911               6 :     JSD_UNLOCK();
     912                 : 
     913               6 :     return JS_TRUE;
     914                 : }
     915                 : 
     916                 : JSBool
     917               0 : jsd_ClearExecutionHook(JSDContext*           jsdc, 
     918                 :                        JSDScript*            jsdscript,
     919                 :                        uintptr_t             pc)
     920                 : {
     921                 :     JSCrossCompartmentCall *call;
     922                 :     JSDExecHook* jsdhook;
     923                 : 
     924               0 :     JSD_LOCK();
     925                 : 
     926               0 :     jsdhook = _findHook(jsdc, jsdscript, pc);
     927               0 :     if( ! jsdhook )
     928                 :     {
     929               0 :         JSD_UNLOCK();
     930               0 :         return JS_FALSE;
     931                 :     }
     932                 : 
     933               0 :     call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script);
     934               0 :     if(!call) {
     935               0 :         JSD_UNLOCK();
     936               0 :         return JS_FALSE;
     937                 :     }
     938                 : 
     939               0 :     JS_ClearTrap(jsdc->dumbContext, jsdscript->script, 
     940                 :                  (jsbytecode*)pc, NULL, NULL );
     941                 : 
     942               0 :     JS_LeaveCrossCompartmentCall(call);
     943                 : 
     944               0 :     JS_REMOVE_LINK(&jsdhook->links);
     945               0 :     free(jsdhook);
     946                 : 
     947               0 :     JSD_UNLOCK();
     948               0 :     return JS_TRUE;
     949                 : }
     950                 : 
     951                 : JSBool
     952          357920 : jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript)
     953                 : {
     954                 :     JSDExecHook* jsdhook;
     955          357920 :     JSCList* list = &jsdscript->hooks;
     956                 : 
     957          357920 :     JSD_LOCK();
     958                 : 
     959          715846 :     while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) )
     960                 :     {
     961               6 :         JS_REMOVE_LINK(&jsdhook->links);
     962               6 :         free(jsdhook);
     963                 :     }
     964                 : 
     965                 :     /* No cross-compartment call here because we may be in the middle of GC */
     966          357920 :     JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script);
     967          357920 :     JSD_UNLOCK();
     968                 : 
     969          357920 :     return JS_TRUE;
     970                 : }
     971                 : 
     972                 : JSBool
     973             280 : jsd_ClearAllExecutionHooks(JSDContext* jsdc)
     974                 : {
     975                 :     JSDScript* jsdscript;
     976             280 :     JSDScript* iterp = NULL;
     977                 : 
     978             280 :     JSD_LOCK();
     979          151907 :     while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
     980          151347 :         jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
     981             280 :     JSD_UNLOCK();
     982             280 :     return JS_TRUE;
     983                 : }
     984                 : 
     985                 : void
     986               0 : jsd_ScriptCreated(JSDContext* jsdc,
     987                 :                   JSContext   *cx,
     988                 :                   const char  *filename,    /* URL this script loads from */
     989                 :                   unsigned       lineno,       /* line where this script starts */
     990                 :                   JSScript    *script,
     991                 :                   JSFunction  *fun)
     992                 : {
     993               0 :     jsd_NewScriptHookProc(cx, filename, lineno, script, fun, jsdc);
     994               0 : }
     995                 : 
     996                 : void
     997               0 : jsd_ScriptDestroyed(JSDContext* jsdc,
     998                 :                     JSContext   *cx,
     999                 :                     JSScript    *script)
    1000                 : {
    1001               0 :     jsd_DestroyScriptHookProc(cx, script, jsdc);
    1002               0 : }

Generated by: LCOV version 1.7