зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1479058 Part 1 - Add NewTimeWarpTarget() API, r=mccr8.
--HG-- extra : rebase_source : 556161b281c21b19f972854b5c3b31e302d0dd26
This commit is contained in:
Родитель
18b12586ae
Коммит
a1556089f7
|
@ -36,6 +36,7 @@ namespace recordreplay {
|
|||
Macro(InternalThingIndex, size_t, (void* aThing), (aThing)) \
|
||||
Macro(InternalVirtualThingName, const char*, (void* aThing), (aThing)) \
|
||||
Macro(ExecutionProgressCounter, ProgressCounter*, (), ()) \
|
||||
Macro(NewTimeWarpTarget, ProgressCounter, (), ()) \
|
||||
Macro(IsInternalScript, bool, (const char* aURL), (aURL)) \
|
||||
Macro(DefineRecordReplayControlObject, bool, (JSContext* aCx, JSObject* aObj), (aCx, aObj))
|
||||
|
||||
|
|
|
@ -342,6 +342,10 @@ AdvanceExecutionProgressCounter()
|
|||
++*ExecutionProgressCounter();
|
||||
}
|
||||
|
||||
// Get an identifier for the current execution point which can be used to warp
|
||||
// here later.
|
||||
MFBT_API ProgressCounter NewTimeWarpTarget();
|
||||
|
||||
// Return whether a script is internal to the record/replay infrastructure,
|
||||
// may run non-deterministically between recording and replaying, and whose
|
||||
// execution must not update the progress counter.
|
||||
|
|
|
@ -51,6 +51,13 @@ bool MaybeDivergeFromRecording();
|
|||
// Notify navigation that a position was hit.
|
||||
void PositionHit(const js::BreakpointPosition& aPosition);
|
||||
|
||||
// Get an execution point for hitting the specified position right now.
|
||||
js::ExecutionPoint CurrentExecutionPoint(const js::BreakpointPosition& aPosition);
|
||||
|
||||
// Convert an identifier from NewTimeWarpTarget() which we have seen while
|
||||
// executing into an ExecutionPoint.
|
||||
js::ExecutionPoint TimeWarpTargetExecutionPoint(ProgressCounter aTarget);
|
||||
|
||||
// Called when running forward, immediately before hitting a normal or
|
||||
// temporary checkpoint.
|
||||
void BeforeCheckpoint();
|
||||
|
|
|
@ -366,6 +366,9 @@ public:
|
|||
// of how much time has elapsed.
|
||||
bool mAlwaysSaveTemporaryCheckpoints;
|
||||
|
||||
// Checkpoints for all time warp targets that have been generated.
|
||||
InfallibleVector<std::pair<ProgressCounter, size_t>, 0, UntrackedAllocPolicy> mTimeWarpTargetCheckpoints;
|
||||
|
||||
// Note: NavigationState is initially zeroed.
|
||||
NavigationState()
|
||||
: mPhase(&mForwardPhase)
|
||||
|
@ -1138,8 +1141,8 @@ RecordReplayInterface_ExecutionProgressCounter()
|
|||
|
||||
} // extern "C"
|
||||
|
||||
static ExecutionPoint
|
||||
NewExecutionPoint(const BreakpointPosition& aPosition)
|
||||
ExecutionPoint
|
||||
CurrentExecutionPoint(const BreakpointPosition& aPosition)
|
||||
{
|
||||
return ExecutionPoint(gNavigation->LastCheckpoint().mNormal,
|
||||
gProgressCounter, aPosition);
|
||||
|
@ -1149,7 +1152,57 @@ void
|
|||
PositionHit(const BreakpointPosition& position)
|
||||
{
|
||||
AutoDisallowThreadEvents disallow;
|
||||
gNavigation->PositionHit(NewExecutionPoint(position));
|
||||
gNavigation->PositionHit(CurrentExecutionPoint(position));
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
MOZ_EXPORT ProgressCounter
|
||||
RecordReplayInterface_NewTimeWarpTarget()
|
||||
{
|
||||
// NewTimeWarpTarget() must be called at consistent points between recording
|
||||
// and replaying.
|
||||
recordreplay::RecordReplayAssert("NewTimeWarpTarget");
|
||||
|
||||
if (!gNavigation) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Advance the progress counter for each time warp target. This can be called
|
||||
// at any place and any number of times where recorded events are allowed.
|
||||
ProgressCounter progress = ++gProgressCounter;
|
||||
|
||||
PositionHit(BreakpointPosition(BreakpointPosition::WarpTarget));
|
||||
|
||||
// Remember the checkpoint associated with each time warp target we have
|
||||
// generated, so we can convert them to ExecutionPoints later. Ignore warp
|
||||
// targets we have already encountered.
|
||||
if (gNavigation->mTimeWarpTargetCheckpoints.empty() ||
|
||||
progress > gNavigation->mTimeWarpTargetCheckpoints.back().first)
|
||||
{
|
||||
size_t checkpoint = gNavigation->LastCheckpoint().mNormal;
|
||||
gNavigation->mTimeWarpTargetCheckpoints.emplaceBack(progress, checkpoint);
|
||||
}
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
ExecutionPoint
|
||||
TimeWarpTargetExecutionPoint(ProgressCounter aTarget)
|
||||
{
|
||||
Maybe<size_t> checkpoint;
|
||||
for (auto entry : gNavigation->mTimeWarpTargetCheckpoints) {
|
||||
if (entry.first == aTarget) {
|
||||
checkpoint.emplace(entry.second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(checkpoint.isSome());
|
||||
|
||||
return ExecutionPoint(checkpoint.ref(), aTarget,
|
||||
BreakpointPosition(BreakpointPosition::WarpTarget));
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -55,7 +55,10 @@ struct BreakpointPosition
|
|||
EnterFrame,
|
||||
|
||||
// Break when a new top-level script is created.
|
||||
NewScript
|
||||
NewScript,
|
||||
|
||||
// Break when NewTimeWarpTarget() is called.
|
||||
WarpTarget
|
||||
));
|
||||
|
||||
Kind mKind;
|
||||
|
@ -106,6 +109,7 @@ struct BreakpointPosition
|
|||
case OnPop: return "OnPop";
|
||||
case EnterFrame: return "EnterFrame";
|
||||
case NewScript: return "NewScript";
|
||||
case WarpTarget: return "WarpTarget";
|
||||
}
|
||||
MOZ_CRASH("Bad BreakpointPosition kind");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче