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