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_TYPE_INFER_H 17 #define ECMASCRIPT_COMPILER_TYPE_INFERENCE_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 TypeInfer { 37 public: TypeInfer(BytecodeCircuitBuilder * builder,Circuit * circuit,PassInfo * info,size_t methodId,bool enableLog,const std::string & name,const CString & recordName)38 TypeInfer(BytecodeCircuitBuilder *builder, Circuit *circuit, 39 PassInfo *info, size_t methodId, bool enableLog, 40 const std::string& name, const CString &recordName) 41 : builder_(builder), circuit_(circuit), 42 gateAccessor_(circuit), 43 tsManager_(info->GetTSManager()), 44 lexEnvManager_(info->GetLexEnvManager()), 45 methodId_(methodId), enableLog_(enableLog), 46 methodName_(name), recordName_(recordName), 47 inQueue_(circuit_->GetGateCount(), true) 48 { 49 } 50 51 ~TypeInfer() = default; 52 53 NO_COPY_SEMANTIC(TypeInfer); 54 NO_MOVE_SEMANTIC(TypeInfer); 55 56 void TraverseCircuit(); 57 IsLogEnabled()58 bool IsLogEnabled() const 59 { 60 return enableLog_; 61 } 62 GetMethodName()63 const std::string& GetMethodName() const 64 { 65 return methodName_; 66 } 67 68 private: 69 bool UpdateType(GateRef gate, const GateType type); 70 bool UpdateType(GateRef gate, const GlobalTSTypeRef &typeRef); 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 InferDiv2(GateRef gate); 89 bool InferIncDec(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 InferLdObjByValue(GateRef gate); 100 bool InferGetNextPropName(GateRef gate); 101 bool InferDefineGetterSetterByValue(GateRef gate); 102 bool InferSuperCall(GateRef gate); 103 bool InferSuperPropertyByName(GateRef gate); 104 bool InferSuperPropertyByValue(GateRef gate); 105 bool InferTryLdGlobalByName(GateRef gate); 106 bool InferLdLexVarDyn(GateRef gate); 107 bool InferStLexVarDyn(GateRef gate); 108 bool InferStModuleVar(GateRef gate); 109 bool InferLdLocalModuleVar(GateRef gate); 110 bool IsNewLexEnv(EcmaOpcode opcode) const; 111 bool InferGetIterator(GateRef gate); 112 bool InferLoopBeginPhiGate(GateRef gate); 113 bool GetObjPropWithName(GateRef gate, GateType objType, uint64_t index); 114 bool GetSuperProp(GateRef gate, uint64_t index, bool isString = true); 115 GlobalTSTypeRef ConvertPrimitiveToBuiltin(const GateType &gateType); 116 void UpdateQueueForLoopPhi(); 117 void TraverseInfer(); 118 GetPropType(const GateType & type,const JSTaggedValue propertyName)119 inline GlobalTSTypeRef GetPropType(const GateType &type, const JSTaggedValue propertyName) const 120 { 121 return tsManager_->GetPropType(type, propertyName); 122 } 123 GetPropType(const GateType & type,const uint64_t key)124 inline GlobalTSTypeRef GetPropType(const GateType &type, const uint64_t key) const 125 { 126 return tsManager_->GetPropType(type, key); 127 } 128 ShouldInferWithLdObjByValue(const GateType & type)129 inline bool ShouldInferWithLdObjByValue(const GateType &type) const 130 { 131 auto flag = tsManager_->IsObjectTypeKind(type) || 132 tsManager_->IsClassTypeKind(type) || 133 tsManager_->IsClassInstanceTypeKind(type); 134 return flag; 135 } 136 ShouldInferWithLdObjByName(const GateType & type)137 inline bool ShouldInferWithLdObjByName(const GateType &type) const 138 { 139 return ShouldInferWithLdObjByValue(type) || tsManager_->IsIteratorInstanceTypeKind(type) || 140 tsManager_->IsInterfaceTypeKind(type); 141 } 142 ShouldConvertToBuiltinArray(const GateType & type)143 inline bool ShouldConvertToBuiltinArray(const GateType &type) const 144 { 145 return tsManager_->IsArrayTypeKind(type) && tsManager_->IsBuiltinsDTSEnabled(); 146 } 147 148 void PrintAllByteCodesTypes() const; 149 void Verify() const; 150 void TypeCheck(GateRef gate) const; 151 void FilterAnyTypeGates() const; 152 153 std::string CollectGateTypeLogInfo(GateRef gate, DebugInfoExtractor *debugExtractor, 154 const std::string &logPreFix) 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 IsByteCodeGate(const GateRef gate)162 bool IsByteCodeGate(const GateRef gate) const 163 { 164 return jsgateToBytecode_.find(gate) != jsgateToBytecode_.end(); 165 } 166 167 BytecodeCircuitBuilder *builder_ {nullptr}; 168 Circuit *circuit_ {nullptr}; 169 GateAccessor gateAccessor_; 170 TSManager *tsManager_ {nullptr}; 171 LexEnvManager *lexEnvManager_ {nullptr}; 172 size_t methodId_ {0}; 173 bool enableLog_ {false}; 174 std::string methodName_; 175 std::map<uint16_t, GateType> stringIdToGateType_; 176 std::unordered_map<GateRef, uint32_t> jsgateToBytecode_ {}; 177 std::map<GateRef, InferState> loopPhiState_ {}; 178 const CString &recordName_; 179 std::vector<bool> inQueue_; 180 std::queue<GateRef> pendingQueue_ {}; 181 }; 182 } // namespace panda::ecmascript::kungfu 183 #endif // ECMASCRIPT_COMPILER_TYPE_INFERENCE_TYPE_INFER_H 184