js/xpconnect/src/XPCWrappedNativeInfo.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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=99: */
     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/. */
     7 /* Manage the shared info about interfaces for use by wrappedNatives. */
     9 #include "xpcprivate.h"
    10 #include "jswrapper.h"
    11 #include "nsCxPusher.h"
    13 #include "mozilla/MemoryReporting.h"
    14 #include "mozilla/XPTInterfaceInfoManager.h"
    16 using namespace JS;
    17 using namespace mozilla;
    19 /***************************************************************************/
    21 // XPCNativeMember
    23 // static
    24 bool
    25 XPCNativeMember::GetCallInfo(JSObject* funobj,
    26                              XPCNativeInterface** pInterface,
    27                              XPCNativeMember**    pMember)
    28 {
    29     funobj = js::UncheckedUnwrap(funobj);
    30     jsval ifaceVal = js::GetFunctionNativeReserved(funobj, 0);
    31     jsval memberVal = js::GetFunctionNativeReserved(funobj, 1);
    33     *pInterface = (XPCNativeInterface*) JSVAL_TO_PRIVATE(ifaceVal);
    34     *pMember = (XPCNativeMember*) JSVAL_TO_PRIVATE(memberVal);
    36     return true;
    37 }
    39 bool
    40 XPCNativeMember::NewFunctionObject(XPCCallContext& ccx,
    41                                    XPCNativeInterface* iface, HandleObject parent,
    42                                    jsval* pval)
    43 {
    44     MOZ_ASSERT(!IsConstant(), "Only call this if you're sure this is not a constant!");
    46     return Resolve(ccx, iface, parent, pval);
    47 }
    49 bool
    50 XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
    51                          HandleObject parent, jsval *vp)
    52 {
    53     if (IsConstant()) {
    54         const nsXPTConstant* constant;
    55         if (NS_FAILED(iface->GetInterfaceInfo()->GetConstant(mIndex, &constant)))
    56             return false;
    58         const nsXPTCMiniVariant& mv = *constant->GetValue();
    60         // XXX Big Hack!
    61         nsXPTCVariant v;
    62         v.flags = 0;
    63         v.type = constant->GetType();
    64         memcpy(&v.val, &mv.val, sizeof(mv.val));
    66         RootedValue resultVal(ccx);
    68         if (!XPCConvert::NativeData2JS(&resultVal, &v.val, v.type, nullptr, nullptr))
    69             return false;
    71         *vp = resultVal;
    73         return true;
    74     }
    75     // else...
    77     // This is a method or attribute - we'll be needing a function object
    79     int argc;
    80     JSNative callback;
    82     if (IsMethod()) {
    83         const nsXPTMethodInfo* info;
    84         if (NS_FAILED(iface->GetInterfaceInfo()->GetMethodInfo(mIndex, &info)))
    85             return false;
    87         // Note: ASSUMES that retval is last arg.
    88         argc = (int) info->GetParamCount();
    89         if (argc && info->GetParam((uint8_t)(argc-1)).IsRetval())
    90             argc-- ;
    92         callback = XPC_WN_CallMethod;
    93     } else {
    94         argc = 0;
    95         callback = XPC_WN_GetterSetter;
    96     }
    98     JSFunction *fun = js::NewFunctionByIdWithReserved(ccx, callback, argc, 0, parent, GetName());
    99     if (!fun)
   100         return false;
   102     JSObject* funobj = JS_GetFunctionObject(fun);
   103     if (!funobj)
   104         return false;
   106     js::SetFunctionNativeReserved(funobj, 0, PRIVATE_TO_JSVAL(iface));
   107     js::SetFunctionNativeReserved(funobj, 1, PRIVATE_TO_JSVAL(this));
   109     *vp = OBJECT_TO_JSVAL(funobj);
   111     return true;
   112 }
   114 /***************************************************************************/
   115 // XPCNativeInterface
   117 // static
   118 XPCNativeInterface*
   119 XPCNativeInterface::GetNewOrUsed(const nsIID* iid)
   120 {
   121     AutoJSContext cx;
   122     AutoMarkingNativeInterfacePtr iface(cx);
   123     XPCJSRuntime* rt = XPCJSRuntime::Get();
   125     IID2NativeInterfaceMap* map = rt->GetIID2NativeInterfaceMap();
   126     if (!map)
   127         return nullptr;
   129     iface = map->Find(*iid);
   131     if (iface)
   132         return iface;
   134     nsCOMPtr<nsIInterfaceInfo> info;
   135     XPTInterfaceInfoManager::GetSingleton()->GetInfoForIID(iid, getter_AddRefs(info));
   136     if (!info)
   137         return nullptr;
   139     iface = NewInstance(info);
   140     if (!iface)
   141         return nullptr;
   143     XPCNativeInterface* iface2 = map->Add(iface);
   144     if (!iface2) {
   145         NS_ERROR("failed to add our interface!");
   146         DestroyInstance(iface);
   147         iface = nullptr;
   148     } else if (iface2 != iface) {
   149         DestroyInstance(iface);
   150         iface = iface2;
   151     }
   153     return iface;
   154 }
   156 // static
   157 XPCNativeInterface*
   158 XPCNativeInterface::GetNewOrUsed(nsIInterfaceInfo* info)
   159 {
   160     AutoJSContext cx;
   161     AutoMarkingNativeInterfacePtr iface(cx);
   163     const nsIID* iid;
   164     if (NS_FAILED(info->GetIIDShared(&iid)) || !iid)
   165         return nullptr;
   167     XPCJSRuntime* rt = XPCJSRuntime::Get();
   169     IID2NativeInterfaceMap* map = rt->GetIID2NativeInterfaceMap();
   170     if (!map)
   171         return nullptr;
   173     iface = map->Find(*iid);
   175     if (iface)
   176         return iface;
   178     iface = NewInstance(info);
   179     if (!iface)
   180         return nullptr;
   182     XPCNativeInterface* iface2 = map->Add(iface);
   183     if (!iface2) {
   184         NS_ERROR("failed to add our interface!");
   185         DestroyInstance(iface);
   186         iface = nullptr;
   187     } else if (iface2 != iface) {
   188         DestroyInstance(iface);
   189         iface = iface2;
   190     }
   192     return iface;
   193 }
   195 // static
   196 XPCNativeInterface*
   197 XPCNativeInterface::GetNewOrUsed(const char* name)
   198 {
   199     nsCOMPtr<nsIInterfaceInfo> info;
   200     XPTInterfaceInfoManager::GetSingleton()->GetInfoForName(name, getter_AddRefs(info));
   201     return info ? GetNewOrUsed(info) : nullptr;
   202 }
   204 // static
   205 XPCNativeInterface*
   206 XPCNativeInterface::GetISupports()
   207 {
   208     // XXX We should optimize this to cache this common XPCNativeInterface.
   209     return GetNewOrUsed(&NS_GET_IID(nsISupports));
   210 }
   212 // static
   213 XPCNativeInterface*
   214 XPCNativeInterface::NewInstance(nsIInterfaceInfo* aInfo)
   215 {
   216     AutoJSContext cx;
   217     static const uint16_t MAX_LOCAL_MEMBER_COUNT = 16;
   218     XPCNativeMember local_members[MAX_LOCAL_MEMBER_COUNT];
   219     XPCNativeInterface* obj = nullptr;
   220     XPCNativeMember* members = nullptr;
   222     int i;
   223     bool failed = false;
   224     uint16_t constCount;
   225     uint16_t methodCount;
   226     uint16_t totalCount;
   227     uint16_t realTotalCount = 0;
   228     XPCNativeMember* cur;
   229     RootedString str(cx);
   230     RootedId interfaceName(cx);
   232     // XXX Investigate lazy init? This is a problem given the
   233     // 'placement new' scheme - we need to at least know how big to make
   234     // the object. We might do a scan of methods to determine needed size,
   235     // then make our object, but avoid init'ing *any* members until asked?
   236     // Find out how often we create these objects w/o really looking at
   237     // (or using) the members.
   239     bool canScript;
   240     if (NS_FAILED(aInfo->IsScriptable(&canScript)) || !canScript)
   241         return nullptr;
   243     if (NS_FAILED(aInfo->GetMethodCount(&methodCount)) ||
   244         NS_FAILED(aInfo->GetConstantCount(&constCount)))
   245         return nullptr;
   247     // If the interface does not have nsISupports in its inheritance chain
   248     // then we know we can't reflect its methods. However, some interfaces that
   249     // are used just to reflect constants are declared this way. We need to
   250     // go ahead and build the thing. But, we'll ignore whatever methods it may
   251     // have.
   252     if (!nsXPConnect::IsISupportsDescendant(aInfo))
   253         methodCount = 0;
   255     totalCount = methodCount + constCount;
   257     if (totalCount > MAX_LOCAL_MEMBER_COUNT) {
   258         members = new XPCNativeMember[totalCount];
   259         if (!members)
   260             return nullptr;
   261     } else {
   262         members = local_members;
   263     }
   265     // NOTE: since getters and setters share a member, we might not use all
   266     // of the member objects.
   268     for (i = 0; i < methodCount; i++) {
   269         const nsXPTMethodInfo* info;
   270         if (NS_FAILED(aInfo->GetMethodInfo(i, &info))) {
   271             failed = true;
   272             break;
   273         }
   275         // don't reflect Addref or Release
   276         if (i == 1 || i == 2)
   277             continue;
   279         if (!XPCConvert::IsMethodReflectable(*info))
   280             continue;
   282         str = JS_InternString(cx, info->GetName());
   283         if (!str) {
   284             NS_ERROR("bad method name");
   285             failed = true;
   286             break;
   287         }
   288         jsid name = INTERNED_STRING_TO_JSID(cx, str);
   290         if (info->IsSetter()) {
   291             MOZ_ASSERT(realTotalCount,"bad setter");
   292             // Note: ASSUMES Getter/Setter pairs are next to each other
   293             // This is a rule of the typelib spec.
   294             cur = &members[realTotalCount-1];
   295             MOZ_ASSERT(cur->GetName() == name,"bad setter");
   296             MOZ_ASSERT(cur->IsReadOnlyAttribute(),"bad setter");
   297             MOZ_ASSERT(cur->GetIndex() == i-1,"bad setter");
   298             cur->SetWritableAttribute();
   299         } else {
   300             // XXX need better way to find dups
   301             // MOZ_ASSERT(!LookupMemberByID(name),"duplicate method name");
   302             cur = &members[realTotalCount++];
   303             cur->SetName(name);
   304             if (info->IsGetter())
   305                 cur->SetReadOnlyAttribute(i);
   306             else
   307                 cur->SetMethod(i);
   308         }
   309     }
   311     if (!failed) {
   312         for (i = 0; i < constCount; i++) {
   313             const nsXPTConstant* constant;
   314             if (NS_FAILED(aInfo->GetConstant(i, &constant))) {
   315                 failed = true;
   316                 break;
   317             }
   319             str = JS_InternString(cx, constant->GetName());
   320             if (!str) {
   321                 NS_ERROR("bad constant name");
   322                 failed = true;
   323                 break;
   324             }
   325             jsid name = INTERNED_STRING_TO_JSID(cx, str);
   327             // XXX need better way to find dups
   328             //MOZ_ASSERT(!LookupMemberByID(name),"duplicate method/constant name");
   330             cur = &members[realTotalCount++];
   331             cur->SetName(name);
   332             cur->SetConstant(i);
   333         }
   334     }
   336     if (!failed) {
   337         const char* bytes;
   338         if (NS_FAILED(aInfo->GetNameShared(&bytes)) || !bytes ||
   339             nullptr == (str = JS_InternString(cx, bytes))) {
   340             failed = true;
   341         }
   342         interfaceName = INTERNED_STRING_TO_JSID(cx, str);
   343     }
   345     if (!failed) {
   346         // Use placement new to create an object with the right amount of space
   347         // to hold the members array
   348         int size = sizeof(XPCNativeInterface);
   349         if (realTotalCount > 1)
   350             size += (realTotalCount - 1) * sizeof(XPCNativeMember);
   351         void* place = new char[size];
   352         if (place)
   353             obj = new(place) XPCNativeInterface(aInfo, interfaceName);
   355         if (obj) {
   356             obj->mMemberCount = realTotalCount;
   357             // copy valid members
   358             if (realTotalCount)
   359                 memcpy(obj->mMembers, members,
   360                        realTotalCount * sizeof(XPCNativeMember));
   361         }
   362     }
   364     if (members && members != local_members)
   365         delete [] members;
   367     return obj;
   368 }
   370 // static
   371 void
   372 XPCNativeInterface::DestroyInstance(XPCNativeInterface* inst)
   373 {
   374     inst->~XPCNativeInterface();
   375     delete [] (char*) inst;
   376 }
   378 size_t
   379 XPCNativeInterface::SizeOfIncludingThis(MallocSizeOf mallocSizeOf)
   380 {
   381     return mallocSizeOf(this);
   382 }
   384 void
   385 XPCNativeInterface::DebugDump(int16_t depth)
   386 {
   387 #ifdef DEBUG
   388     depth--;
   389     XPC_LOG_ALWAYS(("XPCNativeInterface @ %x", this));
   390         XPC_LOG_INDENT();
   391         XPC_LOG_ALWAYS(("name is %s", GetNameString()));
   392         XPC_LOG_ALWAYS(("mMemberCount is %d", mMemberCount));
   393         XPC_LOG_ALWAYS(("mInfo @ %x", mInfo.get()));
   394         XPC_LOG_OUTDENT();
   395 #endif
   396 }
   398 /***************************************************************************/
   399 // XPCNativeSet
   401 // static
   402 XPCNativeSet*
   403 XPCNativeSet::GetNewOrUsed(const nsIID* iid)
   404 {
   405     AutoJSContext cx;
   406     AutoMarkingNativeSetPtr set(cx);
   408     AutoMarkingNativeInterfacePtr iface(cx);
   409     iface = XPCNativeInterface::GetNewOrUsed(iid);
   410     if (!iface)
   411         return nullptr;
   413     XPCNativeSetKey key(nullptr, iface, 0);
   415     XPCJSRuntime* rt = XPCJSRuntime::Get();
   416     NativeSetMap* map = rt->GetNativeSetMap();
   417     if (!map)
   418         return nullptr;
   420     set = map->Find(&key);
   422     if (set)
   423         return set;
   425     // hacky way to get a XPCNativeInterface** using the AutoPtr
   426     XPCNativeInterface* temp[] = {iface};
   427     set = NewInstance(temp, 1);
   428     if (!set)
   429         return nullptr;
   431     XPCNativeSet* set2 = map->Add(&key, set);
   432     if (!set2) {
   433         NS_ERROR("failed to add our set!");
   434         DestroyInstance(set);
   435         set = nullptr;
   436     } else if (set2 != set) {
   437         DestroyInstance(set);
   438         set = set2;
   439     }
   441     return set;
   442 }
   444 // static
   445 XPCNativeSet*
   446 XPCNativeSet::GetNewOrUsed(nsIClassInfo* classInfo)
   447 {
   448     AutoJSContext cx;
   449     AutoMarkingNativeSetPtr set(cx);
   450     XPCJSRuntime* rt = XPCJSRuntime::Get();
   452     ClassInfo2NativeSetMap* map = rt->GetClassInfo2NativeSetMap();
   453     if (!map)
   454         return nullptr;
   456     set = map->Find(classInfo);
   458     if (set)
   459         return set;
   461     nsIID** iidArray = nullptr;
   462     AutoMarkingNativeInterfacePtrArrayPtr interfaceArray(cx);
   463     uint32_t iidCount = 0;
   465     if (NS_FAILED(classInfo->GetInterfaces(&iidCount, &iidArray))) {
   466         // Note: I'm making it OK for this call to fail so that one can add
   467         // nsIClassInfo to classes implemented in script without requiring this
   468         // method to be implemented.
   470         // Make sure these are set correctly...
   471         iidArray = nullptr;
   472         iidCount = 0;
   473     }
   475     MOZ_ASSERT((iidCount && iidArray) || !(iidCount || iidArray), "GetInterfaces returned bad array");
   477     // !!! from here on we only exit through the 'out' label !!!
   479     if (iidCount) {
   480         AutoMarkingNativeInterfacePtrArrayPtr
   481             arr(cx, new XPCNativeInterface*[iidCount], iidCount, true);
   483         interfaceArray = arr;
   485         XPCNativeInterface** currentInterface = interfaceArray;
   486         nsIID**              currentIID = iidArray;
   487         uint16_t             interfaceCount = 0;
   489         for (uint32_t i = 0; i < iidCount; i++) {
   490             nsIID* iid = *(currentIID++);
   491             if (!iid) {
   492                 NS_ERROR("Null found in classinfo interface list");
   493                 continue;
   494             }
   496             XPCNativeInterface* iface =
   497                 XPCNativeInterface::GetNewOrUsed(iid);
   499             if (!iface) {
   500                 // XXX warn here
   501                 continue;
   502             }
   504             *(currentInterface++) = iface;
   505             interfaceCount++;
   506         }
   508         if (interfaceCount) {
   509             set = NewInstance(interfaceArray, interfaceCount);
   510             if (set) {
   511                 NativeSetMap* map2 = rt->GetNativeSetMap();
   512                 if (!map2)
   513                     goto out;
   515                 XPCNativeSetKey key(set, nullptr, 0);
   517                 XPCNativeSet* set2 = map2->Add(&key, set);
   518                 if (!set2) {
   519                     NS_ERROR("failed to add our set!");
   520                     DestroyInstance(set);
   521                     set = nullptr;
   522                     goto out;
   523                 }
   524                 if (set2 != set) {
   525                     DestroyInstance(set);
   526                     set = set2;
   527                 }
   528             }
   529         } else
   530             set = GetNewOrUsed(&NS_GET_IID(nsISupports));
   531     } else
   532         set = GetNewOrUsed(&NS_GET_IID(nsISupports));
   534     if (set) {
   535 #ifdef DEBUG
   536         XPCNativeSet* set2 =
   537 #endif
   538           map->Add(classInfo, set);
   539         MOZ_ASSERT(set2, "failed to add our set!");
   540         MOZ_ASSERT(set2 == set, "hashtables inconsistent!");
   541     }
   543 out:
   544     if (iidArray)
   545         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(iidCount, iidArray);
   546     if (interfaceArray)
   547         delete [] interfaceArray.get();
   549     return set;
   550 }
   552 // static
   553 void
   554 XPCNativeSet::ClearCacheEntryForClassInfo(nsIClassInfo* classInfo)
   555 {
   556     XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
   557     ClassInfo2NativeSetMap* map = rt->GetClassInfo2NativeSetMap();
   558     if (map)
   559         map->Remove(classInfo);
   560 }
   562 // static
   563 XPCNativeSet*
   564 XPCNativeSet::GetNewOrUsed(XPCNativeSet* otherSet,
   565                            XPCNativeInterface* newInterface,
   566                            uint16_t position)
   567 {
   568     AutoJSContext cx;
   569     AutoMarkingNativeSetPtr set(cx);
   570     XPCJSRuntime* rt = XPCJSRuntime::Get();
   571     NativeSetMap* map = rt->GetNativeSetMap();
   572     if (!map)
   573         return nullptr;
   575     XPCNativeSetKey key(otherSet, newInterface, position);
   577     set = map->Find(&key);
   579     if (set)
   580         return set;
   582     if (otherSet)
   583         set = NewInstanceMutate(otherSet, newInterface, position);
   584     else
   585         set = NewInstance(&newInterface, 1);
   587     if (!set)
   588         return nullptr;
   590     XPCNativeSet* set2 = map->Add(&key, set);
   591     if (!set2) {
   592         NS_ERROR("failed to add our set!");
   593         DestroyInstance(set);
   594         set = nullptr;
   595     } else if (set2 != set) {
   596         DestroyInstance(set);
   597         set = set2;
   598     }
   600     return set;
   601 }
   603 // static
   604 XPCNativeSet*
   605 XPCNativeSet::GetNewOrUsed(XPCNativeSet* firstSet,
   606                            XPCNativeSet* secondSet,
   607                            bool preserveFirstSetOrder)
   608 {
   609     // Figure out how many interfaces we'll need in the new set.
   610     uint32_t uniqueCount = firstSet->mInterfaceCount;
   611     for (uint32_t i = 0; i < secondSet->mInterfaceCount; ++i) {
   612         if (!firstSet->HasInterface(secondSet->mInterfaces[i]))
   613             uniqueCount++;
   614     }
   616     // If everything in secondSet was a duplicate, we can just use the first
   617     // set.
   618     if (uniqueCount == firstSet->mInterfaceCount)
   619         return firstSet;
   621     // If the secondSet is just a superset of the first, we can use it provided
   622     // that the caller doesn't care about ordering.
   623     if (!preserveFirstSetOrder && uniqueCount == secondSet->mInterfaceCount)
   624         return secondSet;
   626     // Ok, darn. Now we have to make a new set.
   627     //
   628     // It would be faster to just create the new set all at once, but that
   629     // would involve wrangling with some pretty hairy code - especially since
   630     // a lot of stuff assumes that sets are created by adding one interface to an
   631     // existing set. So let's just do the slow and easy thing and hope that the
   632     // above optimizations handle the common cases.
   633     XPCNativeSet* currentSet = firstSet;
   634     for (uint32_t i = 0; i < secondSet->mInterfaceCount; ++i) {
   635         XPCNativeInterface* iface = secondSet->mInterfaces[i];
   636         if (!currentSet->HasInterface(iface)) {
   637             // Create a new augmented set, inserting this interface at the end.
   638             uint32_t pos = currentSet->mInterfaceCount;
   639             currentSet = XPCNativeSet::GetNewOrUsed(currentSet, iface, pos);
   640             if (!currentSet)
   641                 return nullptr;
   642         }
   643     }
   645     // We've got the union set. Hand it back to the caller.
   646     MOZ_ASSERT(currentSet->mInterfaceCount == uniqueCount);
   647     return currentSet;
   648 }
   650 // static
   651 XPCNativeSet*
   652 XPCNativeSet::NewInstance(XPCNativeInterface** array,
   653                           uint16_t count)
   654 {
   655     XPCNativeSet* obj = nullptr;
   657     if (!array || !count)
   658         return nullptr;
   660     // We impose the invariant:
   661     // "All sets have exactly one nsISupports interface and it comes first."
   662     // This is the place where we impose that rule - even if given inputs
   663     // that don't exactly follow the rule.
   665     XPCNativeInterface* isup = XPCNativeInterface::GetISupports();
   666     uint16_t slots = count+1;
   668     uint16_t i;
   669     XPCNativeInterface** pcur;
   671     for (i = 0, pcur = array; i < count; i++, pcur++) {
   672         if (*pcur == isup)
   673             slots--;
   674     }
   676     // Use placement new to create an object with the right amount of space
   677     // to hold the members array
   678     int size = sizeof(XPCNativeSet);
   679     if (slots > 1)
   680         size += (slots - 1) * sizeof(XPCNativeInterface*);
   681     void* place = new char[size];
   682     if (place)
   683         obj = new(place) XPCNativeSet();
   685     if (obj) {
   686         // Stick the nsISupports in front and skip additional nsISupport(s)
   687         XPCNativeInterface** inp = array;
   688         XPCNativeInterface** outp = (XPCNativeInterface**) &obj->mInterfaces;
   689         uint16_t memberCount = 1;   // for the one member in nsISupports
   691         *(outp++) = isup;
   693         for (i = 0; i < count; i++) {
   694             XPCNativeInterface* cur;
   696             if (isup == (cur = *(inp++)))
   697                 continue;
   698             *(outp++) = cur;
   699             memberCount += cur->GetMemberCount();
   700         }
   701         obj->mMemberCount = memberCount;
   702         obj->mInterfaceCount = slots;
   703     }
   705     return obj;
   706 }
   708 // static
   709 XPCNativeSet*
   710 XPCNativeSet::NewInstanceMutate(XPCNativeSet*       otherSet,
   711                                 XPCNativeInterface* newInterface,
   712                                 uint16_t            position)
   713 {
   714     XPCNativeSet* obj = nullptr;
   716     if (!newInterface)
   717         return nullptr;
   718     if (otherSet && position > otherSet->mInterfaceCount)
   719         return nullptr;
   721     // Use placement new to create an object with the right amount of space
   722     // to hold the members array
   723     int size = sizeof(XPCNativeSet);
   724     if (otherSet)
   725         size += otherSet->mInterfaceCount * sizeof(XPCNativeInterface*);
   726     void* place = new char[size];
   727     if (place)
   728         obj = new(place) XPCNativeSet();
   730     if (obj) {
   731         if (otherSet) {
   732             obj->mMemberCount = otherSet->GetMemberCount() +
   733                                 newInterface->GetMemberCount();
   734             obj->mInterfaceCount = otherSet->mInterfaceCount + 1;
   736             XPCNativeInterface** src = otherSet->mInterfaces;
   737             XPCNativeInterface** dest = obj->mInterfaces;
   738             for (uint16_t i = 0; i < obj->mInterfaceCount; i++) {
   739                 if (i == position)
   740                     *dest++ = newInterface;
   741                 else
   742                     *dest++ = *src++;
   743             }
   744         } else {
   745             obj->mMemberCount = newInterface->GetMemberCount();
   746             obj->mInterfaceCount = 1;
   747             obj->mInterfaces[0] = newInterface;
   748         }
   749     }
   751     return obj;
   752 }
   754 // static
   755 void
   756 XPCNativeSet::DestroyInstance(XPCNativeSet* inst)
   757 {
   758     inst->~XPCNativeSet();
   759     delete [] (char*) inst;
   760 }
   762 size_t
   763 XPCNativeSet::SizeOfIncludingThis(MallocSizeOf mallocSizeOf)
   764 {
   765     return mallocSizeOf(this);
   766 }
   768 void
   769 XPCNativeSet::DebugDump(int16_t depth)
   770 {
   771 #ifdef DEBUG
   772     depth--;
   773     XPC_LOG_ALWAYS(("XPCNativeSet @ %x", this));
   774         XPC_LOG_INDENT();
   776         XPC_LOG_ALWAYS(("mInterfaceCount of %d", mInterfaceCount));
   777         if (depth) {
   778             for (uint16_t i = 0; i < mInterfaceCount; i++)
   779                 mInterfaces[i]->DebugDump(depth);
   780         }
   781         XPC_LOG_ALWAYS(("mMemberCount of %d", mMemberCount));
   782         XPC_LOG_OUTDENT();
   783 #endif
   784 }

mercurial