Pārlūkot izejas kodu

Merge pull request #2553 from fcastellacci/t-frca/type-annotations

Added support for type annotations in method parameters
fcastellacci 9 gadi atpakaļ
vecāks
revīzija
acd579ddaf

+ 26 - 2
lib/Backend/GlobOpt.cpp

@@ -5672,7 +5672,7 @@ GlobOpt::SetLoopFieldInitialValue(Loop *loop, IR::Instr *instr, PropertySym *pro
     // Uninitialized value type. Use the profiled value type from the instruction.
     const ValueType profiledValueType =
         instr->IsProfiledInstr() ? instr->AsProfiledInstr()->u.FldInfo().valueType : ValueType::Uninitialized;
-    Assert(!profiledValueType.IsDefinite()); // Hence the values created here don't need to be tracked for kills
+    //Assert(!profiledValueType.IsDefinite()); // Hence the values created here don't need to be tracked for kills
     initialValue = this->NewGenericValue(profiledValueType, propertySym);
     symStore = StackSym::New(this->func);
 
@@ -5801,7 +5801,31 @@ GlobOpt::OptSrc(IR::Opnd *opnd, IR::Instr * *pInstr, Value **indirIndexValRef, I
                 int paramSlotNum = sym->AsStackSym()->GetParamSlotNum() - 2;
                 if (paramSlotNum >= 0)
                 {
-                    const auto parameterType = instr->m_func->GetReadOnlyProfileInfo()->GetParameterInfo(static_cast<Js::ArgSlot>(paramSlotNum));
+                    ValueType parameterType;
+                    if (instr->m_func->GetJITFunctionBody()->GetParameterTypeInfo() != nullptr)
+                    {
+                        Js::TypeHint typeHint = (Js::TypeHint) instr->m_func->GetJITFunctionBody()->GetParameterTypeInfo()->content[paramSlotNum];
+                        switch (typeHint)
+                        {
+                            case Js::TypeHint::Int:
+                                parameterType = ValueType::Int.SetCanBeTaggedValue(true);
+                                break;
+                            case Js::TypeHint::Float:
+                                parameterType = ValueType::Float.SetCanBeTaggedValue(true);
+                                break;
+                            case Js::TypeHint::Bool:
+                                parameterType = ValueType::Boolean;
+                                break;
+                            case Js::TypeHint::Object:
+                                parameterType = ValueType::UninitializedObject;
+                                break;
+                            default:
+                                parameterType = instr->m_func->GetReadOnlyProfileInfo()->GetParameterInfo(static_cast<Js::ArgSlot>(paramSlotNum));
+                        }
+                    } else
+                    {
+                        parameterType = instr->m_func->GetReadOnlyProfileInfo()->GetParameterInfo(static_cast<Js::ArgSlot>(paramSlotNum));
+                    }
                     val = NewGenericValue(parameterType);
                     opnd->SetValueType(val->GetValueInfo()->Type());
                     return val;

+ 17 - 4
lib/Backend/JITTimeFunctionBody.cpp

@@ -19,7 +19,6 @@ JITTimeFunctionBody::InitializeJITFunctionData(
     __out FunctionBodyDataIDL * jitBody)
 {
     Assert(functionBody != nullptr);
-
     // const table
     jitBody->constCount = functionBody->GetConstantCount();
     if (functionBody->GetConstantCount() > 0)
@@ -250,12 +249,21 @@ JITTimeFunctionBody::InitializeJITFunctionData(
             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)
+            functionBody->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;
+                jitBody->typeAnnotations->content[index].type = (unsigned char) info->type;
+            });
+        }
+        if (functionBody->parameterTypeInfo->Count() > 0)
+        {
+            jitBody->parameterTypeInfo = AnewStruct(arena, ParameterTypeInfoIDL);
+            jitBody->parameterTypeInfo->count = functionBody->parameterTypeInfo->Count();
+            jitBody->parameterTypeInfo->content = AnewArrayZ(arena, unsigned char, functionBody->parameterTypeInfo->Count());
+            functionBody->parameterTypeInfo->Map([jitBody](int index, Js::TypeHint info)
+            {
+                jitBody->parameterTypeInfo->content[index] = (unsigned char) info;
             });
         }
     }
@@ -1091,6 +1099,11 @@ TypeAnnotationsArrayIDL * JITTimeFunctionBody::GetTypeAnnotationsArray() const
     return m_bodyData.typeAnnotations;
 }
 
