<commit_before>//-------------------------------------------------------------------------------------------------------
// 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"

JITTimeFunctionBody::JITTimeFunctionBody(FunctionBodyDataIDL * bodyData) :
    m_bodyData(*bodyData)
{
    CompileAssert(sizeof(JITTimeFunctionBody) == sizeof(FunctionBodyDataIDL));
}

/* static */
void
JITTimeFunctionBody::InitializeJITFunctionData(
    __in ArenaAllocator * arena,
    __in Js::FunctionBody *functionBody,
    __out FunctionBodyDataIDL * jitBody)
{
    Assert(functionBody != nullptr);

    // const table
    jitBody->constCount = functionBody->GetConstantCount();
    if (functionBody->GetConstantCount() > 0)
    {
        jitBody->constTable = (intptr_t *)functionBody->GetConstTable();
        if (!functionBody->GetIsAsmJsFunction())
        {
            jitBody->constTableContent = AnewStructZ(arena, ConstTableContentIDL);
            jitBody->constTableContent->count = functionBody->GetConstantCount();
            jitBody->constTableContent->content = AnewArrayZ(arena, RecyclableObjectIDL*, functionBody->GetConstantCount());

            for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < functionBody->GetConstantCount(); ++reg)
            {
                Js::Var varConst = functionBody->GetConstantVar(reg);
                Assert(varConst != nullptr);
                if (Js::TaggedInt::Is(varConst) ||
                    varConst == (Js::Var)&Js::NullFrameDisplay ||
                    varConst == (Js::Var)&Js::StrictNullFrameDisplay)
                {
                    // don't need TypeId for these
                }
                else
                {
                    if (Js::TaggedNumber::Is(varConst))
                    {
                        // the typeid should be TypeIds_Number, determine this directly from const table
                    }
                    else
                    {
                        jitBody->constTableContent->content[reg - Js::FunctionBody::FirstRegSlot] = (RecyclableObjectIDL*)varConst;
                    }
                }
            }
        }
        else if (functionBody->IsWasmFunction())
        {
            // no consts in wasm
            Assert(jitBody->constTable == nullptr);
            jitBody->constCount = 0;
        }
    }

    Js::SmallSpanSequence * statementMap = functionBody->GetStatementMapSpanSequence();

    // REVIEW: OOP JIT, is it possible for this to not match with isJitInDebugMode?
    if (functionBody->IsInDebugMode())
    {
        Assert(!statementMap);

        jitBody->byteCodeLength = functionBody->GetOriginalByteCode()->GetLength();
        jitBody->byteCodeBuffer = functionBody->GetOriginalByteCode()->GetBuffer();

        auto fullStatementMaps = functionBody->GetStatementMaps();
        jitBody->fullStatementMapCount = fullStatementMaps->Count();
        jitBody->fullStatementMaps = AnewArrayZ(arena, StatementMapIDL, jitBody->fullStatementMapCount);
        fullStatementMaps->Map([jitBody](int index, Js::FunctionBody::StatementMap * map) {

            jitBody->fullStatementMaps[index] = *(StatementMapIDL*)map;

            Assert(jitBody->fullStatementMaps[index].byteCodeSpanBegin == map->byteCodeSpan.Begin());
            Assert(jitBody->fullStatementMaps[index].byteCodeSpanEnd == map->byteCodeSpan.End());
            Assert(jitBody->fullStatementMaps[index].sourceSpanBegin == map->sourceSpan.Begin());
            Assert(jitBody->fullStatementMaps[index].sourceSpanEnd == map->sourceSpan.End());
            Assert((jitBody->fullStatementMaps[index].isSubExpression != FALSE) == map->isSubexpression);
        });

        Js::PropertyIdOnRegSlotsContainer * propOnRegSlots = functionBody->GetPropertyIdOnRegSlotsContainerWithLock();
        if (propOnRegSlots)
        {
            jitBody->propertyIdsForRegSlotsCount = propOnRegSlots->length;
            jitBody->propertyIdsForRegSlots = propOnRegSlots->propertyIdsForRegSlots;
        }
    }
    else
    {
        jitBody->byteCodeLength = functionBody->GetByteCode()->GetLength();
        jitBody->byteCodeBuffer = functionBody->GetByteCode()->GetBuffer();
        if (!functionBody->IsWasmFunction()) {
            Assert(statementMap);
            jitBody->statementMap = AnewStructZ(arena, SmallSpanSequenceIDL);
            jitBody->statementMap->baseValue = statementMap->baseValue;

            if (statementMap->pActualOffsetList)
            {
                jitBody->statementMap->actualOffsetLength = statementMap->pActualOffsetList->Count();
                jitBody->statementMap->actualOffsetList = statementMap->pActualOffsetList->GetBuffer();
            }

            if (statementMap->pStatementBuffer)
            {
                jitBody->statementMap->statementLength = statementMap->pStatementBuffer->Count();
                jitBody->statementMap->statementBuffer = statementMap->pStatementBuffer->GetBuffer();
            }
        }
    }

    jitBody->inlineCacheCount = functionBody->GetInlineCacheCount();
    if (functionBody->GetInlineCacheCount() > 0)
    {
        jitBody->cacheIdToPropertyIdMap = functionBody->GetCacheIdToPropertyIdMap();
    }

    jitBody->inlineCaches = reinterpret_cast<intptr_t*>(functionBody->GetInlineCaches());

    // body data
    jitBody->functionBodyAddr = (intptr_t)functionBody;

    jitBody->funcNumber = functionBody->GetFunctionNumber();
    jitBody->sourceContextId = functionBody->GetSourceContextId();
    jitBody->nestedCount = functionBody->GetNestedCount();
    if (functionBody->GetNestedCount() > 0)
    {
        jitBody->nestedFuncArrayAddr = (intptr_t)functionBody->GetNestedFuncArray();
    }
    jitBody->scopeSlotArraySize = functionBody->scopeSlotArraySize;
    jitBody->paramScopeSlotArraySize = functionBody->paramScopeSlotArraySize;
    jitBody->attributes = functionBody->GetAttributes();
    jitBody->isInstInlineCacheCount = functionBody->GetIsInstInlineCacheCount();

    if (functionBody->GetUtf8SourceInfo()->GetCbLength() > UINT_MAX)
    {
        Js::Throw::OutOfMemory();
    }

    jitBody->byteCodeCount = functionBody->GetByteCodeCount();
    jitBody->byteCodeInLoopCount = functionBody->GetByteCodeInLoopCount();
    jitBody->nonLoadByteCodeCount = functionBody->GetByteCodeWithoutLDACount();
    jitBody->loopCount = functionBody->GetLoopCount();

    Js::LoopHeader * loopHeaders = functionBody->GetLoopHeaderArrayWithLock();
    if (loopHeaders != nullptr)
    {
        jitBody->loopHeaderArrayAddr = (intptr_t)loopHeaders;
        jitBody->loopHeaderArrayLength = functionBody->GetLoopCount();
        jitBody->loopHeaders = AnewArray(arena, JITLoopHeaderIDL, functionBody->GetLoopCount());
        for (uint i = 0; i < functionBody->GetLoopCount(); ++i)
        {
            jitBody->loopHeaders[i].startOffset = loopHeaders[i].startOffset;
            jitBody->loopHeaders[i].endOffset = loopHeaders[i].endOffset;
            jitBody->loopHeaders[i].isNested = loopHeaders[i].isNested;
            jitBody->loopHeaders[i].isInTry = loopHeaders[i].isInTry;
            jitBody->loopHeaders[i].interpretCount = functionBody->GetLoopInterpretCount(&loopHeaders[i]);
        }
    }

    jitBody->localFrameDisplayReg = functionBody->GetLocalFrameDisplayRegister();
    jitBody->localClosureReg = functionBody->GetLocalClosureRegister();
    jitBody->envReg = functionBody->GetEnvRegister();
    jitBody->firstTmpReg = functionBody->GetFirstTmpReg();
    jitBody->varCount = functionBody->GetVarCount();
    jitBody->innerScopeCount = functionBody->GetInnerScopeCount();
    if (functionBody->GetInnerScopeCount() > 0)
    {
        jitBody->firstInnerScopeReg = functionBody->GetFirstInnerScopeRegister();<commit_msg>OS9791203:Failfast in Tweetium and other UWA background task Multi-thread race condition causes inconsistency in chakra's DynamicSourceHolder vs. WWAHost's internal mapping count. Fix by removing call to dynamic source holder from backend JIT code.<commit_after>//-------------------------------------------------------------------------------------------------------
// 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"

JITTimeFunctionBody::JITTimeFunctionBody(FunctionBodyDataIDL * bodyData) :
    m_bodyData(*bodyData)
{
    CompileAssert(sizeof(JITTimeFunctionBody) == sizeof(FunctionBodyDataIDL));
}

/* static */
void
JITTimeFunctionBody::InitializeJITFunctionData(
    __in ArenaAllocator * arena,
    __in Js::FunctionBody *functionBody,
    __out FunctionBodyDataIDL * jitBody)
{
    Assert(functionBody != nullptr);

    // const table
    jitBody->constCount = functionBody->GetConstantCount();
    if (functionBody->GetConstantCount() > 0)
    {
        jitBody->constTable = (intptr_t *)functionBody->GetConstTable();
        if (!functionBody->GetIsAsmJsFunction())
        {
            jitBody->constTableContent = AnewStructZ(arena, ConstTableContentIDL);
            jitBody->constTableContent->count = functionBody->GetConstantCount();
            jitBody->constTableContent->content = AnewArrayZ(arena, RecyclableObjectIDL*, functionBody->GetConstantCount());

            for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < functionBody->GetConstantCount(); ++reg)
            {
                Js::Var varConst = functionBody->GetConstantVar(reg);
                Assert(varConst != nullptr);
                if (Js::TaggedInt::Is(varConst) ||
                    varConst == (Js::Var)&Js::NullFrameDisplay ||
                    varConst == (Js::Var)&Js::StrictNullFrameDisplay)
                {
                    // don't need TypeId for these
                }
                else
                {
                    if (Js::TaggedNumber::Is(varConst))
                    {
                        // the typeid should be TypeIds_Number, determine this directly from const table
                    }
                    else
                    {
                        jitBody->constTableContent->content[reg - Js::FunctionBody::FirstRegSlot] = (RecyclableObjectIDL*)varConst;
                    }
                }
            }
        }
        else if (functionBody->IsWasmFunction())
        {
            // no consts in wasm
            Assert(jitBody->constTable == nullptr);
            jitBody->constCount = 0;
        }
    }

    Js::SmallSpanSequence * statementMap = functionBody->GetStatementMapSpanSequence();

    // REVIEW: OOP JIT, is it possible for this to not match with isJitInDebugMode?
    if (functionBody->IsInDebugMode())
    {
        Assert(!statementMap);

        jitBody->byteCodeLength = functionBody->GetOriginalByteCode()->GetLength();
        jitBody->byteCodeBuffer = functionBody->GetOriginalByteCode()->GetBuffer();

        auto fullStatementMaps = functionBody->GetStatementMaps();
        jitBody->fullStatementMapCount = fullStatementMaps->Count();
        jitBody->fullStatementMaps = AnewArrayZ(arena, StatementMapIDL, jitBody->fullStatementMapCount);
        fullStatementMaps->Map([jitBody](int index, Js::FunctionBody::StatementMap * map) {

            jitBody->fullStatementMaps[index] = *(StatementMapIDL*)map;

            Assert(jitBody->fullStatementMaps[index].byteCodeSpanBegin == map->byteCodeSpan.Begin());
            Assert(jitBody->fullStatementMaps[index].byteCodeSpanEnd == map->byteCodeSpan.End());
            Assert(jitBody->fullStatementMaps[index].sourceSpanBegin == map->sourceSpan.Begin());
            Assert(jitBody->fullStatementMaps[index].sourceSpanEnd == map->sourceSpan.End());
            Assert((jitBody->fullStatementMaps[index].isSubExpression != FALSE) == map->isSubexpression);
        });

        Js::PropertyIdOnRegSlotsContainer * propOnRegSlots = functionBody->GetPropertyIdOnRegSlotsContainerWithLock();
        if (propOnRegSlots)
        {
            jitBody->propertyIdsForRegSlotsCount = propOnRegSlots->length;
            jitBody->propertyIdsForRegSlots = propOnRegSlots->propertyIdsForRegSlots;
        }
    }
    else
    {
        jitBody->byteCodeLength = functionBody->GetByteCode()->GetLength();
        jitBody->byteCodeBuffer = functionBody->GetByteCode()->GetBuffer();
        if (!functionBody->IsWasmFunction()) {
            Assert(statementMap);
            jitBody->statementMap = AnewStructZ(arena, SmallSpanSequenceIDL);
            jitBody->statementMap->baseValue = statementMap->baseValue;

            if (statementMap->pActualOffsetList)
            {
                jitBody->statementMap->actualOffsetLength = statementMap->pActualOffsetList->Count();
                jitBody->statementMap->actualOffsetList = statementMap->pActualOffsetList->GetBuffer();
            }

            if (statementMap->pStatementBuffer)
            {
                jitBody->statementMap->statementLength = statementMap->pStatementBuffer->Count();
                jitBody->statementMap->statementBuffer = statementMap->pStatementBuffer->GetBuffer();
            }
        }
    }

    jitBody->inlineCacheCount = functionBody->GetInlineCacheCount();
    if (functionBody->GetInlineCacheCount() > 0)
    {
        jitBody->cacheIdToPropertyIdMap = functionBody->GetCacheIdToPropertyIdMap();
    }

    jitBody->inlineCaches = reinterpret_cast<intptr_t*>(functionBody->GetInlineCaches());

    // body data
    jitBody->functionBodyAddr = (intptr_t)functionBody;

    jitBody->funcNumber = functionBody->GetFunctionNumber();
    jitBody->sourceContextId = functionBody->GetSourceContextId();
    jitBody->nestedCount = functionBody->GetNestedCount();
    if (functionBody->GetNestedCount() > 0)
    {
        jitBody->nestedFuncArrayAddr = (intptr_t)functionBody->GetNestedFuncArray();
    }
    jitBody->scopeSlotArraySize = functionBody->scopeSlotArraySize;
    jitBody->paramScopeSlotArraySize = functionBody->paramScopeSlotArraySize;
    jitBody->attributes = functionBody->GetAttributes();
    jitBody->isInstInlineCacheCount = functionBody->GetIsInstInlineCacheCount();

    jitBody->byteCodeCount = functionBody->GetByteCodeCount();
    jitBody->byteCodeInLoopCount = functionBody->GetByteCodeInLoopCount();
    jitBody->nonLoadByteCodeCount = functionBody->GetByteCodeWithoutLDACount();
    jitBody->loopCount = functionBody->GetLoopCount();

    Js::LoopHeader * loopHeaders = functionBody->GetLoopHeaderArrayWithLock();
    if (loopHeaders != nullptr)
    {
        jitBody->loopHeaderArrayAddr = (intptr_t)loopHeaders;
        jitBody->loopHeaderArrayLength = functionBody->GetLoopCount();
        jitBody->loopHeaders = AnewArray(arena, JITLoopHeaderIDL, functionBody->GetLoopCount());
        for (uint i = 0; i < functionBody->GetLoopCount(); ++i)
        {
            jitBody->loopHeaders[i].startOffset = loopHeaders[i].startOffset;
            jitBody->loopHeaders[i].endOffset = loopHeaders[i].endOffset;
            jitBody->loopHeaders[i].isNested = loopHeaders[i].isNested;
            jitBody->loopHeaders[i].isInTry = loopHeaders[i].isInTry;
            jitBody->loopHeaders[i].interpretCount = functionBody->GetLoopInterpretCount(&loopHeaders[i]);
        }
    }

    jitBody->localFrameDisplayReg = functionBody->GetLocalFrameDisplayRegister();
    jitBody->localClosureReg = functionBody->GetLocalClosureRegister();
    jitBody->envReg = functionBody->GetEnvRegister();
    jitBody->firstTmpReg = functionBody->GetFirstTmpReg();
    jitBody->varCount = functionBody->GetVarCount();
    jitBody->innerScopeCount = functionBody->GetInnerScopeCount();
    if (functionBody->GetInnerScopeCount() > 0)
    {
        jitBody->firstInnerScopeReg = functionBody->GetFirstInnerScopeRegister();
{'fraction_non_alphanumeric': 0.13853433783699645, 'fraction_numerical': 0.001245252474939294, 'mean_word_length': 2.764237168971174, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 296, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2252550', 'n_tokens_mistral': 4402, 'n_tokens_neox': 4294, 'n_words': 611}