mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
724e70642d
- Bug 1247955 - Add telemetry for compacting GC r=terrence (71fc631b20) - Bug 1200133 - Part1 - Change mochitest using TV Simulator Service. r=seanlin (bbddf95aae) - bit of Bug 1230674 - part 3, (253d2ab0ce) - Bug 1144103 - Support screen recording r=mwu (694cd8f580) - Bug 1237914 - Remove layers.screen-recording.enabled r=mwu (22edbe0944) - Bug 1231042 - clean current composition task and related flag when screen off. r=mchang (45c996e32b) - Bug 1137151: Marked destructor of |nsWindow| as protected, r=mwu (6ebb963472) - Bug 1187503 - use external surface size on CompositorOGL r=nical (8481425ca9) - Bug 1238876 - Move StartRemoteDrawing() implementation from nsWindow to nsScreenGonk r=mwu (9b7a2066d2) - Bug 1006688 - Support capture screen via adb r=mwu (d651416c44) - Bug 1244044 - remember display status; r=jerry (d8a252f081) - Bug 1247570 - unbreak widget/gonk/nativewindow/FakeSurfaceComposer.cpp r=gwagner (de01fd3084) - Bug 1020199 - Make sure APZ works with nested oop iframe. r=kats, r=dvander. (8f4285b97f) - Bug 1235858 - Record the time stamp, use it for crash reports. r=botond (98d999aa25) - Bug 1247671: Increase the crash logging length to 16 by default (+ small white space change in the comments) r=dvander (8a0995cb1c) - Bug 867501 - Pref allows JS locale to be set to US English/C. r=khuey (8d6e5df33d) - Bug 1207972: Move to using USER_INTERACTIVE and JOB_INTERACTIVE by default for the Windows content sandbox. r=tabraldes (494ecebd8e) - Bug 1234673 - Avoid users from locales ar, fa, he, ur for e10s rollout to beta. r=jimm (adf49af577) - Bug 1234675 - Ability to disable e10s for users with addons. r=Mossop (6abaeba541) - Bug 1233837 support migration wizard override from distribution.ini, r=bsmedberg (98c95ecc4b) - Bug 884831 - GTK3 - crash at browser end [@ XFreeColormap() ], r=karlt (13d9067ab0) - Bug 1215078 - [Wayland] Configure display for Wayland session. r=karlt (c4417d3534) - Bug 1111701 - Remove E10S_AUTOSTART histogram. r=dexter (56625e7353) - Bug 1239520 - Enabled e10s on all configurations except release. r=billm (48c760a1f8) - Bug 1241294 - Update E10S_AUTOSTART_STATUS telemetry probe (and rename it to E10S_STATUS). r=vladan (7217e4c9d3) - Bug 1241959 - Add a description of e10s blocked status to about:support. r=jimm (b6cb2e6dac) - Bug 1165818: Remove temporary Nightly only MozTemp-* clean-up code. r=jimm (fdb11aed0e) - Bug 1243882 - Block e10s for locales based on Firefox's locale, not the OS. r=ehsan (873b09db0f) - Bug 1235437 - Add annotation for major graphics preferences. r=bgirard (2e147567be) - Bug 1237404 - Part 1. Exposing some functionality in gfxCrashReporterUtils. r=benwa (dc08c3ba92) - Bug 1237404 - Part 2. Optimizing the main thread scenario. r=benwa (e5b6704b57) - Bug 1237770: Disable D3D9 on XP with E10S. r=jrmuizel (6424700126) - Bug 1210351 - Limit maximum computed tile size to 512x512. r=snorp (162839caf7) - Bug 1221073 - Increase max tile size to 1024 again. r=mstange (29e8513390) - Bug 990017. Prevent skia accelerated canvas backends from rendering content. r=jmuizelaar (b257281035) - Bug 1178385. Add a pref to force enable hw video decode. r=milan (f69cde6047) - Bug 1230196 - Allow release channel to run e10s. r=billm (ab5d0a464c) - Bug 1231915 - Ignore the APZ pref if MOZ_ANDROID_APZ is enabled, since the pref doesn't cover all the relevant code. r=rbarker (3984b57173) - Bug 1187464 - Part 1. We can get the wrong texture source type, so deal with it. Carry r=mstange (0d47ffdd65) - Bug 1187464 - Part 2. RTTI for TextureSource debug purposes. Carry r=botond (af8b92042d) - Bug 1187464 - Part 3. Check if GetSurface returned null. r=mstange (ab7de5dabb) - Bug 1165407 - Properly flush the log stream after logging it. r=botond (6dd38e7e7a) - Bug 1239844 - Log hexadecimal values in a more standard way. r=dholbert (aa7de36cfd) - Bug 1241769 - Use Singleton pattern to nsScreenManagerGonk r=mwu (bb0c30ce80) - Bug 1229262 - Fix nsScreenGonk's thread safety r=mwu (6c60907ce9) - Bug 1165161 - stop bootAnim with "browser-ui-startup-complete" event. r=mwu (e40ddb816a) - Bug 1230397 - Write safe mode pref on the main thread r=dbaron (0538d0353f) - Bug 1172805 - Fix enum comparison warnings in nsAppShell. r=mwu (e77ec14fed) - Bug 1215494 - Don't set b2g.safe_mode pref in child process. r=fabrice (3264d2c872) - Bug 1192949 - Fix nsScreenGonk::SetMirroringScreen() r=mwu (39abf13ff4) - Bug 1243413 - If a plugin window is hidden in an adjacent scroll frame due to APZ scroll state changes, make sure to show the plugin window after the scroll operation complete. r=kats (302f14476f) - Bug 1187322 - Fix bustage. (5fe8e7b3e8) - Bug 241788 - mozilla::Tokenizer - token type for \n should whitespace if given in constructor r=honzab (d4da4354c8) - Bug 1237827 - Be sure to clear LayerComposite::mLayerComposited between each composite. r=mattwoodrow (cc02aef817) - Bug 1244943 - Make PostProcessLayers aware of preserve-3d. r=mattwoodrow (48fadfdcf7) - Bug 1229317 - Allow preserve-3d and opacity to be combined on the root element of a preserve-3d chain. r=roc (030c042699) - Bug 1231564 - Don't take the compositor side layer-tree snapshot until after compositing. r=dvander (c0164b6464) - Bug 1247445 - Rename Layer::GetEffectiveVisibleRegion GetLocalVisibleRegion. r=botond (35125c3f71) - Bug 945613 - Part 3: #ifdef pragma for gcc >= 4.7.0. r=ehsan (67786ad3f8) - Bug 1227210: Ensure the mask and the surface are in the right space when being blended. r=mattwoodrow (6745cd99f8) - Bug 1229587 part 1 - Disable C4464 warning newly added in VS2015u1. r=keeler (65cf58d55d) - Bug 1229587 part 2 - Use verbose format to disable C4061 to workaround bug of VS2015u1. r=keeler (8f8fb5190f) - Bug 1189891 - Avoid including <cstring> from pkix/Input.h. r=bsmith (7202ad2de7) - Bug 1207499 - Part 9: Remove use of expression closure from storage/. r=mak (cf0f139799) - Bug 1230549 - Storage should pass more eslint rules. r=yoric (91e007dacb) - Bug 1230549 - Make Storage pass basic eslint. r=yoric (37c88987e8) - Bug 1237601 - Centralize storage xpcshell promise helpers (support patch). r=bkelly (ebee41dfae) - Bug 1237601 - Perform storage close synchronously if async thread cannot be started. r=bkelly (855430997d) - bug 1227008 use GtkPaperSize in GtkPageSetup directly, instead of maintaining a separate copy r=acomminos (cf1bade905) - Bug 1205643 - Move scrollbar borders to slider to receive button events. r=karlt (76ece6a2fd) - Bug 1141207 add gtk_print_settings_foreach to mozgtk.c. r=karlt (aee4b94e27) - Bug 1206516 - Use temporary widget to construct style context for GtkInfoBar. r=karlt (1ce56b1799) - bug 1205199 keep the socket alive as long as the plug window r=acomminos (bf1e4585da) - Bug 1242135 - Annotate intentional and fix unintentional switch fallthroughs in widget/gtk/. r=karlt (102180ea0a) - Bug 1221610 - Remove ToIntMargin(). r=jrmuizel. (5d234b1dd6) - Bug 1238582 - Skip simulated OOM check in the case where we're growing within reserved space; r=Waldo (2d00fa9605) - Bug 1242812 - Only check for simulated OOM in vectors when growing beyond reserved size r=Waldo (98ad0de5ff) - Bug 1144745 - scale border returned by GetWidgetBorder(), r=karlt (8639c7b240) - Bug 1184936 - Need convert from UTF8 for printer name. r=karlt (99e2863372) - Bug 569295 - limit the number of bytes we attempt to upload to the storage servers. r=rnewman (8072be50bb) - Bug 779430, try to not flush layout while we're in process to restore a bfcached document, r=bz (47d01dd107) - Bug 1241579 - Convert services/ to use channel.open2() (r=sicking) (fd6ee21f67) - Bug 1228510 - initialize 2 more variables. r=bas (e3d144854a) - Bug 1229577 - Rename NewSurfaceDescriptorGralloc into SurfaceDescriptorGralloc. r=sotaro (99b8d621e4) - Bug 1241665 - Correctly convert IOSurfaces to SourceSurfaces in MacIOSurfaceTextureSourceBasic and MacIOSurfaceTextureData. r=mattwoodrow (54ce8c1582) - Bug 1241665 - Move IOSurface YCbCr conversion code to a new file MacIOSurfaceHelpers.cpp. r=mattwoodrow (aeb7f341cf) - Bug 1191161 - p1 - Merge WrapEntireClassForJNI into WrapElementForJNI, r=jchen (684111ca72) - Bug 1246775 - use already_AddRefed in PersistentBufferProvider interface. r=bas (373a63f129) - Bug 1232231 - BorrowDrawTarget can return nullptr - be ready for it. r=nical (0156e1c412) - Bug 1227224 - Further improvements to generic tree traversal algorithms. r=botond (f71854fea6) - Bug 1234047 - Always reuse an existing TextureClient in IMFYCbCrImage if one exist. r=Bas (4c995d1668) - Bug 1240668 - Duplicate GonkNativeHandle::NhObj in ImageClientSingle::UpdateImage() r=nical (ed213d6f07) - Bug 1213095 - Inline the DispatchRepaintRequest function. r=botond (33d14a377c) - Bug 1213095 - Don't allow RequestContentRepaint to mutate the provided FrameMetrics. r=botond (676e6082b5) - Bug 1213095 - Ensure that stale FrameMetrics do not clobber more recent metrics for paint requests. r=botond (b6e75b0e37) - Bug 1238040 - Update telemetry measures for checkerboarding. r=botond,vladan (e41963fce5) - Bug 1238042 - Expose the checkerboard reports out to JS. r=ehsan,botond (986bb53bc5) - Bug 1238137 - Define a telemetry histogram for tracking the input methods used to trigger scrolling. r=kats (9e366c56a5) - remove unused (b0dc04a498) - Bug 1238137 - Telemetry pings for APZ-driven scroll input methods. r=kats (3f026677bd) - Bug 1241371. Properly update mLastUpdateImagesPos on scrollframes when the image visibility pass encounters them. r=mats (128edd5957) - Bug 1241371. Don't schedule an image visibility update every time display port margins change. r=kats (9927515115) - Bug 990916 - When setting a displayport, schedule a timer to remove it as well. r=tnikkel (ddd943226d) - Bug 990916 - Track if a scrollframe is a scroll parent for something else. r=tnikkel (7128db6038) - Bug 1245285 - part 1, Remove unused mRepaintInterval from AsyncPanZoomAnimation r=botond (ec516fe9f0) - Bug 1245285 - part 2, Prevent Zoom and Overscroll animations from repainting durring animation r=botond (6a66a0005a) - Bug 1245285 - part 3, Remove unused repaint_interval prefs r=botond (9987a58743) - Bug 1243413 - Avoid hiding windowed plugins that aren't contained within the active scroll frame. r=roc (f059ce95da) - Bug 1104356 - When doing a smooth scroll on a non-APZ'd scrollframe, fall back to the main thread machinery. r=kip (44d75dc20f) - Bug 990916 - On displayport expiry, trigger another round of expiry up the ancestor chain. r=tnikkel (8ce9a22429) - Bug 1245925 - Don't allow expiring the displayport on root scrollframes. r=tnikkel (2ec6218e2e) - Bug 1236040 - When updating the scroll position, only schedule image visibility checks if the display port has changed. r=tn (aedac7070f) - Bug 1234725. Don't change the dirty rect to the display port when building display lists for documents. r=mstange (6ff3e41934) - Fix crash trying to allocate textures for oversize scrollbars. (bug 1214261, r=mstange) (b4b4fa368d) - Bug 1234877 - Whether a scroll frame is async scrollable is determined by mWillBuildScrollableLayer, not by usingDisplayPort. r=tn (2daacb63f5) - Bug 1241917 - Restrict subframe's displayport base to root composition bounds. r=tn (7e50ff6bae) - Bug 1246443. Don't make nsLayoutUtils::MaybeCreateDisplayPort also set the displayport base anymore. r=botond (2970d8f2a6) - Bug 1246443 - Only restrict displayport base to root composition bounds if content has displayport; r=tnikkel (a841dedff4) - Bug 1208985 - Use height for scroll-snap-points-y percentage values; r=kip (17ce448e8b) - Bug 1238040 - Add a telemetry probe for potential checkerboarding duration. r=botond,vladan (bdf18d520b) - Bug 1240622 - Guard mCheckerboardEvent with a mutex to avoid races. r=botond (b81534272c) - Bug 1240202 - Rename APZOverscrollHandoffTester to APZScrollHandoffTester. r=kats (3c165a103d) - Bug 1240202 - Change input event generation utilities used by APZ gtests to take points instead of loose coordinates. r=kats (e29de86c33) - Bug 1240202 - Avoid getting stuck in overscroll when the screen is tapped during an overscroll animation. r=kats (3822391d27) - Bug 1225045: Fix stagefright include paths for ANDROID_VERSION >= 17, r=gps (1eabe097b5)
763 lines
21 KiB
C++
763 lines
21 KiB
C++
/* -*- 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/. */
|
|
|
|
#include "mozilla/Assertions.h"
|
|
#include "mozilla/Attributes.h"
|
|
#include "mozilla/Compiler.h"
|
|
#include "mozilla/HashFunctions.h"
|
|
#include "mozilla/MemoryReporting.h"
|
|
#include "mozilla/DebugOnly.h"
|
|
#include "mozilla/unused.h"
|
|
|
|
#include "nsAtomTable.h"
|
|
#include "nsStaticAtom.h"
|
|
#include "nsString.h"
|
|
#include "nsCRT.h"
|
|
#include "PLDHashTable.h"
|
|
#include "prenv.h"
|
|
#include "nsThreadUtils.h"
|
|
#include "nsDataHashtable.h"
|
|
#include "nsHashKeys.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "nsUnicharUtils.h"
|
|
|
|
using namespace mozilla;
|
|
|
|
#if defined(__clang__)
|
|
# pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
|
|
#elif MOZ_IS_GCC
|
|
# if MOZ_GCC_VERSION_AT_LEAST(4, 7, 0)
|
|
# pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
|
|
# endif
|
|
#endif
|
|
|
|
/**
|
|
* The shared hash table for atom lookups.
|
|
*
|
|
* XXX This should be manipulated in a threadsafe way or we should make
|
|
* sure it's only manipulated from the main thread. Probably the latter
|
|
* is better, since the former would hurt performance.
|
|
*/
|
|
static PLDHashTable* gAtomTable;
|
|
|
|
class StaticAtomEntry : public PLDHashEntryHdr
|
|
{
|
|
public:
|
|
typedef const nsAString& KeyType;
|
|
typedef const nsAString* KeyTypePointer;
|
|
|
|
explicit StaticAtomEntry(KeyTypePointer aKey) {}
|
|
StaticAtomEntry(const StaticAtomEntry& aOther) : mAtom(aOther.mAtom) {}
|
|
~StaticAtomEntry() {}
|
|
|
|
bool KeyEquals(KeyTypePointer aKey) const
|
|
{
|
|
return mAtom->Equals(*aKey);
|
|
}
|
|
|
|
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
|
static PLDHashNumber HashKey(KeyTypePointer aKey)
|
|
{
|
|
return HashString(*aKey);
|
|
}
|
|
|
|
enum { ALLOW_MEMMOVE = true };
|
|
|
|
// mAtom only points to objects of type PermanentAtomImpl, which are not
|
|
// really refcounted. But since these entries live in a global hashtable,
|
|
// this reference is essentially owning.
|
|
nsIAtom* MOZ_OWNING_REF mAtom;
|
|
};
|
|
|
|
/**
|
|
* A hashtable of static atoms that existed at app startup. This hashtable
|
|
* helps nsHtml5AtomTable.
|
|
*/
|
|
typedef nsTHashtable<StaticAtomEntry> StaticAtomTable;
|
|
static StaticAtomTable* gStaticAtomTable = nullptr;
|
|
|
|
/**
|
|
* Whether it is still OK to add atoms to gStaticAtomTable.
|
|
*/
|
|
static bool gStaticAtomTableSealed = false;
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Note that AtomImpl objects are sometimes converted into PermanentAtomImpl
|
|
* objects using placement new and just overwriting the vtable pointer.
|
|
*/
|
|
|
|
class AtomImpl : public nsIAtom
|
|
{
|
|
public:
|
|
AtomImpl(const nsAString& aString, uint32_t aHash);
|
|
|
|
// This is currently only used during startup when creating a permanent atom
|
|
// from NS_RegisterStaticAtoms
|
|
AtomImpl(nsStringBuffer* aData, uint32_t aLength, uint32_t aHash);
|
|
|
|
protected:
|
|
// This is only intended to be used when a normal atom is turned into a
|
|
// permanent one.
|
|
AtomImpl()
|
|
{
|
|
// We can't really assert that mString is a valid nsStringBuffer string,
|
|
// so do the best we can do and check for some consistencies.
|
|
NS_ASSERTION((mLength + 1) * sizeof(char16_t) <=
|
|
nsStringBuffer::FromData(mString)->StorageSize() &&
|
|
mString[mLength] == 0,
|
|
"Not initialized atom");
|
|
}
|
|
|
|
// We don't need a virtual destructor here because PermanentAtomImpl
|
|
// deletions aren't handled through Release().
|
|
~AtomImpl();
|
|
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIATOM
|
|
|
|
enum { REFCNT_PERMANENT_SENTINEL = UINT32_MAX };
|
|
|
|
virtual bool IsPermanent();
|
|
|
|
// We can't use the virtual function in the base class destructor.
|
|
bool IsPermanentInDestructor()
|
|
{
|
|
return mRefCnt == REFCNT_PERMANENT_SENTINEL;
|
|
}
|
|
|
|
// for |#ifdef NS_BUILD_REFCNT_LOGGING| access to reference count
|
|
nsrefcnt GetRefCount() { return mRefCnt; }
|
|
|
|
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf);
|
|
};
|
|
|
|
/**
|
|
* A non-refcounted implementation of nsIAtom.
|
|
*/
|
|
|
|
class PermanentAtomImpl final : public AtomImpl
|
|
{
|
|
public:
|
|
PermanentAtomImpl(const nsAString& aString, PLDHashNumber aKeyHash)
|
|
: AtomImpl(aString, aKeyHash)
|
|
{
|
|
}
|
|
PermanentAtomImpl(nsStringBuffer* aData, uint32_t aLength,
|
|
PLDHashNumber aKeyHash)
|
|
: AtomImpl(aData, aLength, aKeyHash)
|
|
{
|
|
}
|
|
PermanentAtomImpl() {}
|
|
|
|
~PermanentAtomImpl();
|
|
|
|
virtual bool IsPermanent();
|
|
|
|
// SizeOfIncludingThis() isn't needed -- the one inherited from AtomImpl is
|
|
// good enough, because PermanentAtomImpl doesn't add any new data members.
|
|
|
|
void* operator new(size_t aSize, AtomImpl* aAtom) CPP_THROW_NEW;
|
|
void* operator new(size_t aSize) CPP_THROW_NEW
|
|
{
|
|
return ::operator new(aSize);
|
|
}
|
|
|
|
private:
|
|
NS_IMETHOD_(MozExternalRefCountType) AddRef();
|
|
NS_IMETHOD_(MozExternalRefCountType) Release();
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
struct AtomTableEntry : public PLDHashEntryHdr
|
|
{
|
|
// These references are either to non-permanent atoms, in which case they are
|
|
// non-owning, or they are to permanent atoms that are not really refcounted.
|
|
// The exact lifetime rules are documented in AtomTableClearEntry.
|
|
AtomImpl* MOZ_NON_OWNING_REF mAtom;
|
|
};
|
|
|
|
struct AtomTableKey
|
|
{
|
|
AtomTableKey(const char16_t* aUTF16String, uint32_t aLength, uint32_t aHash)
|
|
: mUTF16String(aUTF16String)
|
|
, mUTF8String(nullptr)
|
|
, mLength(aLength)
|
|
, mHash(aHash)
|
|
{
|
|
MOZ_ASSERT(mHash == HashString(mUTF16String, mLength));
|
|
}
|
|
|
|
AtomTableKey(const char* aUTF8String, uint32_t aLength, uint32_t aHash)
|
|
: mUTF16String(nullptr)
|
|
, mUTF8String(aUTF8String)
|
|
, mLength(aLength)
|
|
, mHash(aHash)
|
|
{
|
|
mozilla::DebugOnly<bool> err;
|
|
MOZ_ASSERT(aHash == HashUTF8AsUTF16(mUTF8String, mLength, &err));
|
|
}
|
|
|
|
AtomTableKey(const char16_t* aUTF16String, uint32_t aLength,
|
|
uint32_t* aHashOut)
|
|
: mUTF16String(aUTF16String)
|
|
, mUTF8String(nullptr)
|
|
, mLength(aLength)
|
|
{
|
|
mHash = HashString(mUTF16String, mLength);
|
|
*aHashOut = mHash;
|
|
}
|
|
|
|
AtomTableKey(const char* aUTF8String, uint32_t aLength, uint32_t* aHashOut)
|
|
: mUTF16String(nullptr)
|
|
, mUTF8String(aUTF8String)
|
|
, mLength(aLength)
|
|
{
|
|
bool err;
|
|
mHash = HashUTF8AsUTF16(mUTF8String, mLength, &err);
|
|
if (err) {
|
|
mUTF8String = nullptr;
|
|
mLength = 0;
|
|
mHash = 0;
|
|
}
|
|
*aHashOut = mHash;
|
|
}
|
|
|
|
const char16_t* mUTF16String;
|
|
const char* mUTF8String;
|
|
uint32_t mLength;
|
|
uint32_t mHash;
|
|
};
|
|
|
|
static PLDHashNumber
|
|
AtomTableGetHash(PLDHashTable* aTable, const void* aKey)
|
|
{
|
|
const AtomTableKey* k = static_cast<const AtomTableKey*>(aKey);
|
|
return k->mHash;
|
|
}
|
|
|
|
static bool
|
|
AtomTableMatchKey(PLDHashTable* aTable, const PLDHashEntryHdr* aEntry,
|
|
const void* aKey)
|
|
{
|
|
const AtomTableEntry* he = static_cast<const AtomTableEntry*>(aEntry);
|
|
const AtomTableKey* k = static_cast<const AtomTableKey*>(aKey);
|
|
|
|
if (k->mUTF8String) {
|
|
return
|
|
CompareUTF8toUTF16(nsDependentCSubstring(k->mUTF8String,
|
|
k->mUTF8String + k->mLength),
|
|
nsDependentAtomString(he->mAtom)) == 0;
|
|
}
|
|
|
|
uint32_t length = he->mAtom->GetLength();
|
|
if (length != k->mLength) {
|
|
return false;
|
|
}
|
|
|
|
return memcmp(he->mAtom->GetUTF16String(),
|
|
k->mUTF16String, length * sizeof(char16_t)) == 0;
|
|
}
|
|
|
|
static void
|
|
AtomTableClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
|
|
{
|
|
// Normal |AtomImpl| atoms are deleted when their refcount hits 0, and
|
|
// they then remove themselves from the table. In other words, they
|
|
// are owned by the callers who own references to them.
|
|
// |PermanentAtomImpl| permanent atoms ignore their refcount and are
|
|
// deleted when they are removed from the table at table destruction.
|
|
// In other words, they are owned by the atom table.
|
|
|
|
AtomImpl* atom = static_cast<AtomTableEntry*>(aEntry)->mAtom;
|
|
if (atom->IsPermanent()) {
|
|
// Note that the cast here is important since AtomImpls doesn't have a
|
|
// virtual dtor.
|
|
delete static_cast<PermanentAtomImpl*>(atom);
|
|
}
|
|
}
|
|
|
|
static void
|
|
AtomTableInitEntry(PLDHashEntryHdr* aEntry, const void* aKey)
|
|
{
|
|
static_cast<AtomTableEntry*>(aEntry)->mAtom = nullptr;
|
|
}
|
|
|
|
|
|
static const PLDHashTableOps AtomTableOps = {
|
|
AtomTableGetHash,
|
|
AtomTableMatchKey,
|
|
PLDHashTable::MoveEntryStub,
|
|
AtomTableClearEntry,
|
|
AtomTableInitEntry
|
|
};
|
|
|
|
#define RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE 31
|
|
static nsIAtom*
|
|
sRecentlyUsedMainThreadAtoms[RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE] = {};
|
|
|
|
static inline
|
|
void
|
|
PromoteToPermanent(AtomImpl* aAtom)
|
|
{
|
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
|
{
|
|
nsrefcnt refcount = aAtom->GetRefCount();
|
|
do {
|
|
NS_LOG_RELEASE(aAtom, --refcount, "AtomImpl");
|
|
} while (refcount);
|
|
}
|
|
#endif
|
|
aAtom = new (aAtom) PermanentAtomImpl();
|
|
}
|
|
|
|
void
|
|
NS_PurgeAtomTable()
|
|
{
|
|
delete gStaticAtomTable;
|
|
gStaticAtomTable = nullptr;
|
|
|
|
if (gAtomTable) {
|
|
#ifdef DEBUG
|
|
const char* dumpAtomLeaks = PR_GetEnv("MOZ_DUMP_ATOM_LEAKS");
|
|
if (dumpAtomLeaks && *dumpAtomLeaks) {
|
|
uint32_t leaked = 0;
|
|
printf("*** %d atoms still exist (including permanent):\n",
|
|
gAtomTable->EntryCount());
|
|
for (auto iter = gAtomTable->Iter(); !iter.Done(); iter.Next()) {
|
|
auto entry = static_cast<AtomTableEntry*>(iter.Get());
|
|
AtomImpl* atom = entry->mAtom;
|
|
if (!atom->IsPermanent()) {
|
|
leaked++;
|
|
nsAutoCString str;
|
|
atom->ToUTF8String(str);
|
|
fputs(str.get(), stdout);
|
|
fputs("\n", stdout);
|
|
}
|
|
}
|
|
printf("*** %u non-permanent atoms leaked\n", leaked);
|
|
}
|
|
#endif
|
|
delete gAtomTable;
|
|
gAtomTable = nullptr;
|
|
}
|
|
}
|
|
|
|
AtomImpl::AtomImpl(const nsAString& aString, uint32_t aHash)
|
|
{
|
|
mLength = aString.Length();
|
|
RefPtr<nsStringBuffer> buf = nsStringBuffer::FromString(aString);
|
|
if (buf) {
|
|
mString = static_cast<char16_t*>(buf->Data());
|
|
} else {
|
|
buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(char16_t));
|
|
mString = static_cast<char16_t*>(buf->Data());
|
|
CopyUnicodeTo(aString, 0, mString, mLength);
|
|
mString[mLength] = char16_t(0);
|
|
}
|
|
|
|
mHash = aHash;
|
|
MOZ_ASSERT(mHash == HashString(mString, mLength));
|
|
|
|
NS_ASSERTION(mString[mLength] == char16_t(0), "null terminated");
|
|
NS_ASSERTION(buf && buf->StorageSize() >= (mLength + 1) * sizeof(char16_t),
|
|
"enough storage");
|
|
NS_ASSERTION(Equals(aString), "correct data");
|
|
|
|
// Take ownership of buffer
|
|
mozilla::Unused << buf.forget();
|
|
}
|
|
|
|
AtomImpl::AtomImpl(nsStringBuffer* aStringBuffer, uint32_t aLength,
|
|
uint32_t aHash)
|
|
{
|
|
mLength = aLength;
|
|
mString = static_cast<char16_t*>(aStringBuffer->Data());
|
|
// Technically we could currently avoid doing this addref by instead making
|
|
// the static atom buffers have an initial refcount of 2.
|
|
aStringBuffer->AddRef();
|
|
|
|
mHash = aHash;
|
|
MOZ_ASSERT(mHash == HashString(mString, mLength));
|
|
|
|
NS_ASSERTION(mString[mLength] == char16_t(0), "null terminated");
|
|
NS_ASSERTION(aStringBuffer &&
|
|
aStringBuffer->StorageSize() == (mLength + 1) * sizeof(char16_t),
|
|
"correct storage");
|
|
}
|
|
|
|
AtomImpl::~AtomImpl()
|
|
{
|
|
MOZ_ASSERT(gAtomTable, "uninitialized atom hashtable");
|
|
// Permanent atoms are removed from the hashtable at shutdown, and we
|
|
// don't want to remove them twice. See comment above in
|
|
// |AtomTableClearEntry|.
|
|
if (!IsPermanentInDestructor()) {
|
|
AtomTableKey key(mString, mLength, mHash);
|
|
gAtomTable->Remove(&key);
|
|
if (gAtomTable->EntryCount() == 0) {
|
|
delete gAtomTable;
|
|
gAtomTable = nullptr;
|
|
}
|
|
}
|
|
|
|
nsStringBuffer::FromData(mString)->Release();
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(AtomImpl, nsIAtom)
|
|
|
|
PermanentAtomImpl::~PermanentAtomImpl()
|
|
{
|
|
// So we can tell if we were permanent while running the base class dtor.
|
|
mRefCnt = REFCNT_PERMANENT_SENTINEL;
|
|
}
|
|
|
|
NS_IMETHODIMP_(MozExternalRefCountType)
|
|
PermanentAtomImpl::AddRef()
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
|
|
return 2;
|
|
}
|
|
|
|
NS_IMETHODIMP_(MozExternalRefCountType)
|
|
PermanentAtomImpl::Release()
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
|
|
return 1;
|
|
}
|
|
|
|
/* virtual */ bool
|
|
AtomImpl::IsPermanent()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* virtual */ bool
|
|
PermanentAtomImpl::IsPermanent()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void*
|
|
PermanentAtomImpl::operator new(size_t aSize, AtomImpl* aAtom) CPP_THROW_NEW
|
|
{
|
|
MOZ_ASSERT(!aAtom->IsPermanent(),
|
|
"converting atom that's already permanent");
|
|
|
|
// Just let the constructor overwrite the vtable pointer.
|
|
return aAtom;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AtomImpl::ScriptableToString(nsAString& aBuf)
|
|
{
|
|
nsStringBuffer::FromData(mString)->ToString(mLength, aBuf);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AtomImpl::ToUTF8String(nsACString& aBuf)
|
|
{
|
|
CopyUTF16toUTF8(nsDependentString(mString, mLength), aBuf);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP_(bool)
|
|
AtomImpl::EqualsUTF8(const nsACString& aString)
|
|
{
|
|
return CompareUTF8toUTF16(aString,
|
|
nsDependentString(mString, mLength)) == 0;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
AtomImpl::ScriptableEquals(const nsAString& aString, bool* aResult)
|
|
{
|
|
*aResult = aString.Equals(nsDependentString(mString, mLength));
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP_(bool)
|
|
AtomImpl::IsStaticAtom()
|
|
{
|
|
return IsPermanent();
|
|
}
|
|
|
|
size_t
|
|
AtomImpl::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
|
|
{
|
|
size_t n = aMallocSizeOf(this);
|
|
|
|
// Don't measure static atoms. Nb: here "static" means "permanent", and while
|
|
// it's not guaranteed that permanent atoms are actually stored in static
|
|
// data, it is very likely. And we don't want to call |aMallocSizeOf| on
|
|
// static data, so we err on the side of caution.
|
|
if (!IsStaticAtom()) {
|
|
n += nsStringBuffer::FromData(mString)->SizeOfIncludingThisIfUnshared(
|
|
aMallocSizeOf);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void
|
|
NS_SizeOfAtomTablesIncludingThis(MallocSizeOf aMallocSizeOf,
|
|
size_t* aMain, size_t* aStatic)
|
|
{
|
|
*aMain = 0;
|
|
if (gAtomTable) {
|
|
*aMain += gAtomTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
|
for (auto iter = gAtomTable->Iter(); !iter.Done(); iter.Next()) {
|
|
auto entry = static_cast<AtomTableEntry*>(iter.Get());
|
|
*aMain += entry->mAtom->SizeOfIncludingThis(aMallocSizeOf);
|
|
}
|
|
}
|
|
|
|
// The atoms in the this table are almost certainly stored in static data, so
|
|
// we don't need to measure entries separately.
|
|
*aStatic = gStaticAtomTable
|
|
? gStaticAtomTable->ShallowSizeOfIncludingThis(aMallocSizeOf)
|
|
: 0;
|
|
}
|
|
|
|
#define ATOM_HASHTABLE_INITIAL_LENGTH 2048
|
|
|
|
static inline void
|
|
EnsureTableExists()
|
|
{
|
|
if (!gAtomTable) {
|
|
gAtomTable = new PLDHashTable(&AtomTableOps, sizeof(AtomTableEntry),
|
|
ATOM_HASHTABLE_INITIAL_LENGTH);
|
|
}
|
|
}
|
|
|
|
static inline AtomTableEntry*
|
|
GetAtomHashEntry(const char* aString, uint32_t aLength, uint32_t* aHashOut)
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
|
|
EnsureTableExists();
|
|
AtomTableKey key(aString, aLength, aHashOut);
|
|
// This is an infallible add.
|
|
return static_cast<AtomTableEntry*>(gAtomTable->Add(&key));
|
|
}
|
|
|
|
static inline AtomTableEntry*
|
|
GetAtomHashEntry(const char16_t* aString, uint32_t aLength, uint32_t* aHashOut)
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
|
|
EnsureTableExists();
|
|
AtomTableKey key(aString, aLength, aHashOut);
|
|
// This is an infallible add.
|
|
return static_cast<AtomTableEntry*>(gAtomTable->Add(&key));
|
|
}
|
|
|
|
class CheckStaticAtomSizes
|
|
{
|
|
CheckStaticAtomSizes()
|
|
{
|
|
static_assert((sizeof(nsFakeStringBuffer<1>().mRefCnt) ==
|
|
sizeof(nsStringBuffer().mRefCount)) &&
|
|
(sizeof(nsFakeStringBuffer<1>().mSize) ==
|
|
sizeof(nsStringBuffer().mStorageSize)) &&
|
|
(offsetof(nsFakeStringBuffer<1>, mRefCnt) ==
|
|
offsetof(nsStringBuffer, mRefCount)) &&
|
|
(offsetof(nsFakeStringBuffer<1>, mSize) ==
|
|
offsetof(nsStringBuffer, mStorageSize)) &&
|
|
(offsetof(nsFakeStringBuffer<1>, mStringData) ==
|
|
sizeof(nsStringBuffer)),
|
|
"mocked-up strings' representations should be compatible");
|
|
}
|
|
};
|
|
|
|
nsresult
|
|
RegisterStaticAtoms(const nsStaticAtom* aAtoms, uint32_t aAtomCount)
|
|
{
|
|
if (!gStaticAtomTable && !gStaticAtomTableSealed) {
|
|
gStaticAtomTable = new StaticAtomTable();
|
|
}
|
|
|
|
for (uint32_t i = 0; i < aAtomCount; ++i) {
|
|
NS_ASSERTION(nsCRT::IsAscii((char16_t*)aAtoms[i].mStringBuffer->Data()),
|
|
"Static atoms must be ASCII!");
|
|
|
|
uint32_t stringLen =
|
|
aAtoms[i].mStringBuffer->StorageSize() / sizeof(char16_t) - 1;
|
|
|
|
uint32_t hash;
|
|
AtomTableEntry* he =
|
|
GetAtomHashEntry((char16_t*)aAtoms[i].mStringBuffer->Data(),
|
|
stringLen, &hash);
|
|
|
|
AtomImpl* atom = he->mAtom;
|
|
if (atom) {
|
|
if (!atom->IsPermanent()) {
|
|
// We wanted to create a static atom but there is already a non-static
|
|
// atom there. So convert it to a non-refcounting permanent atom.
|
|
PromoteToPermanent(atom);
|
|
}
|
|
} else {
|
|
atom = new PermanentAtomImpl(aAtoms[i].mStringBuffer, stringLen, hash);
|
|
he->mAtom = atom;
|
|
}
|
|
*aAtoms[i].mAtom = atom;
|
|
|
|
if (!gStaticAtomTableSealed) {
|
|
StaticAtomEntry* entry =
|
|
gStaticAtomTable->PutEntry(nsDependentAtomString(atom));
|
|
entry->mAtom = atom;
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
already_AddRefed<nsIAtom>
|
|
NS_NewAtom(const char* aUTF8String)
|
|
{
|
|
return NS_NewAtom(nsDependentCString(aUTF8String));
|
|
}
|
|
|
|
already_AddRefed<nsIAtom>
|
|
NS_NewAtom(const nsACString& aUTF8String)
|
|
{
|
|
uint32_t hash;
|
|
AtomTableEntry* he = GetAtomHashEntry(aUTF8String.Data(),
|
|
aUTF8String.Length(),
|
|
&hash);
|
|
|
|
if (he->mAtom) {
|
|
nsCOMPtr<nsIAtom> atom = he->mAtom;
|
|
|
|
return atom.forget();
|
|
}
|
|
|
|
// This results in an extra addref/release of the nsStringBuffer.
|
|
// Unfortunately there doesn't seem to be any APIs to avoid that.
|
|
// Actually, now there is, sort of: ForgetSharedBuffer.
|
|
nsString str;
|
|
CopyUTF8toUTF16(aUTF8String, str);
|
|
RefPtr<AtomImpl> atom = new AtomImpl(str, hash);
|
|
|
|
he->mAtom = atom;
|
|
|
|
return atom.forget();
|
|
}
|
|
|
|
already_AddRefed<nsIAtom>
|
|
NS_NewAtom(const char16_t* aUTF16String)
|
|
{
|
|
return NS_NewAtom(nsDependentString(aUTF16String));
|
|
}
|
|
|
|
// Equivalent to current NS_Atomize.
|
|
// Left as such for legacy callers in our older 45-era codebase.
|
|
already_AddRefed<nsIAtom>
|
|
NS_NewAtom(const nsAString& aUTF16String)
|
|
{
|
|
uint32_t hash;
|
|
AtomTableEntry* he = GetAtomHashEntry(aUTF16String.Data(),
|
|
aUTF16String.Length(),
|
|
&hash);
|
|
|
|
if (he->mAtom) {
|
|
nsCOMPtr<nsIAtom> atom = he->mAtom;
|
|
|
|
return atom.forget();
|
|
}
|
|
|
|
RefPtr<AtomImpl> atom = new AtomImpl(aUTF16String, hash);
|
|
he->mAtom = atom;
|
|
|
|
return atom.forget();
|
|
}
|
|
|
|
// From bug 1351303, modified for Mozilla 45.
|
|
already_AddRefed<nsIAtom>
|
|
NS_AtomizeMainThread(const nsAString& aUTF16String)
|
|
{
|
|
#if(0)
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
nsCOMPtr<nsIAtom> retVal;
|
|
uint32_t hash;
|
|
AtomTableKey key(aUTF16String.Data(), aUTF16String.Length(), &hash);
|
|
uint32_t index = hash % RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE;
|
|
nsIAtom* atom = sRecentlyUsedMainThreadAtoms[index];
|
|
|
|
if (atom && atom->GetUTF16String()) { // wallpaper
|
|
// This isn't ideal, but covers for the collision case, I guess.
|
|
// The atom names shouldn't be very long in any event.
|
|
uint32_t length = atom->GetLength();
|
|
if (length == key.mLength &&
|
|
(memcmp(atom->GetUTF16String(),
|
|
key.mUTF16String, length * sizeof(char16_t)) == 0)) {
|
|
retVal = atom;
|
|
return retVal.forget();
|
|
}
|
|
}
|
|
|
|
// Inline relevant parts of GetAtomHashEntry.
|
|
AtomTableEntry* he = static_cast<AtomTableEntry*>(PL_DHashTableAdd(&gAtomTable, &key));
|
|
if (he->mAtom) {
|
|
retVal = he->mAtom;
|
|
} else {
|
|
RefPtr<AtomImpl> atom = new AtomImpl(aUTF16String, hash);
|
|
he->mAtom = atom;
|
|
retVal = he->mAtom; // XXX?
|
|
}
|
|
|
|
sRecentlyUsedMainThreadAtoms[index] = retVal;
|
|
return retVal.forget();
|
|
#else
|
|
return NS_NewAtom(aUTF16String);
|
|
#endif
|
|
}
|
|
|
|
nsIAtom*
|
|
NS_NewPermanentAtom(const nsAString& aUTF16String)
|
|
{
|
|
uint32_t hash;
|
|
AtomTableEntry* he = GetAtomHashEntry(aUTF16String.Data(),
|
|
aUTF16String.Length(),
|
|
&hash);
|
|
|
|
AtomImpl* atom = he->mAtom;
|
|
if (atom) {
|
|
if (!atom->IsPermanent()) {
|
|
PromoteToPermanent(atom);
|
|
}
|
|
} else {
|
|
atom = new PermanentAtomImpl(aUTF16String, hash);
|
|
he->mAtom = atom;
|
|
}
|
|
|
|
// No need to addref since permanent atoms aren't refcounted anyway
|
|
return atom;
|
|
}
|
|
|
|
nsrefcnt
|
|
NS_GetNumberOfAtoms(void)
|
|
{
|
|
MOZ_ASSERT(gAtomTable);
|
|
return gAtomTable->EntryCount();
|
|
}
|
|
|
|
nsIAtom*
|
|
NS_GetStaticAtom(const nsAString& aUTF16String)
|
|
{
|
|
NS_PRECONDITION(gStaticAtomTable, "Static atom table not created yet.");
|
|
NS_PRECONDITION(gStaticAtomTableSealed, "Static atom table not sealed yet.");
|
|
StaticAtomEntry* entry = gStaticAtomTable->GetEntry(aUTF16String);
|
|
return entry ? entry->mAtom : nullptr;
|
|
}
|
|
|
|
void
|
|
NS_SealStaticAtomTable()
|
|
{
|
|
gStaticAtomTableSealed = true;
|
|
}
|