blob: 590c6e7c0605ca61859638b2443b2aac14960caf [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "Backend.h"
JITTimeWorkItem::JITTimeWorkItem(CodeGenWorkItemIDL * workItemData) :
m_workItemData(workItemData),
m_jitBody(workItemData->jitData->bodyData),
m_fullStatementList(nullptr)
{
}
CodeGenWorkItemType
JITTimeWorkItem::Type() const
{
return static_cast<CodeGenWorkItemType>(m_workItemData->type);
}
ExecutionMode
JITTimeWorkItem::GetJitMode() const
{
return static_cast<ExecutionMode>(m_workItemData->jitMode);
}
// loop number if IsLoopBody, otherwise Js::LoopHeader::NoLoop
uint
JITTimeWorkItem::GetLoopNumber() const
{
Assert(IsLoopBody() || m_workItemData->loopNumber == Js::LoopHeader::NoLoop);
return m_workItemData->loopNumber;
}
bool
JITTimeWorkItem::IsLoopBody() const
{
return Type() == JsLoopBodyWorkItemType;
}
bool
JITTimeWorkItem::IsJitInDebugMode() const
{
// TODO (michhol): flags?
return Js::Configuration::Global.EnableJitInDebugMode()
&& m_workItemData->isJitInDebugMode;
}
intptr_t
JITTimeWorkItem::GetCallsCountAddress() const
{
Assert(Type() == JsFunctionType);
return m_workItemData->jitData->callsCountAddress;
}
intptr_t
JITTimeWorkItem::GetJittedLoopIterationsSinceLastBailoutAddr() const
{
Assert(IsLoopBody());
Assert(m_workItemData->jittedLoopIterationsSinceLastBailoutAddr != 0);
return m_workItemData->jittedLoopIterationsSinceLastBailoutAddr;
}
const JITLoopHeaderIDL *
JITTimeWorkItem::GetLoopHeader() const
{
return m_jitBody.GetLoopHeaderData(GetLoopNumber());
}
intptr_t
JITTimeWorkItem::GetLoopHeaderAddr() const
{
return m_jitBody.GetLoopHeaderAddr(GetLoopNumber());
}
void
JITTimeWorkItem::InitializeReader(
Js::ByteCodeReader * reader,
Js::StatementReader<Js::FunctionBody::ArenaStatementMapList> * statementReader, ArenaAllocator* alloc)
{
uint startOffset = IsLoopBody() ? GetLoopHeader()->startOffset : 0;
if (IsJitInDebugMode())
{
// TODO: OOP JIT, directly use the array rather than making a list
m_fullStatementList = Js::FunctionBody::ArenaStatementMapList::New(alloc);
CompileAssert(sizeof(StatementMapIDL) == sizeof(Js::FunctionBody::StatementMap));
StatementMapIDL * fullArr = m_jitBody.GetFullStatementMap();
for (uint i = 0; i < m_jitBody.GetFullStatementMapCount(); ++i)
{
m_fullStatementList->Add((Js::FunctionBody::StatementMap*)&fullArr[i]);
}
}
#if DBG
reader->Create(m_jitBody.GetByteCodeBuffer(), startOffset, m_jitBody.GetByteCodeLength());
if (!JITManager::GetJITManager()->IsOOPJITEnabled())
{
Js::FunctionBody::StatementMapList * runtimeMap = ((Js::FunctionBody*)m_jitBody.GetAddr())->GetStatementMaps();
Assert(!m_fullStatementList || ((int)m_jitBody.GetFullStatementMapCount() == runtimeMap->Count() && runtimeMap->Count() >= 0));
for (uint i = 0; i < m_jitBody.GetFullStatementMapCount(); ++i)
{
Assert(runtimeMap->Item(i)->byteCodeSpan.begin == m_fullStatementList->Item(i)->byteCodeSpan.begin);
Assert(runtimeMap->Item(i)->byteCodeSpan.end == m_fullStatementList->Item(i)->byteCodeSpan.end);
Assert(runtimeMap->Item(i)->sourceSpan.begin == m_fullStatementList->Item(i)->sourceSpan.begin);
Assert(runtimeMap->Item(i)->sourceSpan.end == m_fullStatementList->Item(i)->sourceSpan.end);
Assert(runtimeMap->Item(i)->isSubexpression == m_fullStatementList->Item(i)->isSubexpression);
}
}
#else
reader->Create(m_jitBody.GetByteCodeBuffer(), startOffset);
#endif
bool hasSpanSequenceMap = m_jitBody.InitializeStatementMap(&m_statementMap, alloc);
Js::SmallSpanSequence * spanSeq = hasSpanSequenceMap ? &m_statementMap : nullptr;
statementReader->Create(m_jitBody.GetByteCodeBuffer(), startOffset, spanSeq, m_fullStatementList);
}
JITTimeFunctionBody *
JITTimeWorkItem::GetJITFunctionBody()
{
return &m_jitBody;
}
uint16
JITTimeWorkItem::GetProfiledIterations() const
{
return m_workItemData->profiledIterations;
}
CodeGenWorkItemIDL *
JITTimeWorkItem::GetWorkItemData()
{
return m_workItemData;
}
JITTimePolymorphicInlineCacheInfo *
JITTimeWorkItem::GetPolymorphicInlineCacheInfo()
{
return (JITTimePolymorphicInlineCacheInfo *)m_workItemData->selfInfo;
}
JITTimePolymorphicInlineCacheInfo *
JITTimeWorkItem::GetInlineePolymorphicInlineCacheInfo(intptr_t funcBodyAddr)
{
for (uint i = 0; i < m_workItemData->inlineeInfoCount; ++i)
{
if (m_workItemData->inlineeInfo[i].functionBodyAddr == (void*)funcBodyAddr)
{
return (JITTimePolymorphicInlineCacheInfo *)&m_workItemData->inlineeInfo[i];
}
}
return nullptr;
}
void
JITTimeWorkItem::SetJITTimeData(FunctionJITTimeDataIDL * jitData)
{
m_workItemData->jitData = jitData;
}
FunctionJITTimeInfo *
JITTimeWorkItem::GetJITTimeInfo() const
{
return reinterpret_cast<FunctionJITTimeInfo *>(m_workItemData->jitData);
}
bool
JITTimeWorkItem::HasSymIdToValueTypeMap() const
{
return m_workItemData->symIdToValueTypeMap != nullptr;
}
bool
JITTimeWorkItem::TryGetValueType(uint symId, ValueType * valueType) const
{
Assert(IsLoopBody());
uint index = symId - m_jitBody.GetConstCount();
if (symId >= m_jitBody.GetConstCount() && index < m_workItemData->symIdToValueTypeMapCount)
{
ValueType type = ((ValueType*)m_workItemData->symIdToValueTypeMap)[index];
if (type.GetRawData() != 0)
{
*valueType = type;
return true;
}
}
return false;
}