LCOV - code coverage report
Current view: directory - js/xpconnect/src - XPCWrappedNativeInfo.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 390 309 79.2 %
Date: 2012-06-02 Functions: 20 18 90.0 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : // vim:cindent:ts=8:et:sw=4:
       3                 : /*
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is Mozilla Communicator client code, released
      18                 :  * March 31, 1998.
      19                 :  *
      20                 :  * The Initial Developer of the Original Code is
      21                 :  * Netscape Communications Corporation.
      22                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      23                 :  * the Initial Developer. All Rights Reserved.
      24                 :  *
      25                 :  * Contributor(s):
      26                 :  *   John Bandhauer <jband@netscape.com> (original author)
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : /* Manage the shared info about interfaces for use by wrappedNatives. */
      43                 : 
      44                 : #include "xpcprivate.h"
      45                 : 
      46                 : /***************************************************************************/
      47                 : 
      48                 : // XPCNativeMember
      49                 : 
      50                 : // static
      51                 : JSBool
      52         6721770 : XPCNativeMember::GetCallInfo(XPCCallContext& ccx,
      53                 :                              JSObject* funobj,
      54                 :                              XPCNativeInterface** pInterface,
      55                 :                              XPCNativeMember**    pMember)
      56                 : {
      57         6721770 :     funobj = js::UnwrapObject(funobj);
      58         6721770 :     jsval ifaceVal = js::GetFunctionNativeReserved(funobj, 0);
      59         6721770 :     jsval memberVal = js::GetFunctionNativeReserved(funobj, 1);
      60                 : 
      61         6721770 :     *pInterface = (XPCNativeInterface*) JSVAL_TO_PRIVATE(ifaceVal);
      62         6721770 :     *pMember = (XPCNativeMember*) JSVAL_TO_PRIVATE(memberVal);
      63                 : 
      64         6721770 :     return true;
      65                 : }
      66                 : 
      67                 : JSBool
      68         1710919 : XPCNativeMember::NewFunctionObject(XPCCallContext& ccx,
      69                 :                                    XPCNativeInterface* iface, JSObject *parent,
      70                 :                                    jsval* pval)
      71                 : {
      72         1710919 :     NS_ASSERTION(!IsConstant(),
      73                 :                  "Only call this if you're sure this is not a constant!");
      74                 : 
      75         1710919 :     return Resolve(ccx, iface, parent, pval);
      76                 : }
      77                 : 
      78                 : JSBool
      79         1730999 : XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
      80                 :                          JSObject *parent, jsval *vp)
      81                 : {
      82         1730999 :     if (IsConstant()) {
      83                 :         const nsXPTConstant* constant;
      84           20080 :         if (NS_FAILED(iface->GetInterfaceInfo()->GetConstant(mIndex, &constant)))
      85               0 :             return false;
      86                 : 
      87           20080 :         const nsXPTCMiniVariant& mv = *constant->GetValue();
      88                 : 
      89                 :         // XXX Big Hack!
      90           20080 :         nsXPTCVariant v;
      91           20080 :         v.flags = 0;
      92           20080 :         v.type = constant->GetType();
      93           20080 :         memcpy(&v.val, &mv.val, sizeof(mv.val));
      94                 : 
      95                 :         jsval resultVal;
      96                 : 
      97           20080 :         if (!XPCConvert::NativeData2JS(ccx, &resultVal, &v.val, v.type,
      98           20080 :                                        nsnull, nsnull))
      99               0 :             return false;
     100                 : 
     101           20080 :         *vp = resultVal;
     102                 : 
     103           20080 :         return true;
     104                 :     }
     105                 :     // else...
     106                 : 
     107                 :     // This is a method or attribute - we'll be needing a function object
     108                 : 
     109                 :     int argc;
     110                 :     JSNative callback;
     111                 : 
     112         1710919 :     if (IsMethod()) {
     113                 :         const nsXPTMethodInfo* info;
     114          688855 :         if (NS_FAILED(iface->GetInterfaceInfo()->GetMethodInfo(mIndex, &info)))
     115               0 :             return false;
     116                 : 
     117                 :         // Note: ASSUMES that retval is last arg.
     118          688855 :         argc = (int) info->GetParamCount();
     119          688855 :         if (argc && info->GetParam((uint8_t)(argc-1)).IsRetval())
     120          495110 :             argc-- ;
     121                 : 
     122          688855 :         callback = XPC_WN_CallMethod;
     123                 :     } else {
     124         1022064 :         argc = 0;
     125         1022064 :         callback = XPC_WN_GetterSetter;
     126                 :     }
     127                 : 
     128         1710919 :     JSFunction *fun = js::NewFunctionByIdWithReserved(ccx, callback, argc, 0, parent, GetName());
     129         1710919 :     if (!fun)
     130               0 :         return false;
     131                 : 
     132         1710919 :     JSObject* funobj = JS_GetFunctionObject(fun);
     133         1710919 :     if (!funobj)
     134               0 :         return false;
     135                 : 
     136         1710919 :     js::SetFunctionNativeReserved(funobj, 0, PRIVATE_TO_JSVAL(iface));
     137         1710919 :     js::SetFunctionNativeReserved(funobj, 1, PRIVATE_TO_JSVAL(this));
     138                 : 
     139         1710919 :     *vp = OBJECT_TO_JSVAL(funobj);
     140                 : 
     141         1710919 :     return true;
     142                 : }
     143                 : 
     144                 : /***************************************************************************/
     145                 : // XPCNativeInterface
     146                 : 
     147                 : // static
     148                 : XPCNativeInterface*
     149         2559361 : XPCNativeInterface::GetNewOrUsed(XPCCallContext& ccx, const nsIID* iid)
     150                 : {
     151         5118722 :     AutoMarkingNativeInterfacePtr iface(ccx);
     152         2559361 :     XPCJSRuntime* rt = ccx.GetRuntime();
     153                 : 
     154         2559361 :     IID2NativeInterfaceMap* map = rt->GetIID2NativeInterfaceMap();
     155         2559361 :     if (!map)
     156               0 :         return nsnull;
     157                 : 
     158                 :     {   // scoped lock
     159         5118722 :         XPCAutoLock lock(rt->GetMapLock());
     160         2559361 :         iface = map->Find(*iid);
     161                 :     }
     162                 : 
     163         2559361 :     if (iface)
     164         2365643 :         return iface;
     165                 : 
     166          387436 :     nsCOMPtr<nsIInterfaceInfo> info;
     167          193718 :     ccx.GetXPConnect()->GetInfoForIID(iid, getter_AddRefs(info));
     168          193718 :     if (!info)
     169            2023 :         return nsnull;
     170                 : 
     171          191695 :     iface = NewInstance(ccx, info);
     172          191695 :     if (!iface)
     173           64144 :         return nsnull;
     174                 : 
     175                 :     {   // scoped lock
     176          255102 :         XPCAutoLock lock(rt->GetMapLock());
     177          127551 :         XPCNativeInterface* iface2 = map->Add(iface);
     178          127551 :         if (!iface2) {
     179               0 :             NS_ERROR("failed to add our interface!");
     180               0 :             DestroyInstance(iface);
     181               0 :             iface = nsnull;
     182          127551 :         } else if (iface2 != iface) {
     183               0 :             DestroyInstance(iface);
     184               0 :             iface = iface2;
     185                 :         }
     186                 :     }
     187                 : 
     188          127551 :     return iface;
     189                 : }
     190                 : 
     191                 : // static
     192                 : XPCNativeInterface*
     193              39 : XPCNativeInterface::GetNewOrUsed(XPCCallContext& ccx, nsIInterfaceInfo* info)
     194                 : {
     195              78 :     AutoMarkingNativeInterfacePtr iface(ccx);
     196                 : 
     197                 :     const nsIID* iid;
     198              39 :     if (NS_FAILED(info->GetIIDShared(&iid)) || !iid)
     199               0 :         return nsnull;
     200                 : 
     201              39 :     XPCJSRuntime* rt = ccx.GetRuntime();
     202                 : 
     203              39 :     IID2NativeInterfaceMap* map = rt->GetIID2NativeInterfaceMap();
     204              39 :     if (!map)
     205               0 :         return nsnull;
     206                 : 
     207                 :     {   // scoped lock
     208              78 :         XPCAutoLock lock(rt->GetMapLock());
     209              39 :         iface = map->Find(*iid);
     210                 :     }
     211                 : 
     212              39 :     if (iface)
     213              31 :         return iface;
     214                 : 
     215               8 :     iface = NewInstance(ccx, info);
     216               8 :     if (!iface)
     217               0 :         return nsnull;
     218                 : 
     219                 :     {   // scoped lock
     220              16 :         XPCAutoLock lock(rt->GetMapLock());
     221               8 :         XPCNativeInterface* iface2 = map->Add(iface);
     222               8 :         if (!iface2) {
     223               0 :             NS_ERROR("failed to add our interface!");
     224               0 :             DestroyInstance(iface);
     225               0 :             iface = nsnull;
     226               8 :         } else if (iface2 != iface) {
     227               0 :             DestroyInstance(iface);
     228               0 :             iface = iface2;
     229                 :         }
     230                 :     }
     231                 : 
     232               8 :     return iface;
     233                 : }
     234                 : 
     235                 : // static
     236                 : XPCNativeInterface*
     237            5400 : XPCNativeInterface::GetNewOrUsed(XPCCallContext& ccx, const char* name)
     238                 : {
     239           10800 :     nsCOMPtr<nsIInterfaceInfo> info;
     240            5400 :     ccx.GetXPConnect()->GetInfoForName(name, getter_AddRefs(info));
     241            5400 :     return info ? GetNewOrUsed(ccx, info) : nsnull;
     242                 : }
     243                 : 
     244                 : // static
     245                 : XPCNativeInterface*
     246          171062 : XPCNativeInterface::GetISupports(XPCCallContext& ccx)
     247                 : {
     248                 :     // XXX We should optimize this to cache this common XPCNativeInterface.
     249          171062 :     return GetNewOrUsed(ccx, &NS_GET_IID(nsISupports));
     250                 : }
     251                 : 
     252                 : // static
     253                 : XPCNativeInterface*
     254          191703 : XPCNativeInterface::NewInstance(XPCCallContext& ccx,
     255                 :                                 nsIInterfaceInfo* aInfo)
     256                 : {
     257                 :     static const PRUint16 MAX_LOCAL_MEMBER_COUNT = 16;
     258         3258951 :     XPCNativeMember local_members[MAX_LOCAL_MEMBER_COUNT];
     259          191703 :     XPCNativeInterface* obj = nsnull;
     260          191703 :     XPCNativeMember* members = nsnull;
     261                 : 
     262                 :     int i;
     263          191703 :     JSBool failed = false;
     264                 :     PRUint16 constCount;
     265                 :     PRUint16 methodCount;
     266                 :     PRUint16 totalCount;
     267          191703 :     PRUint16 realTotalCount = 0;
     268                 :     XPCNativeMember* cur;
     269          191703 :     JSString* str = NULL;
     270                 :     jsid name;
     271                 :     jsid interfaceName;
     272                 : 
     273                 :     // XXX Investigate lazy init? This is a problem given the
     274                 :     // 'placement new' scheme - we need to at least know how big to make
     275                 :     // the object. We might do a scan of methods to determine needed size,
     276                 :     // then make our object, but avoid init'ing *any* members until asked?
     277                 :     // Find out how often we create these objects w/o really looking at
     278                 :     // (or using) the members.
     279                 : 
     280                 :     bool canScript;
     281          191703 :     if (NS_FAILED(aInfo->IsScriptable(&canScript)) || !canScript)
     282           64144 :         return nsnull;
     283                 : 
     284          255118 :     if (NS_FAILED(aInfo->GetMethodCount(&methodCount)) ||
     285          127559 :         NS_FAILED(aInfo->GetConstantCount(&constCount)))
     286               0 :         return nsnull;
     287                 : 
     288                 :     // If the interface does not have nsISupports in its inheritance chain
     289                 :     // then we know we can't reflect its methods. However, some interfaces that
     290                 :     // are used just to reflect constants are declared this way. We need to
     291                 :     // go ahead and build the thing. But, we'll ignore whatever methods it may
     292                 :     // have.
     293          127559 :     if (!nsXPConnect::IsISupportsDescendant(aInfo))
     294              31 :         methodCount = 0;
     295                 : 
     296          127559 :     totalCount = methodCount + constCount;
     297                 : 
     298          127559 :     if (totalCount > MAX_LOCAL_MEMBER_COUNT) {
     299           82752 :         members = new XPCNativeMember[totalCount];
     300           41376 :         if (!members)
     301               0 :             return nsnull;
     302                 :     } else {
     303           86183 :         members = local_members;
     304                 :     }
     305                 : 
     306                 :     // NOTE: since getters and setters share a member, we might not use all
     307                 :     // of the member objects.
     308                 : 
     309         1980440 :     for (i = 0; i < methodCount; i++) {
     310                 :         const nsXPTMethodInfo* info;
     311         1852881 :         if (NS_FAILED(aInfo->GetMethodInfo(i, &info))) {
     312               0 :             failed = true;
     313               0 :             break;
     314                 :         }
     315                 : 
     316                 :         // don't reflect Addref or Release
     317         1852881 :         if (i == 1 || i == 2)
     318          255056 :             continue;
     319                 : 
     320         1597825 :         if (!XPCConvert::IsMethodReflectable(*info))
     321          111403 :             continue;
     322                 : 
     323         1486422 :         str = JS_InternString(ccx, info->GetName());
     324         1486422 :         if (!str) {
     325               0 :             NS_ERROR("bad method name");
     326               0 :             failed = true;
     327               0 :             break;
     328                 :         }
     329         1486422 :         name = INTERNED_STRING_TO_JSID(ccx, str);
     330                 : 
     331         1486422 :         if (info->IsSetter()) {
     332          172725 :             NS_ASSERTION(realTotalCount,"bad setter");
     333                 :             // Note: ASSUMES Getter/Setter pairs are next to each other
     334                 :             // This is a rule of the typelib spec.
     335          172725 :             cur = &members[realTotalCount-1];
     336          172725 :             NS_ASSERTION(cur->GetName() == name,"bad setter");
     337          172725 :             NS_ASSERTION(cur->IsReadOnlyAttribute(),"bad setter");
     338          172725 :             NS_ASSERTION(cur->GetIndex() == i-1,"bad setter");
     339          172725 :             cur->SetWritableAttribute();
     340                 :         } else {
     341                 :             // XXX need better way to find dups
     342                 :             // NS_ASSERTION(!LookupMemberByID(name),"duplicate method name");
     343         1313697 :             cur = &members[realTotalCount++];
     344         1313697 :             cur->SetName(name);
     345         1313697 :             if (info->IsGetter())
     346          503531 :                 cur->SetReadOnlyAttribute(i);
     347                 :             else
     348          810166 :                 cur->SetMethod(i);
     349                 :         }
     350                 :     }
     351                 : 
     352          127559 :     if (!failed) {
     353          515752 :         for (i = 0; i < constCount; i++) {
     354                 :             const nsXPTConstant* constant;
     355          388193 :             if (NS_FAILED(aInfo->GetConstant(i, &constant))) {
     356               0 :                 failed = true;
     357               0 :                 break;
     358                 :             }
     359                 : 
     360          388193 :             str = JS_InternString(ccx, constant->GetName());
     361          388193 :             if (!str) {
     362               0 :                 NS_ERROR("bad constant name");
     363               0 :                 failed = true;
     364               0 :                 break;
     365                 :             }
     366          388193 :             name = INTERNED_STRING_TO_JSID(ccx, str);
     367                 : 
     368                 :             // XXX need better way to find dups
     369                 :             //NS_ASSERTION(!LookupMemberByID(name),"duplicate method/constant name");
     370                 : 
     371          388193 :             cur = &members[realTotalCount++];
     372          388193 :             cur->SetName(name);
     373          388193 :             cur->SetConstant(i);
     374                 :         }
     375                 :     }
     376                 : 
     377          127559 :     if (!failed) {
     378                 :         const char* bytes;
     379          255118 :         if (NS_FAILED(aInfo->GetNameShared(&bytes)) || !bytes ||
     380          127559 :             nsnull == (str = JS_InternString(ccx, bytes))) {
     381               0 :             failed = true;
     382                 :         }
     383          127559 :         interfaceName = INTERNED_STRING_TO_JSID(ccx, str);
     384                 :     }
     385                 : 
     386          127559 :     if (!failed) {
     387                 :         // Use placement new to create an object with the right amount of space
     388                 :         // to hold the members array
     389          127559 :         int size = sizeof(XPCNativeInterface);
     390          127559 :         if (realTotalCount > 1)
     391          118205 :             size += (realTotalCount - 1) * sizeof(XPCNativeMember);
     392          255118 :         void* place = new char[size];
     393          127559 :         if (place)
     394          127559 :             obj = new(place) XPCNativeInterface(aInfo, interfaceName);
     395                 : 
     396          127559 :         if (obj) {
     397          127559 :             obj->mMemberCount = realTotalCount;
     398                 :             // copy valid members
     399          127559 :             if (realTotalCount)
     400                 :                 memcpy(obj->mMembers, members,
     401          127559 :                        realTotalCount * sizeof(XPCNativeMember));
     402                 :         }
     403                 :     }
     404                 : 
     405          127559 :     if (members && members != local_members)
     406           41376 :         delete [] members;
     407                 : 
     408         3194807 :     return obj;
     409                 : }
     410                 : 
     411                 : // static
     412                 : void
     413          127539 : XPCNativeInterface::DestroyInstance(XPCNativeInterface* inst)
     414                 : {
     415          127539 :     inst->~XPCNativeInterface();
     416          127539 :     delete [] (char*) inst;
     417          127539 : }
     418                 : 
     419                 : size_t
     420             303 : XPCNativeInterface::SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf)
     421                 : {
     422             303 :     return mallocSizeOf(this);
     423                 : }
     424                 : 
     425                 : void
     426               0 : XPCNativeInterface::DebugDump(PRInt16 depth)
     427                 : {
     428                 : #ifdef DEBUG
     429               0 :     depth--;
     430               0 :     XPC_LOG_ALWAYS(("XPCNativeInterface @ %x", this));
     431               0 :         XPC_LOG_INDENT();
     432               0 :         XPC_LOG_ALWAYS(("name is %s", GetNameString()));
     433               0 :         XPC_LOG_ALWAYS(("mMemberCount is %d", mMemberCount));
     434               0 :         XPC_LOG_ALWAYS(("mInfo @ %x", mInfo.get()));
     435               0 :         XPC_LOG_OUTDENT();
     436                 : #endif
     437               0 : }
     438                 : 
     439                 : /***************************************************************************/
     440                 : // XPCNativeSet
     441                 : 
     442                 : // static
     443                 : XPCNativeSet*
     444           44655 : XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx, const nsIID* iid)
     445                 : {
     446           89310 :     AutoMarkingNativeSetPtr set(ccx);
     447                 : 
     448           89310 :     AutoMarkingNativeInterfacePtr iface(ccx);
     449           44655 :     iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
     450           44655 :     if (!iface)
     451               0 :         return nsnull;
     452                 : 
     453           89310 :     XPCNativeSetKey key(nsnull, iface, 0);
     454                 : 
     455           44655 :     XPCJSRuntime* rt = ccx.GetRuntime();
     456           44655 :     NativeSetMap* map = rt->GetNativeSetMap();
     457           44655 :     if (!map)
     458               0 :         return nsnull;
     459                 : 
     460                 :     {   // scoped lock
     461           89310 :         XPCAutoLock lock(rt->GetMapLock());
     462           44655 :         set = map->Find(&key);
     463                 :     }
     464                 : 
     465           44655 :     if (set)
     466           43264 :         return set;
     467                 : 
     468                 :     // hacky way to get a XPCNativeInterface** using the AutoPtr
     469            1391 :     XPCNativeInterface* temp[] = {iface};
     470            1391 :     set = NewInstance(ccx, temp, 1);
     471            1391 :     if (!set)
     472               0 :         return nsnull;
     473                 : 
     474                 :     {   // scoped lock
     475            2782 :         XPCAutoLock lock(rt->GetMapLock());
     476            1391 :         XPCNativeSet* set2 = map->Add(&key, set);
     477            1391 :         if (!set2) {
     478               0 :             NS_ERROR("failed to add our set!");
     479               0 :             DestroyInstance(set);
     480               0 :             set = nsnull;
     481            1391 :         } else if (set2 != set) {
     482               0 :             DestroyInstance(set);
     483               0 :             set = set2;
     484                 :         }
     485                 :     }
     486                 : 
     487            1391 :     return set;
     488                 : }
     489                 : 
     490                 : // static
     491                 : XPCNativeSet*
     492          186934 : XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx, nsIClassInfo* classInfo)
     493                 : {
     494          373868 :     AutoMarkingNativeSetPtr set(ccx);
     495          186934 :     XPCJSRuntime* rt = ccx.GetRuntime();
     496                 : 
     497          186934 :     ClassInfo2NativeSetMap* map = rt->GetClassInfo2NativeSetMap();
     498          186934 :     if (!map)
     499               0 :         return nsnull;
     500                 : 
     501                 :     {   // scoped lock
     502          373868 :         XPCAutoLock lock(rt->GetMapLock());
     503          186934 :         set = map->Find(classInfo);
     504                 :     }
     505                 : 
     506          186934 :     if (set)
     507           38121 :         return set;
     508                 : 
     509          148813 :     nsIID** iidArray = nsnull;
     510          297626 :     AutoMarkingNativeInterfacePtrArrayPtr interfaceArray(ccx);
     511          148813 :     PRUint32 iidCount = 0;
     512                 : 
     513          148813 :     if (NS_FAILED(classInfo->GetInterfaces(&iidCount, &iidArray))) {
     514                 :         // Note: I'm making it OK for this call to fail so that one can add
     515                 :         // nsIClassInfo to classes implemented in script without requiring this
     516                 :         // method to be implemented.
     517                 : 
     518                 :         // Make sure these are set correctly...
     519               0 :         iidArray = nsnull;
     520               0 :         iidCount = 0;
     521                 :     }
     522                 : 
     523          148813 :     NS_ASSERTION((iidCount && iidArray) || !(iidCount || iidArray), "GetInterfaces returned bad array");
     524                 : 
     525                 :     // !!! from here on we only exit through the 'out' label !!!
     526                 : 
     527          148813 :     if (iidCount) {
     528                 :         AutoMarkingNativeInterfacePtrArrayPtr
     529          316668 :             arr(ccx, new XPCNativeInterface*[iidCount], iidCount, true);
     530          105556 :         if (!arr)
     531                 :             goto out;
     532                 : 
     533          105556 :         interfaceArray = arr;
     534                 : 
     535          105556 :         XPCNativeInterface** currentInterface = interfaceArray;
     536          105556 :         nsIID**              currentIID = iidArray;
     537          105556 :         PRUint16             interfaceCount = 0;
     538                 : 
     539          384097 :         for (PRUint32 i = 0; i < iidCount; i++) {
     540          278541 :             nsIID* iid = *(currentIID++);
     541          278541 :             if (!iid) {
     542               0 :                 NS_ERROR("Null found in classinfo interface list");
     543               0 :                 continue;
     544                 :             }
     545                 : 
     546                 :             XPCNativeInterface* iface =
     547          278541 :                 XPCNativeInterface::GetNewOrUsed(ccx, iid);
     548                 : 
     549          278541 :             if (!iface) {
     550                 :                 // XXX warn here
     551           66167 :                 continue;
     552                 :             }
     553                 : 
     554          212374 :             *(currentInterface++) = iface;
     555          212374 :             interfaceCount++;
     556                 :         }
     557                 : 
     558          105556 :         if (interfaceCount) {
     559          104158 :             set = NewInstance(ccx, interfaceArray, interfaceCount);
     560          104158 :             if (set) {
     561          104158 :                 NativeSetMap* map2 = rt->GetNativeSetMap();
     562          104158 :                 if (!map2)
     563                 :                     goto out;
     564                 : 
     565          208316 :                 XPCNativeSetKey key(set, nsnull, 0);
     566                 : 
     567                 :                 {   // scoped lock
     568          208316 :                     XPCAutoLock lock(rt->GetMapLock());
     569          104158 :                     XPCNativeSet* set2 = map2->Add(&key, set);
     570          104158 :                     if (!set2) {
     571               0 :                         NS_ERROR("failed to add our set!");
     572               0 :                         DestroyInstance(set);
     573               0 :                         set = nsnull;
     574                 :                         goto out;
     575                 :                     }
     576          104158 :                     if (set2 != set) {
     577           77013 :                         DestroyInstance(set);
     578           77013 :                         set = set2;
     579                 :                     }
     580                 :                 }
     581                 :             }
     582                 :         } else
     583            1398 :             set = GetNewOrUsed(ccx, &NS_GET_IID(nsISupports));
     584                 :     } else
     585           43257 :         set = GetNewOrUsed(ccx, &NS_GET_IID(nsISupports));
     586                 : 
     587          148813 :     if (set)
     588                 :     {   // scoped lock
     589          297626 :         XPCAutoLock lock(rt->GetMapLock());
     590                 : 
     591                 : #ifdef DEBUG
     592                 :         XPCNativeSet* set2 =
     593                 : #endif
     594          148813 :           map->Add(classInfo, set);
     595          148813 :         NS_ASSERTION(set2, "failed to add our set!");
     596          148813 :         NS_ASSERTION(set2 == set, "hashtables inconsistent!");
     597                 :     }
     598                 : 
     599                 : out:
     600          148813 :     if (iidArray)
     601          105556 :         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(iidCount, iidArray);
     602          148813 :     if (interfaceArray)
     603          105556 :         delete [] interfaceArray.get();
     604                 : 
     605          148813 :     return set;
     606                 : }
     607                 : 
     608                 : // static
     609                 : void
     610          186781 : XPCNativeSet::ClearCacheEntryForClassInfo(nsIClassInfo* classInfo)
     611                 : {
     612          186781 :     XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
     613          186781 :     ClassInfo2NativeSetMap* map = rt->GetClassInfo2NativeSetMap();
     614          186781 :     if (map)
     615                 :     {   // scoped lock
     616          373562 :         XPCAutoLock lock(rt->GetMapLock());
     617          186781 :         map->Remove(classInfo);
     618                 :     }
     619          186781 : }
     620                 : 
     621                 : // static
     622                 : XPCNativeSet*
     623         1044765 : XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx,
     624                 :                            XPCNativeSet* otherSet,
     625                 :                            XPCNativeInterface* newInterface,
     626                 :                            PRUint16 position)
     627                 : {
     628         2089530 :     AutoMarkingNativeSetPtr set(ccx);
     629         1044765 :     XPCJSRuntime* rt = ccx.GetRuntime();
     630         1044765 :     NativeSetMap* map = rt->GetNativeSetMap();
     631         1044765 :     if (!map)
     632               0 :         return nsnull;
     633                 : 
     634         2089530 :     XPCNativeSetKey key(otherSet, newInterface, position);
     635                 : 
     636                 :     {   // scoped lock
     637         2089530 :         XPCAutoLock lock(rt->GetMapLock());
     638         1044765 :         set = map->Find(&key);
     639                 :     }
     640                 : 
     641         1044765 :     if (set)
     642          958038 :         return set;
     643                 : 
     644           86727 :     if (otherSet)
     645           25631 :         set = NewInstanceMutate(otherSet, newInterface, position);
     646                 :     else
     647           61096 :         set = NewInstance(ccx, &newInterface, 1);
     648                 : 
     649           86727 :     if (!set)
     650               0 :         return nsnull;
     651                 : 
     652                 :     {   // scoped lock
     653          173454 :         XPCAutoLock lock(rt->GetMapLock());
     654           86727 :         XPCNativeSet* set2 = map->Add(&key, set);
     655           86727 :         if (!set2) {
     656               0 :             NS_ERROR("failed to add our set!");
     657               0 :             DestroyInstance(set);
     658               0 :             set = nsnull;
     659           86727 :         } else if (set2 != set) {
     660               0 :             DestroyInstance(set);
     661               0 :             set = set2;
     662                 :         }
     663                 :     }
     664                 : 
     665           86727 :     return set;
     666                 : }
     667                 : 
     668                 : // static
     669                 : XPCNativeSet*
     670          166645 : XPCNativeSet::NewInstance(XPCCallContext& ccx,
     671                 :                           XPCNativeInterface** array,
     672                 :                           PRUint16 count)
     673                 : {
     674          166645 :     XPCNativeSet* obj = nsnull;
     675                 : 
     676          166645 :     if (!array || !count)
     677               0 :         return nsnull;
     678                 : 
     679                 :     // We impose the invariant:
     680                 :     // "All sets have exactly one nsISupports interface and it comes first."
     681                 :     // This is the place where we impose that rule - even if given inputs
     682                 :     // that don't exactly follow the rule.
     683                 : 
     684          166645 :     XPCNativeInterface* isup = XPCNativeInterface::GetISupports(ccx);
     685          166645 :     PRUint16 slots = count+1;
     686                 : 
     687                 :     PRUint16 i;
     688                 :     XPCNativeInterface** pcur;
     689                 : 
     690          441506 :     for (i = 0, pcur = array; i < count; i++, pcur++) {
     691          274861 :         if (*pcur == isup)
     692            1401 :             slots--;
     693                 :     }
     694                 : 
     695                 :     // Use placement new to create an object with the right amount of space
     696                 :     // to hold the members array
     697          166645 :     int size = sizeof(XPCNativeSet);
     698          166645 :     if (slots > 1)
     699          165244 :         size += (slots - 1) * sizeof(XPCNativeInterface*);
     700          333290 :     void* place = new char[size];
     701          166645 :     if (place)
     702          166645 :         obj = new(place) XPCNativeSet();
     703                 : 
     704          166645 :     if (obj) {
     705                 :         // Stick the nsISupports in front and skip additional nsISupport(s)
     706          166645 :         XPCNativeInterface** inp = array;
     707          166645 :         XPCNativeInterface** outp = (XPCNativeInterface**) &obj->mInterfaces;
     708          166645 :         PRUint16 memberCount = 1;   // for the one member in nsISupports
     709                 : 
     710          166645 :         *(outp++) = isup;
     711                 : 
     712          441506 :         for (i = 0; i < count; i++) {
     713                 :             XPCNativeInterface* cur;
     714                 : 
     715          274861 :             if (isup == (cur = *(inp++)))
     716            1401 :                 continue;
     717          273460 :             *(outp++) = cur;
     718          273460 :             memberCount += cur->GetMemberCount();
     719                 :         }
     720          166645 :         obj->mMemberCount = memberCount;
     721          166645 :         obj->mInterfaceCount = slots;
     722                 :     }
     723                 : 
     724          166645 :     return obj;
     725                 : }
     726                 : 
     727                 : // static
     728                 : XPCNativeSet*
     729           25631 : XPCNativeSet::NewInstanceMutate(XPCNativeSet*       otherSet,
     730                 :                                 XPCNativeInterface* newInterface,
     731                 :                                 PRUint16            position)
     732                 : {
     733           25631 :     XPCNativeSet* obj = nsnull;
     734                 : 
     735           25631 :     if (!newInterface)
     736               0 :         return nsnull;
     737           25631 :     if (otherSet && position > otherSet->mInterfaceCount)
     738               0 :         return nsnull;
     739                 : 
     740                 :     // Use placement new to create an object with the right amount of space
     741                 :     // to hold the members array
     742           25631 :     int size = sizeof(XPCNativeSet);
     743           25631 :     if (otherSet)
     744           25631 :         size += otherSet->mInterfaceCount * sizeof(XPCNativeInterface*);
     745           51262 :     void* place = new char[size];
     746           25631 :     if (place)
     747           25631 :         obj = new(place) XPCNativeSet();
     748                 : 
     749           25631 :     if (obj) {
     750           25631 :         if (otherSet) {
     751           25631 :             obj->mMemberCount = otherSet->GetMemberCount() +
     752           25631 :                                 newInterface->GetMemberCount();
     753           25631 :             obj->mInterfaceCount = otherSet->mInterfaceCount + 1;
     754                 : 
     755           25631 :             XPCNativeInterface** src = otherSet->mInterfaces;
     756           25631 :             XPCNativeInterface** dest = obj->mInterfaces;
     757          102997 :             for (PRUint16 i = 0; i < obj->mInterfaceCount; i++) {
     758           77366 :                 if (i == position)
     759           25631 :                     *dest++ = newInterface;
     760                 :                 else
     761           51735 :                     *dest++ = *src++;
     762                 :             }
     763                 :         } else {
     764               0 :             obj->mMemberCount = newInterface->GetMemberCount();
     765               0 :             obj->mInterfaceCount = 1;
     766               0 :             obj->mInterfaces[0] = newInterface;
     767                 :         }
     768                 :     }
     769                 : 
     770           25631 :     return obj;
     771                 : }
     772                 : 
     773                 : // static
     774                 : void
     775          192264 : XPCNativeSet::DestroyInstance(XPCNativeSet* inst)
     776                 : {
     777          192264 :     inst->~XPCNativeSet();
     778          192264 :     delete [] (char*) inst;
     779          192264 : }
     780                 : 
     781                 : size_t
     782             284 : XPCNativeSet::SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf)
     783                 : {
     784             284 :     return mallocSizeOf(this);
     785                 : }
     786                 : 
     787                 : void
     788               0 : XPCNativeSet::DebugDump(PRInt16 depth)
     789                 : {
     790                 : #ifdef DEBUG
     791               0 :     depth--;
     792               0 :     XPC_LOG_ALWAYS(("XPCNativeSet @ %x", this));
     793               0 :         XPC_LOG_INDENT();
     794                 : 
     795               0 :         XPC_LOG_ALWAYS(("mInterfaceCount of %d", mInterfaceCount));
     796               0 :         if (depth) {
     797               0 :             for (PRUint16 i = 0; i < mInterfaceCount; i++)
     798               0 :                 mInterfaces[i]->DebugDump(depth);
     799                 :         }
     800               0 :         XPC_LOG_ALWAYS(("mMemberCount of %d", mMemberCount));
     801               0 :         XPC_LOG_OUTDENT();
     802                 : #endif
     803               0 : }

Generated by: LCOV version 1.7