1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_COMPILER_TYPE_INFERENCE_METHOD_TYPE_INFER_H 17 #define ECMASCRIPT_COMPILER_TYPE_INFERENCE_METHOD_TYPE_INFER_H 18 19 #include "ecmascript/compiler/argument_accessor.h" 20 #include "ecmascript/compiler/bytecode_circuit_builder.h" 21 #include "ecmascript/compiler/compiler_log.h" 22 #include "ecmascript/compiler/circuit.h" 23 #include "ecmascript/compiler/gate_accessor.h" 24 #include "ecmascript/compiler/pass_manager.h" 25 #include "ecmascript/ts_types/ts_manager.h" 26 27 namespace panda::ecmascript::kungfu { 28 enum InferState : uint8_t { 29 // loop-begin gate has been infered to non-any type 30 NORMAL_INFERED = 0, 31 // loop-begin gate has been fixed to any type manually and it should not be infered to other types 32 ANY_INFERED, 33 // the number-types of loop-begin gate under this state should be promoted to number type 34 NUMBER_INFERED, 35 }; 36 37 class MethodTypeInfer { 38 public: 39 MethodTypeInfer(BytecodeCircuitBuilder *builder, Circuit *circuit, 40 PassContext *ctx, size_t methodId, bool enableLog, 41 const std::string &name, const CString &recordName, 42 MethodInfo *methodInfo, const MethodLiteral *methodLiteral, 43 bool enableGlobalTypeInfer, bool hasType); 44 ~MethodTypeInfer() = default; 45 46 NO_COPY_SEMANTIC(MethodTypeInfer); 47 NO_MOVE_SEMANTIC(MethodTypeInfer); 48 49 std::pair<GateType, uint32_t> TraverseInfer(); 50 void CheckAndPrint(); 51 void SetNamespaceArgType(GateType type); 52 IsLogEnabled()53 bool IsLogEnabled() const 54 { 55 return enableLog_; 56 } 57 58 private: 59 static constexpr int PERCENT_LENS = 2; 60 static constexpr int HUNDRED_TIME = 100; 61 GetMethodName()62 const std::string &GetMethodName() const 63 { 64 return methodName_; 65 } 66 67 // savePreType: save the previous type, which is true by default 68 bool UpdateType(GateRef gate, const GateType type, bool savePreType = true); 69 bool UpdateType(GateRef gate, const GlobalTSTypeRef &typeRef, bool savePreType = true); 70 GateType HandleTypeCompatibility(const GateType preType, const GateType type) const; 71 bool ShouldInfer(const GateRef gate) const; 72 bool Infer(GateRef gate); 73 bool InferPhiGate(GateRef gate); 74 bool SetIntType(GateRef gate); 75 bool SetNumberType(GateRef gate); 76 bool SetBigIntType(GateRef gate); 77 bool SetBooleanType(GateRef gate); 78 bool InferLdUndefined(GateRef gate); 79 bool InferLdNull(GateRef gate); 80 bool InferLdai(GateRef gate); 81 bool InferFLdai(GateRef gate); 82 bool InferLdSymbol(GateRef gate); 83 bool InferThrow(GateRef gate); 84 bool InferTypeOf(GateRef gate); 85 bool InferAdd2(GateRef gate); 86 bool InferSub2(GateRef gate); 87 bool InferMul2(GateRef gate); 88 bool InferMod2(GateRef gate); 89 bool InferDiv2(GateRef gate); 90 bool InferIncDec(GateRef gate); 91 bool InferToNumberic(GateRef gate); 92 bool InferLdObjByIndex(GateRef gate); 93 bool InferLdGlobalVar(GateRef gate); 94 bool InferReturnUndefined(GateRef gate); 95 bool InferReturn(GateRef gate); 96 bool InferLdObjByName(GateRef gate); 97 bool InferNewObject(GateRef gate); 98 bool SetStGlobalBcType(GateRef gate, bool hasIC = false); 99 bool InferLdStr(GateRef gate); 100 bool InferCallFunction(GateRef gate); 101 bool InferCallMethod(GateRef gate); 102 bool InferLdObjByValue(GateRef gate); 103 bool InferGetNextPropName(GateRef gate); 104 bool InferDefineGetterSetterByValue(GateRef gate); 105 bool InferSuperCall(GateRef gate); 106 bool InferSuperPropertyByName(GateRef gate); 107 bool InferSuperPropertyByValue(GateRef gate); 108 bool InferTryLdGlobalByName(GateRef gate); 109 bool InferLdLexVarDyn(GateRef gate); 110 bool InferStLexVarDyn(GateRef gate); 111 bool InferStModuleVar(GateRef gate); 112 bool InferLdLocalModuleVar(GateRef gate); 113 bool InferLdExternalModuleVar(GateRef gate); 114 bool InferStObjByName(GateRef gate); 115 bool IsNewLexEnv(EcmaOpcode opcode) const; 116 bool InferGetIterator(GateRef gate); 117 bool InferLoopBeginPhiGate(GateRef gate); 118 bool GetObjPropWithName(GateRef gate, GateType objType, uint64_t index); 119 bool GetSuperProp(GateRef gate, uint64_t index, bool isString = true); 120 GlobalTSTypeRef ConvertPrimitiveToBuiltin(const GateType &gateType); 121 GlobalTSTypeRef GetPropType(const GateType type, const JSTaggedValue propertyName) const; 122 GlobalTSTypeRef GetPropType(const GateType type, const uint64_t key) const; 123 void UpdateQueueForLoopPhi(); 124 ShouldInferWithLdObjByValue(const GateType & type)125 inline bool ShouldInferWithLdObjByValue(const GateType &type) const 126 { 127 auto flag = tsManager_->IsObjectTypeKind(type) || 128 tsManager_->IsClassTypeKind(type) || 129 tsManager_->IsClassInstanceTypeKind(type); 130 return flag; 131 } 132 ShouldInferWithLdObjByName(const GateType & type)133 inline bool ShouldInferWithLdObjByName(const GateType &type) const 134 { 135 return ShouldInferWithLdObjByValue(type) || tsManager_->IsIteratorInstanceTypeKind(type) || 136 tsManager_->IsInterfaceTypeKind(type) || tsManager_->IsNamespaceTypeKind(type); 137 } 138 ShouldConvertToBuiltinArray(const GateType & type)139 inline bool ShouldConvertToBuiltinArray(const GateType &type) const 140 { 141 return tsManager_->IsArrayTypeKind(type) && tsManager_->IsBuiltinsDTSEnabled(); 142 } 143 144 void PrintTypeAnnotation() const; 145 void PrintByteCodesWithTypes() const; 146 void PrintCircuitWithTypes() const; 147 void Verify() const; 148 void VerifyTypePercent(); 149 void TypeCheck(GateRef gate) const; 150 void PGOTypeCheck(GateRef gate) const; 151 void Enqueue(GateRef gate); 152 153 std::string CollectGateTypeLogInfo(GateRef gate, DebugInfoExtractor *debugExtractor, 154 const std::string &logPreFix, bool isPGO) const; 155 GetByteCodeInfo(const GateRef gate)156 const BytecodeInfo &GetByteCodeInfo(const GateRef gate) const 157 { 158 const auto bcIndex = jsgateToBytecode_.at(gate); 159 return builder_->GetBytecodeInfo(bcIndex); 160 } 161 162 std::pair<GateType, uint32_t> SetAndReturnNamespaceObjType(GateRef gate); 163 GlobalTSTypeRef TryGetNamespaceType(GateRef gate) const; 164 bool IsNamespace(GateRef gate) const; 165 bool CheckNamespaceFunc(GateRef func) const; 166 IsByteCodeGate(const GateRef gate)167 bool IsByteCodeGate(const GateRef gate) const 168 { 169 return jsgateToBytecode_.find(gate) != jsgateToBytecode_.end(); 170 } 171 172 BytecodeCircuitBuilder *builder_ {nullptr}; 173 Circuit *circuit_ {nullptr}; 174 GateAccessor gateAccessor_; 175 TSManager *tsManager_ {nullptr}; 176 PassContext *ctx_ {nullptr}; 177 LexEnvManager *lexEnvManager_ {nullptr}; 178 size_t methodId_ {0}; 179 bool enableLog_ {false}; 180 std::string methodName_; 181 std::map<uint16_t, GateType> stringIdToGateType_; 182 std::unordered_map<GateRef, uint32_t> jsgateToBytecode_ {}; 183 std::map<GateRef, InferState> loopPhiState_ {}; 184 const CString &recordName_; 185 size_t shouldInferNum_ {0}; 186 size_t normalInferNum_ {0}; 187 MethodInfo *methodInfo_ {nullptr}; 188 const MethodLiteral *methodLiteral_ {nullptr}; 189 std::vector<bool> inQueue_; 190 std::unordered_set<GateRef> needInferGates_ {}; 191 std::queue<GateRef> pendingQueue_ {}; 192 bool needUpdateForLoopPhi_ {true}; 193 bool enableGlobalTypeInfer_ {false}; 194 bool hasType_ {false}; 195 }; 196 } // namespace panda::ecmascript::kungfu 197 #endif // ECMASCRIPT_COMPILER_TYPE_INFERENCE_METHOD_TYPE_INFER_H 198