Merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Razvan Maries 2018-11-27 11:43:31 +02:00
Родитель 74cd2bf73e 0b6dcf0862
Коммит 0859e6b10f
14 изменённых файлов: 1252 добавлений и 863 удалений

Просмотреть файл

@ -114,7 +114,7 @@ public:
class Decoder
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Decoder)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_RECORDED(Decoder)
explicit Decoder(RasterImage* aImage);

Просмотреть файл

@ -75,7 +75,7 @@ private:
class MetadataDecodingTask final : public IDecodingTask
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MetadataDecodingTask, override)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_RECORDED(MetadataDecodingTask, override)
explicit MetadataDecodingTask(NotNull<Decoder*> aDecoder);
@ -107,7 +107,7 @@ private:
class AnonymousDecodingTask final : public IDecodingTask
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnonymousDecodingTask, override)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_RECORDED(AnonymousDecodingTask, override)
explicit AnonymousDecodingTask(NotNull<Decoder*> aDecoder,
bool aResumable);

Просмотреть файл

@ -635,6 +635,7 @@ js::Nursery::renderProfileJSON(JSONPrinter& json) const
json.property("reason", JS::gcreason::ExplainReason(previousGC.reason));
json.property("bytes_tenured", previousGC.tenuredBytes);
json.property("cells_tenured", previousGC.tenuredCells);
json.property("strings_tenured", stats().getStat(gcstats::STAT_STRINGS_TENURED));
json.property("bytes_used", previousGC.nurseryUsedBytes);
json.property("cur_capacity", previousGC.nurseryCapacity);
const size_t newCapacity = spaceToEnd(maxChunkCount());
@ -661,6 +662,10 @@ js::Nursery::renderProfileJSON(JSONPrinter& json) const
json.property("groups_pretenured",
stats().getStat(gcstats::STAT_OBJECT_GROUPS_PRETENURED));
}
if (stats().getStat(gcstats::STAT_NURSERY_STRING_REALMS_DISABLED)) {
json.property("nursery_string_realms_disabled",
stats().getStat(gcstats::STAT_NURSERY_STRING_REALMS_DISABLED));
}
json.beginObjectProperty("phase_times");
@ -833,6 +838,8 @@ js::Nursery::collect(JS::gcreason::Reason reason)
stats().setStat(gcstats::STAT_OBJECT_GROUPS_PRETENURED, pretenureCount);
mozilla::Maybe<AutoGCSession> session;
uint32_t numStringsTenured = 0;
uint32_t numNurseryStringRealmsDisabled = 0;
for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
if (shouldPretenure && zone->allocNurseryStrings && zone->tenuredStrings >= 30 * 1000) {
if (!session.isSome()) {
@ -847,13 +854,17 @@ js::Nursery::collect(JS::gcreason::Reason reason)
if (jit::JitRealm* jitRealm = r->jitRealm()) {
jitRealm->discardStubs();
jitRealm->stringsCanBeInNursery = false;
numNurseryStringRealmsDisabled++;
}
}
zone->allocNurseryStrings = false;
}
numStringsTenured += zone->tenuredStrings;
zone->tenuredStrings = 0;
}
session.reset(); // End the minor GC session, if running one.
stats().setStat(gcstats::STAT_NURSERY_STRING_REALMS_DISABLED, numNurseryStringRealmsDisabled);
stats().setStat(gcstats::STAT_STRINGS_TENURED, numStringsTenured);
endProfile(ProfileKey::Pretenure);
// We ignore gcMaxBytes when allocating for minor collection. However, if we

Просмотреть файл