+ParameterTypeInfoIDL * JITTimeFunctionBody::GetParameterTypeInfo() const
+{
+    return m_bodyData.parameterTypeInfo;
+}
+
 Js::ForInCache *
 JITTimeFunctionBody::GetForInCache(uint profileId) const
 {

+ 1 - 0
lib/Backend/JITTimeFunctionBody.h

@@ -183,6 +183,7 @@ public:
     Js::PropertyIdArray * GetFormalsPropIdArray() const;
     
     TypeAnnotationsArrayIDL* GetTypeAnnotationsArray() const;
+    ParameterTypeInfoIDL* GetParameterTypeInfo() const;
 
     Js::ForInCache * GetForInCache(uint profileId) const;
     bool InitializeStatementMap(Js::SmallSpanSequence * statementMap, ArenaAllocator* alloc) const;

+ 7 - 0
lib/JITIDL/JITTypes.h

@@ -479,6 +479,12 @@ typedef struct TypeAnnotationsArrayIDL
     IDL_DEF([size_is(count)]) TypeInformationIDL* content;
 } TypeAnnotationsArrayIDL;
 
+typedef struct ParameterTypeInfoIDL
+{
+    unsigned int count;
+    /* [size_is] */ unsigned char *content;
+}   ParameterTypeInfoIDL;
+
 // FunctionBody fields, read only in JIT, gathered in foreground
 typedef struct FunctionBodyDataIDL
 {
@@ -553,6 +559,7 @@ typedef struct FunctionBodyDataIDL
     SmallSpanSequenceIDL * statementMap;
 
     TypeAnnotationsArrayIDL * typeAnnotations;
+    ParameterTypeInfoIDL * parameterTypeInfo;
 
     IDL_DEF([size_is(fullStatementMapCount)]) StatementMapIDL * fullStatementMaps;
 

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

@@ -559,6 +559,7 @@ namespace Js
         , callCountStats(0)
 #endif
         , typeAnnotationsArray(nullptr)
+        , parameterTypeInfo(nullptr)
     {
         SetCountField(CounterFields::ConstantCount, 1);
 
@@ -580,6 +581,7 @@ namespace Js
         if (CONFIG_FLAG(TypeAnnotations))
         {
             this->typeAnnotationsArray = RecyclerNew(this->m_scriptContext->GetRecycler(), TypeAnnotationsArray, this->m_scriptContext->GetRecycler());
+            this->parameterTypeInfo = RecyclerNew(this->m_scriptContext->GetRecycler(), ParameterTypeInfo, this->m_scriptContext->GetRecycler());
         }
 
         this->AddEntryPointToEntryPointList(this->GetDefaultFunctionEntryPointInfo());
@@ -704,6 +706,7 @@ namespace Js
         , callCountStats(0)
 #endif
         , typeAnnotationsArray(nullptr)
+        , parameterTypeInfo(nullptr)
     {
         ScriptContext * scriptContext = proxy->GetScriptContext();
 
@@ -735,6 +738,7 @@ namespace Js
         if (CONFIG_FLAG(TypeAnnotations))
         {
             this->typeAnnotationsArray = RecyclerNew(scriptContext->GetRecycler(), TypeAnnotationsArray, scriptContext->GetRecycler());
+            this->parameterTypeInfo = RecyclerNew(scriptContext->GetRecycler(), ParameterTypeInfo, scriptContext->GetRecycler());
         }
 
         Assert(this->GetDefaultEntryPointInfo()->jsMethod != nullptr);

+ 3 - 0
lib/Runtime/Base/FunctionBody.h

@@ -2317,6 +2317,9 @@ namespace Js
             typedef JsUtil::List<TypeInformation*, Recycler> TypeAnnotationsArray;
             TypeAnnotationsArray* typeAnnotationsArray;
 
+            typedef JsUtil::List<Js::TypeHint, Recycler> ParameterTypeInfo;
+            ParameterTypeInfo* parameterTypeInfo;
+
             // Contains recorded at bytecode generation time information about statements and try-catch blocks.
             // Used by debugger.
             struct AuxStatementData

+ 8 - 0
lib/Runtime/ByteCode/ByteCodeEmitter.cpp

@@ -3389,6 +3389,14 @@ void ByteCodeGenerator::EmitOneFunction(ParseNode *pnode)
             EmitFunctionBody(funcInfo);
         }
 
+        if (CONFIG_FLAG(TypeAnnotations))
+        {
+            MapFormalsWithoutRest(pnode, [&](ParseNode* argPnode)
+            {
+                funcInfo->GetParsedFunctionBody()->parameterTypeInfo->Add(argPnode->typeHint);
+            });
+        }
+
         if (pnode->sxFnc.pnodeBodyScope != nullptr)
         {
             ::EndEmitBlock(pnode->sxFnc.pnodeBodyScope, this, funcInfo);