Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Private maps (hashtables). */
#include "mozilla/MathAlgorithms.h"
#include "mozilla/MemoryReporting.h"
#include "xpcprivate.h"
#include "XPCMaps.h"
#include "js/HashTable.h"
using namespace mozilla;
/***************************************************************************/
// implement JSObject2WrappedJSMap...
void JSObject2WrappedJSMap::UpdateWeakPointersAfterGC(JSTracer* trc) {
// Check all wrappers and update their JSObject pointer if it has been
// moved. Release any wrappers whose weakly held JSObject has died.
nsTArray<RefPtr<nsXPCWrappedJS>> dying;
for (auto iter = mTable.modIter(); !iter.done(); iter.next()) {
nsXPCWrappedJS* wrapper = iter.get().value();
MOZ_ASSERT(wrapper, "found a null JS wrapper!");
// There's no need to walk the entire chain, because only the root can be
// subject to finalization due to the double release behavior in Release.
// See the comment at the top of XPCWrappedJS.cpp about nsXPCWrappedJS
// lifetime.
if (wrapper && wrapper->IsSubjectToFinalization()) {
wrapper->UpdateObjectPointerAfterGC(trc);
if (!wrapper->GetJSObjectPreserveColor()) {
dying.AppendElement(dont_AddRef(wrapper));
}
}
// Remove or update the JSObject key in the table if necessary.
if (!JS_UpdateWeakPointerAfterGC(trc, &iter.get().mutableKey())) {
iter.remove();
}
}
}
void JSObject2WrappedJSMap::ShutdownMarker() {
for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
nsXPCWrappedJS* wrapper = iter.get().value();
MOZ_ASSERT(wrapper, "found a null JS wrapper!");
MOZ_ASSERT(wrapper->IsValid(), "found an invalid JS wrapper!");
wrapper->SystemIsBeingShutDown();
}
}
size_t JSObject2WrappedJSMap::SizeOfIncludingThis(
mozilla::MallocSizeOf mallocSizeOf) const {
size_t n = mallocSizeOf(this);
n += mTable.shallowSizeOfExcludingThis(mallocSizeOf);
return n;
}
size_t JSObject2WrappedJSMap::SizeOfWrappedJS(
mozilla::MallocSizeOf mallocSizeOf) const {
size_t n = 0;
for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
n += iter.get().value()->SizeOfIncludingThis(mallocSizeOf);
}
return n;
}
/***************************************************************************/
// implement Native2WrappedNativeMap...
Native2WrappedNativeMap::Native2WrappedNativeMap()
: mMap(XPC_NATIVE_MAP_LENGTH) {}
size_t Native2WrappedNativeMap::SizeOfIncludingThis(
mozilla::MallocSizeOf mallocSizeOf) const {
size_t n = mallocSizeOf(this);
n += mMap.shallowSizeOfExcludingThis(mallocSizeOf);
for (auto iter = mMap.iter(); !iter.done(); iter.next()) {
n += mallocSizeOf(iter.get().value());
}
return n;
}
/***************************************************************************/
// implement IID2NativeInterfaceMap...
IID2NativeInterfaceMap::IID2NativeInterfaceMap()
: mMap(XPC_NATIVE_INTERFACE_MAP_LENGTH) {}
size_t IID2NativeInterfaceMap::SizeOfIncludingThis(
mozilla::MallocSizeOf mallocSizeOf) const {
size_t n = mallocSizeOf(this);
n += mMap.shallowSizeOfExcludingThis(mallocSizeOf);
for (auto iter = mMap.iter(); !iter.done(); iter.next()) {
n += iter.get().value()->SizeOfIncludingThis(mallocSizeOf);
}
return n;
}
/***************************************************************************/
// implement ClassInfo2NativeSetMap...
ClassInfo2NativeSetMap::ClassInfo2NativeSetMap()
: mMap(XPC_NATIVE_SET_MAP_LENGTH) {}
size_t ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(
mozilla::MallocSizeOf mallocSizeOf) {
size_t n = mallocSizeOf(this);
n += mMap.shallowSizeOfExcludingThis(mallocSizeOf);
return n;
}
/***************************************************************************/
// implement ClassInfo2WrappedNativeProtoMap...
ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap()
: mMap(XPC_NATIVE_PROTO_MAP_LENGTH) {}
size_t ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(
mozilla::MallocSizeOf mallocSizeOf) const {
size_t n = mallocSizeOf(this);
n += mMap.shallowSizeOfExcludingThis(mallocSizeOf);
for (auto iter = mMap.iter(); !iter.done(); iter.next()) {
n += mallocSizeOf(iter.get().value());
}
return n;
}
/***************************************************************************/
// implement NativeSetMap...
bool NativeSetHasher::match(Key key, Lookup lookup) {
// The |key| argument is for the existing table entry and |lookup| is the
// value passed by the caller that is being compared with it.
XPCNativeSet* SetInTable = key;
XPCNativeSet* Set = lookup->GetBaseSet();
XPCNativeInterface* Addition = lookup->GetAddition();
if (!Set) {
// This is a special case to deal with the invariant that says:
// "All sets have exactly one nsISupports interface and it comes first."
// See XPCNativeSet::NewInstance for details.
//
// Though we might have a key that represents only one interface, we
// know that if that one interface were contructed into a set then
// it would end up really being a set with two interfaces (except for
// the case where the one interface happened to be nsISupports).
return (SetInTable->GetInterfaceCount() == 1 &&
SetInTable->GetInterfaceAt(0) == Addition) ||
(SetInTable->GetInterfaceCount() == 2 &&
SetInTable->GetInterfaceAt(1) == Addition);
}
if (!Addition && Set == SetInTable) {
return true;
}
uint16_t count = Set->GetInterfaceCount();
if (count + (Addition ? 1 : 0) != SetInTable->GetInterfaceCount()) {
return false;
}
XPCNativeInterface** CurrentInTable = SetInTable->GetInterfaceArray();
XPCNativeInterface** Current = Set->GetInterfaceArray();
for (uint16_t i = 0; i < count; i++) {
if (*(Current++) != *(CurrentInTable++)) {
return false;
}
}
return !Addition || Addition == *(CurrentInTable++);
}
NativeSetMap::NativeSetMap() : mSet(XPC_NATIVE_SET_MAP_LENGTH) {}
size_t NativeSetMap::SizeOfIncludingThis(
mozilla::MallocSizeOf mallocSizeOf) const {
size_t n = mallocSizeOf(this);
n += mSet.shallowSizeOfExcludingThis(mallocSizeOf);
for (auto iter = mSet.iter(); !iter.done(); iter.next()) {
n += iter.get()->SizeOfIncludingThis(mallocSizeOf);
}
return n;
}
/***************************************************************************/