@ -50,9 +50,15 @@ enum Count {
// Stats can be set with Statistics::setStat(). They're not reset automatically.
enum Stat {
// Number of strings tenured.
STAT_STRINGS_TENURED,
// Number of object types pretenured this minor GC.
STAT_OBJECT_GROUPS_PRETENURED,
// Number of realms that had nursery strings disabled due to large numbers being tenured.
STAT_NURSERY_STRING_REALMS_DISABLED,
STAT_LIMIT
};

Просмотреть файл

@ -63,6 +63,7 @@ jittest:
by-test-platform:
android-hw.*: ['try']
linux.*: [] # redundant with SM(...)
windows.*: [] # redundant with SM(p)
default: built-projects
chunks:
by-test-platform:

Просмотреть файл

@ -159,8 +159,17 @@ Stream::RecordOrReplayThreadEvent(ThreadEvent aEvent)
} else {
ThreadEvent oldEvent = (ThreadEvent) ReadScalar();
if (oldEvent != aEvent) {
child::ReportFatalError(Nothing(), "Event Mismatch: Recorded %s Replayed %s",
ThreadEventName(oldEvent), ThreadEventName(aEvent));
const char* extra = "";
if (oldEvent == ThreadEvent::Assert) {
// Include the asserted string in the error. This must match up with
// the writes in RecordReplayAssert.
if (mNameIndex == MainThreadId) {
(void) ReadScalar(); // For the ExecutionProgressCounter write below.
}
extra = ReadInputString();
}
child::ReportFatalError(Nothing(), "Event Mismatch: Recorded %s %s Replayed %s",
ThreadEventName(oldEvent), extra, ThreadEventName(aEvent));
}
mLastEvent = aEvent;
}
@ -185,6 +194,16 @@ Stream::CheckInput(size_t aValue)
}
}
const char*
Stream::ReadInputString()
{
size_t len = ReadScalar();
EnsureInputBallast(len + 1);
ReadBytes(mInputBallast.get(), len);
mInputBallast[len] = 0;
return mInputBallast.get();
}
void
Stream::CheckInput(const char* aValue)
{
@ -193,14 +212,10 @@ Stream::CheckInput(const char* aValue)
WriteScalar(len);
WriteBytes(aValue, len);
} else {
size_t oldLen = ReadScalar();
EnsureInputBallast(oldLen + 1);
ReadBytes(mInputBallast.get(), oldLen);
mInputBallast[oldLen] = 0;
if (len != oldLen || memcmp(aValue, mInputBallast.get(), len) != 0) {
const char* oldInput = ReadInputString();
if (strcmp(oldInput, aValue) != 0) {
child::ReportFatalError(Nothing(), "Input Mismatch: %s Recorded %s Replayed %s",
ThreadEventName(mLastEvent), mInputBallast.get(), aValue);
ThreadEventName(mLastEvent), oldInput, aValue);
}
}
}

Просмотреть файл

@ -197,6 +197,7 @@ private:
ShouldCopy aCopy);
void EnsureInputBallast(size_t aSize);
void Flush(bool aTakeLock);
const char* ReadInputString();
static size_t BallastMaxSize();
};

Просмотреть файл

