blob: 8c8ae1c52592d3bdee1ebfcc3513f56bb68ba0f6 [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
#if ENABLE_TTD
namespace TTD
{
namespace NSLogEvents
{
//true if this is a root call function
bool IsJsRTActionRootCall(const EventLogEntry* evt);
//We have a number of loops where we look for a snapshot or root with a given time value -- this encapsulates the access logic
int64 AccessTimeInRootCallOrSnapshot(const EventLogEntry* evt, bool& isSnap, bool& isRoot, bool& hasRtrSnap);
bool TryGetTimeFromRootCallOrSnapshot(const EventLogEntry* evt, int64& res);
int64 GetTimeFromRootCallOrSnapshot(const EventLogEntry* evt);
//Handle the replay of the result of an action for the the given action type and tag
template <typename T, EventKind tag>
void JsRTActionHandleResultForReplay(ThreadContextTTD* executeContext, const EventLogEntry* evt, Js::Var result)
{
TTDVar origResult = GetInlineEventDataAs<T, tag>(evt)->Result;
PassVarToHostInReplay(executeContext, origResult, result);
}
//////////////////
//A generic struct for actions that only need a result value
struct JsRTResultOnlyAction
{
TTDVar Result;
};
template <EventKind tag>
void JsRTResultOnlyAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
{
const JsRTResultOnlyAction* vAction = GetInlineEventDataAs<JsRTResultOnlyAction, tag>(evt);
writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
NSSnapValues::EmitTTDVar(vAction->Result, writer, NSTokens::Separator::NoSeparator);
}
template <EventKind tag>
void JsRTResultOnlyAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
{
JsRTResultOnlyAction* vAction = GetInlineEventDataAs<JsRTResultOnlyAction, tag>(evt);
reader->ReadKey(NSTokens::Key::argRetVal, true);
vAction->Result = NSSnapValues::ParseTTDVar(false, reader);
}
//A generic struct for actions that only need a single integral value
struct JsRTIntegralArgumentAction
{
TTDVar Result;
int64 Scalar;
};
template <EventKind tag>
void JsRTIntegralArgumentAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
{
const JsRTIntegralArgumentAction* vAction = GetInlineEventDataAs<JsRTIntegralArgumentAction, tag>(evt);
writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
NSSnapValues::EmitTTDVar(vAction->Result, writer, NSTokens::Separator::NoSeparator);
writer->WriteInt64(NSTokens::Key::i64Val, vAction->Scalar, NSTokens::Separator::CommaSeparator);
}
template <EventKind tag>
void JsRTIntegralArgumentAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
{
JsRTIntegralArgumentAction* vAction = GetInlineEventDataAs<JsRTIntegralArgumentAction, tag>(evt);
reader->ReadKey(NSTokens::Key::argRetVal, true);
vAction->Result = NSSnapValues::ParseTTDVar(false, reader);
vAction->Scalar = reader->ReadInt64(NSTokens::Key::i64Val, true);
}
//A generic struct for actions that only need variables
template <size_t count>
struct JsRTVarsArgumentAction_InternalUse
{
TTDVar Result;
TTDVar VarArray[count];
};
template <EventKind tag, size_t count>
void JsRTVarsArgumentAction_InternalUse_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
{
const JsRTVarsArgumentAction_InternalUse<count>* vAction = GetInlineEventDataAs<JsRTVarsArgumentAction_InternalUse<count>, tag>(evt);
writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
NSSnapValues::EmitTTDVar(vAction->Result, writer, NSTokens::Separator::NoSeparator);
if(count == 1)
{
NSSnapValues::EmitTTDVar(vAction->VarArray[0], writer, NSTokens::Separator::CommaSeparator);
}
else
{
writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
for(size_t i = 0; i < count; ++i)
{
NSSnapValues::EmitTTDVar(vAction->VarArray[i], writer, i != 0 ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator);
}
writer->WriteSequenceEnd();
}
}
template <EventKind tag, size_t count>
void JsRTVarsArgumentAction_InternalUse_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
{
JsRTVarsArgumentAction_InternalUse<count>* vAction = GetInlineEventDataAs<JsRTVarsArgumentAction_InternalUse<count>, tag>(evt);
reader->ReadKey(NSTokens::Key::argRetVal, true);
vAction->Result = NSSnapValues::ParseTTDVar(false, reader);
if(count == 1)
{
vAction->VarArray[0] = NSSnapValues::ParseTTDVar(true, reader);
}
else
{
reader->ReadSequenceStart_WDefaultKey(true);
for(size_t i = 0; i < count; ++i)
{
vAction->VarArray[i] = NSSnapValues::ParseTTDVar(i != 0, reader);
}
reader->ReadSequenceEnd();
}
}
template <size_t count, size_t index>
TTDVar GetVarItem_InternalUse(const JsRTVarsArgumentAction_InternalUse<count>* argAction)
{
static_assert(index < count, "Index out of bounds in JsRTVarAndIntegralArgumentsAction.");
return argAction->VarArray[index];
}
template <size_t count> TTDVar GetVarItem_0(const JsRTVarsArgumentAction_InternalUse<count>* argAction) { return GetVarItem_InternalUse<count, 0>(argAction); }
template <size_t count> TTDVar GetVarItem_1(const JsRTVarsArgumentAction_InternalUse<count>* argAction) { return GetVarItem_InternalUse<count, 1>(argAction); }
template <size_t count> TTDVar GetVarItem_2(const JsRTVarsArgumentAction_InternalUse<count>* argAction) { return GetVarItem_InternalUse<count, 2>(argAction); }
template <size_t count, size_t index>
void SetVarItem_InternalUse(JsRTVarsArgumentAction_InternalUse<count>* argAction, TTDVar value)
{
static_assert(index < count, "Index out of bounds in JsRTVarAndIntegralArgumentsAction.");
argAction->VarArray[index] = value;
}
template <size_t count> void SetVarItem_0(JsRTVarsArgumentAction_InternalUse<count>* argAction, TTDVar value) { return SetVarItem_InternalUse<count, 0>(argAction, value); }
template <size_t count> void SetVarItem_1(JsRTVarsArgumentAction_InternalUse<count>* argAction, TTDVar value) { return SetVarItem_InternalUse<count, 1>(argAction, value); }
template <size_t count> void SetVarItem_2(JsRTVarsArgumentAction_InternalUse<count>* argAction, TTDVar value) { return SetVarItem_InternalUse<count, 2>(argAction, value); }
typedef JsRTVarsArgumentAction_InternalUse<1> JsRTSingleVarArgumentAction;
template <EventKind tag> void JsRTSingleVarArgumentAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext) { JsRTVarsArgumentAction_InternalUse_Emit<tag, 1>(evt, writer, threadContext); }
template <EventKind tag> void JsRTSingleVarArgumentAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc) { JsRTVarsArgumentAction_InternalUse_Parse<tag, 1>(evt, threadContext, reader, alloc); }
typedef JsRTVarsArgumentAction_InternalUse<2> JsRTDoubleVarArgumentAction;
template <EventKind tag> void JsRTDoubleVarArgumentAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext) { JsRTVarsArgumentAction_InternalUse_Emit<tag, 2>(evt, writer, threadContext); }
template <EventKind tag> void JsRTDoubleVarArgumentAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc) { JsRTVarsArgumentAction_InternalUse_Parse<tag, 2>(evt, threadContext, reader, alloc); }
typedef JsRTVarsArgumentAction_InternalUse<3> JsRTTrippleVarArgumentAction;
template <EventKind tag> void JsRTTrippleVarArgumentAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext) { JsRTVarsArgumentAction_InternalUse_Emit<tag, 3>(evt, writer, threadContext); }
template <EventKind tag> void JsRTTrippleVarArgumentAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc) { JsRTVarsArgumentAction_InternalUse_Parse<tag, 3>(evt, threadContext, reader, alloc); }
//A generic struct for actions that need variables and scalar data
template <size_t vcount, size_t icount>
struct JsRTVarAndIntegralArgumentsAction_InternalUse
{
TTDVar Result;
TTDVar VarArray[vcount];
int64 ScalarArray[icount];
};
template <EventKind tag, size_t vcount, size_t icount>
void JsRTVarAndIntegralArgumentsAction_InternalUse_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
{
const JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* vAction = GetInlineEventDataAs<JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>, tag>(evt);
writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
NSSnapValues::EmitTTDVar(vAction->Result, writer, NSTokens::Separator::NoSeparator);
writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
for(size_t i = 0; i < vcount; ++i)
{
NSSnapValues::EmitTTDVar(vAction->VarArray[i], writer, i != 0 ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator);
}
for(size_t i = 0; i < icount; ++i)
{
writer->WriteNakedInt64(vAction->ScalarArray[i], vcount + i != 0 ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator);
}
writer->WriteSequenceEnd();
}
template <EventKind tag, size_t vcount, size_t icount>
void JsRTVarAndIntegralArgumentsAction_InternalUse_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
{
JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* vAction = GetInlineEventDataAs<JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>, tag>(evt);
reader->ReadKey(NSTokens::Key::argRetVal, true);
vAction->Result = NSSnapValues::ParseTTDVar(false, reader);
reader->ReadSequenceStart_WDefaultKey(true);
for(size_t i = 0; i < vcount; ++i)
{
vAction->VarArray[i] = NSSnapValues::ParseTTDVar(i != 0, reader);
}
for(size_t i = 0; i < icount; ++i)
{
vAction->ScalarArray[i] = reader->ReadNakedInt64(vcount + i != 0);
}
reader->ReadSequenceEnd();
}
template <size_t vcount, size_t icount, size_t index>
TTDVar GetVarItem_InternalUse(const JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction)
{
static_assert(index < vcount, "Index out of bounds in JsRTVarAndIntegralArgumentsAction.");
return argAction->VarArray[index];
}
template <size_t vcount, size_t icount> TTDVar GetVarItem_0(const JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction) { return GetVarItem_InternalUse<vcount, icount, 0>(argAction); }
template <size_t vcount, size_t icount> TTDVar GetVarItem_1(const JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction) { return GetVarItem_InternalUse<vcount, icount, 1>(argAction); }
template <size_t vcount, size_t icount, size_t index>
void SetVarItem_InternalUse(JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction, TTDVar value)
{
static_assert(index < vcount, "Index out of bounds in JsRTVarAndIntegralArgumentsAction.");
argAction->VarArray[index] = value;
}
template <size_t vcount, size_t icount> void SetVarItem_0(JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction, TTDVar value) { return SetVarItem_InternalUse<vcount, icount, 0>(argAction, value); }
template <size_t vcount, size_t icount> void SetVarItem_1(JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction, TTDVar value) { return SetVarItem_InternalUse<vcount, icount, 1>(argAction, value); }
template <size_t vcount, size_t icount, size_t index>
int64 GetScalarItem_InternalUse(const JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction)
{
static_assert(index < icount, "Index out of bounds in JsRTVarAndIntegralArgumentsAction.");
return argAction->ScalarArray[index];
}
template <size_t vcount, size_t icount> int64 GetScalarItem_0(const JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction) { return GetScalarItem_InternalUse<vcount, icount, 0>(argAction); }
template <size_t vcount, size_t icount> int64 GetScalarItem_1(const JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction) { return GetScalarItem_InternalUse<vcount, icount, 1>(argAction); }
template <size_t vcount, size_t icount, size_t index>
void SetScalarItem_InternalUse(JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction, int64 value)
{
static_assert(index < icount, "Index out of bounds in JsRTVarAndIntegralArgumentsAction.");
argAction->ScalarArray[index] = value;
}
template <size_t vcount, size_t icount> void SetScalarItem_0(JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction, int64 value) { return SetScalarItem_InternalUse<vcount, icount, 0>(argAction, value); }
template <size_t vcount, size_t icount> void SetScalarItem_1(JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction, int64 value) { return SetScalarItem_InternalUse<vcount, icount, 1>(argAction, value); }
template <size_t vcount, size_t icount>
Js::PropertyId GetPropertyIdItem(const JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction)
{
static_assert(0 < icount, "Index out of bounds in JsRTVarAndIntegralArgumentsAction.");
return (Js::PropertyId)argAction->ScalarArray[0];
}
template <size_t vcount, size_t icount>
void SetPropertyIdItem(JsRTVarAndIntegralArgumentsAction_InternalUse<vcount, icount>* argAction, Js::PropertyId value)
{
AssertMsg(0 < icount, "Index out of bounds in JsRTVarAndIntegralArgumentsAction.");
argAction->ScalarArray[0] = (int64)value;
}
typedef JsRTVarAndIntegralArgumentsAction_InternalUse<1, 1> JsRTSingleVarScalarArgumentAction;
template <EventKind tag> void JsRTSingleVarScalarArgumentAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext) { JsRTVarAndIntegralArgumentsAction_InternalUse_Emit<tag, 1, 1>(evt, writer, threadContext); }
template <EventKind tag> void JsRTSingleVarScalarArgumentAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc) { JsRTVarAndIntegralArgumentsAction_InternalUse_Parse<tag, 1, 1>(evt, threadContext, reader, alloc); }
typedef JsRTVarAndIntegralArgumentsAction_InternalUse<2, 1> JsRTDoubleVarSingleScalarArgumentAction;
template <EventKind tag> void JsRTDoubleVarSingleScalarArgumentAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext) { JsRTVarAndIntegralArgumentsAction_InternalUse_Emit<tag, 2, 1>(evt, writer, threadContext); }
template <EventKind tag> void JsRTDoubleVarSingleScalarArgumentAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc) { JsRTVarAndIntegralArgumentsAction_InternalUse_Parse<tag, 2, 1>(evt, threadContext, reader, alloc); }
typedef JsRTVarAndIntegralArgumentsAction_InternalUse<1, 2> JsRTSingleVarDoubleScalarArgumentAction;
template <EventKind tag> void JsRTSingleVarDoubleScalarArgumentAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext) { JsRTVarAndIntegralArgumentsAction_InternalUse_Emit<tag, 1, 2>(evt, writer, threadContext); }
template <EventKind tag> void JsRTSingleVarDoubleScalarArgumentAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc) { JsRTVarAndIntegralArgumentsAction_InternalUse_Parse<tag, 1, 2>(evt, threadContext, reader, alloc); }
typedef JsRTVarAndIntegralArgumentsAction_InternalUse<2, 2> JsRTDoubleVarDoubleScalarArgumentAction;
template <EventKind tag> void JsRTDoubleVarDoubleScalarArgumentAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext) { JsRTVarAndIntegralArgumentsAction_InternalUse_Emit<tag, 2, 2>(evt, writer, threadContext); }
template <EventKind tag> void JsRTDoubleVarDoubleScalarArgumentAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc) { JsRTVarAndIntegralArgumentsAction_InternalUse_Parse<tag, 2, 2>(evt, threadContext, reader, alloc); }
//A struct for actions that are definied by their tag and a double
struct JsRTDoubleArgumentAction
{
TTDVar Result;
double DoubleValue;
};
template <EventKind tag>
void JsRTDoubleArgumentAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
{
const JsRTDoubleArgumentAction* dblAction = GetInlineEventDataAs<JsRTDoubleArgumentAction, tag>(evt);
writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
NSSnapValues::EmitTTDVar(dblAction->Result, writer, NSTokens::Separator::NoSeparator);
writer->WriteDouble(NSTokens::Key::doubleVal, dblAction->DoubleValue, NSTokens::Separator::CommaSeparator);
}
template <EventKind tag>
void JsRTDoubleArgumentAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
{
JsRTDoubleArgumentAction* dblAction = GetInlineEventDataAs<JsRTDoubleArgumentAction, tag>(evt);
reader->ReadKey(NSTokens::Key::argRetVal, true);
dblAction->Result = NSSnapValues::ParseTTDVar(false, reader);
dblAction->DoubleValue = reader->ReadDouble(NSTokens::Key::doubleVal, true);
}
//A struct for actions that are definied by their tag and a single string
struct JsRTStringArgumentAction
{
TTDVar Result;
TTString StringValue;
};
template <EventKind tag>
void JsRTStringArgumentAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
{
JsRTStringArgumentAction* strAction = GetInlineEventDataAs<JsRTStringArgumentAction, tag>(evt);
alloc.UnlinkString(strAction->StringValue);
}
template <EventKind tag>
void JsRTStringArgumentAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
{
const JsRTStringArgumentAction* strAction = GetInlineEventDataAs<JsRTStringArgumentAction, tag>(evt);
writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
NSSnapValues::EmitTTDVar(strAction->Result, writer, NSTokens::Separator::NoSeparator);
writer->WriteString(NSTokens::Key::stringVal, strAction->StringValue, NSTokens::Separator::CommaSeparator);
}
template <EventKind tag>
void JsRTStringArgumentAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
{
JsRTStringArgumentAction* strAction = GetInlineEventDataAs<JsRTStringArgumentAction, tag>(evt);
reader->ReadKey(NSTokens::Key::argRetVal, true);
strAction->Result = NSSnapValues::ParseTTDVar(false, reader);
reader->ReadString(NSTokens::Key::stringVal, alloc, strAction->StringValue, true);
}
//A struct for actions that are definied by a raw byte* + length
struct JsRTByteBufferAction
{
TTDVar Result;
byte* Buffer;
uint32 Length;
};
template <EventKind tag>
void JsRTByteBufferAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
{
JsRTByteBufferAction* bufferAction = GetInlineEventDataAs<JsRTByteBufferAction, tag>(evt);
if(bufferAction->Buffer != nullptr)
{
alloc.UnlinkAllocation(bufferAction->Buffer);
}
}
template <EventKind tag>
void JsRTByteBufferAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
{
const JsRTByteBufferAction* bufferAction = GetInlineEventDataAs<JsRTByteBufferAction, tag>(evt);
writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
NSSnapValues::EmitTTDVar(bufferAction->Result, writer, NSTokens::Separator::NoSeparator);
bool badValue = (bufferAction->Buffer == nullptr && bufferAction->Length > 0);
writer->WriteBool(NSTokens::Key::boolVal, badValue, NSTokens::Separator::CommaSeparator);
writer->WriteLengthValue(bufferAction->Length, NSTokens::Separator::CommaSeparator);
writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
if(!badValue)
{
for(uint32 i = 0; i < bufferAction->Length; ++i)
{
writer->WriteNakedByte(bufferAction->Buffer[i], i != 0 ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator);
}
}
writer->WriteSequenceEnd();
}
template <EventKind tag>
void JsRTByteBufferAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
{
JsRTByteBufferAction* bufferAction = GetInlineEventDataAs<JsRTByteBufferAction, tag>(evt);
reader->ReadKey(NSTokens::Key::argRetVal, true);
bufferAction->Result = NSSnapValues::ParseTTDVar(false, reader);
bool badValue = reader->ReadBool(NSTokens::Key::boolVal, true);
bufferAction->Length = reader->ReadLengthValue(true);
bufferAction->Buffer = nullptr;
reader->ReadSequenceStart_WDefaultKey(true);
if(!badValue)
{
bufferAction->Buffer = (bufferAction->Length != 0) ? alloc.SlabAllocateArray<byte>(bufferAction->Length) : nullptr;
for(uint32 i = 0; i < bufferAction->Length; ++i)
{
bufferAction->Buffer[i] = reader->ReadNakedByte(i != 0);
}
reader->ReadSequenceEnd();
}
}
//////////////////
//A class for constructor calls
struct JsRTCreateScriptContextAction_KnownObjects
{
TTD_LOG_PTR_ID UndefinedObject;
TTD_LOG_PTR_ID NullObject;
TTD_LOG_PTR_ID TrueObject;
TTD_LOG_PTR_ID FalseObject;
};
struct JsRTCreateScriptContextAction
{
TTD_LOG_PTR_ID GlobalObject;
JsRTCreateScriptContextAction_KnownObjects* KnownObjects;
};
void CreateScriptContext_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void CreateScriptContext_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc);
void CreateScriptContext_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
void CreateScriptContext_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
void SetActiveScriptContext_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
#if !INT32VAR
void CreateInt_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
#endif
void CreateNumber_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void CreateBoolean_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void CreateString_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void CreateSymbol_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void Execute_CreateErrorHelper(const JsRTSingleVarArgumentAction* errorData, ThreadContextTTD* executeContext, Js::ScriptContext* ctx, EventKind eventKind, Js::Var* res);
template<EventKind errorKind>
void CreateError_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
{
const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, errorKind>(evt);
Js::Var res = nullptr;
Execute_CreateErrorHelper(action, executeContext, executeContext->GetActiveScriptContext(), errorKind, &res);
if(res != nullptr)
{
JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, errorKind>(executeContext, evt, res);
}
}
void VarConvertToNumber_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void VarConvertToBoolean_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void VarConvertToString_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void VarConvertToObject_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void AddRootRef_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void AddWeakRootRef_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void AllocateObject_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void AllocateExternalObject_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void AllocateArrayAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void AllocateArrayBufferAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void AllocateExternalArrayBufferAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void AllocateFunctionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void HostProcessExitAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void GetAndClearExceptionWithMetadataAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void GetAndClearExceptionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void SetExceptionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void HasPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void InstanceOfAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void EqualsAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void GetPropertyIdFromSymbolAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void GetPrototypeAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void GetPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void GetIndexAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void GetOwnPropertyInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void GetOwnPropertyNamesInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void GetOwnPropertySymbolsInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void DefinePropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void DeletePropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void SetPrototypeAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void SetPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void SetIndexAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void GetTypedArrayInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
//////////////////
//A generic struct for the naked buffer copy action
struct JsRTRawBufferCopyAction
{
TTDVar Dst;
TTDVar Src;
uint32 DstIndx;
uint32 SrcIndx;
uint32 Count;
};
void JsRTRawBufferCopyAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
void JsRTRawBufferCopyAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
//A generic struct for the naked buffer modify action (with buffer data)
struct JsRTRawBufferModifyAction
{
TTDVar Trgt;
byte* Data;
uint32 Index;
uint32 Length;
};
template <EventKind tag>
void JsRTRawBufferModifyAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
{
JsRTRawBufferModifyAction* bufferAction = GetInlineEventDataAs<JsRTRawBufferModifyAction, tag>(evt);
if(bufferAction->Data != nullptr)
{
alloc.UnlinkAllocation(bufferAction->Data);
}
}
template <EventKind tag>
void JsRTRawBufferModifyAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
{
const JsRTRawBufferModifyAction* bufferAction = GetInlineEventDataAs<JsRTRawBufferModifyAction, tag>(evt);
writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
NSSnapValues::EmitTTDVar(bufferAction->Trgt, writer, NSTokens::Separator::NoSeparator);
writer->WriteUInt32(NSTokens::Key::index, bufferAction->Index, NSTokens::Separator::CommaSeparator);
writer->WriteLengthValue(bufferAction->Length, NSTokens::Separator::CommaSeparator);
writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
for(uint32 i = 0; i < bufferAction->Length; ++i)
{
writer->WriteNakedByte(bufferAction->Data[i], i != 0 ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator);
}
writer->WriteSequenceEnd();
}
template <EventKind tag>
void JsRTRawBufferModifyAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
{
JsRTRawBufferModifyAction* bufferAction = GetInlineEventDataAs<JsRTRawBufferModifyAction, tag>(evt);
reader->ReadKey(NSTokens::Key::argRetVal, true);
bufferAction->Trgt = NSSnapValues::ParseTTDVar(false, reader);
bufferAction->Index = reader->ReadUInt32(NSTokens::Key::index, true);
bufferAction->Length = reader->ReadUInt32(NSTokens::Key::count, true);
bufferAction->Data = (bufferAction->Length != 0) ? alloc.SlabAllocateArray<byte>(bufferAction->Length) : nullptr;
reader->ReadSequenceStart_WDefaultKey(true);
for(uint32 i = 0; i < bufferAction->Length; ++i)
{
bufferAction->Data[i] = reader->ReadNakedByte(i != 0);
}
reader->ReadSequenceEnd();
}
void RawBufferCopySync_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void RawBufferModifySync_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void RawBufferAsyncModificationRegister_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void RawBufferAsyncModifyComplete_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
//////////////////
//A class for constructor calls
struct JsRTConstructCallAction
{
TTDVar Result;
//The arguments info (constructor function is always args[0])
uint32 ArgCount;
TTDVar* ArgArray;
//A buffer we can use for the actual invocation
Js::Var* ExecArgs;
};
void JsRTConstructCallAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void JsRTConstructCallAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc);
void JsRTConstructCallAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
void JsRTConstructCallAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
//A struct for calls to script parse
struct JsRTCodeParseAction
{
TTDVar Result;
//The body counter id associated with this load
uint32 BodyCtrId;
//Is the code utf8
bool IsUtf8;
//The actual source code and the length in bytes
byte* SourceCode;
uint32 SourceByteLength;
//The URI the souce code was loaded from and the source context id
TTString SourceUri;
uint64 SourceContextId;
//The flags for loading this script
LoadScriptFlag LoadFlag;
};
void JsRTCodeParseAction_SetBodyCtrId(EventLogEntry* parseEvent, uint32 bodyCtrId);
void JsRTCodeParseAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void JsRTCodeParseAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc);
void JsRTCodeParseAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
void JsRTCodeParseAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
//A struct for the replay-debugger info associated with a JsRTCallFunctionAction
struct JsRTCallFunctionAction_ReplayAdditionalInfo
{
//ready-to-run snapshot information -- null if not set and if we want to unload it we just throw it away
SnapShot* RtRSnap;
//A buffer we can use for the actual invocation
Js::Var* ExecArgs;
//Info on the last executed statement in this call
TTDebuggerSourceLocation LastExecutedLocation;
};
//A struct for calls to that execute existing functions
struct JsRTCallFunctionAction
{
TTDVar Result;
//The re-entry depth we are at when this happens
int32 CallbackDepth;
//the number of arguments and the argument array -- function is always argument[0]
uint32 ArgCount;
TTDVar* ArgArray;
//The actual event time associated with this call (is >= the TopLevelCallbackEventTime)
int64 CallEventTime;
//The event time that corresponds to the top-level event time around this call
int64 TopLevelCallbackEventTime;
//The additional info assocated with this action that we use in replay/debug but doesn't matter for record
JsRTCallFunctionAction_ReplayAdditionalInfo* AdditionalReplayInfo;
#if ENABLE_TTD_INTERNAL_DIAGNOSTICS
//The last event time that is nested in this call
int64 LastNestedEvent;
//The name of the function
TTString FunctionName;
#endif
};
#if ENABLE_TTD_INTERNAL_DIAGNOSTICS
int64 JsRTCallFunctionAction_GetLastNestedEventTime(const EventLogEntry* evt);
void JsRTCallFunctionAction_ProcessDiagInfoPre(EventLogEntry* evt, Js::Var funcVar, UnlinkableSlabAllocator& alloc);
void JsRTCallFunctionAction_ProcessDiagInfoPost(EventLogEntry* evt, int64 lastNestedEvent);
#endif
void JsRTCallFunctionAction_ProcessArgs(EventLogEntry* evt, int32 rootDepth, int64 callEventTime, Js::Var funcVar, uint32 argc, Js::Var* argv, int64 topLevelCallbackEventTime, UnlinkableSlabAllocator& alloc);
void JsRTCallFunctionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void JsRTCallFunctionAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc);
void JsRTCallFunctionAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
void JsRTCallFunctionAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
//Unload the snapshot
void JsRTCallFunctionAction_UnloadSnapshot(EventLogEntry* evt);
//Set the last executed statement and frame (in debugging mode -- nops for replay mode)
void JsRTCallFunctionAction_SetLastExecutedStatementAndFrameInfo(EventLogEntry* evt, const TTDebuggerSourceLocation& lastSourceLocation);
bool JsRTCallFunctionAction_GetLastExecutedStatementAndFrameInfoForDebugger(const EventLogEntry* evt, TTDebuggerSourceLocation& lastSourceInfo);
}
}
#endif