//------------------------------------------------------------------------------------------------------- // 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(m_workItemData->type); } ExecutionMode JITTimeWorkItem::GetJitMode() const { return static_cast(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 { return 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 * 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; if (statementReader) { 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(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; }