зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1470795 Part 3 - Trivial renaming due to API changes, r=froydnj.
--HG-- extra : rebase_source : 95fd379bb385ead70fa241933639e704267229d9
This commit is contained in:
Родитель
312bb81dda
Коммит
4f9e9a98ca
|
@ -110,12 +110,12 @@ public:
|
||||||
, mCallbackStorage(nullptr)
|
, mCallbackStorage(nullptr)
|
||||||
{
|
{
|
||||||
// Use AllocateMemory, as the result will have RWX permissions.
|
// Use AllocateMemory, as the result will have RWX permissions.
|
||||||
mCallbackStorage = (uint8_t*) AllocateMemory(CallbackStorageCapacity, TrackedMemoryKind);
|
mCallbackStorage = (uint8_t*) AllocateMemory(CallbackStorageCapacity, MemoryKind::Tracked);
|
||||||
}
|
}
|
||||||
|
|
||||||
~StableHashTableInfo() {
|
~StableHashTableInfo() {
|
||||||
MOZ_ASSERT(mHashToKey.empty());
|
MOZ_ASSERT(mHashToKey.empty());
|
||||||
DeallocateMemory(mCallbackStorage, CallbackStorageCapacity, TrackedMemoryKind);
|
DeallocateMemory(mCallbackStorage, CallbackStorageCapacity, MemoryKind::Tracked);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppearsValid() {
|
bool AppearsValid() {
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
#include "MemorySnapshot.h"
|
#include "MemorySnapshot.h"
|
||||||
|
|
||||||
#include "ipc/ChildIPC.h"
|
#include "ipc/ChildInternal.h"
|
||||||
#include "js/ReplayHooks.h"
|
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "DirtyMemoryHandler.h"
|
#include "DirtyMemoryHandler.h"
|
||||||
#include "InfallibleVector.h"
|
#include "InfallibleVector.h"
|
||||||
|
@ -161,7 +160,7 @@ struct DirtyPage {
|
||||||
|
|
||||||
// A set of dirty pages that can be searched quickly.
|
// A set of dirty pages that can be searched quickly.
|
||||||
typedef SplayTree<DirtyPage, DirtyPage::AddressSort,
|
typedef SplayTree<DirtyPage, DirtyPage::AddressSort,
|
||||||
AllocPolicy<UntrackedMemoryKind::SortedDirtyPageSet>, 4> SortedDirtyPageSet;
|
AllocPolicy<MemoryKind::SortedDirtyPageSet>, 4> SortedDirtyPageSet;
|
||||||
|
|
||||||
// A set of dirty pages associated with some checkpoint.
|
// A set of dirty pages associated with some checkpoint.
|
||||||
struct DirtyPageSet {
|
struct DirtyPageSet {
|
||||||
|
@ -172,7 +171,7 @@ struct DirtyPageSet {
|
||||||
// thread when all other threads are idle, by the dirty memory handler when
|
// thread when all other threads are idle, by the dirty memory handler when
|
||||||
// it is active and this is the active page set, and by the snapshot thread
|
// it is active and this is the active page set, and by the snapshot thread
|
||||||
// which owns this set.
|
// which owns this set.
|
||||||
InfallibleVector<DirtyPage, 256, AllocPolicy<UntrackedMemoryKind::DirtyPageSet>> mPages;
|
InfallibleVector<DirtyPage, 256, AllocPolicy<MemoryKind::DirtyPageSet>> mPages;
|
||||||
|
|
||||||
explicit DirtyPageSet(const CheckpointId& aCheckpoint)
|
explicit DirtyPageSet(const CheckpointId& aCheckpoint)
|
||||||
: mCheckpoint(aCheckpoint)
|
: mCheckpoint(aCheckpoint)
|
||||||
|
@ -189,7 +188,7 @@ struct SnapshotThreadWorklist {
|
||||||
|
|
||||||
// Sets of pages in the thread's worklist. Each set is for a different diff,
|
// Sets of pages in the thread's worklist. Each set is for a different diff,
|
||||||
// with the oldest checkpoints first.
|
// with the oldest checkpoints first.
|
||||||
InfallibleVector<DirtyPageSet, 256, AllocPolicy<UntrackedMemoryKind::Generic>> mSets;
|
InfallibleVector<DirtyPageSet, 256, AllocPolicy<MemoryKind::Generic>> mSets;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Structure used to coordinate activity between the main thread and all
|
// Structure used to coordinate activity between the main thread and all
|
||||||
|
@ -232,7 +231,7 @@ static const size_t NumSnapshotThreads = 8;
|
||||||
class FreeRegionSet {
|
class FreeRegionSet {
|
||||||
// Kind of memory being managed. This also describes the memory used by the
|
// Kind of memory being managed. This also describes the memory used by the
|
||||||
// set itself.
|
// set itself.
|
||||||
AllocatedMemoryKind mKind;
|
MemoryKind mKind;
|
||||||
|
|
||||||
// Lock protecting contents of the structure.
|
// Lock protecting contents of the structure.
|
||||||
SpinLock mLock;
|
SpinLock mLock;
|
||||||
|
@ -277,12 +276,12 @@ class FreeRegionSet {
|
||||||
void* ExtractLockHeld(size_t aSize, AutoSpinLock& aLockHeld);
|
void* ExtractLockHeld(size_t aSize, AutoSpinLock& aLockHeld);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FreeRegionSet(AllocatedMemoryKind aKind)
|
explicit FreeRegionSet(MemoryKind aKind)
|
||||||
: mKind(aKind), mRegions(MyAllocPolicy(*this))
|
: mKind(aKind), mRegions(MyAllocPolicy(*this))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Get the single region set for a given memory kind.
|
// Get the single region set for a given memory kind.
|
||||||
static FreeRegionSet& Get(AllocatedMemoryKind aKind);
|
static FreeRegionSet& Get(MemoryKind aKind);
|
||||||
|
|
||||||
// Add a free region to the set.
|
// Add a free region to the set.
|
||||||
void Insert(void* aAddress, size_t aSize);
|
void Insert(void* aAddress, size_t aSize);
|
||||||
|
@ -312,9 +311,9 @@ struct MemoryInfo {
|
||||||
// All tracked memory in the process. This may be updated by any thread while
|
// All tracked memory in the process. This may be updated by any thread while
|
||||||
// holding mTrackedRegionsLock.
|
// holding mTrackedRegionsLock.
|
||||||
SplayTree<AllocatedMemoryRegion, AllocatedMemoryRegion::AddressSort,
|
SplayTree<AllocatedMemoryRegion, AllocatedMemoryRegion::AddressSort,
|
||||||
AllocPolicy<UntrackedMemoryKind::TrackedRegions>, 4>
|
AllocPolicy<MemoryKind::TrackedRegions>, 4>
|
||||||
mTrackedRegions;
|
mTrackedRegions;
|
||||||
InfallibleVector<AllocatedMemoryRegion, 512, AllocPolicy<UntrackedMemoryKind::TrackedRegions>>
|
InfallibleVector<AllocatedMemoryRegion, 512, AllocPolicy<MemoryKind::TrackedRegions>>
|
||||||
mTrackedRegionsByAllocationOrder;
|
mTrackedRegionsByAllocationOrder;
|
||||||
SpinLock mTrackedRegionsLock;
|
SpinLock mTrackedRegionsLock;
|
||||||
|
|
||||||
|
@ -347,7 +346,7 @@ struct MemoryInfo {
|
||||||
double mTimeTotals[(size_t) TimerKind::Count];
|
double mTimeTotals[(size_t) TimerKind::Count];
|
||||||
|
|
||||||
// Information for memory allocation.
|
// Information for memory allocation.
|
||||||
Atomic<ssize_t, Relaxed, Behavior::DontPreserve> mMemoryBalance[UntrackedMemoryKind::Count];
|
Atomic<ssize_t, Relaxed, Behavior::DontPreserve> mMemoryBalance[(size_t) MemoryKind::Count];
|
||||||
|
|
||||||
// Recent dirty memory faults.
|
// Recent dirty memory faults.
|
||||||
void* mDirtyMemoryFaults[50];
|
void* mDirtyMemoryFaults[50];
|
||||||
|
@ -360,7 +359,7 @@ struct MemoryInfo {
|
||||||
|
|
||||||
MemoryInfo()
|
MemoryInfo()
|
||||||
: mMemoryChangesAllowed(true)
|
: mMemoryChangesAllowed(true)
|
||||||
, mFreeUntrackedRegions(UntrackedMemoryKind::FreeRegions)
|
, mFreeUntrackedRegions(MemoryKind::FreeRegions)
|
||||||
, mStartTime(CurrentTime())
|
, mStartTime(CurrentTime())
|
||||||
, mIntentionalCrashesAllowed(true)
|
, mIntentionalCrashesAllowed(true)
|
||||||
{
|
{
|
||||||
|
@ -483,7 +482,7 @@ RecordReplayInterface_InternalRecordReplayDirective(long aDirective)
|
||||||
gMemoryInfo->mCrashSoon = false;
|
gMemoryInfo->mCrashSoon = false;
|
||||||
break;
|
break;
|
||||||
case Directive::AlwaysSaveTemporaryCheckpoints:
|
case Directive::AlwaysSaveTemporaryCheckpoints:
|
||||||
JS::replay::hooks.alwaysSaveTemporaryCheckpoints();
|
navigation::AlwaysSaveTemporaryCheckpoints();
|
||||||
break;
|
break;
|
||||||
case Directive::AlwaysMarkMajorCheckpoints:
|
case Directive::AlwaysMarkMajorCheckpoints:
|
||||||
child::NotifyAlwaysMarkMajorCheckpoints();
|
child::NotifyAlwaysMarkMajorCheckpoints();
|
||||||
|
@ -558,14 +557,14 @@ SnapshotThreadCondition::WaitUntilNoLongerActive()
|
||||||
static uint8_t*
|
static uint8_t*
|
||||||
AllocatePageCopy()
|
AllocatePageCopy()
|
||||||
{
|
{
|
||||||
return (uint8_t*) AllocateMemory(PageSize, UntrackedMemoryKind::PageCopy);
|
return (uint8_t*) AllocateMemory(PageSize, MemoryKind::PageCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free a page allocated by AllocatePageCopy.
|
// Free a page allocated by AllocatePageCopy.
|
||||||
static void
|
static void
|
||||||
FreePageCopy(uint8_t* aPage)
|
FreePageCopy(uint8_t* aPage)
|
||||||
{
|
{
|
||||||
DeallocateMemory(aPage, PageSize, UntrackedMemoryKind::PageCopy);
|
DeallocateMemory(aPage, PageSize, MemoryKind::PageCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -875,7 +874,7 @@ ProcessAllInitialMemoryRegions()
|
||||||
|
|
||||||
// All memory in gMemoryInfo->mTrackedRegions that is not in use at the current
|
// All memory in gMemoryInfo->mTrackedRegions that is not in use at the current
|
||||||
// point in execution.
|
// point in execution.
|
||||||
static FreeRegionSet gFreeRegions(TrackedMemoryKind);
|
static FreeRegionSet gFreeRegions(MemoryKind::Tracked);
|
||||||
|
|
||||||
// The size of gMemoryInfo->mTrackedRegionsByAllocationOrder we expect to see
|
// The size of gMemoryInfo->mTrackedRegionsByAllocationOrder we expect to see
|
||||||
// at the point of the last saved checkpoint.
|
// at the point of the last saved checkpoint.
|
||||||
|
@ -902,9 +901,9 @@ FixupFreeRegionsAfterRewind()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ FreeRegionSet&
|
/* static */ FreeRegionSet&
|
||||||
FreeRegionSet::Get(AllocatedMemoryKind aKind)
|
FreeRegionSet::Get(MemoryKind aKind)
|
||||||
{
|
{
|
||||||
return (aKind == TrackedMemoryKind) ? gFreeRegions : gMemoryInfo->mFreeUntrackedRegions;
|
return (aKind == MemoryKind::Tracked) ? gFreeRegions : gMemoryInfo->mFreeUntrackedRegions;
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
|
@ -931,7 +930,7 @@ FreeRegionSet::MaybeRefillNextChunk(AutoSpinLock& aLockHeld)
|
||||||
|
|
||||||
// Look for a free region we can take the next chunk from.
|
// Look for a free region we can take the next chunk from.
|
||||||
size_t size = ChunkPages * PageSize;
|
size_t size = ChunkPages * PageSize;
|
||||||
gMemoryInfo->mMemoryBalance[mKind] += size;
|
gMemoryInfo->mMemoryBalance[(size_t) mKind] += size;
|
||||||
|
|
||||||
mNextChunk = ExtractLockHeld(size, aLockHeld);
|
mNextChunk = ExtractLockHeld(size, aLockHeld);
|
||||||
|
|
||||||
|
@ -1026,14 +1025,14 @@ FreeRegionSet::Intersects(void* aAddress, size_t aSize)
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void
|
||||||
RegisterAllocatedMemory(void* aBaseAddress, size_t aSize, AllocatedMemoryKind aKind)
|
RegisterAllocatedMemory(void* aBaseAddress, size_t aSize, MemoryKind aKind)
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(aBaseAddress == PageBase(aBaseAddress));
|
MOZ_RELEASE_ASSERT(aBaseAddress == PageBase(aBaseAddress));
|
||||||
MOZ_RELEASE_ASSERT(aSize == RoundupSizeToPageBoundary(aSize));
|
MOZ_RELEASE_ASSERT(aSize == RoundupSizeToPageBoundary(aSize));
|
||||||
|
|
||||||
uint8_t* aAddress = reinterpret_cast<uint8_t*>(aBaseAddress);
|
uint8_t* aAddress = reinterpret_cast<uint8_t*>(aBaseAddress);
|
||||||
|
|
||||||
if (aKind != TrackedMemoryKind) {
|
if (aKind != MemoryKind::Tracked) {
|
||||||
if (!HasSavedCheckpoint()) {
|
if (!HasSavedCheckpoint()) {
|
||||||
AddInitialUntrackedMemoryRegion(aAddress, aSize);
|
AddInitialUntrackedMemoryRegion(aAddress, aSize);
|
||||||
}
|
}
|
||||||
|
@ -1096,13 +1095,13 @@ RestoreWritableFixedMemory(void* aAddress, size_t aSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
AllocateMemoryTryAddress(void* aAddress, size_t aSize, AllocatedMemoryKind aKind)
|
AllocateMemoryTryAddress(void* aAddress, size_t aSize, MemoryKind aKind)
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(aAddress == PageBase(aAddress));
|
MOZ_RELEASE_ASSERT(aAddress == PageBase(aAddress));
|
||||||
aSize = RoundupSizeToPageBoundary(aSize);
|
aSize = RoundupSizeToPageBoundary(aSize);
|
||||||
|
|
||||||
if (gMemoryInfo) {
|
if (gMemoryInfo) {
|
||||||
gMemoryInfo->mMemoryBalance[aKind] += aSize;
|
gMemoryInfo->mMemoryBalance[(size_t) aKind] += aSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasSavedCheckpoint()) {
|
if (HasSavedCheckpoint()) {
|
||||||
|
@ -1116,10 +1115,8 @@ AllocateMemoryTryAddress(void* aAddress, size_t aSize, AllocatedMemoryKind aKind
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
void*
|
||||||
|
AllocateMemory(size_t aSize, MemoryKind aKind)
|
||||||
MOZ_EXPORT void*
|
|
||||||
RecordReplayInterface_AllocateMemory(size_t aSize, AllocatedMemoryKind aKind)
|
|
||||||
{
|
{
|
||||||
if (!IsReplaying()) {
|
if (!IsReplaying()) {
|
||||||
return DirectAllocateMemory(nullptr, aSize);
|
return DirectAllocateMemory(nullptr, aSize);
|
||||||
|
@ -1127,8 +1124,8 @@ RecordReplayInterface_AllocateMemory(size_t aSize, AllocatedMemoryKind aKind)
|
||||||
return AllocateMemoryTryAddress(nullptr, aSize, aKind);
|
return AllocateMemoryTryAddress(nullptr, aSize, aKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_EXPORT void
|
void
|
||||||
RecordReplayInterface_DeallocateMemory(void* aAddress, size_t aSize, AllocatedMemoryKind aKind)
|
DeallocateMemory(void* aAddress, size_t aSize, MemoryKind aKind)
|
||||||
{
|
{
|
||||||
// Round the supplied region to the containing page boundaries.
|
// Round the supplied region to the containing page boundaries.
|
||||||
aSize += (uint8_t*) aAddress - PageBase(aAddress);
|
aSize += (uint8_t*) aAddress - PageBase(aAddress);
|
||||||
|
@ -1140,19 +1137,19 @@ RecordReplayInterface_DeallocateMemory(void* aAddress, size_t aSize, AllocatedMe
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gMemoryInfo) {
|
if (gMemoryInfo) {
|
||||||
gMemoryInfo->mMemoryBalance[aKind] -= aSize;
|
gMemoryInfo->mMemoryBalance[(size_t) aKind] -= aSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memory is returned to the system before saving the first checkpoint.
|
// Memory is returned to the system before saving the first checkpoint.
|
||||||
if (!HasSavedCheckpoint()) {
|
if (!HasSavedCheckpoint()) {
|
||||||
if (IsReplaying() && aKind != TrackedMemoryKind) {
|
if (IsReplaying() && aKind != MemoryKind::Tracked) {
|
||||||
RemoveInitialUntrackedRegion((uint8_t*) aAddress, aSize);
|
RemoveInitialUntrackedRegion((uint8_t*) aAddress, aSize);
|
||||||
}
|
}
|
||||||
DirectDeallocateMemory(aAddress, aSize);
|
DirectDeallocateMemory(aAddress, aSize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aKind == TrackedMemoryKind) {
|
if (aKind == MemoryKind::Tracked) {
|
||||||
// For simplicity, all free regions must be executable, so ignore deallocated
|
// For simplicity, all free regions must be executable, so ignore deallocated
|
||||||
// memory in regions that are not executable.
|
// memory in regions that are not executable.
|
||||||
bool executable;
|
bool executable;
|
||||||
|
@ -1167,8 +1164,6 @@ RecordReplayInterface_DeallocateMemory(void* aAddress, size_t aSize, AllocatedMe
|
||||||
FreeRegionSet::Get(aKind).Insert(aAddress, aSize);
|
FreeRegionSet::Get(aKind).Insert(aAddress, aSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // extern "C"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Snapshot Threads
|
// Snapshot Threads
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1273,7 +1268,7 @@ void
|
||||||
InitializeMemorySnapshots()
|
InitializeMemorySnapshots()
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(gMemoryInfo == nullptr);
|
MOZ_RELEASE_ASSERT(gMemoryInfo == nullptr);
|
||||||
void* memory = AllocateMemory(sizeof(MemoryInfo), UntrackedMemoryKind::Generic);
|
void* memory = AllocateMemory(sizeof(MemoryInfo), MemoryKind::Generic);
|
||||||
gMemoryInfo = new(memory) MemoryInfo();
|
gMemoryInfo = new(memory) MemoryInfo();
|
||||||
|
|
||||||
// Mark gMemoryInfo as untracked. See AddInitialUntrackedMemoryRegion.
|
// Mark gMemoryInfo as untracked. See AddInitialUntrackedMemoryRegion.
|
||||||
|
|
|
@ -40,11 +40,11 @@ void RestoreWritableFixedMemory(void* aAddress, size_t aSize);
|
||||||
|
|
||||||
// Allocate memory, trying to use a specific address if provided but only if
|
// Allocate memory, trying to use a specific address if provided but only if
|
||||||
// it is free.
|
// it is free.
|
||||||
void* AllocateMemoryTryAddress(void* aAddress, size_t aSize, AllocatedMemoryKind aKind);
|
void* AllocateMemoryTryAddress(void* aAddress, size_t aSize, MemoryKind aKind);
|
||||||
|
|
||||||
// Note a range of memory that was just allocated from the system, and the
|
// Note a range of memory that was just allocated from the system, and the
|
||||||
// kind of memory allocation that was performed.
|
// kind of memory allocation that was performed.
|
||||||
void RegisterAllocatedMemory(void* aBaseAddress, size_t aSize, AllocatedMemoryKind aKind);
|
void RegisterAllocatedMemory(void* aBaseAddress, size_t aSize, MemoryKind aKind);
|
||||||
|
|
||||||
// Initialize the memory snapshots system.
|
// Initialize the memory snapshots system.
|
||||||
void InitializeMemorySnapshots();
|
void InitializeMemorySnapshots();
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "ProcessRecordReplay.h"
|
#include "ProcessRecordReplay.h"
|
||||||
|
|
||||||
#include "ipc/ChildIPC.h"
|
#include "ipc/ChildInternal.h"
|
||||||
#include "mozilla/Compression.h"
|
#include "mozilla/Compression.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Sprintf.h"
|
#include "mozilla/Sprintf.h"
|
||||||
|
@ -221,7 +221,7 @@ FlushRecording()
|
||||||
MOZ_RELEASE_ASSERT(Thread::CurrentIsMainThread());
|
MOZ_RELEASE_ASSERT(Thread::CurrentIsMainThread());
|
||||||
|
|
||||||
// Save the endpoint of the recording.
|
// Save the endpoint of the recording.
|
||||||
JS::replay::ExecutionPoint endpoint = JS::replay::hooks.getRecordingEndpoint();
|
js::ExecutionPoint endpoint = navigation::GetRecordingEndpoint();
|
||||||
Stream* endpointStream = gRecordingFile->OpenStream(StreamName::Main, 0);
|
Stream* endpointStream = gRecordingFile->OpenStream(StreamName::Main, 0);
|
||||||
endpointStream->WriteScalar(++gNumEndpoints);
|
endpointStream->WriteScalar(++gNumEndpoints);
|
||||||
endpointStream->WriteBytes(&endpoint, sizeof(endpoint));
|
endpointStream->WriteBytes(&endpoint, sizeof(endpoint));
|
||||||
|
@ -274,10 +274,10 @@ HitRecordingEndpoint()
|
||||||
// Check if there is a new endpoint in the endpoint data stream.
|
// Check if there is a new endpoint in the endpoint data stream.
|
||||||
Stream* endpointStream = gRecordingFile->OpenStream(StreamName::Main, 0);
|
Stream* endpointStream = gRecordingFile->OpenStream(StreamName::Main, 0);
|
||||||
if (!endpointStream->AtEnd()) {
|
if (!endpointStream->AtEnd()) {
|
||||||
JS::replay::ExecutionPoint endpoint;
|
js::ExecutionPoint endpoint;
|
||||||
size_t index = endpointStream->ReadScalar();
|
size_t index = endpointStream->ReadScalar();
|
||||||
endpointStream->ReadBytes(&endpoint, sizeof(endpoint));
|
endpointStream->ReadBytes(&endpoint, sizeof(endpoint));
|
||||||
JS::replay::hooks.setRecordingEndpoint(index, endpoint);
|
navigation::SetRecordingEndpoint(index, endpoint);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,16 +308,14 @@ HitEndOfRecording()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
bool
|
||||||
|
SpewEnabled()
|
||||||
MOZ_EXPORT bool
|
|
||||||
RecordReplayInterface_SpewEnabled()
|
|
||||||
{
|
{
|
||||||
return gSpewEnabled;
|
return gSpewEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_EXPORT void
|
void
|
||||||
RecordReplayInterface_InternalPrint(const char* aFormat, va_list aArgs)
|
InternalPrint(const char* aFormat, va_list aArgs)
|
||||||
{
|
{
|
||||||
char buf1[2048];
|
char buf1[2048];
|
||||||
VsprintfLiteral(buf1, aFormat, aArgs);
|
VsprintfLiteral(buf1, aFormat, aArgs);
|
||||||
|
@ -326,8 +324,6 @@ RecordReplayInterface_InternalPrint(const char* aFormat, va_list aArgs)
|
||||||
DirectPrint(buf2);
|
DirectPrint(buf2);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // extern "C"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Record/Replay Assertions
|
// Record/Replay Assertions
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -638,7 +638,7 @@ RR_mmap(void* aAddress, size_t aSize, int aProt, int aFlags, int aFd, off_t aOff
|
||||||
memory = aAddress;
|
memory = aAddress;
|
||||||
} else {
|
} else {
|
||||||
memory = AllocateMemoryTryAddress(aAddress, RoundupSizeToPageBoundary(aSize),
|
memory = AllocateMemoryTryAddress(aAddress, RoundupSizeToPageBoundary(aSize),
|
||||||
TrackedMemoryKind);
|
MemoryKind::Tracked);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We have to call mmap itself, which can change memory protection flags
|
// We have to call mmap itself, which can change memory protection flags
|
||||||
|
@ -652,7 +652,7 @@ RR_mmap(void* aAddress, size_t aSize, int aProt, int aFlags, int aFd, off_t aOff
|
||||||
MOZ_RELEASE_ASSERT(memory == aAddress);
|
MOZ_RELEASE_ASSERT(memory == aAddress);
|
||||||
RestoreWritableFixedMemory(memory, RoundupSizeToPageBoundary(aSize));
|
RestoreWritableFixedMemory(memory, RoundupSizeToPageBoundary(aSize));
|
||||||
} else if (memory && memory != (void*)-1) {
|
} else if (memory && memory != (void*)-1) {
|
||||||
RegisterAllocatedMemory(memory, RoundupSizeToPageBoundary(aSize), TrackedMemoryKind);
|
RegisterAllocatedMemory(memory, RoundupSizeToPageBoundary(aSize), MemoryKind::Tracked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,7 +670,7 @@ RR_mmap(void* aAddress, size_t aSize, int aProt, int aFlags, int aFd, off_t aOff
|
||||||
static ssize_t
|
static ssize_t
|
||||||
RR_munmap(void* aAddress, size_t aSize)
|
RR_munmap(void* aAddress, size_t aSize)
|
||||||
{
|
{
|
||||||
DeallocateMemory(aAddress, aSize, TrackedMemoryKind);
|
DeallocateMemory(aAddress, aSize, MemoryKind::Tracked);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1505,14 +1505,14 @@ static kern_return_t
|
||||||
RR_mach_vm_allocate(vm_map_t aTarget, mach_vm_address_t* aAddress,
|
RR_mach_vm_allocate(vm_map_t aTarget, mach_vm_address_t* aAddress,
|
||||||
mach_vm_size_t aSize, int aFlags)
|
mach_vm_size_t aSize, int aFlags)
|
||||||
{
|
{
|
||||||
*aAddress = (mach_vm_address_t) AllocateMemory(aSize, TrackedMemoryKind);
|
*aAddress = (mach_vm_address_t) AllocateMemory(aSize, MemoryKind::Tracked);
|
||||||
return KERN_SUCCESS;
|
return KERN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static kern_return_t
|
static kern_return_t
|
||||||
RR_mach_vm_deallocate(vm_map_t aTarget, mach_vm_address_t aAddress, mach_vm_size_t aSize)
|
RR_mach_vm_deallocate(vm_map_t aTarget, mach_vm_address_t aAddress, mach_vm_size_t aSize)
|
||||||
{
|
{
|
||||||
DeallocateMemory((void*) aAddress, aSize, TrackedMemoryKind);
|
DeallocateMemory((void*) aAddress, aSize, MemoryKind::Tracked);
|
||||||
return KERN_SUCCESS;
|
return KERN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "ProcessRewind.h"
|
#include "ProcessRewind.h"
|
||||||
|
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
#include "ipc/ChildInternal.h"
|
||||||
#include "mozilla/dom/ScriptSettings.h"
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
#include "mozilla/StaticMutex.h"
|
#include "mozilla/StaticMutex.h"
|
||||||
#include "InfallibleVector.h"
|
#include "InfallibleVector.h"
|
||||||
|
@ -14,10 +15,6 @@
|
||||||
#include "Monitor.h"
|
#include "Monitor.h"
|
||||||
#include "ProcessRecordReplay.h"
|
#include "ProcessRecordReplay.h"
|
||||||
#include "ThreadSnapshot.h"
|
#include "ThreadSnapshot.h"
|
||||||
#include "prcvar.h"
|
|
||||||
|
|
||||||
#include <setjmp.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace recordreplay {
|
namespace recordreplay {
|
||||||
|
@ -35,11 +32,11 @@ struct RewindInfo
|
||||||
|
|
||||||
// Checkpoints which have been saved. This includes only entries from
|
// Checkpoints which have been saved. This includes only entries from
|
||||||
// mShouldSaveCheckpoints, plus all temporary checkpoints.
|
// mShouldSaveCheckpoints, plus all temporary checkpoints.
|
||||||
InfallibleVector<SavedCheckpoint, 1024, AllocPolicy<UntrackedMemoryKind::Generic>> mSavedCheckpoints;
|
InfallibleVector<SavedCheckpoint, 1024, AllocPolicy<MemoryKind::Generic>> mSavedCheckpoints;
|
||||||
|
|
||||||
// Unsorted list of checkpoints which the middleman has instructed us to
|
// Unsorted list of checkpoints which the middleman has instructed us to
|
||||||
// save. All those equal to or prior to mLastCheckpoint will have been saved.
|
// save. All those equal to or prior to mLastCheckpoint will have been saved.
|
||||||
InfallibleVector<size_t, 1024, AllocPolicy<UntrackedMemoryKind::Generic>> mShouldSaveCheckpoints;
|
InfallibleVector<size_t, 1024, AllocPolicy<MemoryKind::Generic>> mShouldSaveCheckpoints;
|
||||||
};
|
};
|
||||||
|
|
||||||
static RewindInfo* gRewindInfo;
|
static RewindInfo* gRewindInfo;
|
||||||
|
@ -55,7 +52,7 @@ void
|
||||||
InitializeRewindState()
|
InitializeRewindState()
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(gRewindInfo == nullptr);
|
MOZ_RELEASE_ASSERT(gRewindInfo == nullptr);
|
||||||
void* memory = AllocateMemory(sizeof(RewindInfo), UntrackedMemoryKind::Generic);
|
void* memory = AllocateMemory(sizeof(RewindInfo), MemoryKind::Generic);
|
||||||
gRewindInfo = new(memory) RewindInfo();
|
gRewindInfo = new(memory) RewindInfo();
|
||||||
|
|
||||||
gMainThreadCallbackMonitor = new Monitor();
|
gMainThreadCallbackMonitor = new Monitor();
|
||||||
|
@ -67,10 +64,8 @@ CheckpointPrecedes(const CheckpointId& aFirst, const CheckpointId& aSecond)
|
||||||
return aFirst.mNormal < aSecond.mNormal || aFirst.mTemporary < aSecond.mTemporary;
|
return aFirst.mNormal < aSecond.mNormal || aFirst.mTemporary < aSecond.mTemporary;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
void
|
||||||
|
RestoreCheckpointAndResume(const CheckpointId& aCheckpoint)
|
||||||
MOZ_EXPORT void
|
|
||||||
RecordReplayInterface_RestoreCheckpointAndResume(const CheckpointId& aCheckpoint)
|
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(IsReplaying());
|
MOZ_RELEASE_ASSERT(IsReplaying());
|
||||||
MOZ_RELEASE_ASSERT(Thread::CurrentIsMainThread());
|
MOZ_RELEASE_ASSERT(Thread::CurrentIsMainThread());
|
||||||
|
@ -115,19 +110,6 @@ RecordReplayInterface_RestoreCheckpointAndResume(const CheckpointId& aCheckpoint
|
||||||
Unreachable();
|
Unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static BeforeCheckpointHook gBeforeCheckpointHook;
|
|
||||||
static AfterCheckpointHook gAfterCheckpointHook;
|
|
||||||
|
|
||||||
MOZ_EXPORT void
|
|
||||||
RecordReplayInterface_SetCheckpointHooks(BeforeCheckpointHook aBeforeCheckpoint,
|
|
||||||
AfterCheckpointHook aAfterCheckpoint)
|
|
||||||
{
|
|
||||||
gBeforeCheckpointHook = aBeforeCheckpoint;
|
|
||||||
gAfterCheckpointHook = aAfterCheckpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // extern "C"
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SetSaveCheckpoint(size_t aCheckpoint, bool aSave)
|
SetSaveCheckpoint(size_t aCheckpoint, bool aSave)
|
||||||
{
|
{
|
||||||
|
@ -135,26 +117,17 @@ SetSaveCheckpoint(size_t aCheckpoint, bool aSave)
|
||||||
VectorAddOrRemoveEntry(gRewindInfo->mShouldSaveCheckpoints, aCheckpoint, aSave);
|
VectorAddOrRemoveEntry(gRewindInfo->mShouldSaveCheckpoints, aCheckpoint, aSave);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
bool
|
||||||
|
NewCheckpoint(bool aTemporary)
|
||||||
// Mark a checkpoint, which we might or might not save.
|
|
||||||
MOZ_EXPORT bool
|
|
||||||
RecordReplayInterface_NewCheckpoint(bool aTemporary)
|
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(Thread::CurrentIsMainThread());
|
MOZ_RELEASE_ASSERT(Thread::CurrentIsMainThread());
|
||||||
MOZ_RELEASE_ASSERT(!AreThreadEventsPassedThrough());
|
MOZ_RELEASE_ASSERT(!AreThreadEventsPassedThrough());
|
||||||
MOZ_RELEASE_ASSERT(IsReplaying() || !aTemporary);
|
MOZ_RELEASE_ASSERT(IsReplaying() || !aTemporary);
|
||||||
|
|
||||||
gBeforeCheckpointHook();
|
navigation::BeforeCheckpoint();
|
||||||
|
|
||||||
// Get the ID of the new checkpoint.
|
// Get the ID of the new checkpoint.
|
||||||
CheckpointId checkpoint = gRewindInfo->mLastCheckpoint;
|
CheckpointId checkpoint = gRewindInfo->mLastCheckpoint.NextCheckpoint(aTemporary);
|
||||||
if (aTemporary) {
|
|
||||||
checkpoint.mTemporary++;
|
|
||||||
} else {
|
|
||||||
checkpoint.mNormal++;
|
|
||||||
checkpoint.mTemporary = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save all checkpoints the middleman tells us to, and temporary checkpoints
|
// Save all checkpoints the middleman tells us to, and temporary checkpoints
|
||||||
// (which the middleman never knows about).
|
// (which the middleman never knows about).
|
||||||
|
@ -202,11 +175,7 @@ RecordReplayInterface_NewCheckpoint(bool aTemporary)
|
||||||
|
|
||||||
gRewindInfo->mLastCheckpoint = checkpoint;
|
gRewindInfo->mLastCheckpoint = checkpoint;
|
||||||
|
|
||||||
AutoDisallowThreadEvents disallow;
|
navigation::AfterCheckpoint(checkpoint);
|
||||||
|
|
||||||
dom::AutoJSAPI jsapi;
|
|
||||||
jsapi.Init();
|
|
||||||
gAfterCheckpointHook(checkpoint);
|
|
||||||
|
|
||||||
return reachedCheckpoint;
|
return reachedCheckpoint;
|
||||||
}
|
}
|
||||||
|
@ -214,8 +183,8 @@ RecordReplayInterface_NewCheckpoint(bool aTemporary)
|
||||||
static bool gRecordingDiverged;
|
static bool gRecordingDiverged;
|
||||||
static bool gUnhandledDivergeAllowed;
|
static bool gUnhandledDivergeAllowed;
|
||||||
|
|
||||||
MOZ_EXPORT void
|
void
|
||||||
RecordReplayInterface_DivergeFromRecording()
|
DivergeFromRecording()
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(Thread::CurrentIsMainThread());
|
MOZ_RELEASE_ASSERT(Thread::CurrentIsMainThread());
|
||||||
MOZ_RELEASE_ASSERT(IsReplaying());
|
MOZ_RELEASE_ASSERT(IsReplaying());
|
||||||
|
@ -223,27 +192,23 @@ RecordReplayInterface_DivergeFromRecording()
|
||||||
gUnhandledDivergeAllowed = true;
|
gUnhandledDivergeAllowed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
MOZ_EXPORT bool
|
MOZ_EXPORT bool
|
||||||
RecordReplayInterface_InternalHasDivergedFromRecording()
|
RecordReplayInterface_InternalHasDivergedFromRecording()
|
||||||
{
|
{
|
||||||
return Thread::CurrentIsMainThread() && gRecordingDiverged;
|
return Thread::CurrentIsMainThread() && gRecordingDiverged;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_EXPORT void
|
} // extern "C"
|
||||||
RecordReplayInterface_DisallowUnhandledDivergeFromRecording()
|
|
||||||
|
void
|
||||||
|
DisallowUnhandledDivergeFromRecording()
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(Thread::CurrentIsMainThread());
|
MOZ_RELEASE_ASSERT(Thread::CurrentIsMainThread());
|
||||||
gUnhandledDivergeAllowed = false;
|
gUnhandledDivergeAllowed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MFBT_API void
|
|
||||||
RecordReplayInterface_SaveTemporaryCheckpoint()
|
|
||||||
{
|
|
||||||
NewCheckpoint(/* aTemporary = */ true);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // extern "C"
|
|
||||||
|
|
||||||
void
|
void
|
||||||
EnsureNotDivergedFromRecording()
|
EnsureNotDivergedFromRecording()
|
||||||
{
|
{
|
||||||
|
@ -335,18 +300,14 @@ PauseMainThreadAndInvokeCallback(const std::function<void()>& aCallback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
void
|
||||||
|
ResumeExecution()
|
||||||
MOZ_EXPORT void
|
|
||||||
RecordReplayInterface_ResumeExecution()
|
|
||||||
{
|
{
|
||||||
MonitorAutoLock lock(*gMainThreadCallbackMonitor);
|
MonitorAutoLock lock(*gMainThreadCallbackMonitor);
|
||||||
gMainThreadShouldPause = false;
|
gMainThreadShouldPause = false;
|
||||||
gMainThreadCallbackMonitor->Notify();
|
gMainThreadCallbackMonitor->Notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // extern "C"
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SetIsActiveChild(bool aActive)
|
SetIsActiveChild(bool aActive)
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,7 +57,7 @@ void
|
||||||
InitializeThreadSnapshots(size_t aNumThreads)
|
InitializeThreadSnapshots(size_t aNumThreads)
|
||||||
{
|
{
|
||||||
gThreadState = (ThreadState*) AllocateMemory(aNumThreads * sizeof(ThreadState),
|
gThreadState = (ThreadState*) AllocateMemory(aNumThreads * sizeof(ThreadState),
|
||||||
UntrackedMemoryKind::ThreadSnapshot);
|
MemoryKind::ThreadSnapshot);
|
||||||
|
|
||||||
jmp_buf buf;
|
jmp_buf buf;
|
||||||
if (setjmp(buf) == 0) {
|
if (setjmp(buf) == 0) {
|
||||||
|
@ -70,7 +70,7 @@ static void
|
||||||
ClearThreadState(ThreadState* aInfo)
|
ClearThreadState(ThreadState* aInfo)
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(aInfo->mShouldRestore);
|
MOZ_RELEASE_ASSERT(aInfo->mShouldRestore);
|
||||||
DeallocateMemory(aInfo->mStackContents, aInfo->mStackBytes, UntrackedMemoryKind::ThreadSnapshot);
|
DeallocateMemory(aInfo->mStackContents, aInfo->mStackBytes, MemoryKind::ThreadSnapshot);
|
||||||
aInfo->mShouldRestore = false;
|
aInfo->mShouldRestore = false;
|
||||||
aInfo->mStackContents = nullptr;
|
aInfo->mStackContents = nullptr;
|
||||||
aInfo->mStackBytes = 0;
|
aInfo->mStackBytes = 0;
|
||||||
|
@ -221,7 +221,7 @@ SaveThreadStack(SavedThreadStack& aStack, size_t aId)
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(stackBytes >= info.mStackTopBytes);
|
MOZ_RELEASE_ASSERT(stackBytes >= info.mStackTopBytes);
|
||||||
|
|
||||||
aStack.mStack = (uint8_t*) AllocateMemory(stackBytes, UntrackedMemoryKind::ThreadSnapshot);
|
aStack.mStack = (uint8_t*) AllocateMemory(stackBytes, MemoryKind::ThreadSnapshot);
|
||||||
aStack.mStackBytes = stackBytes;
|
aStack.mStackBytes = stackBytes;
|
||||||
|
|
||||||
MemoryMove(aStack.mStack, info.mStackTop, info.mStackTopBytes);
|
MemoryMove(aStack.mStack, info.mStackTop, info.mStackTopBytes);
|
||||||
|
@ -241,7 +241,7 @@ RestoreStackForLoadingByThread(const SavedThreadStack& aStack, size_t aId)
|
||||||
info.mStackBytes = aStack.mStackBytes;
|
info.mStackBytes = aStack.mStackBytes;
|
||||||
|
|
||||||
uint8_t* stackContents =
|
uint8_t* stackContents =
|
||||||
(uint8_t*) AllocateMemory(info.mStackBytes, UntrackedMemoryKind::ThreadSnapshot);
|
(uint8_t*) AllocateMemory(info.mStackBytes, MemoryKind::ThreadSnapshot);
|
||||||
MemoryMove(stackContents, aStack.mStack, aStack.mStackBytes);
|
MemoryMove(stackContents, aStack.mStack, aStack.mStackBytes);
|
||||||
info.mStackContents = stackContents;
|
info.mStackContents = stackContents;
|
||||||
info.mShouldRestore = true;
|
info.mShouldRestore = true;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define mozilla_recordreplay_ThreadSnapshot_h
|
#define mozilla_recordreplay_ThreadSnapshot_h
|
||||||
|
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
|
#include "ProcessRewind.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -70,7 +71,7 @@ struct SavedThreadStack
|
||||||
|
|
||||||
void ReleaseContents() {
|
void ReleaseContents() {
|
||||||
if (mStackBytes) {
|
if (mStackBytes) {
|
||||||
DeallocateMemory(mStack, mStackBytes, UntrackedMemoryKind::ThreadSnapshot);
|
DeallocateMemory(mStack, mStackBytes, MemoryKind::ThreadSnapshot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
|
|
||||||
#include "base/process.h"
|
#include "base/process.h"
|
||||||
|
|
||||||
#include "js/ReplayHooks.h"
|
|
||||||
#include "mozilla/gfx/Types.h"
|
#include "mozilla/gfx/Types.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
|
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
|
#include "JSControl.h"
|
||||||
#include "Monitor.h"
|
#include "Monitor.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -260,9 +260,9 @@ struct SetBreakpointMessage : public Message
|
||||||
|
|
||||||
// New position of the breakpoint. If this is invalid then the breakpoint is
|
// New position of the breakpoint. If this is invalid then the breakpoint is
|
||||||
// being cleared.
|
// being cleared.
|
||||||
JS::replay::ExecutionPosition mPosition;
|
js::BreakpointPosition mPosition;
|
||||||
|
|
||||||
SetBreakpointMessage(size_t aId, const JS::replay::ExecutionPosition& aPosition)
|
SetBreakpointMessage(size_t aId, const js::BreakpointPosition& aPosition)
|
||||||
: Message(MessageType::SetBreakpoint, sizeof(*this))
|
: Message(MessageType::SetBreakpoint, sizeof(*this))
|
||||||
, mId(aId)
|
, mId(aId)
|
||||||
, mPosition(aPosition)
|
, mPosition(aPosition)
|
||||||
|
@ -425,7 +425,7 @@ private:
|
||||||
Monitor mMonitor;
|
Monitor mMonitor;
|
||||||
|
|
||||||
// Buffer for message data received from the other side of the channel.
|
// Buffer for message data received from the other side of the channel.
|
||||||
InfallibleVector<char, 0, AllocPolicy<UntrackedMemoryKind::Generic>> mMessageBuffer;
|
InfallibleVector<char, 0, AllocPolicy<MemoryKind::Generic>> mMessageBuffer;
|
||||||
|
|
||||||
// The number of bytes of data already in the message buffer.
|
// The number of bytes of data already in the message buffer.
|
||||||
size_t mMessageBytes;
|
size_t mMessageBytes;
|
||||||
|
|
|
@ -133,9 +133,8 @@ ChildProcessInfo::IsPausedAtMatchingBreakpoint(const BreakpointFilter& aFilter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MOZ_RELEASE_ASSERT(lastSet &&
|
MOZ_RELEASE_ASSERT(lastSet && lastSet->mPosition.IsValid());
|
||||||
lastSet->mPosition.kind != JS::replay::ExecutionPosition::Invalid);
|
if (aFilter(lastSet->mPosition.mKind)) {
|
||||||
if (aFilter(lastSet->mPosition.kind)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,7 +308,7 @@ ChildProcessInfo::Recover(bool aPaused, Message* aPausedMessage, size_t aLastChe
|
||||||
for (Message* msg : mMessages) {
|
for (Message* msg : mMessages) {
|
||||||
if (msg->mType == MessageType::SetBreakpoint) {
|
if (msg->mType == MessageType::SetBreakpoint) {
|
||||||
SetBreakpointMessage* nmsg = static_cast<SetBreakpointMessage*>(msg);
|
SetBreakpointMessage* nmsg = static_cast<SetBreakpointMessage*>(msg);
|
||||||
SendMessageRaw(SetBreakpointMessage(nmsg->mId, JS::replay::ExecutionPosition()));
|
SendMessageRaw(SetBreakpointMessage(nmsg->mId, js::BreakpointPosition()));
|
||||||
}
|
}
|
||||||
free(msg);
|
free(msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -761,10 +761,10 @@ HasSavedCheckpointsInRange(ChildProcessInfo* aChild, size_t aStart, size_t aEnd)
|
||||||
// child to inspect its state. This excludes breakpoints set for things
|
// child to inspect its state. This excludes breakpoints set for things
|
||||||
// internal to the debugger.
|
// internal to the debugger.
|
||||||
static bool
|
static bool
|
||||||
IsUserBreakpoint(JS::replay::ExecutionPosition::Kind aKind)
|
IsUserBreakpoint(js::BreakpointPosition::Kind aKind)
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(aKind != JS::replay::ExecutionPosition::Invalid);
|
MOZ_RELEASE_ASSERT(aKind != js::BreakpointPosition::Invalid);
|
||||||
return aKind != JS::replay::ExecutionPosition::NewScript;
|
return aKind != js::BreakpointPosition::NewScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -829,9 +829,6 @@ MainThreadMessageLoop()
|
||||||
return gMainThreadMessageLoop;
|
return gMainThreadMessageLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize hooks used by the debugger.
|
|
||||||
static void InitDebuggerHooks();
|
|
||||||
|
|
||||||
// Contents of the prefs shmem block that is sent to the child on startup.
|
// Contents of the prefs shmem block that is sent to the child on startup.
|
||||||
static char* gShmemPrefs;
|
static char* gShmemPrefs;
|
||||||
static size_t gShmemPrefsLen;
|
static size_t gShmemPrefsLen;
|
||||||
|
@ -859,7 +856,6 @@ InitializeMiddleman(int aArgc, char* aArgv[], base::ProcessId aParentPid)
|
||||||
MOZ_RELEASE_ASSERT(gProcessKind == ProcessKind::MiddlemanRecording ||
|
MOZ_RELEASE_ASSERT(gProcessKind == ProcessKind::MiddlemanRecording ||
|
||||||
gProcessKind == ProcessKind::MiddlemanReplaying);
|
gProcessKind == ProcessKind::MiddlemanReplaying);
|
||||||
|
|
||||||
InitDebuggerHooks();
|
|
||||||
InitializeGraphicsMemory();
|
InitializeGraphicsMemory();
|
||||||
|
|
||||||
gMonitor = new Monitor();
|
gMonitor = new Monitor();
|
||||||
|
@ -882,19 +878,17 @@ InitializeMiddleman(int aArgc, char* aArgv[], base::ProcessId aParentPid)
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Buffer for receiving the next debugger response.
|
// Buffer for receiving the next debugger response.
|
||||||
static JS::replay::CharBuffer* gResponseBuffer;
|
static js::CharBuffer* gResponseBuffer;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
RecvDebuggerResponse(const DebuggerResponseMessage& aMsg)
|
RecvDebuggerResponse(const DebuggerResponseMessage& aMsg)
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(gResponseBuffer && gResponseBuffer->empty());
|
MOZ_RELEASE_ASSERT(gResponseBuffer && gResponseBuffer->empty());
|
||||||
if (!gResponseBuffer->append(aMsg.Buffer(), aMsg.BufferSize())) {
|
gResponseBuffer->append(aMsg.Buffer(), aMsg.BufferSize());
|
||||||
MOZ_CRASH("RecvDebuggerResponse");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
HookDebuggerRequest(const JS::replay::CharBuffer& aBuffer, JS::replay::CharBuffer* aResponse)
|
SendRequest(const js::CharBuffer& aBuffer, js::CharBuffer* aResponse)
|
||||||
{
|
{
|
||||||
MaybeCreateCheckpointInRecordingChild();
|
MaybeCreateCheckpointInRecordingChild();
|
||||||
gActiveChild->WaitUntilPaused();
|
gActiveChild->WaitUntilPaused();
|
||||||
|
@ -913,8 +907,8 @@ HookDebuggerRequest(const JS::replay::CharBuffer& aBuffer, JS::replay::CharBuffe
|
||||||
gResponseBuffer = nullptr;
|
gResponseBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
HookSetBreakpoint(size_t aId, const JS::replay::ExecutionPosition& aPosition)
|
SetBreakpoint(size_t aId, const js::BreakpointPosition& aPosition)
|
||||||
{
|
{
|
||||||
MaybeCreateCheckpointInRecordingChild();
|
MaybeCreateCheckpointInRecordingChild();
|
||||||
gActiveChild->WaitUntilPaused();
|
gActiveChild->WaitUntilPaused();
|
||||||
|
@ -938,8 +932,8 @@ static bool gChildExecuteBackward = false;
|
||||||
// main thread. This will continue execution in the preferred direction.
|
// main thread. This will continue execution in the preferred direction.
|
||||||
static bool gResumeForwardOrBackward = false;
|
static bool gResumeForwardOrBackward = false;
|
||||||
|
|
||||||
static void
|
void
|
||||||
HookResume(bool aForward)
|
Resume(bool aForward)
|
||||||
{
|
{
|
||||||
gActiveChild->WaitUntilPaused();
|
gActiveChild->WaitUntilPaused();
|
||||||
|
|
||||||
|
@ -1000,8 +994,8 @@ HookResume(bool aForward)
|
||||||
gActiveChild->SendMessage(ResumeMessage(aForward));
|
gActiveChild->SendMessage(ResumeMessage(aForward));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
HookPause()
|
Pause()
|
||||||
{
|
{
|
||||||
MaybeCreateCheckpointInRecordingChild();
|
MaybeCreateCheckpointInRecordingChild();
|
||||||
gActiveChild->WaitUntilPaused();
|
gActiveChild->WaitUntilPaused();
|
||||||
|
@ -1020,7 +1014,7 @@ ResumeForwardOrBackward()
|
||||||
MOZ_RELEASE_ASSERT(!gChildExecuteForward || !gChildExecuteBackward);
|
MOZ_RELEASE_ASSERT(!gChildExecuteForward || !gChildExecuteBackward);
|
||||||
|
|
||||||
if (gResumeForwardOrBackward && (gChildExecuteForward || gChildExecuteBackward)) {
|
if (gResumeForwardOrBackward && (gChildExecuteForward || gChildExecuteBackward)) {
|
||||||
HookResume(gChildExecuteForward);
|
Resume(gChildExecuteForward);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,7 +1028,7 @@ RecvHitCheckpoint(const HitCheckpointMessage& aMsg)
|
||||||
// the process to pause. Immediately resume if the main thread is blocked.
|
// the process to pause. Immediately resume if the main thread is blocked.
|
||||||
if (MainThreadIsWaitingForIPDLReply()) {
|
if (MainThreadIsWaitingForIPDLReply()) {
|
||||||
MOZ_RELEASE_ASSERT(gChildExecuteForward);
|
MOZ_RELEASE_ASSERT(gChildExecuteForward);
|
||||||
HookResume(true);
|
Resume(true);
|
||||||
} else if (!gResumeForwardOrBackward) {
|
} else if (!gResumeForwardOrBackward) {
|
||||||
gResumeForwardOrBackward = true;
|
gResumeForwardOrBackward = true;
|
||||||
gMainThreadMessageLoop->PostTask(NewRunnableFunction("ResumeForwardOrBackward",
|
gMainThreadMessageLoop->PostTask(NewRunnableFunction("ResumeForwardOrBackward",
|
||||||
|
@ -1054,7 +1048,7 @@ HitBreakpoint(uint32_t* aBreakpoints, size_t aNumBreakpoints)
|
||||||
// backward travel.
|
// backward travel.
|
||||||
for (size_t i = 0; i < aNumBreakpoints && gResumeForwardOrBackward; i++) {
|
for (size_t i = 0; i < aNumBreakpoints && gResumeForwardOrBackward; i++) {
|
||||||
AutoSafeJSContext cx;
|
AutoSafeJSContext cx;
|
||||||
if (!JS::replay::hooks.hitBreakpointMiddleman(cx, aBreakpoints[i])) {
|
if (!js::HitBreakpoint(cx, aBreakpoints[i])) {
|
||||||
Print("Warning: hitBreakpoint hook threw an exception.\n");
|
Print("Warning: hitBreakpoint hook threw an exception.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1077,16 +1071,6 @@ RecvHitBreakpoint(const HitBreakpointMessage& aMsg)
|
||||||
breakpoints, aMsg.NumBreakpoints()));
|
breakpoints, aMsg.NumBreakpoints()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
InitDebuggerHooks()
|
|
||||||
{
|
|
||||||
JS::replay::hooks.debugRequestMiddleman = HookDebuggerRequest;
|
|
||||||
JS::replay::hooks.setBreakpointMiddleman = HookSetBreakpoint;
|
|
||||||
JS::replay::hooks.resumeMiddleman = HookResume;
|
|
||||||
JS::replay::hooks.pauseMiddleman = HookPause;
|
|
||||||
JS::replay::hooks.canRewindMiddleman = CanRewind;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace parent
|
} // namespace parent
|
||||||
} // namespace recordreplay
|
} // namespace recordreplay
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
Загрузка…
Ссылка в новой задаче