Files
palemoon27/xpcom/base/CodeAddressService.h
T
roytam1 e1c4d9e76f import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1077318 - call out to C++ for ARMv6 sub-word atomics. r=luke (2810c3f93)
- Bug 1142593 - factor atomics into the platform layer. r=waldo (f5088b2af)
- Bug 1173642 - Import unimplemented ARM64 Ion components. r=efaust (2567975a1)
- Bug 1170107 part 1 - Call GetProperty/CallProperty from the interpreter and Baseline. r=bhackett (fe45a446a)
- Bug 1170107 part 2 - Don't allocate a wrapper object for (pure) primitive.foo operations. r=bhackett (8793d7d2d)
- Bug 1152079 - Remove Purify support files. r=froydnj (69836c373)
- Bug 1152079 - Remove references to deleted Purify files from moz.build. r=bustage (ebd68a5fa)
- Bug 1126089 - Assert we don't Destroy nsFrameLoader in destructor (r=smaug) (c0894ed2b)
- Bug 1250871 - only send messages to child scripts when the docShell is still around. r=smaug (ac2562f55)
- Bug 1168750 - SharedStubs: (part3) Make split between baseline only and shared stubs, r=jandem (21c89cffe)
- Bug 1168750 - SharedStubs: (part4) Track for which engine a stub needs to get compiled, r=jandem (a36eb943b)
- Bug 1168753 - SharedStubs: Simplification to push BaselineFrame* in stubs, r=jandem (4a26b318d)
- pointer style (e20a50c7e)
- Bug 1169391 - Use a ReservedRooted class for optimized Rooted use in vm/Interpreter.cpp, r=terrence (1b80a857d)
- Bug 1182865 - Relax assertion on the allowed class for home objects, r=efaust (33009a9fe)
- Bug 1154391 - Update import declarations to current ES6 spec r=shu (ad7042d54)
- Bug 1154391 - Update parsing of export declarations to match current ES6 spec r=shu (4b509d9ec)
- Bug 1169171 - Split PNK_DELETE into several different kinds for each of the syntactically distinct modes of |delete| operation, depending upon the syntax of the operand. r=efaust (5667265fc)
- Bug 1169511 - Split PNK_TYPEOF into one kind for application to names one kind for application to other expressions. r=efaust (91a1086d8)
- pointer style (0546201d8)
- Bug 1163851 - Remove the remaining two tests of |pc->parsingForInit|, replacing them with yet another argument provided by the caller. r=efaust (919903e1e)
- Bug 1163851 - |pc->parsingForInit| is dead. Long live |InHandling|! r=efaust (bf35fb405)
- Bug 1167030 - Suppress MSVC warning C4661 in js/src. r=luke (1d28ed1d2)
- Bug 1167845 - Rejigger {in,de}crement/assignment parsing to vet targets primarily through a single Parser::isValidSimpleAssignmentTarget method, so that this method can also be called outside the parser. r=efaust (87484d3fc)
- Bug 1166950 - Introduce a new FunctionKind for class-constructors. r=efaust (e9dd197e1)
- Bug 1166950 - Make generator methods constructors. r=efaust (e076cacd6)
- Bug 1167845 - Rename ParseHandler::isName to ParseHandler::maybeName. r=efaust (1e090741b)
- Bug 1141865 - Part 3: Parse new.target, add Reflect support, and tests. (r=jorendorff, r=shu) (9e0282870)
- Bug 1139759 - Self-host %TypedArray%.prototype.copyWithin. r=till (8beea5f7c)
- pointer style (0da72f30a)
- Bug 1139769 - Add TypedArrayBuffer, TypedArrayByteOffset, and TypedArrayElementShift intrinsics to safely get the relevant information for a typed array. r=till (b5847a441)
- pointer style (5486dd33d)
- Bug 1139769 - Self-host %TypedArray%.prototype.subarray. r=t (b10c55e93)
- pointer style (335ab6c87)
- Bug 1140752 - Land code to self-host %TypedArray%.prototype.set, but don't enable it yet, pending perf-testing. This shouldn't make any changes to the build, except in terms of adding more code to it and affecting binary layout. r=jandem, also much feedback from till that effectively amounts to a review as well (98050308d)
- Bug 1144692: Fix --disable-ion builds; r=h4writer (3be32046c)
- Bug 1148970 - Check for possibly incomplete type sets when double checking the correctness of argument type set information, r=jandem. (934130c2e)
- bug 1171125 - Fix nsStackWalk to build for iOS. r=froydnj (c076c4d22)
- Bug 1119980 - Use 'snprintf' instead of 'sprintf' to avoid a warning on Lollipop-based builds. r=froydnj (a000af66c)
- Bug 1146597 - Avoid unnecessary calls to maybeSweep under hasUnanalyzedPreliminaryObjects, r=jandem. (335ba3fc3)
- Bug 1162134 - IonMonkey MIPS: Fix build failure on MIPS (js/src/jit/CodeGenerator.cpp:6740:28: error: `obj' was not declared in this scope). r=bhackett (56824379b)
- Bug 1160884 followup - Add testcase. r=me (5495ad016)
- Bug 1141865 - Part 4: Remove LCallDirectEvalV in anticipation of register pressure with new.target in eval frames. (r=jandem) (cbb706356)
- Bug 1162242 - Part 1: Remove instances of #ifdef PR_LOGGING. r=froydnj PR_LOGGING is now always defined, we can remove #ifdefs checking for it. (878131a4a)
- revert pointer style for patch (a263375f1)
- Bug 1144097. Fix yet another is<ScopeObject>() assert. r=shu (96d516117)
- Bug 1145282. Reverse the sense of IsValidTerminatingScope and rename it to IsSyntacticScope. r=luke (3681fc831)
- Bug 1149897 - PerformanceStatsService data is not monotonic. r=jandem (927639ac6)
- Bug 1142457 - Compute stopwatch durations per thread on MacOS X. r=jandem, r=areinald (a52c388be)
2020-10-02 18:15:14 +08:00

199 lines
6.6 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/. */
#ifndef CodeAddressService_h__
#define CodeAddressService_h__
#include "mozilla/Assertions.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Types.h"
#include "nsStackWalk.h"
namespace mozilla {
// This class is used to print details about code locations.
//
// |StringTable| must implement an Intern() method that returns an interned
// copy of the string that was passed in, as well as a standard
// SizeOfExcludingThis() method.
//
// |StringAlloc| must implement |copy| and |free|. |copy| copies a string,
// while |free| is used to free strings created by |copy|.
//
// |DescribeCodeAddressLock| is needed when the callers may be holding a lock
// used by NS_DescribeCodeAddress. |DescribeCodeAddressLock| must implement
// static methods IsLocked(), Unlock() and Lock().
template <class StringTable,
class StringAlloc,
class DescribeCodeAddressLock>
class CodeAddressService
{
// GetLocation() is the key function in this class. It's basically a wrapper
// around NS_DescribeCodeAddress.
//
// However, NS_DescribeCodeAddress is very slow on some platforms, and we
// have lots of repeated (i.e. same PC) calls to it. So we do some caching
// of results. Each cached result includes two strings (|mFunction| and
// |mLibrary|), so we also optimize them for space in the following ways.
//
// - The number of distinct library names is small, e.g. a few dozen. There
// is lots of repetition, especially of libxul. So we intern them in their
// own table, which saves space over duplicating them for each cache entry.
//
// - The number of distinct function names is much higher, so we duplicate
// them in each cache entry. That's more space-efficient than interning
// because entries containing single-occurrence function names are quickly
// overwritten, and their copies released. In addition, empty function
// names are common, so we use nullptr to represent them compactly.
StringTable mLibraryStrings;
struct Entry
{
const void* mPc;
char* mFunction; // owned by the Entry; may be null
const char* mLibrary; // owned by mLibraryStrings; never null
// in a non-empty entry is in use
ptrdiff_t mLOffset;
char* mFileName; // owned by the Entry; may be null
uint32_t mLineNo:31;
uint32_t mInUse:1; // is the entry used?
Entry()
: mPc(0), mFunction(nullptr), mLibrary(nullptr), mLOffset(0),
mFileName(nullptr), mLineNo(0), mInUse(0)
{}
~Entry()
{
// We don't free mLibrary because it's externally owned.
StringAlloc::free(mFunction);
StringAlloc::free(mFileName);
}
void Replace(const void* aPc, const char* aFunction,
const char* aLibrary, ptrdiff_t aLOffset,
const char* aFileName, unsigned long aLineNo)
{
mPc = aPc;
// Convert "" to nullptr. Otherwise, make a copy of the name.
StringAlloc::free(mFunction);
mFunction = !aFunction[0] ? nullptr : StringAlloc::copy(aFunction);
StringAlloc::free(mFileName);
mFileName = !aFileName[0] ? nullptr : StringAlloc::copy(aFileName);
mLibrary = aLibrary;
mLOffset = aLOffset;
mLineNo = aLineNo;
mInUse = 1;
}
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
// Don't measure mLibrary because it's externally owned.
size_t n = 0;
n += aMallocSizeOf(mFunction);
n += aMallocSizeOf(mFileName);
return n;
}
};
// A direct-mapped cache. When doing dmd::Analyze() just after starting
// desktop Firefox (which is similar to analyzing after a longer-running
// session, thanks to the limit on how many records we print), a cache with
// 2^24 entries (which approximates an infinite-entry cache) has a ~91% hit
// rate. A cache with 2^12 entries has a ~83% hit rate, and takes up ~85 KiB
// (on 32-bit platforms) or ~150 KiB (on 64-bit platforms).
static const size_t kNumEntries = 1 << 12;
static const size_t kMask = kNumEntries - 1;
Entry mEntries[kNumEntries];
size_t mNumCacheHits;
size_t mNumCacheMisses;
public:
CodeAddressService()
: mEntries(), mNumCacheHits(0), mNumCacheMisses(0)
{
}
void GetLocation(uint32_t aFrameNumber, const void* aPc, char* aBuf,
size_t aBufLen)
{
MOZ_ASSERT(DescribeCodeAddressLock::IsLocked());
uint32_t index = HashGeneric(aPc) & kMask;
MOZ_ASSERT(index < kNumEntries);
Entry& entry = mEntries[index];
if (!entry.mInUse || entry.mPc != aPc) {
mNumCacheMisses++;
// NS_DescribeCodeAddress can (on Linux) acquire a lock inside
// the shared library loader. Another thread might call malloc
// while holding that lock (when loading a shared library). So
// we have to exit the lock around this call. For details, see
// https://bugzilla.mozilla.org/show_bug.cgi?id=363334#c3
nsCodeAddressDetails details;
{
DescribeCodeAddressLock::Unlock();
(void)NS_DescribeCodeAddress(const_cast<void*>(aPc), &details);
DescribeCodeAddressLock::Lock();
}
const char* library = mLibraryStrings.Intern(details.library);
entry.Replace(aPc, details.function, library, details.loffset,
details.filename, details.lineno);
} else {
mNumCacheHits++;
}
MOZ_ASSERT(entry.mPc == aPc);
NS_FormatCodeAddress(aBuf, aBufLen, aFrameNumber, entry.mPc,
entry.mFunction, entry.mLibrary, entry.mLOffset,
entry.mFileName, entry.mLineNo);
}
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
for (uint32_t i = 0; i < kNumEntries; i++) {
n += mEntries[i].SizeOfExcludingThis(aMallocSizeOf);
}
n += mLibraryStrings.SizeOfExcludingThis(aMallocSizeOf);
return n;
}
size_t CacheCapacity() const { return kNumEntries; }
size_t CacheCount() const
{
size_t n = 0;
for (size_t i = 0; i < kNumEntries; i++) {
if (mEntries[i].mInUse) {
n++;
}
}
return n;
}
size_t NumCacheHits() const { return mNumCacheHits; }
size_t NumCacheMisses() const { return mNumCacheMisses; }
};
} // namespace mozilla
#endif // CodeAddressService_h__