Bug 1610775 [wpt PR 21336] - Update urllib3 to 1.25.8, a=testonly
[gecko.git] / mfbt / RecordReplay.cpp
blob2f0df117f4987be45219390cb44c27656a030888
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 #include "RecordReplay.h"
9 #include "js/GCAnnotations.h"
10 #include "mozilla/Atomics.h"
11 #include "mozilla/Casting.h"
12 #include "mozilla/Utf8.h"
14 #include <stdlib.h>
16 // Recording and replaying is only enabled on Mac nightlies.
17 #if defined(XP_MACOSX) && defined(NIGHTLY_BUILD)
18 # define ENABLE_RECORD_REPLAY
19 #endif
21 #ifdef ENABLE_RECORD_REPLAY
22 # include <dlfcn.h>
23 #endif
25 namespace mozilla::recordreplay {
27 // clang-format off
28 #define FOR_EACH_INTERFACE(Macro) \
29 Macro(InternalAreThreadEventsPassedThrough, bool, (), ()) \
30 Macro(InternalAreThreadEventsDisallowed, bool, (), ()) \
31 Macro(InternalRecordReplayValue, size_t, (size_t aValue), (aValue)) \
32 Macro(InternalHasDivergedFromRecording, bool, (), ()) \
33 Macro(InternalGeneratePLDHashTableCallbacks, const PLDHashTableOps*, \
34 (const PLDHashTableOps* aOps), (aOps)) \
35 Macro(InternalUnwrapPLDHashTableCallbacks, const PLDHashTableOps*, \
36 (const PLDHashTableOps* aOps), (aOps)) \
37 Macro(InternalThingIndex, size_t, (void* aThing), (aThing)) \
38 Macro(InternalVirtualThingName, const char*, (void* aThing), (aThing)) \
39 Macro(ExecutionProgressCounter, ProgressCounter*, (), ()) \
40 Macro(NewTimeWarpTarget, ProgressCounter, (), ()) \
41 Macro(ShouldUpdateProgressCounter, bool, (const char* aURL), (aURL)) \
42 Macro(DefineRecordReplayControlObject, bool, (void* aCx, void* aObj), \
43 (aCx, aObj))
45 #define FOR_EACH_INTERFACE_VOID(Macro) \
46 Macro(InternalBeginOrderedAtomicAccess, (const void* aValue), (aValue)) \
47 Macro(InternalEndOrderedAtomicAccess, (), ()) \
48 Macro(InternalBeginPassThroughThreadEvents, (), ()) \
49 Macro(InternalEndPassThroughThreadEvents, (), ()) \
50 Macro(InternalBeginPassThroughThreadEventsWithLocalReplay, (), ()) \
51 Macro(InternalEndPassThroughThreadEventsWithLocalReplay, (), ()) \
52 Macro(InternalBeginDisallowThreadEvents, (), ()) \
53 Macro(InternalEndDisallowThreadEvents, (), ()) \
54 Macro(InternalRecordReplayBytes, (void* aData, size_t aSize), \
55 (aData, aSize)) \
56 Macro(InternalInvalidateRecording, (const char* aWhy), (aWhy)) \
57 Macro(InternalDestroyPLDHashTableCallbacks, (const PLDHashTableOps* aOps), \
58 (aOps)) \
59 Macro(InternalMovePLDHashTableContents, \
60 (const PLDHashTableOps* aFirstOps, const PLDHashTableOps* aSecondOps), \
61 (aFirstOps, aSecondOps)) \
62 Macro(InternalHoldJSObject, (void* aJSObj), (aJSObj)) \
63 Macro(InternalRecordReplayAssert, (const char* aFormat, va_list aArgs), \
64 (aFormat, aArgs)) \
65 Macro(InternalRecordReplayAssertBytes, (const void* aData, size_t aSize), \
66 (aData, aSize)) \
67 Macro(InternalRegisterThing, (void* aThing), (aThing)) \
68 Macro(InternalUnregisterThing, (void* aThing), (aThing)) \
69 Macro(BeginContentParse, \
70 (const void* aToken, const char* aURL, const char* aContentType), \
71 (aToken, aURL, aContentType)) \
72 Macro(AddContentParseData8, \
73 (const void* aToken, const mozilla::Utf8Unit* aUtf8Buffer, \
74 size_t aLength), \
75 (aToken, aUtf8Buffer, aLength)) \
76 Macro(AddContentParseData16, \
77 (const void* aToken, const char16_t* aBuffer, size_t aLength), \
78 (aToken, aBuffer, aLength)) \
79 Macro(EndContentParse, (const void* aToken), (aToken))
80 // clang-format on
82 #define DECLARE_SYMBOL(aName, aReturnType, aFormals, _) \
83 static aReturnType(*gPtr##aName) aFormals;
84 #define DECLARE_SYMBOL_VOID(aName, aFormals, _) \
85 DECLARE_SYMBOL(aName, void, aFormals, _)
87 FOR_EACH_INTERFACE(DECLARE_SYMBOL)
88 FOR_EACH_INTERFACE_VOID(DECLARE_SYMBOL_VOID)
90 #undef DECLARE_SYMBOL
91 #undef DECLARE_SYMBOL_VOID
93 static void* LoadSymbol(const char* aName) {
94 #ifdef ENABLE_RECORD_REPLAY
95 void* rv = dlsym(RTLD_DEFAULT, aName);
96 if (!rv) {
97 fprintf(stderr, "Record/Replay LoadSymbol failed: %s\n", aName);
98 MOZ_CRASH("LoadSymbol");
100 return rv;
101 #else
102 return nullptr;
103 #endif
106 void Initialize(int aArgc, char* aArgv[]) {
107 // Only initialize if the right command line option was specified.
108 bool found = false;
109 for (int i = 0; i < aArgc; i++) {
110 if (!strcmp(aArgv[i], gProcessKindOption)) {
111 found = true;
112 break;
115 if (!found) {
116 return;
119 void (*initialize)(int, char**);
120 BitwiseCast(LoadSymbol("RecordReplayInterface_Initialize"), &initialize);
121 if (!initialize) {
122 return;
125 #define INIT_SYMBOL(aName, _1, _2, _3) \
126 BitwiseCast(LoadSymbol("RecordReplayInterface_" #aName), &gPtr##aName);
127 #define INIT_SYMBOL_VOID(aName, _2, _3) INIT_SYMBOL(aName, void, _2, _3)
129 FOR_EACH_INTERFACE(INIT_SYMBOL)
130 FOR_EACH_INTERFACE_VOID(INIT_SYMBOL_VOID)
132 #undef INIT_SYMBOL
133 #undef INIT_SYMBOL_VOID
135 initialize(aArgc, aArgv);
138 // Record/replay API functions can't GC, but we can't use
139 // JS::AutoSuppressGCAnalysis here due to linking issues.
140 struct AutoSuppressGCAnalysis {
141 AutoSuppressGCAnalysis() {}
142 ~AutoSuppressGCAnalysis() {
143 #ifdef DEBUG
144 // Need nontrivial destructor.
145 static Atomic<int, SequentiallyConsistent, Behavior::DontPreserve> dummy;
146 dummy++;
147 #endif
149 } JS_HAZ_GC_SUPPRESSED;
151 #define DEFINE_WRAPPER(aName, aReturnType, aFormals, aActuals) \
152 aReturnType aName aFormals { \
153 AutoSuppressGCAnalysis suppress; \
154 MOZ_ASSERT(IsRecordingOrReplaying() || IsMiddleman()); \
155 return gPtr##aName aActuals; \
158 #define DEFINE_WRAPPER_VOID(aName, aFormals, aActuals) \
159 void aName aFormals { \
160 AutoSuppressGCAnalysis suppress; \
161 MOZ_ASSERT(IsRecordingOrReplaying() || IsMiddleman()); \
162 gPtr##aName aActuals; \
165 FOR_EACH_INTERFACE(DEFINE_WRAPPER)
166 FOR_EACH_INTERFACE_VOID(DEFINE_WRAPPER_VOID)
168 #undef DEFINE_WRAPPER
169 #undef DEFINE_WRAPPER_VOID
171 #ifdef ENABLE_RECORD_REPLAY
173 bool gIsRecordingOrReplaying;
174 bool gIsRecording;
175 bool gIsReplaying;
176 bool gIsMiddleman;
178 #endif // ENABLE_RECORD_REPLAY
180 #undef ENABLE_RECORD_REPLAY
182 } // namespace mozilla::recordreplay