Bug 1535487 - determine rootUrl directly in buglist creator r=tomprince
[gecko.git] / mfbt / RecordReplay.cpp
blob67d84609997f3d2f96ae6623dec806a65c56150c
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 {
26 namespace recordreplay {
28 #define FOR_EACH_INTERFACE(Macro) \
29 Macro(InternalAreThreadEventsPassedThrough, bool, (), ()) Macro( \
30 InternalAreThreadEventsDisallowed, bool, (), \
31 ()) Macro(InternalRecordReplayValue, size_t, (size_t aValue), (aValue)) \
32 Macro(InternalHasDivergedFromRecording, bool, (), ()) Macro( \
33 InternalGeneratePLDHashTableCallbacks, const PLDHashTableOps*, \
34 (const PLDHashTableOps* aOps), \
35 (aOps)) Macro(InternalUnwrapPLDHashTableCallbacks, \
36 const PLDHashTableOps*, (const PLDHashTableOps* aOps), \
37 (aOps)) \
38 Macro(InternalThingIndex, size_t, (void* aThing), (aThing)) Macro( \
39 InternalVirtualThingName, const char*, (void* aThing), (aThing)) \
40 Macro(ExecutionProgressCounter, ProgressCounter*, (), ()) \
41 Macro(NewTimeWarpTarget, ProgressCounter, (), ()) Macro( \
42 ShouldUpdateProgressCounter, bool, (const char* aURL), \
43 (aURL)) \
44 Macro(DefineRecordReplayControlObject, bool, \
45 (JSContext * aCx, JSObject * aObj), (aCx, aObj))
47 #define FOR_EACH_INTERFACE_VOID(Macro) \
48 Macro( \
49 InternalBeginOrderedAtomicAccess, (const void* aValue), \
50 (aValue)) Macro(InternalEndOrderedAtomicAccess, (), \
51 ()) Macro(InternalBeginPassThroughThreadEvents, (), \
52 ()) Macro(InternalEndPassThroughThreadEvents, \
53 (), ()) \
54 Macro(InternalBeginDisallowThreadEvents, (), ()) Macro( \
55 InternalEndDisallowThreadEvents, (), \
56 ()) Macro(InternalRecordReplayBytes, (void* aData, size_t aSize), \
57 (aData, aSize)) Macro(InternalInvalidateRecording, \
58 (const char* aWhy), (aWhy)) \
59 Macro(InternalDestroyPLDHashTableCallbacks, \
60 (const PLDHashTableOps* aOps), \
61 (aOps)) Macro(InternalMovePLDHashTableContents, \
62 (const PLDHashTableOps* aFirstOps, \
63 const PLDHashTableOps* aSecondOps), \
64 (aFirstOps, \
65 aSecondOps)) Macro(SetWeakPointerJSRoot, \
66 (const void* aPtr, \
67 JSObject* aJSObj), \
68 (aPtr, aJSObj)) \
69 Macro(RegisterTrigger, \
70 (void* aObj, const std::function<void()>& aCallback), \
71 (aObj, aCallback)) Macro(UnregisterTrigger, (void* aObj), \
72 (aObj)) \
73 Macro(ActivateTrigger, (void* aObj), (aObj)) Macro( \
74 ExecuteTriggers, (), \
75 ()) Macro(InternalRecordReplayAssert, \
76 (const char* aFormat, va_list aArgs), \
77 (aFormat, aArgs)) \
78 Macro(InternalRecordReplayAssertBytes, \
79 (const void* aData, size_t aSize), \
80 (aData, aSize)) Macro(InternalRegisterThing, \
81 (void* aThing), (aThing)) \
82 Macro(InternalUnregisterThing, (void* aThing), \
83 (aThing)) Macro(InternalRecordReplayDirective, \
84 (long aDirective), \
85 (aDirective)) \
86 Macro(BeginContentParse, \
87 (const void* aToken, const char* aURL, \
88 const char* aContentType), \
89 (aToken, aURL, aContentType)) \
90 Macro(AddContentParseData8, \
91 (const void* aToken, \
92 const mozilla::Utf8Unit* aUtf8Buffer, \
93 size_t aLength), \
94 (aToken, aUtf8Buffer, aLength)) \
95 Macro(AddContentParseData16, \
96 (const void* aToken, \
97 const char16_t* aBuffer, \
98 size_t aLength), \
99 (aToken, aBuffer, aLength)) \
100 Macro(EndContentParse, \
101 (const void* aToken), \
102 (aToken))
104 #define DECLARE_SYMBOL(aName, aReturnType, aFormals, _) \
105 static aReturnType(*gPtr##aName) aFormals;
106 #define DECLARE_SYMBOL_VOID(aName, aFormals, _) \
107 DECLARE_SYMBOL(aName, void, aFormals, _)
109 FOR_EACH_INTERFACE(DECLARE_SYMBOL)
110 FOR_EACH_INTERFACE_VOID(DECLARE_SYMBOL_VOID)
112 #undef DECLARE_SYMBOL
113 #undef DECLARE_SYMBOL_VOID
115 static void* LoadSymbol(const char* aName) {
116 #ifdef ENABLE_RECORD_REPLAY
117 void* rv = dlsym(RTLD_DEFAULT, aName);
118 MOZ_RELEASE_ASSERT(rv);
119 return rv;
120 #else
121 return nullptr;
122 #endif
125 void Initialize(int aArgc, char* aArgv[]) {
126 // Only initialize if the right command line option was specified.
127 bool found = false;
128 for (int i = 0; i < aArgc; i++) {
129 if (!strcmp(aArgv[i], gProcessKindOption)) {
130 found = true;
131 break;
134 if (!found) {
135 return;
138 void (*initialize)(int, char**);
139 BitwiseCast(LoadSymbol("RecordReplayInterface_Initialize"), &initialize);
140 if (!initialize) {
141 return;
144 #define INIT_SYMBOL(aName, _1, _2, _3) \
145 BitwiseCast(LoadSymbol("RecordReplayInterface_" #aName), &gPtr##aName);
146 #define INIT_SYMBOL_VOID(aName, _2, _3) INIT_SYMBOL(aName, void, _2, _3)
148 FOR_EACH_INTERFACE(INIT_SYMBOL)
149 FOR_EACH_INTERFACE_VOID(INIT_SYMBOL_VOID)
151 #undef INIT_SYMBOL
152 #undef INIT_SYMBOL_VOID
154 initialize(aArgc, aArgv);
157 // Record/replay API functions can't GC, but we can't use
158 // JS::AutoSuppressGCAnalysis here due to linking issues.
159 struct AutoSuppressGCAnalysis {
160 AutoSuppressGCAnalysis() {}
161 ~AutoSuppressGCAnalysis() {
162 #ifdef DEBUG
163 // Need nontrivial destructor.
164 static Atomic<int, SequentiallyConsistent, Behavior::DontPreserve> dummy;
165 dummy++;
166 #endif
168 } JS_HAZ_GC_SUPPRESSED;
170 #define DEFINE_WRAPPER(aName, aReturnType, aFormals, aActuals) \
171 aReturnType aName aFormals { \
172 AutoSuppressGCAnalysis suppress; \
173 MOZ_ASSERT(IsRecordingOrReplaying() || IsMiddleman()); \
174 return gPtr##aName aActuals; \
177 #define DEFINE_WRAPPER_VOID(aName, aFormals, aActuals) \
178 void aName aFormals { \
179 AutoSuppressGCAnalysis suppress; \
180 MOZ_ASSERT(IsRecordingOrReplaying() || IsMiddleman()); \
181 gPtr##aName aActuals; \
184 FOR_EACH_INTERFACE(DEFINE_WRAPPER)
185 FOR_EACH_INTERFACE_VOID(DEFINE_WRAPPER_VOID)
187 #undef DEFINE_WRAPPER
188 #undef DEFINE_WRAPPER_VOID
190 #ifdef ENABLE_RECORD_REPLAY
192 bool gIsRecordingOrReplaying;
193 bool gIsRecording;
194 bool gIsReplaying;
195 bool gIsMiddleman;
197 #endif // ENABLE_RECORD_REPLAY
199 #undef ENABLE_RECORD_REPLAY
201 } // namespace recordreplay
202 } // namespace mozilla