js/src/devtools/rootAnalysis/annotations.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: Javascript; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     3 "use strict";
     5 // Ignore calls made through these function pointers
     6 var ignoreIndirectCalls = {
     7     "mallocSizeOf" : true,
     8     "aMallocSizeOf" : true,
     9     "_malloc_message" : true,
    10     "__conv" : true,
    11     "__convf" : true,
    12     "prerrortable.c:callback_newtable" : true,
    13     "mozalloc_oom.cpp:void (* gAbortHandler)(size_t)" : true,
    15     // I don't know why these are getting truncated
    16     "nsTraceRefcnt.cpp:void (* leakyLogAddRef)(void*": true,
    17     "nsTraceRefcnt.cpp:void (* leakyLogAddRef)(void*, int, int)": true,
    18     "nsTraceRefcnt.cpp:void (* leakyLogRelease)(void*": true,
    19     "nsTraceRefcnt.cpp:void (* leakyLogRelease)(void*, int, int)": true,
    20 };
    22 function indirectCallCannotGC(fullCaller, fullVariable)
    23 {
    24     var caller = readable(fullCaller);
    26     // This is usually a simple variable name, but sometimes a full name gets
    27     // passed through. And sometimes that name is truncated. Examples:
    28     //   _ZL13gAbortHandler|mozalloc_oom.cpp:void (* gAbortHandler)(size_t)
    29     //   _ZL14pMutexUnlockFn|umutex.cpp:void (* pMutexUnlockFn)(const void*
    30     var name = readable(fullVariable);
    32     if (name in ignoreIndirectCalls)
    33         return true;
    35     if (name == "mapper" && caller == "ptio.c:pt_MapError")
    36         return true;
    38     if (name == "params" && caller == "PR_ExplodeTime")
    39         return true;
    41     if (name == "op" && /GetWeakmapKeyDelegate/.test(caller))
    42         return true;
    44     var CheckCallArgs = "AsmJS.cpp:uint8 CheckCallArgs(FunctionCompiler*, js::frontend::ParseNode*, (uint8)(FunctionCompiler*,js::frontend::ParseNode*,Type)*, FunctionCompiler::Call*)";
    45     if (name == "checkArg" && caller == CheckCallArgs)
    46         return true;
    48     // hook called during script finalization which cannot GC.
    49     if (/CallDestroyScriptHook/.test(caller))
    50         return true;
    52     // template method called during marking and hence cannot GC
    53     if (name == "op" && caller.indexOf("bool js::WeakMap<Key, Value, HashPolicy>::keyNeedsMark(JSObject*)") != -1)
    54     {
    55         return true;
    56     }
    58     return false;
    59 }
    61 // Ignore calls through functions pointers with these types
    62 var ignoreClasses = {
    63     "JSTracer" : true,
    64     "JSStringFinalizer" : true,
    65     "SprintfState" : true,
    66     "SprintfStateStr" : true,
    67     "JSLocaleCallbacks" : true,
    68     "JSC::ExecutableAllocator" : true,
    69     "PRIOMethods": true,
    70     "XPCOMFunctions" : true, // I'm a little unsure of this one
    71     "_MD_IOVector" : true,
    72 };
    74 // Ignore calls through TYPE.FIELD, where TYPE is the class or struct name containing
    75 // a function pointer field named FIELD.
    76 var ignoreCallees = {
    77     "js::Class.trace" : true,
    78     "js::Class.finalize" : true,
    79     "JSRuntime.destroyPrincipals" : true,
    80     "icu_50::UObject.__deleting_dtor" : true, // destructors in ICU code can't cause GC
    81     "mozilla::CycleCollectedJSRuntime.DescribeCustomObjects" : true, // During tracing, cannot GC.
    82     "mozilla::CycleCollectedJSRuntime.NoteCustomGCThingXPCOMChildren" : true, // During tracing, cannot GC.
    83     "PLDHashTableOps.hashKey" : true,
    84     "z_stream_s.zfree" : true,
    85 };
    87 function fieldCallCannotGC(csu, fullfield)
    88 {
    89     if (csu in ignoreClasses)
    90         return true;
    91     if (fullfield in ignoreCallees)
    92         return true;
    93     return false;
    94 }
    96 function ignoreEdgeUse(edge, variable)
    97 {
    98     // Functions which should not be treated as using variable.
    99     if (edge.Kind == "Call") {
   100         var callee = edge.Exp[0];
   101         if (callee.Kind == "Var") {
   102             var name = callee.Variable.Name[0];
   103             if (/~Anchor/.test(name))
   104                 return true;
   105             if (/~DebugOnly/.test(name))
   106                 return true;
   107             if (/~ScopedThreadSafeStringInspector/.test(name))
   108                 return true;
   109         }
   110     }
   112     return false;
   113 }
   115 function ignoreEdgeAddressTaken(edge)
   116 {
   117     // Functions which may take indirect pointers to unrooted GC things,
   118     // but will copy them into rooted locations before calling anything
   119     // that can GC. These parameters should usually be replaced with
   120     // handles or mutable handles.
   121     if (edge.Kind == "Call") {
   122         var callee = edge.Exp[0];
   123         if (callee.Kind == "Var") {
   124             var name = callee.Variable.Name[0];
   125             if (/js::Invoke\(/.test(name))
   126                 return true;
   127         }
   128     }
   130     return false;
   131 }
   133 // Ignore calls of these functions (so ignore any stack containing these)
   134 var ignoreFunctions = {
   135     "ptio.c:pt_MapError" : true,
   136     "PR_ExplodeTime" : true,
   137     "PR_ErrorInstallTable" : true,
   138     "PR_SetThreadPrivate" : true,
   139     "JSObject* js::GetWeakmapKeyDelegate(JSObject*)" : true, // FIXME: mark with AutoAssertNoGC instead
   140     "uint8 NS_IsMainThread()" : true,
   142     // FIXME!
   143     "NS_LogInit": true,
   144     "NS_LogTerm": true,
   145     "NS_LogAddRef": true,
   146     "NS_LogRelease": true,
   147     "NS_LogCtor": true,
   148     "NS_LogDtor": true,
   149     "NS_LogCOMPtrAddRef": true,
   150     "NS_LogCOMPtrRelease": true,
   152     // FIXME!
   153     "NS_DebugBreak": true,
   155     // These are a little overzealous -- these destructors *can* GC if they end
   156     // up wrapping a pending exception. See bug 898815 for the heavyweight fix.
   157     "void js::AutoCompartment::~AutoCompartment(int32)" : true,
   158     "void JSAutoCompartment::~JSAutoCompartment(int32)" : true,
   160     // Bug 948646 - the only thing AutoJSContext's constructor calls
   161     // is an Init() routine whose entire body is covered with an
   162     // AutoAssertNoGC. AutoSafeJSContext is the same thing, just with
   163     // a different value for the 'aSafe' parameter.
   164     "void mozilla::AutoJSContext::AutoJSContext(mozilla::detail::GuardObjectNotifier*)" : true,
   165     "void mozilla::AutoSafeJSContext::~AutoSafeJSContext(int32)" : true,
   167     // And these are workarounds to avoid even more analysis work,
   168     // which would sadly still be needed even with bug 898815.
   169     "void js::AutoCompartment::AutoCompartment(js::ExclusiveContext*, JSCompartment*)": true,
   170 };
   172 function ignoreGCFunction(mangled)
   173 {
   174     assert(mangled in readableNames);
   175     var fun = readableNames[mangled][0];
   177     if (fun in ignoreFunctions)
   178         return true;
   180     // Templatized function
   181     if (fun.indexOf("void nsCOMPtr<T>::Assert_NoQueryNeeded()") >= 0)
   182         return true;
   184     // XXX modify refillFreeList<NoGC> to not need data flow analysis to understand it cannot GC.
   185     if (/refillFreeList/.test(fun) && /\(js::AllowGC\)0u/.test(fun))
   186         return true;
   187     return false;
   188 }
   190 function isRootedTypeName(name)
   191 {
   192     if (name == "mozilla::ErrorResult" ||
   193         name == "JSErrorResult" ||
   194         name == "WrappableJSErrorResult" ||
   195         name == "js::frontend::TokenStream" ||
   196         name == "js::frontend::TokenStream::Position" ||
   197         name == "ModuleCompiler")
   198     {
   199         return true;
   200     }
   201     return false;
   202 }
   204 function isRootedPointerTypeName(name)
   205 {
   206     if (name.startsWith('struct '))
   207         name = name.substr(7);
   208     if (name.startsWith('class '))
   209         name = name.substr(6);
   210     if (name.startsWith('const '))
   211         name = name.substr(6);
   212     if (name.startsWith('js::ctypes::'))
   213         name = name.substr(12);
   214     if (name.startsWith('js::'))
   215         name = name.substr(4);
   216     if (name.startsWith('JS::'))
   217         name = name.substr(4);
   218     if (name.startsWith('mozilla::dom::'))
   219         name = name.substr(14);
   221     if (name.startsWith('MaybeRooted<'))
   222         return /\(js::AllowGC\)1u>::RootType/.test(name);
   224     return name.startsWith('Rooted') || name.startsWith('PersistentRooted');
   225 }
   227 function isSuppressConstructor(name)
   228 {
   229     return name.indexOf("::AutoSuppressGC") != -1
   230         || name.indexOf("::AutoEnterAnalysis") != -1
   231         || name.indexOf("::AutoAssertNoGC") != -1
   232         || name.indexOf("::AutoIgnoreRootingHazards") != -1;
   233 }
   235 // nsISupports subclasses' methods may be scriptable (or overridden
   236 // via binary XPCOM), and so may GC. But some fields just aren't going
   237 // to get overridden with something that can GC.
   238 function isOverridableField(initialCSU, csu, field)
   239 {
   240     if (csu != 'nsISupports')
   241         return false;
   242     if (field == 'GetCurrentJSContext')
   243         return false;
   244     if (field == 'IsOnCurrentThread')
   245         return false;
   246     if (field == 'GetNativeContext')
   247         return false;
   248     if (field == "GetGlobalJSObject")
   249         return false;
   250     if (field == "GetIsMainThread")
   251         return false;
   252     if (initialCSU == 'nsIXPConnectJSObjectHolder' && field == 'GetJSObject')
   253         return false;
   255     return true;
   256 }

mercurial