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); }
// The logic below makes use of number of tmp (temp) registers of A and B. // Set next statement is not allowed. // if numberOfTmpReg(A) < numberOfTmpReg(B) // or if any statement between A and B has number of tmpReg more than the lowest found. // // Get the temp register count for the A // This is a base and will store the lowest tmp reg count we have got yet, while walking the skipped statements. bool ProbeContainer::IsTmpRegCountIncreased(Js::FunctionBody* functionBody, ByteCodeReader* reader, int currentOffset, int nextStmOffset, bool restoreOffset) { Js::FunctionBody::StatementMapList* pStatementMaps = functionBody->GetStatementMaps(); Assert(pStatementMaps && pStatementMaps->Count() > 0); int direction = currentOffset < nextStmOffset ? 1 : -1; int startIndex = functionBody->GetEnclosingStatementIndexFromByteCode(currentOffset, true); uint32 tmpRegCountLowest = 0; // In the native code-gen (or interpreter which created from bailout points) the EmitTmpRegCount is not handled, // so lets calculate it by going through all statements backward from the current offset int index = startIndex; for (; index > 0; index--) { Js::FunctionBody::StatementMap* pStatementMap = pStatementMaps->Item(index); Js::OpCode op; if (!pStatementMap->isSubexpression && FetchTmpRegCount(functionBody, reader, pStatementMap->byteCodeSpan.begin, &tmpRegCountLowest, &op)) { break; } } // Reset to the current offset. reader->SetCurrentOffset(currentOffset); uint32 tmpRegCountOnNext = tmpRegCountLowest; // Will fetch the tmp reg count till the B and skipped statements. Assert(startIndex != -1); index = startIndex + direction; while (index > 0 && index < pStatementMaps->Count()) { Js::FunctionBody::StatementMap* pStatementMap = pStatementMaps->Item(index); if (pStatementMap->isSubexpression) { index += direction; continue; } if (direction == 1) // NOTE: Direction & corresponding condition { if (nextStmOffset < pStatementMap->byteCodeSpan.begin) // check only till nextstatement offset { break; } } Js::OpCode op; FetchTmpRegCount(functionBody, reader, pStatementMap->byteCodeSpan.begin, &tmpRegCountOnNext, &op); if (tmpRegCountOnNext < tmpRegCountLowest) { tmpRegCountLowest = tmpRegCountOnNext; } // On the reverse direction stop only when we find the tmpRegCount info for the setnext or below. if (direction == -1 && (op == Js::OpCode::EmitTmpRegCount)) { if (nextStmOffset >= pStatementMap->byteCodeSpan.begin) { break; } } index += direction; } // On the reverse way if we have reached the first statement, then our tmpRegCountOnNext is 0. if (direction == -1 && index == 0) { tmpRegCountOnNext = 0; } if (restoreOffset) { // Restore back the original IP. reader->SetCurrentOffset(currentOffset); } return (tmpRegCountOnNext > tmpRegCountLowest); }