Ver código fonte

Added type information to the FunctionBody

Franco Castellacci 9 anos atrás
pai
commit
260be3ee5f

+ 22 - 0
lib/Backend/JITTimeFunctionBody.cpp

@@ -243,6 +243,23 @@ JITTimeFunctionBody::InitializeJITFunctionData(
     jitBody->literalRegexCount = functionBody->GetLiteralRegexCount();
     jitBody->literalRegexes = (intptr_t*)functionBody->GetLiteralRegexesWithLock();
 
+    if (CONFIG_FLAG(TypeAnnotations)) 
+    {
+        if (functionBody->typeAnnotationsArray->Count() > 0)
+        {
+            jitBody->typeAnnotations = AnewStruct(arena, TypeAnnotationsArrayIDL);
+            jitBody->typeAnnotations->count = functionBody->typeAnnotationsArray->Count();
+            jitBody->typeAnnotations->content = AnewArrayZ(arena, TypeInformationIDL, functionBody->typeAnnotationsArray->Count());
+            auto typeAnnotationsArray = functionBody->typeAnnotationsArray;
+            typeAnnotationsArray->Map([jitBody](int index, Js::FunctionBody::TypeInformation * info)
+            {
+                jitBody->typeAnnotations->content[index].bytecodeOffset = info->bytecodeOffset;
+                jitBody->typeAnnotations->content[index].regSlot = info->regSlot;
+                jitBody->typeAnnotations->content[index].type = (unsigned char)info->type;
+            });
+        }
+    }
+
 #ifdef ASMJS_PLAT
     if (functionBody->GetIsAsmJsFunction())
     {
@@ -1069,6 +1086,11 @@ JITTimeFunctionBody::GetFormalsPropIdArray() const
     return  (Js::PropertyIdArray *)m_bodyData.formalsPropIdArray;
 }
 
+TypeAnnotationsArrayIDL * JITTimeFunctionBody::GetTypeAnnotationsArray() const
+{
+    return m_bodyData.typeAnnotations;
+}
+
 Js::ForInCache *
 JITTimeFunctionBody::GetForInCache(uint profileId) const
 {

+ 2 - 0
lib/Backend/JITTimeFunctionBody.h

@@ -181,6 +181,8 @@ public:
     intptr_t GetAuxDataAddr(uint offset) const;
     const Js::PropertyIdArray * ReadPropertyIdArrayFromAuxData(uint offset) const;
     Js::PropertyIdArray * GetFormalsPropIdArray() const;
+    
+    TypeAnnotationsArrayIDL* GetTypeAnnotationsArray() const;
 
     Js::ForInCache * GetForInCache(uint profileId) const;
     bool InitializeStatementMap(Js::SmallSpanSequence * statementMap, ArenaAllocator* alloc) const;

+ 15 - 0
lib/JITIDL/JITTypes.h

@@ -466,6 +466,19 @@ typedef struct ConstTableContentIDL
     IDL_DEF([size_is(count)]) RecyclableObjectIDL** content;
 } ConstTableContentIDL;
 
+typedef struct TypeInformationIDL {
+    unsigned int bytecodeOffset;
+    unsigned int regSlot;
+    unsigned char type;
+} TypeInformationIDL;
+
+typedef struct TypeAnnotationsArrayIDL
+{
+    unsigned int count;
+    //Should I use some padding?
+    IDL_DEF([size_is(count)]) TypeInformationIDL* content;
+} TypeAnnotationsArrayIDL;
+
 // FunctionBody fields, read only in JIT, gathered in foreground
 typedef struct FunctionBodyDataIDL
 {
@@ -539,6 +552,8 @@ typedef struct FunctionBodyDataIDL
 
     SmallSpanSequenceIDL * statementMap;
 
+    TypeAnnotationsArrayIDL * typeAnnotations;
+
     IDL_DEF([size_is(fullStatementMapCount)]) StatementMapIDL * fullStatementMaps;
 
     IDL_DEF([size_is(byteCodeLength)]) byte * byteCodeBuffer;

+ 21 - 0
lib/Runtime/Base/FunctionBody.cpp

@@ -558,6 +558,7 @@ namespace Js
         , regAllocStoreCount(0)
         , callCountStats(0)
 #endif
+        , typeAnnotationsArray(nullptr)
     {
         SetCountField(CounterFields::ConstantCount, 1);
 
@@ -576,6 +577,11 @@ namespace Js
         CriticalSection* syncObj = scriptContext->GetThreadContext()->GetEtwRundownCriticalSection();
         this->entryPoints = RecyclerNew(this->m_scriptContext->GetRecycler(), FunctionEntryPointList, this->m_scriptContext->GetRecycler(), syncObj);
 
+        if (CONFIG_FLAG(TypeAnnotations))
+        {
+            this->typeAnnotationsArray = RecyclerNew(this->m_scriptContext->GetRecycler(), TypeAnnotationsArray, this->m_scriptContext->GetRecycler());
+        }
+
         this->AddEntryPointToEntryPointList(this->GetDefaultFunctionEntryPointInfo());
 
         Assert(this->GetDefaultEntryPointInfo()->jsMethod != nullptr);
@@ -697,6 +703,7 @@ namespace Js
         , regAllocStoreCount(0)
         , callCountStats(0)
 #endif
+        , typeAnnotationsArray(nullptr)
     {
         ScriptContext * scriptContext = proxy->GetScriptContext();
 
@@ -725,6 +732,11 @@ namespace Js
 
         this->AddEntryPointToEntryPointList(this->GetDefaultFunctionEntryPointInfo());
 
+        if (CONFIG_FLAG(TypeAnnotations))
+        {
+            this->typeAnnotationsArray = RecyclerNew(scriptContext->GetRecycler(), TypeAnnotationsArray, scriptContext->GetRecycler());
+        }
+
         Assert(this->GetDefaultEntryPointInfo()->jsMethod != nullptr);
 
         InitDisableInlineApply();
@@ -10189,6 +10201,15 @@ namespace Js
         return m_hasFuncExprScopeRegister ? GetCountField(CounterFields::FuncExprScopeRegister) : Constants::NoRegister;
     }
 
+    void FunctionBody::AddBytecodeOffsetTypeAnnotation(uint offset, RegSlot reg, TypeHint type) 
+    {
+        TypeInformation* typeInfo = RecyclerNew(this->m_scriptContext->GetRecycler(), TypeInformation);
+        typeInfo->regSlot = reg;
+        typeInfo->type = type;
+        typeInfo->bytecodeOffset = offset;
+        this->typeAnnotationsArray->Add(typeInfo);
+    }
+
     void FunctionBody::SetFirstTmpRegister(RegSlot reg)
     {
         if (reg == Constants::NoRegister)

+ 11 - 1
lib/Runtime/Base/FunctionBody.h

@@ -2173,7 +2173,7 @@ namespace Js
             return sourceContextInfo->url;
         }
     }
-
+    
     class FunctionBody : public ParseableFunctionInfo
     {
         DEFINE_VTABLE_CTOR_NO_REGISTER(FunctionBody, ParseableFunctionInfo);
@@ -2309,6 +2309,14 @@ namespace Js
             typedef JsUtil::List<StatementAdjustmentRecord, Recycler, /* isLeaf = */ true> StatementAdjustmentRecordList;
             typedef JsUtil::List<CrossFrameEntryExitRecord, Recycler, /* isLeaf = */ true> CrossFrameEntryExitRecordList;
 
+            struct TypeInformation {
+                uint bytecodeOffset;
+                Js::RegSlot regSlot;
+                Js::TypeHint type;
+            };
+            typedef JsUtil::List<TypeInformation*, Recycler> TypeAnnotationsArray;
+            TypeAnnotationsArray* typeAnnotationsArray;
+
             // Contains recorded at bytecode generation time information about statements and try-catch blocks.
             // Used by debugger.
             struct AuxStatementData
@@ -2651,6 +2659,8 @@ namespace Js
         void MapAndSetFuncExprScopeRegister(RegSlot reg);
         RegSlot GetFuncExprScopeRegister() const;
 
+        void AddBytecodeOffsetTypeAnnotation(uint offset, RegSlot reg, TypeHint type);
+
         bool HasScopeObject() const { return hasScopeObject; }
         void SetHasScopeObject(bool has) { hasScopeObject = has; }
         uint GetInnerScopeCount() const { return GetCountField(CounterFields::InnerScopeCount); }