LCOV - code coverage report
Current view: top level - xpcom/reflect/xptinfo - xptiInterfaceInfoManager.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 66 102 64.7 %
Date: 2017-07-14 16:53:18 Functions: 13 19 68.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set ts=8 sts=4 et sw=4 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* Implementation of xptiInterfaceInfoManager. */
       8             : 
       9             : #include "mozilla/XPTInterfaceInfoManager.h"
      10             : 
      11             : #include "mozilla/FileUtils.h"
      12             : #include "mozilla/MemoryReporting.h"
      13             : #include "mozilla/StaticPtr.h"
      14             : 
      15             : #include "xptiprivate.h"
      16             : #include "nsDependentString.h"
      17             : #include "nsString.h"
      18             : #include "nsArrayEnumerator.h"
      19             : #include "nsDirectoryService.h"
      20             : #include "nsIMemoryReporter.h"
      21             : 
      22             : using namespace mozilla;
      23             : 
      24         102 : NS_IMPL_ISUPPORTS(
      25             :   XPTInterfaceInfoManager,
      26             :   nsIInterfaceInfoManager,
      27             :   nsIMemoryReporter)
      28             : 
      29           3 : static StaticRefPtr<XPTInterfaceInfoManager> gInterfaceInfoManager;
      30             : 
      31             : size_t
      32           0 : XPTInterfaceInfoManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
      33             : {
      34           0 :     size_t n = aMallocSizeOf(this);
      35           0 :     ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
      36             :     // The entries themselves are allocated out of an arena accounted
      37             :     // for elsewhere, so don't measure them
      38           0 :     n += mWorkingSet.mIIDTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
      39           0 :     n += mWorkingSet.mNameTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
      40           0 :     return n;
      41             : }
      42             : 
      43           0 : MOZ_DEFINE_MALLOC_SIZE_OF(XPTIMallocSizeOf)
      44             : 
      45             : NS_IMETHODIMP
      46           0 : XPTInterfaceInfoManager::CollectReports(nsIHandleReportCallback* aHandleReport,
      47             :                                         nsISupports* aData, bool aAnonymize)
      48             : {
      49           0 :     size_t amount = SizeOfIncludingThis(XPTIMallocSizeOf);
      50             : 
      51             :     // Measure gXPTIStructArena here, too.  This is a bit grotty because it
      52             :     // doesn't belong to the XPTIInterfaceInfoManager, but there's no
      53             :     // obviously better place to measure it.
      54           0 :     amount += XPT_SizeOfArenaIncludingThis(gXPTIStructArena, XPTIMallocSizeOf);
      55             : 
      56           0 :     MOZ_COLLECT_REPORT(
      57             :         "explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, amount,
      58           0 :         "Memory used by the XPCOM typelib system.");
      59             : 
      60           0 :     return NS_OK;
      61             : }
      62             : 
      63             : // static
      64             : XPTInterfaceInfoManager*
      65        6630 : XPTInterfaceInfoManager::GetSingleton()
      66             : {
      67        6630 :     if (!gInterfaceInfoManager) {
      68           3 :         gInterfaceInfoManager = new XPTInterfaceInfoManager();
      69           3 :         gInterfaceInfoManager->InitMemoryReporter();
      70             :     }
      71        6630 :     return gInterfaceInfoManager;
      72             : }
      73             : 
      74             : void
      75           0 : XPTInterfaceInfoManager::FreeInterfaceInfoManager()
      76             : {
      77           0 :     gInterfaceInfoManager = nullptr;
      78           0 : }
      79             : 
      80           3 : XPTInterfaceInfoManager::XPTInterfaceInfoManager()
      81             :     :   mWorkingSet(),
      82           3 :         mResolveLock("XPTInterfaceInfoManager.mResolveLock")
      83             : {
      84           3 : }
      85             : 
      86           0 : XPTInterfaceInfoManager::~XPTInterfaceInfoManager()
      87             : {
      88             :     // We only do this on shutdown of the service.
      89           0 :     mWorkingSet.InvalidateInterfaceInfos();
      90             : 
      91           0 :     UnregisterWeakMemoryReporter(this);
      92           0 : }
      93             : 
      94             : void
      95           3 : XPTInterfaceInfoManager::InitMemoryReporter()
      96             : {
      97           3 :     RegisterWeakMemoryReporter(this);
      98           3 : }
      99             : 
     100             : void
     101         522 : XPTInterfaceInfoManager::RegisterBuffer(char *buf, uint32_t length)
     102             : {
     103             :     XPTState state;
     104         522 :     XPT_InitXDRState(&state, buf, length);
     105             : 
     106             :     XPTCursor curs;
     107         522 :     NotNull<XPTCursor*> cursor = WrapNotNull(&curs);
     108         522 :     if (!XPT_MakeCursor(&state, XPT_HEADER, 0, cursor)) {
     109           0 :         return;
     110             :     }
     111             : 
     112         522 :     XPTHeader *header = nullptr;
     113         522 :     if (XPT_DoHeader(gXPTIStructArena, cursor, &header)) {
     114         522 :         RegisterXPTHeader(header);
     115             :     }
     116             : }
     117             : 
     118             : void
     119         522 : XPTInterfaceInfoManager::RegisterXPTHeader(XPTHeader* aHeader)
     120             : {
     121         522 :     if (aHeader->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) {
     122           0 :         NS_ASSERTION(!aHeader->num_interfaces,"bad libxpt");
     123             :         LOG_AUTOREG(("      file is version %d.%d  Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
     124             :     }
     125             : 
     126         522 :     xptiTypelibGuts* typelib = xptiTypelibGuts::Create(aHeader);
     127             : 
     128        1044 :     ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
     129        6924 :     for(uint16_t k = 0; k < aHeader->num_interfaces; k++)
     130        6402 :         VerifyAndAddEntryIfNew(aHeader->interface_directory + k, k, typelib);
     131         522 : }
     132             : 
     133             : void
     134        6402 : XPTInterfaceInfoManager::VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* iface,
     135             :                                                 uint16_t idx,
     136             :                                                 xptiTypelibGuts* typelib)
     137             : {
     138        6402 :     if (!iface->interface_descriptor)
     139        5073 :         return;
     140             : 
     141             :     // The number of maximum methods is not arbitrary. It is the same value as
     142             :     // in xpcom/reflect/xptcall/genstubs.pl; do not change this value
     143             :     // without changing that one or you WILL see problems.
     144        3882 :     if (iface->interface_descriptor->num_methods > 250 &&
     145           0 :             !(XPT_ID_IS_BUILTINCLASS(iface->interface_descriptor->flags))) {
     146           0 :         NS_ASSERTION(0, "Too many methods to handle for the stub, cannot load");
     147           0 :         fprintf(stderr, "ignoring too large interface: %s\n", iface->name);
     148           0 :         return;
     149             :     }
     150             : 
     151        3882 :     mWorkingSet.mTableReentrantMonitor.AssertCurrentThreadIn();
     152        3882 :     xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(iface->iid);
     153        3882 :     if (entry) {
     154             :         // XXX validate this info to find possible inconsistencies
     155             :         LOG_AUTOREG(("      ignoring repeated interface: %s\n", iface->name));
     156          33 :         return;
     157             :     }
     158             : 
     159             :     // Build a new xptiInterfaceEntry object and hook it up.
     160             : 
     161        3849 :     entry = xptiInterfaceEntry::Create(iface->name,
     162             :                                        iface->iid,
     163             :                                        iface->interface_descriptor,
     164             :                                        typelib);
     165        3849 :     if (!entry)
     166           0 :         return;
     167             : 
     168             :     //XXX  We should SetHeader too as part of the validation, no?
     169        3849 :     entry->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags));
     170        3849 :     entry->SetBuiltinClassFlag(XPT_ID_IS_BUILTINCLASS(iface->interface_descriptor->flags));
     171        3849 :     entry->SetMainProcessScriptableOnlyFlag(
     172        7698 :       XPT_ID_IS_MAIN_PROCESS_SCRIPTABLE_ONLY(iface->interface_descriptor->flags));
     173             : 
     174        3849 :     mWorkingSet.mIIDTable.Put(entry->IID(), entry);
     175        3849 :     mWorkingSet.mNameTable.Put(entry->GetTheName(), entry);
     176             : 
     177        3849 :     typelib->SetEntryAt(idx, entry);
     178             : 
     179             :     LOG_AUTOREG(("      added interface: %s\n", iface->name));
     180             : }
     181             : 
     182             : // this is a private helper
     183             : static nsresult
     184        2901 : EntryToInfo(xptiInterfaceEntry* entry, nsIInterfaceInfo **_retval)
     185             : {
     186        2901 :     if (!entry) {
     187        1383 :         *_retval = nullptr;
     188        1383 :         return NS_ERROR_FAILURE;
     189             :     }
     190             : 
     191        3036 :     RefPtr<xptiInterfaceInfo> info = entry->InterfaceInfo();
     192        1518 :     info.forget(_retval);
     193        1518 :     return NS_OK;
     194             : }
     195             : 
     196             : xptiInterfaceEntry*
     197         940 : XPTInterfaceInfoManager::GetInterfaceEntryForIID(const nsIID *iid)
     198             : {
     199        1880 :     ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
     200        1880 :     return mWorkingSet.mIIDTable.Get(*iid);
     201             : }
     202             : 
     203             : NS_IMETHODIMP
     204        2159 : XPTInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval)
     205             : {
     206        2159 :     NS_ASSERTION(iid, "bad param");
     207        2159 :     NS_ASSERTION(_retval, "bad param");
     208             : 
     209        4318 :     ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
     210        2159 :     xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(*iid);
     211        4318 :     return EntryToInfo(entry, _retval);
     212             : }
     213             : 
     214             : NS_IMETHODIMP
     215         742 : XPTInterfaceInfoManager::GetInfoForName(const char *name, nsIInterfaceInfo **_retval)
     216             : {
     217         742 :     NS_ASSERTION(name, "bad param");
     218         742 :     NS_ASSERTION(_retval, "bad param");
     219             : 
     220        1484 :     ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
     221         742 :     xptiInterfaceEntry* entry = mWorkingSet.mNameTable.Get(name);
     222        1484 :     return EntryToInfo(entry, _retval);
     223             : }
     224             : 
     225             : void
     226           0 : XPTInterfaceInfoManager::GetScriptableInterfaces(nsCOMArray<nsIInterfaceInfo>& aInterfaces)
     227             : {
     228             :     // I didn't want to incur the size overhead of using nsHashtable just to
     229             :     // make building an enumerator easier. So, this code makes a snapshot of
     230             :     // the table using an nsCOMArray and builds an enumerator for that.
     231             :     // We can afford this transient cost.
     232             : 
     233           0 :     ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
     234           0 :     aInterfaces.SetCapacity(mWorkingSet.mNameTable.Count());
     235           0 :     for (auto iter = mWorkingSet.mNameTable.Iter(); !iter.Done(); iter.Next()) {
     236           0 :         xptiInterfaceEntry* entry = iter.UserData();
     237           0 :         if (entry->GetScriptableFlag()) {
     238           0 :             nsCOMPtr<nsIInterfaceInfo> ii = entry->InterfaceInfo();
     239           0 :             aInterfaces.AppendElement(ii);
     240             :         }
     241             :     }
     242           0 : }

Generated by: LCOV version 1.13