@ -44,6 +44,8 @@ GatherDependentCalls(InfallibleVector<MiddlemanCall*>& aOutgoingCalls, Middleman
MOZ_RELEASE_ASSERT(!aCall->mSent);
aCall->mSent = true;
const Redirection& redirection = GetRedirection(aCall->mCallId);
CallArguments arguments;
aCall->mArguments.CopyTo(&arguments);
@ -51,8 +53,12 @@ GatherDependentCalls(InfallibleVector<MiddlemanCall*>& aOutgoingCalls, Middleman
MiddlemanCallContext cx(aCall, &arguments, MiddlemanCallPhase::ReplayInput);
cx.mDependentCalls = &dependentCalls;
gRedirections[aCall->mCallId].mMiddlemanCall(cx);
redirection.mMiddlemanCall(cx);
if (cx.mFailed) {
if (child::CurrentRepaintCannotFail()) {
child::ReportFatalError(Nothing(), "Middleman call input failed: %s\n",
redirection.mName);
}
return false;
}
@ -71,7 +77,7 @@ SendCallToMiddleman(size_t aCallId, CallArguments* aArguments, bool aDiverged)
{
MOZ_RELEASE_ASSERT(IsReplaying());
const Redirection& redirection = gRedirections[aCallId];
const Redirection& redirection = GetRedirection(aCallId);
MOZ_RELEASE_ASSERT(redirection.mMiddlemanCall);
MonitorAutoLock lock(*gMonitor);
@ -91,6 +97,10 @@ SendCallToMiddleman(size_t aCallId, CallArguments* aArguments, bool aDiverged)
if (cx.mFailed) {
delete newCall;
gMiddlemanCalls.popBack();
if (child::CurrentRepaintCannotFail()) {
child::ReportFatalError(Nothing(), "Middleman call preface failed: %s\n",
redirection.mName);
}
return false;
}
}
@ -132,7 +142,7 @@ SendCallToMiddleman(size_t aCallId, CallArguments* aArguments, bool aDiverged)
call->mArguments.CopyTo(&oldArguments);
MiddlemanCallContext cx(call, &oldArguments, MiddlemanCallPhase::ReplayOutput);
cx.mReplayOutputIsOld = true;
gRedirections[call->mCallId].mMiddlemanCall(cx);
GetRedirection(call->mCallId).mMiddlemanCall(cx);
}
}
@ -156,7 +166,7 @@ ProcessMiddlemanCall(const char* aInputData, size_t aInputSize,
MiddlemanCall* call = new MiddlemanCall();
call->DecodeInput(inputStream);
const Redirection& redirection = gRedirections[call->mCallId];
const Redirection& redirection = GetRedirection(call->mCallId);
MOZ_RELEASE_ASSERT(redirection.mMiddlemanCall);
CallArguments arguments;
@ -167,7 +177,7 @@ ProcessMiddlemanCall(const char* aInputData, size_t aInputSize,
redirection.mMiddlemanCall(cx);
}
RecordReplayInvokeCall(call->mCallId, &arguments);
RecordReplayInvokeCall(redirection.mBaseFunction, &arguments);
{
MiddlemanCallContext cx(call, &arguments, MiddlemanCallPhase::MiddlemanOutput);
@ -213,17 +223,22 @@ ResetMiddlemanCalls()
call->mArguments.CopyTo(&arguments);
MiddlemanCallContext cx(call, &arguments, MiddlemanCallPhase::MiddlemanRelease);
gRedirections[call->mCallId].mMiddlemanCall(cx);
delete call;
GetRedirection(call->mCallId).mMiddlemanCall(cx);
}
}
// Delete the calls in a second pass. The MiddlemanRelease phase depends on
// previous middleman calls still existing.
for (MiddlemanCall* call : gMiddlemanCalls) {
delete call;
}
gMiddlemanCalls.clear();
for (auto buffer : gAllocatedBuffers) {
free(buffer);
}
gAllocatedBuffers.clear();
gMiddlemanCallMap->clear();
}
///////////////////////////////////////////////////////////////////////////////
@ -258,7 +273,7 @@ GetMiddlemanCallValue(size_t aId)
}
bool
Middleman_SystemInput(MiddlemanCallContext& aCx, const void** aThingPtr)
MM_SystemInput(MiddlemanCallContext& aCx, const void** aThingPtr)
{
MOZ_RELEASE_ASSERT(aCx.AccessPreface());
@ -314,7 +329,7 @@ MangleSystemValue(const void* aValue, bool aFromRecording)
}
void
Middleman_SystemOutput(MiddlemanCallContext& aCx, const void** aOutput, bool aUpdating)
MM_SystemOutput(MiddlemanCallContext& aCx, const void** aOutput, bool aUpdating)
{
if (!*aOutput) {
if (aCx.mPhase == MiddlemanCallPhase::MiddlemanOutput) {

Просмотреть файл

@ -356,7 +356,7 @@ void ResetMiddlemanCalls();
// Capture the contents of an input buffer at BufferArg with element count at CountArg.
template <size_t BufferArg, size_t CountArg, typename ElemType = char>
static inline void
Middleman_Buffer(MiddlemanCallContext& aCx)
MM_Buffer(MiddlemanCallContext& aCx)
{
if (aCx.AccessPreface()) {
auto& buffer = aCx.mArguments->Arg<BufferArg, void*>();
@ -368,7 +368,7 @@ Middleman_Buffer(MiddlemanCallContext& aCx)
// Capture the contents of a fixed size input buffer.
template <size_t BufferArg, size_t ByteSize>
static inline void
Middleman_BufferFixedSize(MiddlemanCallContext& aCx)
MM_BufferFixedSize(MiddlemanCallContext& aCx)
{
if (aCx.AccessPreface()) {
auto& buffer = aCx.mArguments->Arg<BufferArg, void*>();
@ -381,7 +381,7 @@ Middleman_BufferFixedSize(MiddlemanCallContext& aCx)
// Capture a C string argument.
template <size_t StringArg>
static inline void
Middleman_CString(MiddlemanCallContext& aCx)
MM_CString(MiddlemanCallContext& aCx)
{
if (aCx.AccessPreface()) {
auto& buffer = aCx.mArguments->Arg<StringArg, char*>();
@ -394,7 +394,7 @@ Middleman_CString(MiddlemanCallContext& aCx)
// Capture the data written to an output buffer at BufferArg with element count at CountArg.
template <size_t BufferArg, size_t CountArg, typename ElemType>
static inline void
Middleman_WriteBuffer(MiddlemanCallContext& aCx)
MM_WriteBuffer(MiddlemanCallContext& aCx)
{
auto& buffer = aCx.mArguments->Arg<BufferArg, void*>();
auto count = aCx.mArguments->Arg<CountArg, size_t>();
@ -404,7 +404,7 @@ Middleman_WriteBuffer(MiddlemanCallContext& aCx)
// Capture the data written to a fixed size output buffer.
template <size_t BufferArg, size_t ByteSize>
static inline void
Middleman_WriteBufferFixedSize(MiddlemanCallContext& aCx)
MM_WriteBufferFixedSize(MiddlemanCallContext& aCx)
{
auto& buffer = aCx.mArguments->Arg<BufferArg, void*>();
aCx.ReadOrWriteOutputBuffer(&buffer, ByteSize);
@ -413,15 +413,15 @@ Middleman_WriteBufferFixedSize(MiddlemanCallContext& aCx)
// Capture return values that are too large for register storage.
template <size_t ByteSize>
static inline void
Middleman_OversizeRval(MiddlemanCallContext& aCx)
MM_OversizeRval(MiddlemanCallContext& aCx)
{
Middleman_WriteBufferFixedSize<0, ByteSize>(aCx);
MM_WriteBufferFixedSize<0, ByteSize>(aCx);
}
// Capture a byte count of stack argument data.
template <size_t ByteSize>
static inline void
Middleman_StackArgumentData(MiddlemanCallContext& aCx)
MM_StackArgumentData(MiddlemanCallContext& aCx)
{
if (aCx.AccessPreface()) {
auto stack = aCx.mArguments->StackAddress<0>();
@ -430,17 +430,17 @@ Middleman_StackArgumentData(MiddlemanCallContext& aCx)
}
static inline void
Middleman_NoOp(MiddlemanCallContext& aCx)
MM_NoOp(MiddlemanCallContext& aCx)
{
}
template <MiddlemanCallFn Fn0,
MiddlemanCallFn Fn1,
MiddlemanCallFn Fn2 = Middleman_NoOp,
MiddlemanCallFn Fn3 = Middleman_NoOp,
MiddlemanCallFn Fn4 = Middleman_NoOp>
MiddlemanCallFn Fn2 = MM_NoOp,
MiddlemanCallFn Fn3 = MM_NoOp,
MiddlemanCallFn Fn4 = MM_NoOp>
static inline void
Middleman_Compose(MiddlemanCallContext& aCx)
MM_Compose(MiddlemanCallContext& aCx)
{
Fn0(aCx);
Fn1(aCx);
@ -452,11 +452,11 @@ Middleman_Compose(MiddlemanCallContext& aCx)
// Helper for capturing inputs that are produced by other middleman calls.
// Returns false in the ReplayInput or MiddlemanInput phases if the input
// system value could not be found.
bool Middleman_SystemInput(MiddlemanCallContext& aCx, const void** aThingPtr);
bool MM_SystemInput(MiddlemanCallContext& aCx, const void** aThingPtr);
// Helper for capturing output system values that might be consumed by other
// middleman calls.
void Middleman_SystemOutput(MiddlemanCallContext& aCx, const void** aOutput, bool aUpdating = false);
void MM_SystemOutput(MiddlemanCallContext& aCx, const void** aOutput, bool aUpdating = false);
} // namespace recordreplay
} // namespace mozilla

Просмотреть файл

@ -134,6 +134,7 @@ RecordReplayInterface_Initialize(int aArgc, char* aArgv[])
fprintf(stderr, "Initialization Failure: %s\n", gInitializationFailureMessage);
}
LateInitializeRedirections();
Thread::InitializeThreads();
Thread* thread = Thread::GetById(MainThreadId);
@ -326,7 +327,7 @@ ThreadEventName(ThreadEvent aEvent)
case ThreadEvent::CallStart: break;
}
size_t callId = (size_t) aEvent - (size_t) ThreadEvent::CallStart;
return gRedirections[callId].mName;
return GetRedirection(callId).mName;
}
int
@ -354,6 +355,8 @@ RecordReplayInterface_InternalRecordReplayAssert(const char* aFormat, va_list aA
char text[1024];
VsprintfLiteral(text, aFormat, aArgs);
// This must be kept in sync with Stream::RecordOrReplayThreadEvent, which
// peeks at the input string written after the thread event.
thread->Events().RecordOrReplayThreadEvent(ThreadEvent::Assert);
thread->Events().CheckInput(text);
}

Просмотреть файл

@ -39,7 +39,7 @@ CallPreambleHook(PreambleFn aPreamble, size_t aCallId, CallArguments* aArguments
return true;
case PreambleResult::PassThrough: {
AutoEnsurePassThroughThreadEvents pt;
RecordReplayInvokeCall(aCallId, aArguments);
RecordReplayInvokeCall(OriginalFunction(aCallId), aArguments);
return true;
}
case PreambleResult::Redirect:
@ -53,7 +53,7 @@ extern "C" {
__attribute__((used)) int
RecordReplayInterceptCall(int aCallId, CallArguments* aArguments)
{
Redirection& redirection = gRedirections[aCallId];
Redirection& redirection = GetRedirection(aCallId);
// Call the preamble to see if this call needs special handling, even when
// events have been passed through.
@ -120,7 +120,7 @@ RecordReplayInterceptCall(int aCallId, CallArguments* aArguments)
// from being flushed in case we end up blocking.
res.reset();
thread->SetPassThrough(true);
RecordReplayInvokeCall(aCallId, aArguments);
RecordReplayInvokeCall(redirection.mOriginalFunction, aArguments);
thread->SetPassThrough(false);
res.emplace(thread);
}
@ -287,9 +287,9 @@ __asm(
} // extern "C"
MOZ_NEVER_INLINE void
RecordReplayInvokeCall(size_t aCallId, CallArguments* aArguments)
RecordReplayInvokeCall(void* aFunction, CallArguments* aArguments)
{
RecordReplayInvokeCallRaw(aArguments, OriginalFunction(aCallId));
RecordReplayInvokeCallRaw(aArguments, aFunction);
}
///////////////////////////////////////////////////////////////////////////////
@ -738,22 +738,6 @@ CopyInstructions(const char* aName, uint8_t* aIpStart, uint8_t* aIpEnd,
return ip;
}
// Get the instruction pointer to use as the address of the base function for a
// redirection.
static uint8_t*
FunctionStartAddress(Redirection& aRedirection)
{
uint8_t* addr = static_cast<uint8_t*>(dlsym(RTLD_DEFAULT, aRedirection.mName));
if (!addr)
return nullptr;
if (addr[0] == 0xFF && addr[1] == 0x25) {
return *(uint8_t**)(addr + 6 + *reinterpret_cast<int32_t*>(addr + 2));
}
return addr;
}
// Generate code to set %rax and enter RecordReplayRedirectCall.
static uint8_t*
GenerateRedirectStub(Assembler& aAssembler, size_t aCallId)
@ -909,34 +893,6 @@ Redirect(size_t aCallId, Redirection& aRedirection, Assembler& aAssembler, bool
AddClobberPatch(functionStart + ShortJumpBytes, nro);
}
void
EarlyInitializeRedirections()
{
for (size_t i = 0;; i++) {
Redirection& redirection = gRedirections[i];
if (!redirection.mName) {
break;
}
MOZ_RELEASE_ASSERT(!redirection.mBaseFunction);
MOZ_RELEASE_ASSERT(!redirection.mOriginalFunction);
redirection.mBaseFunction = FunctionStartAddress(redirection);
redirection.mOriginalFunction = redirection.mBaseFunction;
if (redirection.mBaseFunction && IsRecordingOrReplaying()) {
// We will get confused if we try to redirect the same address in multiple places.
for (size_t j = 0; j < i; j++) {
if (gRedirections[j].mBaseFunction == redirection.mBaseFunction) {
PrintSpew("Redirection %s shares the same address as %s, skipping.\n",
redirection.mName, gRedirections[j].mName);
redirection.mBaseFunction = nullptr;
break;
}
}
}
}
}
bool
InitializeRedirections()
{
@ -944,20 +900,15 @@ InitializeRedirections()
{
Assembler assembler;
size_t numRedirections = NumRedirections();
for (size_t i = 0;; i++) {
Redirection& redirection = gRedirections[i];
if (!redirection.mName) {
break;
}
for (size_t i = 0; i < numRedirections; i++) {
Redirection& redirection = GetRedirection(i);
Redirect(i, redirection, assembler, /* aFirstPass = */ true);
}
for (size_t i = 0;; i++) {
Redirection& redirection = gRedirections[i];
if (!redirection.mName) {
break;
}
for (size_t i = 0; i < numRedirections; i++) {
Redirection& redirection = GetRedirection(i);
Redirect(i, redirection, assembler, /* aFirstPass = */ false);
}
}
@ -1002,6 +953,19 @@ InitializeRedirections()
return true;
}
void*
OriginalFunction(const char* aName)
{
size_t numRedirections = NumRedirections();
for (size_t i = 0; i < numRedirections; i++) {
const Redirection& redirection = GetRedirection(i);
if (!strcmp(aName, redirection.mName)) {
return redirection.mOriginalFunction;
}
}
MOZ_CRASH("OriginalFunction: unknown redirection");
}
///////////////////////////////////////////////////////////////////////////////
// Utility
///////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -114,27 +114,35 @@ public:
// expected, per the requirements of the System V x64 ABI.
struct CallArguments : public CallRegisterArguments
{
// The maximum number of stack arguments that can be captured.
static const size_t NumStackArguments = 64;
protected:
size_t stack[64]; // 104
// Size: 616
size_t stack[NumStackArguments]; // 104
// Size: 616
public:
template <size_t Index, typename T>
T& Arg() {
template <typename T>
T& Arg(size_t aIndex) {
static_assert(sizeof(T) == sizeof(size_t), "Size must match");
static_assert(IsFloatingPoint<T>::value == false, "FloatArg NYI");
static_assert(Index < 70, "Bad index");
switch (Index) {
MOZ_RELEASE_ASSERT(aIndex < 70);
switch (aIndex) {
case 0: return (T&)arg0;
case 1: return (T&)arg1;
case 2: return (T&)arg2;
case 3: return (T&)arg3;
case 4: return (T&)arg4;
case 5: return (T&)arg5;
default: return (T&)stack[Index - 6];
default: return (T&)stack[aIndex - 6];
}
}
template <size_t Index, typename T>
T& Arg() {
return Arg<T>(Index);
}
template <size_t Offset>
size_t* StackAddress() {
static_assert(Offset % sizeof(size_t) == 0, "Bad stack offset");
@ -248,10 +256,11 @@ struct Redirection
PreambleFn mMiddlemanPreamble;
};
// All platform specific redirections, indexed by the call event.
extern Redirection gRedirections[];
// Platform specific methods describing the set of redirections.
size_t NumRedirections();
Redirection& GetRedirection(size_t aCallId);
// Do early initialization of redirections. This is done on both
// Platform specific early initialization of redirections. This is done on both
// recording/replaying and middleman processes, and allows OriginalCall() to
// work in either case.
void EarlyInitializeRedirections();
@ -260,6 +269,10 @@ void EarlyInitializeRedirections();
// gInitializationFailureMessage.
bool InitializeRedirections();
// Platform specific function called after setting up redirections in recording
// or replaying processes.
void LateInitializeRedirections();
// Functions for saving or restoring system error codes.
static inline ErrorType SaveError() { return errno; }
static inline void RestoreError(ErrorType aError) { errno = aError; }
@ -274,20 +287,11 @@ DefineAllCallFunctions(DEFAULTABI)
static inline void*
OriginalFunction(size_t aCallId)
{
return gRedirections[aCallId].mOriginalFunction;
return GetRedirection(aCallId).mOriginalFunction;
}
#define TokenPaste(aFirst, aSecond) aFirst ## aSecond
// Call the original function for a call event ID with a particular ABI and any
// number of arguments.
#define OriginalCallABI(aName, aReturnType, aABI, ...) \
TokenPaste(CallFunction, aABI) <aReturnType> \
(OriginalFunction(CallEvent_ ##aName), ##__VA_ARGS__)
// Call the original function for a call event ID with the default ABI.
#define OriginalCall(aName, aReturnType, ...) \
OriginalCallABI(aName, aReturnType, DEFAULTABI, ##__VA_ARGS__)
// Get the address of the original function by name.
void* OriginalFunction(const char* aName);
static inline ThreadEvent
CallIdToThreadEvent(size_t aCallId)
@ -296,7 +300,7 @@ CallIdToThreadEvent(size_t aCallId)
}
void
RecordReplayInvokeCall(size_t aCallId, CallArguments* aArguments);
RecordReplayInvokeCall(void* aFunction, CallArguments* aArguments);
///////////////////////////////////////////////////////////////////////////////
// Callback Redirections

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -611,7 +611,7 @@ public:
#define NS_INLINE_DECL_REFCOUNTING(_class, ...) \
NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, delete(this), __VA_ARGS__)
#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, _decl, ...) \
#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, _decl, _recording, ...) \
public: \
_decl(MozExternalRefCountType) AddRef(void) __VA_ARGS__ { \
MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
@ -632,7 +632,7 @@ public: \
} \
typedef mozilla::TrueType HasThreadSafeRefCnt; \
protected: \
::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
::mozilla::ThreadSafeAutoRefCntWithRecording<_recording> mRefCnt; \
public:
/**
@ -644,14 +644,36 @@ public:
* @param _class The name of the class implementing the method
*/
#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING(_class, ...) \
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_METHOD_, __VA_ARGS__)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_METHOD_, \
mozilla::recordreplay::Behavior::DontPreserve, \
__VA_ARGS__)
/**
* Like NS_INLINE_DECL_THREADSAFE_REFCOUNTING with AddRef & Release declared
* virtual.
*/
#define NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING(_class, ...) \
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_IMETHOD_, __VA_ARGS__)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_IMETHOD_, \
mozilla::recordreplay::Behavior::DontPreserve, \
__VA_ARGS__)
/**
* Like NS_INLINE_DECL_THREADSAFE_REFCOUNTING except that reference changes
* are recorded and replayed.
*/
#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_RECORDED(_class, ...) \
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_METHOD_, \
mozilla::recordreplay::Behavior::Preserve, \
__VA_ARGS__)
/**
* Like NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING except that reference
* changes are recorded and replayed.
*/
#define NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING_RECORDED(_class, ...) \
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_IMETHOD_, \
mozilla::recordreplay::Behavior::Preserve, \
__VA_ARGS__)
/**
* Use this macro in interface classes that you want to be able to reference