diff --git a/ecmascript/compiler/bytecode_circuit_builder.h b/ecmascript/compiler/bytecode_circuit_builder.h index 5e2e8ad5de43fe552a5ba97020988bbc99ccf899..535ea765f5b096c4f3040b2271d5a03c4c47a359 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.h +++ b/ecmascript/compiler/bytecode_circuit_builder.h @@ -265,7 +265,7 @@ public: std::string name, const CString &recordName, PGOProfilerDecoder *decoder, - bool isInline) + bool isInline = false) : tsManager_(tsManager), circuit_(circuit), file_(jsPandaFile), method_(methodLiteral), gateAcc_(circuit), argAcc_(circuit, method_), typeRecorder_(jsPandaFile, method_, tsManager, recordName, decoder, methodPCInfo, bytecodes), diff --git a/ecmascript/compiler/bytecode_info_collector.cpp b/ecmascript/compiler/bytecode_info_collector.cpp index 6a03a7059c6b01ff083a3be4767c5beae59a943a..dfe08b85cf948c1b832bf50a1eac60ae3e777962 100644 --- a/ecmascript/compiler/bytecode_info_collector.cpp +++ b/ecmascript/compiler/bytecode_info_collector.cpp @@ -170,9 +170,10 @@ void BytecodeInfoCollector::CollectFunctionTypeId(panda_file::File::EntityId fie uint32_t typeId = annoExtractor.GetMethodTypeOffset(); if (typeId != 0) { bytecodeInfo_.SetFunctionTypeIDAndMethodOffset(typeId, offset); - } - if (annoExtractor.IsNamespace()) { - MarkMethodNamespace(offset); + } else if (annoExtractor.IsNamespace()) { + SetMethodKind(offset, TSMethodKind::NAMESPACE); + } else if (annoExtractor.IsEnum()) { + SetMethodKind(offset, TSMethodKind::ENUM); } } @@ -332,17 +333,18 @@ void BytecodeInfoCollector::CollectInnerMethods(uint32_t methodId, uint32_t inne methodList.emplace(innerMethodOffset, innerInfo); } -void BytecodeInfoCollector::MarkMethodNamespace(const uint32_t methodOffset) +void BytecodeInfoCollector::SetMethodKind(const uint32_t methodOffset, TSMethodKind kind) { auto &methodList = bytecodeInfo_.GetMethodList(); auto iter = methodList.find(methodOffset); if (iter != methodList.end()) { MethodInfo &methodInfo = iter->second; - methodInfo.MarkMethodNamespace(); + methodInfo.SetMethodKind(kind); return; } MethodInfo info(GetMethodInfoID(), 0, LexEnv::DEFAULT_ROOT, MethodInfo::DEFAULT_OUTMETHOD_OFFSET, - 0, LexicalEnvStatus::VIRTUAL_LEXENV, true); + 0, LexicalEnvStatus::VIRTUAL_LEXENV); + info.SetMethodKind(kind); methodList.emplace(methodOffset, info); } diff --git a/ecmascript/compiler/bytecode_info_collector.h b/ecmascript/compiler/bytecode_info_collector.h index 153ae3ae7a71b226754480d26cec0a4d23aa97cf..a297f4e433673ab692913dc7f7ce683e6e71d6a4 100644 --- a/ecmascript/compiler/bytecode_info_collector.h +++ b/ecmascript/compiler/bytecode_info_collector.h @@ -186,13 +186,19 @@ private: std::unordered_set starExportRecord_ {}; }; +enum class TSMethodKind : uint8_t { + DEFAULT, + NAMESPACE, + ENUM +}; + class MethodInfo { public: MethodInfo(uint32_t methodInfoIndex, uint32_t methodPcInfoIndex, uint32_t outMethodIdx, uint32_t outMethodOffset = MethodInfo::DEFAULT_OUTMETHOD_OFFSET, uint32_t num = 0, - LexicalEnvStatus lexEnvStatus = LexicalEnvStatus::VIRTUAL_LEXENV, bool isNamespace = false) + LexicalEnvStatus lexEnvStatus = LexicalEnvStatus::VIRTUAL_LEXENV) : methodInfoIndex_(methodInfoIndex), methodPcInfoIndex_(methodPcInfoIndex), outerMethodId_(outMethodIdx), - outerMethodOffset_(outMethodOffset), numOfLexVars_(num), status_(lexEnvStatus), isNamespace_(isNamespace) + outerMethodOffset_(outMethodOffset), numOfLexVars_(num), status_(lexEnvStatus) { } @@ -284,16 +290,6 @@ public: return bcToFuncTypeId_; } - inline void MarkMethodNamespace() - { - isNamespace_ = true; - } - - inline bool IsNamespace() const - { - return isNamespace_; - } - inline const std::vector &GetInnerMethods() const { return innerMethods_; @@ -354,6 +350,22 @@ public: CompileStateBit::ResolvedMethodBit::Set(isDeoptResolveNeed, &compileState_.value_); } + inline void SetMethodKind(TSMethodKind kind) + { + ASSERT(methodKind_ == TSMethodKind::DEFAULT); + methodKind_ = kind; + } + + inline bool IsNamespace() const + { + return methodKind_ == TSMethodKind::NAMESPACE; + } + + inline bool IsEnum() const + { + return methodKind_ == TSMethodKind::ENUM; + } + private: class CompileStateBit { public: @@ -386,7 +398,7 @@ private: LexicalEnvStatus status_ { LexicalEnvStatus::VIRTUAL_LEXENV }; std::set importIndex_ {}; CompileStateBit compileState_ { 0 }; - bool isNamespace_ {false}; + TSMethodKind methodKind_ { TSMethodKind::DEFAULT }; }; @@ -791,7 +803,7 @@ private: void CollectRecordReferenceREL(); void CollectRecordImportInfo(const CString &recordName); void CollectRecordExportInfo(const CString &recordName); - void MarkMethodNamespace(const uint32_t methodOffset); + void SetMethodKind(const uint32_t methodOffset, TSMethodKind kind); EcmaVM *vm_; JSPandaFile *jsPandaFile_ {nullptr}; diff --git a/ecmascript/compiler/type.h b/ecmascript/compiler/type.h index 82d85c0346f3602aecacf489dd26205b6ab5f2cd..d91727728b1e3df9910327622cc01d00c5a6405c 100644 --- a/ecmascript/compiler/type.h +++ b/ecmascript/compiler/type.h @@ -202,6 +202,11 @@ public: return (m == 0) && (l == static_cast(TSPrimitiveType::BIG_INT)); } + bool IsNullOrUndefinedType() const + { + return IsNullType() || IsUndefinedType(); + } + bool IsNJSValueType() const { return type_ == NJS_VALUE; diff --git a/ecmascript/compiler/type_inference/global_type_infer.cpp b/ecmascript/compiler/type_inference/global_type_infer.cpp index 3158d98a06711dfa4f4d843b794f881a83662e34..1a622e721016aa03196a1ddcf69ed1cb79097407 100644 --- a/ecmascript/compiler/type_inference/global_type_infer.cpp +++ b/ecmascript/compiler/type_inference/global_type_infer.cpp @@ -134,10 +134,14 @@ void GlobalTypeInfer::ProcessTypeInference(BytecodeCircuitBuilder *builder, Circ GateType type; std::tie(type, methodId) = infer->TraverseInfer(); if (IsLegalMethod(methodId)) { + if (tsManager->IsEnumTypeKind(type)) { + InferEnum(methodId, type); + continue; + } MethodTypeInfer *nextInfer = GetTypeInfer(methodId); if (nextInfer != nullptr) { - nextInfer->SetNamespaceArgType(type); - tsManager->StoreNamespaceType(methodId, type); + nextInfer->SetIIFEArgType(type); + tsManager->StoreIIFEObjType(methodId, type); typeInferStack.push(nextInfer); continue; } @@ -149,6 +153,34 @@ void GlobalTypeInfer::ProcessTypeInference(BytecodeCircuitBuilder *builder, Circ RunTypeCheck(); } +void GlobalTypeInfer::InferIIFE(const uint32_t methodOffset, GateType type) +{ + auto module = ctx_->GetAOTModule(); + auto &methodList = bcInfo_.GetMethodList(); + MethodInfo &methodInfo = methodList.at(methodOffset); + const auto &methodPcInfos = bcInfo_.GetMethodPcInfos(); + auto &methodPcInfo = methodPcInfos[methodInfo.GetMethodPcInfoIndex()]; + auto methodLiteral = jsPandaFile_->FindMethodLiteral(methodOffset); + std::string fullName = module->GetFuncName(methodLiteral, jsPandaFile_); + + Circuit circuit(ctx_->GetNativeAreaAllocator(), module->GetDebugInfo(), + fullName.c_str(), ctx_->GetCompilerConfig()->Is64Bit()); + circuit.SetFrameType(FrameType::OPTIMIZED_JS_FUNCTION_FRAME); + + BytecodeCircuitBuilder builder(jsPandaFile_, methodLiteral, methodPcInfo, ctx_->GetTSManager(), &circuit, + ctx_->GetByteCodes(), jsPandaFile_->HasTSTypes(recordName_), enableLog_, true, + fullName, recordName_, decoder_); + builder.BytecodeToCircuit(); + + MethodTypeInfer typeInfer(&builder, &circuit, ctx_, methodInfo.GetMethodInfoIndex(), + enableLog_, fullName, recordName_, &methodInfo, + methodLiteral, enableGlobalTypeInfer_); + typeInfer.SetIIFEArgType(type); + ctx_->GetTSManager()->StoreIIFEObjType(methodOffset, type); + typeInfer.TraverseInfer(); + typeInfer.CheckAndPrint(); +} + void GlobalTypeInfer::RunTypeCheck() { for (auto it : typeInfers_) { diff --git a/ecmascript/compiler/type_inference/global_type_infer.h b/ecmascript/compiler/type_inference/global_type_infer.h index 190cc0f63c03692f7f87ce86078afe37727ab0cf..9ba7d2352d43e83ba584f0bf539f2a4b9b93f061 100644 --- a/ecmascript/compiler/type_inference/global_type_infer.h +++ b/ecmascript/compiler/type_inference/global_type_infer.h @@ -44,9 +44,18 @@ private: return (methodOffset != 0); } + inline void InferEnum(const uint32_t methodId, GateType type) + { + if (inferredMethod_.find(methodId) == inferredMethod_.end()) { + InferIIFE(methodId, type); + inferredMethod_.insert(methodId); + } + } + void NewTypeInfer(const uint32_t methodOffset); void CollectNamespaceMethod(const uint32_t methodOffset); void CollectNamespaceMethods(const uint32_t methodOffset); + void InferIIFE(const uint32_t methodOffset, GateType type); void RunTypeCheck(); PassContext *ctx_ {nullptr}; @@ -61,6 +70,7 @@ private: std::vector builders_ {}; std::vector circuits_ {}; std::map typeInfers_ {}; + std::set inferredMethod_ {}; }; } // namespace panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_TYPE_INFERENCE_GLOBAL_TYPE_INFER_H diff --git a/ecmascript/compiler/type_inference/method_type_infer.cpp b/ecmascript/compiler/type_inference/method_type_infer.cpp index 220daaae9a71e664109e8f6075cad00cd4648fa8..4104f72e13e77bcae4342dd8be521f48ba035666 100644 --- a/ecmascript/compiler/type_inference/method_type_infer.cpp +++ b/ecmascript/compiler/type_inference/method_type_infer.cpp @@ -29,10 +29,10 @@ MethodTypeInfer::MethodTypeInfer(BytecodeCircuitBuilder *builder, Circuit *circu recordName_(recordName), methodInfo_(methodInfo), methodLiteral_(methodLiteral), inQueue_(circuit_->GetGateCount(), true), enableGlobalTypeInfer_(enableGlobalTypeInfer) { - if (enableGlobalTypeInfer_ && methodInfo->IsNamespace()) { + if (enableGlobalTypeInfer_ && (methodInfo->IsNamespace() || methodInfo->IsEnum())) { uint32_t methodOffset = methodLiteral_->GetMethodId().GetOffset(); - if (tsManager_->HasInferredNamespaceType(methodOffset)) { - SetNamespaceArgType(tsManager_->GetNamespaceObjType(methodOffset)); + if (tsManager_->HasInferredIIFEObjType(methodOffset)) { + SetIIFEArgType(tsManager_->GetIIFEObjType(methodOffset)); } } @@ -84,8 +84,12 @@ std::pair MethodTypeInfer::TraverseInfer() inQueue_[gateId] = true; pendingQueue_.push(*useIt); } - if (enableGlobalTypeInfer_ && IsNamespace(*useIt)) { - return SetAndReturnNamespaceObjType(*useIt); + if (!enableGlobalTypeInfer_) { + continue; + } + auto kind = IsIIFE(*useIt); + if (kind != TSMethodKind::DEFAULT) { + return SetAndReturnIIFEObjType(*useIt, kind); } } if (pendingQueue_.empty() && needUpdateForLoopPhi_) { @@ -346,6 +350,9 @@ bool MethodTypeInfer::Infer(GateRef gate) case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: return InferStObjByName(gate); + case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8: + case EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8: + return InferStObjByValue(gate); default: break; } @@ -372,7 +379,7 @@ bool MethodTypeInfer::InferPhiGate(GateRef gate) } if (valueInType.IsNumberType()) { numberTypeSet.insert(valueInType.GetGTRef()); - } else { + } else if (!valueInType.IsNullOrUndefinedType()) { typeList.emplace_back(valueInType.GetGTRef()); } } @@ -717,8 +724,9 @@ bool MethodTypeInfer::InferStObjByName(GateRef gate) uint16_t index = gateAccessor_.GetConstantValue(gateAccessor_.GetValueIn(gate, 1)); // 1: index of key JSTaggedValue propKey = tsManager_->GetStringFromConstantPool(index); - if (tsManager_->IsNamespaceTypeKind(receiverType)) { - tsManager_->AddNamespacePropType(receiverType, propKey, valueType); + if (tsManager_->IsNamespaceTypeKind(receiverType) || + tsManager_->IsEnumTypeKind(receiverType)) { + tsManager_->AddIIFEObjPropType(receiverType, propKey, valueType); return true; } @@ -734,6 +742,35 @@ bool MethodTypeInfer::InferStObjByName(GateRef gate) return false; } +bool MethodTypeInfer::InferStObjByValue(GateRef gate) +{ + GateRef value = gateAccessor_.GetValueIn(gate, 3); // 3: index of value + GateType valueType = gateAccessor_.GetGateType(value); + if (valueType.IsAnyType()) { + return false; + } + + GateRef receiver = gateAccessor_.GetValueIn(gate, 1); // 1: index of receiver + GateType receiverType = gateAccessor_.GetGateType(receiver); + if (!tsManager_->IsEnumTypeKind(receiverType)) { + return false; + } + + GateRef key = gateAccessor_.GetValueIn(gate, 2); // 2: index of key + if (!IsByteCodeGate(key)) { + return false; + } + auto &info = GetByteCodeInfo(key); + if (!info.IsBc(EcmaOpcode::LDA_STR_ID16)) { + return false; + } + + uint16_t index = gateAccessor_.GetConstantValue(gateAccessor_.GetValueIn(key, 0)); // 0: index of string + JSTaggedValue propKey = tsManager_->GetStringFromConstantPool(index); + tsManager_->AddIIFEObjPropType(receiverType, propKey, valueType); + return true; +} + bool MethodTypeInfer::InferNewObject(GateRef gate) { auto objType = gateAccessor_.GetGateType(gate); @@ -1166,9 +1203,9 @@ GlobalTSTypeRef MethodTypeInfer::GetPropType(const GateType type, const uint64_t return tsManager_->GetIndexSignType(objGT, GateType::NumberType()); } -// In TS, a namespace can be thought of as a formalization of the IIFE pattern. -// The function has only one parameter, which corresponds to the namespace object. -void MethodTypeInfer::SetNamespaceArgType(GateType type) +// In TS, a namespace/enum can be thought of as a formalization of the IIFE pattern. +// The function has only one parameter, which corresponds to the namespace/enum object. +void MethodTypeInfer::SetIIFEArgType(GateType type) { ArgumentAccessor argAcc(circuit_, methodLiteral_); // the last position is where the only parameter of the function are placed @@ -1176,68 +1213,77 @@ void MethodTypeInfer::SetNamespaceArgType(GateType type) gateAccessor_.SetGateType(gate, type); } -// When a IIFE which corresponds to namespaces declaration being called, -// A namespace type will be set to the namespace object. -std::pair MethodTypeInfer::SetAndReturnNamespaceObjType(GateRef gate) +// When a IIFE which corresponds to namespaces/enums declaration being called, +// A namespace/enum type will be set to the namespace/enum object. +std::pair MethodTypeInfer::SetAndReturnIIFEObjType(GateRef gate, TSMethodKind kind) { GateRef func = gateAccessor_.GetValueIn(gate, 1); // 1: index of func uint16_t id = gateAccessor_.GetConstantValue(gateAccessor_.GetValueIn(func, 0)); // 0: index of methodId GateRef obj = gateAccessor_.GetValueIn(gate, 0); // 0: index of obj - // the obj must be phi gate due to the conversion of syntax sugar of namespace + // the obj must be phi gate due to the conversion of syntax sugar of namespace/enum ASSERT(gateAccessor_.IsValueSelector(obj)); - GlobalTSTypeRef gt = TryGetNamespaceType(obj); + GlobalTSTypeRef gt = TryGetIIFEObjType(obj); uint32_t methodId = ctx_->GetJSPandaFile()->ResolveMethodIndex(methodLiteral_->GetMethodId(), id).GetOffset(); uint32_t length = gateAccessor_.GetNumValueIn(obj); for (uint32_t i = 0; i < length; i++) { - GateRef namespaceObj = gateAccessor_.GetValueIn(obj, i); - if (!IsByteCodeGate(namespaceObj)) { + GateRef value = gateAccessor_.GetValueIn(obj, i); + if (!IsByteCodeGate(value)) { continue; } - auto &bytecodeInfo = GetByteCodeInfo(namespaceObj); + auto &bytecodeInfo = GetByteCodeInfo(value); if (!bytecodeInfo.IsBc(EcmaOpcode::CREATEEMPTYOBJECT)) { continue; } if (gt.IsDefault()) { - gt = tsManager_->CreateNamespaceType(); + if (kind == TSMethodKind::NAMESPACE) { + gt = tsManager_->CreateNamespaceType(); + } else if (kind == TSMethodKind::ENUM) { + gt = tsManager_->CreateEnumType(); + } else { + continue; + } } - gateAccessor_.SetGateType(namespaceObj, GateType(gt)); + gateAccessor_.SetGateType(value, GateType(gt)); return std::make_pair(GateType(gt), methodId); } return std::make_pair((GateType(gt)), methodId); } -GlobalTSTypeRef MethodTypeInfer::TryGetNamespaceType(GateRef gate) const +GlobalTSTypeRef MethodTypeInfer::TryGetIIFEObjType(GateRef gate) const { ASSERT(gateAccessor_.IsValueSelector(gate)); uint32_t length = gateAccessor_.GetNumValueIn(gate); for (uint32_t i = 0; i < length; i++) { - GateRef namespaceObj = gateAccessor_.GetValueIn(gate, i); - GateType type = gateAccessor_.GetGateType(namespaceObj); - GlobalTSTypeRef namespaceGT(type.Value()); - if (tsManager_->IsNamespaceTypeKind(namespaceGT)) { - return namespaceGT; + GateRef obj = gateAccessor_.GetValueIn(gate, i); + GateType type = gateAccessor_.GetGateType(obj); + GlobalTSTypeRef objGT(type.Value()); + if (tsManager_->IsNamespaceTypeKind(objGT) || + tsManager_->IsEnumTypeKind(objGT)) { + return objGT; } } return GlobalTSTypeRef::Default(); } -bool MethodTypeInfer::IsNamespace(GateRef gate) const +TSMethodKind MethodTypeInfer::IsIIFE(GateRef gate) const { if (IsByteCodeGate(gate)) { auto &bytecodeInfo = GetByteCodeInfo(gate); if (bytecodeInfo.IsBc(EcmaOpcode::CALLARG1_IMM8_V8)) { GateRef obj = gateAccessor_.GetValueIn(gate, 0); // 0: index of obj GateRef func = gateAccessor_.GetValueIn(gate, 1); // 1: index of func - return CheckNamespaceFunc(func) && gateAccessor_.IsValueSelector(obj); + if (gateAccessor_.IsValueSelector(obj)) { + return CheckIIFEFunc(func); + } } } - return false; + return TSMethodKind::DEFAULT; } -bool MethodTypeInfer::CheckNamespaceFunc(GateRef func) const +TSMethodKind MethodTypeInfer::CheckIIFEFunc(GateRef func) const { if (IsByteCodeGate(func)) { auto &bytecodeInfo = GetByteCodeInfo(func); @@ -1249,10 +1295,14 @@ bool MethodTypeInfer::CheckNamespaceFunc(GateRef func) const auto &bcInfo = ctx_->GetBytecodeInfo(); auto &methodLists = bcInfo.GetMethodList(); auto &methodInfo = methodLists.at(methodId); - return methodInfo.IsNamespace(); + if (methodInfo.IsNamespace()) { + return TSMethodKind::NAMESPACE; + } else if (methodInfo.IsEnum()) { + return TSMethodKind::ENUM; + } } } - return false; + return TSMethodKind::DEFAULT; } void MethodTypeInfer::PrintTypeAnnotation() const diff --git a/ecmascript/compiler/type_inference/method_type_infer.h b/ecmascript/compiler/type_inference/method_type_infer.h index 072e17290a244aa40c963830856895a2e05b76bf..fd340954c0965c87fc565229f155a6dc082ed82c 100644 --- a/ecmascript/compiler/type_inference/method_type_infer.h +++ b/ecmascript/compiler/type_inference/method_type_infer.h @@ -47,7 +47,7 @@ public: std::pair TraverseInfer(); void CheckAndPrint(); - void SetNamespaceArgType(GateType type); + void SetIIFEArgType(GateType type); bool IsLogEnabled() const { @@ -107,6 +107,7 @@ private: bool InferLdLocalModuleVar(GateRef gate); bool InferLdExternalModuleVar(GateRef gate); bool InferStObjByName(GateRef gate); + bool InferStObjByValue(GateRef gate); bool IsNewLexEnv(EcmaOpcode opcode) const; bool InferGetIterator(GateRef gate); bool InferLoopBeginPhiGate(GateRef gate); @@ -127,8 +128,11 @@ private: inline bool ShouldInferWithLdObjByName(const GateType &type) const { - return ShouldInferWithLdObjByValue(type) || tsManager_->IsIteratorInstanceTypeKind(type) || - tsManager_->IsInterfaceTypeKind(type) || tsManager_->IsNamespaceTypeKind(type); + return ShouldInferWithLdObjByValue(type) || + tsManager_->IsIteratorInstanceTypeKind(type) || + tsManager_->IsInterfaceTypeKind(type) || + tsManager_->IsNamespaceTypeKind(type) || + tsManager_->IsEnumTypeKind(type); } inline bool ShouldConvertToBuiltinArray(const GateType &type) const @@ -152,10 +156,10 @@ private: return builder_->GetBytecodeInfo(bcIndex); } - std::pair SetAndReturnNamespaceObjType(GateRef gate); - GlobalTSTypeRef TryGetNamespaceType(GateRef gate) const; - bool IsNamespace(GateRef gate) const; - bool CheckNamespaceFunc(GateRef func) const; + std::pair SetAndReturnIIFEObjType(GateRef gate, TSMethodKind kind); + GlobalTSTypeRef TryGetIIFEObjType(GateRef gate) const; + TSMethodKind IsIIFE(GateRef gate) const; + TSMethodKind CheckIIFEFunc(GateRef func) const; bool IsByteCodeGate(const GateRef gate) const { diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index 9b2178ba3a7b0bdb584f5c1d94e6d3d4d5328a3d..78a9950877097cd69720f6b283f7b27d90f2da12 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -373,6 +373,8 @@ CString JSHClass::DumpJSType(JSType type) return "TSIteratorInstanceType"; case JSType::TS_NAMESPACE_TYPE: return "TSNamespaceType"; + case JSType::TS_ENUM_TYPE: + return "TSEnumType"; case JSType::JS_API_ARRAYLIST_ITERATOR: return "JSArraylistIterator"; case JSType::LINKED_NODE: @@ -969,6 +971,9 @@ static void DumpObject(TaggedObject *obj, std::ostream &os) case JSType::TS_NAMESPACE_TYPE: TSNamespaceType::Cast(obj)->Dump(os); break; + case JSType::TS_ENUM_TYPE: + TSEnumType::Cast(obj)->Dump(os); + break; case JSType::LINKED_NODE: case JSType::RB_TREENODE: break; @@ -3397,7 +3402,27 @@ void TSNamespaceType::Dump(std::ostream &os) const os << localTypeId; os << "\n"; os << " - Properties: "; - DumpArrayClass(TaggedArray::Cast(GetPropertyType().GetTaggedObject()), os); + DumpArrayClass(TaggedArray::Cast(GetObjLayoutInfo().GetTaggedObject()), os); +} + +void TSEnumType::Dump(std::ostream &os) const +{ + os << " - Dump Enum Type - " << "\n"; + os << " - TSEnumType globalTSTypeRef: "; + GlobalTSTypeRef gt = GetGT(); + uint64_t globalTSTypeRef = gt.GetType(); + os << globalTSTypeRef; + os << "\n"; + os << " - TSEnumType moduleId: "; + uint32_t moduleId = gt.GetModuleId(); + os << moduleId; + os << "\n"; + os << " - TSEnumType localTypeId: "; + uint32_t localTypeId = gt.GetLocalId(); + os << localTypeId; + os << "\n"; + os << " - Properties: "; + DumpArrayClass(TaggedArray::Cast(GetObjLayoutInfo().GetTaggedObject()), os); } void SourceTextModule::Dump(std::ostream &os) const @@ -4109,6 +4134,9 @@ static void DumpObject(TaggedObject *obj, case JSType::TS_NAMESPACE_TYPE: TSNamespaceType::Cast(obj)->DumpForSnapshot(vec); return; + case JSType::TS_ENUM_TYPE: + TSEnumType::Cast(obj)->DumpForSnapshot(vec); + return; case JSType::METHOD: Method::Cast(obj)->DumpForSnapshot(vec); return; @@ -5308,7 +5336,14 @@ void TSIteratorInstanceType::DumpForSnapshot(std::vector> &vec) const { - vec.emplace_back("PropertyType", GetPropertyType()); + vec.emplace_back("ObjLayoutInfo", GetObjLayoutInfo()); + vec.emplace_back("IndexSigns", GetIndexSigns()); +} + +void TSEnumType::DumpForSnapshot(std::vector> &vec) const +{ + vec.emplace_back("ObjLayoutInfo", GetObjLayoutInfo()); + vec.emplace_back("IndexSigns", GetIndexSigns()); } void SourceTextModule::DumpForSnapshot(std::vector> &vec) const diff --git a/ecmascript/global_env_constants.cpp b/ecmascript/global_env_constants.cpp index 47b2ae39d1a37b318b7be1688da0002ad1fd6b98..50c1f5b19b6328c20ebb20098bd820adfeae2593 100644 --- a/ecmascript/global_env_constants.cpp +++ b/ecmascript/global_env_constants.cpp @@ -229,6 +229,8 @@ void GlobalEnvConstants::InitRootsClass(JSThread *thread, JSHClass *hClass) JSType::TS_ITERATOR_INSTANCE_TYPE)); SetConstant(ConstantIndex::TS_NAMESPACE_TYPE_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, TSNamespaceType::SIZE, JSType::TS_NAMESPACE_TYPE)); + SetConstant(ConstantIndex::TS_ENUM_TYPE_CLASS_INDEX, + factory->NewEcmaReadOnlyHClass(hClass, TSEnumType::SIZE, JSType::TS_ENUM_TYPE)); SetConstant(ConstantIndex::JS_REGEXP_ITERATOR_CLASS_INDEX, factory->NewEcmaHClass(hClass, JSRegExpIterator::SIZE, JSType::JS_REG_EXP_ITERATOR)); SetConstant(ConstantIndex::JS_SET_ITERATOR_CLASS_INDEX, diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index 22e0cf14b0542fdbe7538c1980afa1cae7183c4a..b2a07fe2538e4e967a201a46d76e20f875e7e072 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -92,6 +92,7 @@ class ObjectFactory; V(JSTaggedValue, TSArrayTypeClass, TS_ARRAY_TYPE_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, TSIteratorInstanceTypeClass, TS_ITERATOR_INSTANCE_TYPE_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, TSNamespaceTypeClass, TS_NAMESPACE_TYPE_CLASS_INDEX, ecma_roots_class) \ + V(JSTaggedValue, TSEnumTypeClass, TS_ENUM_TYPE_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, JSSetIteratorClass, JS_SET_ITERATOR_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, JSRegExpIteratorClass, JS_REGEXP_ITERATOR_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, JSMapIteratorClass, JS_MAP_ITERATOR_CLASS_INDEX, ecma_roots_class) \ diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index 66f30431e8db03d1a0aff4cc1422087eba8eaf0c..714c0241d8475f6e4448534c921125cac3e05b9b 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -247,6 +247,7 @@ class PropertyLookupResult; TS_INTERFACE_TYPE, /* //////////////////////////////////////////////////////////////////////////-PADDING */ \ TS_ITERATOR_INSTANCE_TYPE, /* //////////////////////////////////////////////////////////////////-PADDING */ \ TS_NAMESPACE_TYPE, /* ////////////////////////////////////////////////////////////////////////////-PADDING */ \ + TS_ENUM_TYPE, /* /////////////////////////////////////////////////////////////////////////////////-PADDING */ \ \ VTABLE, /* //////////////////////////////////////////////////////////////////-PADDING */ \ AOT_LITERAL_INFO, /* //////////////////////////////////////////////////////////////////////////////-PADDING */ \ @@ -277,7 +278,7 @@ class PropertyLookupResult; MODULE_RECORD_LAST = SOURCE_TEXT_MODULE_RECORD, /* ////////////////////////////////////////////////-PADDING */ \ \ TS_TYPE_FIRST = TS_ARRAY_TYPE, /* /////////////////////////////////////////////////////////////////-PADDING */ \ - TS_TYPE_LAST = TS_NAMESPACE_TYPE, /* ///////////////////////////////////////////////////////////////-PADDING */\ + TS_TYPE_LAST = TS_ENUM_TYPE, /* ////////////////////////////////////////////////////////////////////-PADDING */\ \ STRING_FIRST = LINE_STRING, /* /////////////////////////////////////////////////////////////////////-PADDING */\ STRING_LAST = TREE_STRING /* /////////////////////////////////////////////////////////////////////-PADDING */ @@ -1353,7 +1354,10 @@ public: inline bool IsTSObjectType() const { - return GetObjectType() == JSType::TS_OBJECT_TYPE; + JSType jsType = GetObjectType(); + return jsType == JSType::TS_OBJECT_TYPE || + jsType == JSType::TS_NAMESPACE_TYPE || + jsType == JSType::TS_ENUM_TYPE; } inline bool IsTSClassType() const @@ -1396,6 +1400,11 @@ public: return GetObjectType() == JSType::TS_NAMESPACE_TYPE; } + inline bool IsTSEnumType() const + { + return GetObjectType() == JSType::TS_ENUM_TYPE; + } + inline bool IsAOTLiteralInfo() const { return GetObjectType() == JSType::AOT_LITERAL_INFO; diff --git a/ecmascript/js_runtime_options.cpp b/ecmascript/js_runtime_options.cpp index 5a7cc3ab5721957a47050639b6ba707890802d05..d79a94358e9c6418e21b0c7bbf654f8043da57b0 100644 --- a/ecmascript/js_runtime_options.cpp +++ b/ecmascript/js_runtime_options.cpp @@ -63,7 +63,7 @@ const std::string PUBLIC_API HELP_OPTION_MSG = "Default: 'none'\n" "--compiler-type-threshold: enable to skip methods whose type is no more than threshold. Default: -1\n" "--compiler-log-snapshot: Enable to print snapshot information. Default: 'false'\n" - "--compiler-opt-global-typeinfer: Enable global typeinfer for aot compiler: Default: 'false'\n" + "--compiler-opt-global-typeinfer: Enable global typeinfer for aot compiler: Default: 'true'\n" "--compiler-log-time: Enable to print pass compiler time. Default: 'false'\n" "--enable-ark-tools: Enable ark tools to debug. Default: 'false'\n" "--compiler-trace-bc: Enable tracing bytecode for aot runtime. Default: 'false'\n" diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index 1086bd451db530a3ec15a1ed47060d43c6ec94dd..fdf941b3bbbbf286d10fffd647eb0f6fb6cb5aeb 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -1204,7 +1204,7 @@ private: bool enableValueNumbering_ {true}; bool enableOptInlining_ {false}; bool enableOptPGOType_ {true}; - bool enableGlobalTypeInfer_ {false}; + bool enableGlobalTypeInfer_ {true}; uint32_t compilerModuleMethods_ {100}; uint64_t wasSet_ {0}; bool enablePrintExecuteTime_ {false}; diff --git a/ecmascript/js_tagged_value-inl.h b/ecmascript/js_tagged_value-inl.h index 0d5be6ffa8a67d885388e16d3e275ddfda664201..d3f18be9048e49350d348837419b4a1305d6cc6a 100644 --- a/ecmascript/js_tagged_value-inl.h +++ b/ecmascript/js_tagged_value-inl.h @@ -1334,6 +1334,11 @@ inline bool JSTaggedValue::IsTSNamespaceType() const return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSNamespaceType(); } +inline bool JSTaggedValue::IsTSEnumType() const +{ + return IsHeapObject() && GetTaggedObject()->GetClass()->IsTSEnumType(); +} + inline bool JSTaggedValue::IsModuleRecord() const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsModuleRecord(); diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index afe68e793aa366c03794a6cda1a9cbadf04a899a..c32d49e4f0df410bae0aaa05f6eac006c0d5a3c8 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -675,6 +675,7 @@ public: bool IsTSArrayType() const; bool IsTSIteratorInstanceType() const; bool IsTSNamespaceType() const; + bool IsTSEnumType() const; bool IsCjsExports() const; bool IsCjsModule() const; diff --git a/ecmascript/jspandafile/type_literal_extractor.cpp b/ecmascript/jspandafile/type_literal_extractor.cpp index 38d46813ecc52a33cdc7f0eb61e8ff3e557f3b2a..02163216670d14277cf639e35ef4ec5a661cfd6f 100644 --- a/ecmascript/jspandafile/type_literal_extractor.cpp +++ b/ecmascript/jspandafile/type_literal_extractor.cpp @@ -284,10 +284,9 @@ void TypeAnnotationExtractor::CollectTSMethodKind() return; } - if (typeIds_[i] == METHOD_ANNOTATION_NAMESPACE) { - isNamespace_ = true; - } + methodKind_ = static_cast(typeIds_[i]); typeIds_[i] = 0; // set default value + return; } } @@ -297,7 +296,7 @@ void TypeAnnotationExtractor::Print() const ASSERT(bcOffsets_.size() == typeIds_.size()); ASSERT(tags_.size() == typeIds_.size()); LOG_COMPILER(INFO) << "===================================================================="; - LOG_COMPILER(INFO) << "[TypeAnnotation]"; + LOG_COMPILER(INFO) << "[TypeAnnotation] " << PrintMethodKind(); uint32_t length = bcOffsets_.size(); for (uint32_t i = 0; i < length; ++i) { LOG_COMPILER(INFO) << "Order of bytecodes: " << std::setw(typeRightAdjustment) << bcOffsets_[i] << ", " @@ -306,6 +305,16 @@ void TypeAnnotationExtractor::Print() const } } +std::string TypeAnnotationExtractor::PrintMethodKind() const +{ + if (IsNamespace()) { + return "Method kind: namespace"; + } else if (IsEnum()) { + return "Method kind: enum"; + } + return ""; +} + std::string TypeAnnotationExtractor::PrintTag(LiteralTag tag) const { switch (tag) { diff --git a/ecmascript/jspandafile/type_literal_extractor.h b/ecmascript/jspandafile/type_literal_extractor.h index f884c622938f438f5d456b691bb802a06a49aff3..cfb9629271178e14a6153b8fadab74a93bca16f7 100644 --- a/ecmascript/jspandafile/type_literal_extractor.h +++ b/ecmascript/jspandafile/type_literal_extractor.h @@ -188,7 +188,12 @@ public: bool IsNamespace() const { - return isNamespace_; + return methodKind_ == METHOD_ANNOTATION_NAMESPACE; + } + + bool IsEnum() const + { + return methodKind_ == METHOD_ANNOTATION_ENUM; } void Print() const; @@ -196,18 +201,19 @@ public: private: static constexpr const char *TYPE_ANNO_ELEMENT_NAME = "_TypeOfInstruction"; static constexpr int METHOD_ANNOTATION_FUNCTION_TYPE_OFFSET = -1; - static constexpr int METHOD_ANNOTATION_NAMESPACE = 255; - static constexpr int METHOD_ANNOTATION_ENUM = 254; + static constexpr uint8_t METHOD_ANNOTATION_NAMESPACE = 255; + static constexpr uint8_t METHOD_ANNOTATION_ENUM = 254; void ProcessTypeAnnotation(const JSPandaFile *jsPandaFile, const uint32_t methodOffset); void CollectTSMethodKind(); std::string PrintTag(LiteralTag tag) const; + std::string PrintMethodKind() const; uint32_t methodTypeOffset_ {0}; std::vector bcOffsets_ {}; std::vector typeIds_ {}; std::vector tags_ {}; - bool isNamespace_ {false}; + uint8_t methodKind_ {0}; }; class ExportTypeTableExtractor { diff --git a/ecmascript/mem/object_xray.h b/ecmascript/mem/object_xray.h index badfbaeef4cf182c832a776a907aa477e2f35a54..2751adeb899d65802167abf039cb725ae0ab8266 100644 --- a/ecmascript/mem/object_xray.h +++ b/ecmascript/mem/object_xray.h @@ -512,6 +512,9 @@ public: case JSType::TS_NAMESPACE_TYPE: TSNamespaceType::Cast(object)->VisitRangeSlot(visitor); break; + case JSType::TS_ENUM_TYPE: + TSEnumType::Cast(object)->VisitRangeSlot(visitor); + break; case JSType::RB_TREENODE: RBTreeNode::Cast(object)->VisitRangeSlot(visitor); break; diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index 99b20013a6d18f7e127ee717b37eae2a138d2a98..74ef1520735ea1e4c7a1acc66c8af850dc866177 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -3282,7 +3282,6 @@ JSHandle ObjectFactory::NewTSInterfaceType() return interfaceType; } - JSHandle ObjectFactory::NewTSUnionType(uint32_t length) { NewObjectHook(); @@ -3401,11 +3400,29 @@ JSHandle ObjectFactory::NewTSNamespaceType() JSHClass::Cast(thread_->GlobalConstants()->GetTSNamespaceTypeClass().GetTaggedObject())); JSHandle namespaceType(thread_, header); - namespaceType->SetPropertyType(thread_, JSTaggedValue::Undefined()); + namespaceType->SetObjLayoutInfo(thread_, JSTaggedValue::Undefined()); + namespaceType->SetIndexSigns(thread_, JSTaggedValue::Undefined()); + namespaceType->SetGT(GlobalTSTypeRef::Default()); JSHandle tsPropInfo = CreateTSObjLayoutInfo(TSObjLayoutInfo::DEFAULT_CAPACITY); - namespaceType->SetPropertyType(thread_, tsPropInfo); + namespaceType->SetObjLayoutInfo(thread_, tsPropInfo); return namespaceType; } + +JSHandle ObjectFactory::NewTSEnumType() +{ + NewObjectHook(); + + TaggedObject *header = heap_->AllocateYoungOrHugeObject( + JSHClass::Cast(thread_->GlobalConstants()->GetTSEnumTypeClass().GetTaggedObject())); + JSHandle enumType(thread_, header); + + enumType->SetObjLayoutInfo(thread_, JSTaggedValue::Undefined()); + enumType->SetIndexSigns(thread_, JSTaggedValue::Undefined()); + enumType->SetGT(GlobalTSTypeRef::Default()); + JSHandle valueInfo = CreateTSObjLayoutInfo(TSObjLayoutInfo::DEFAULT_CAPACITY); + enumType->SetObjLayoutInfo(thread_, valueInfo); + return enumType; +} // ----------------------------------- new string ---------------------------------------- JSHandle ObjectFactory::NewFromASCII(const CString &data) { diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index 295819396723d054511bfcbacf1dc1af93ade307..7389092912d7cb5ecbddc9fed01e7200e64ba591 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -107,6 +107,7 @@ class TSFunctionType; class TSArrayType; class TSIteratorInstanceType; class TSNamespaceType; +class TSEnumType; class JSAPIArrayList; class JSAPIArrayListIterator; class JSAPIDeque; @@ -512,6 +513,7 @@ public: JSHandle NewTSArrayType(); JSHandle NewTSIteratorInstanceType(); JSHandle NewTSNamespaceType(); + JSHandle NewTSEnumType(); // ----------------------------------- new string ---------------------------------------- JSHandle NewFromASCII(const CString &data); diff --git a/ecmascript/tests/dump_test.cpp b/ecmascript/tests/dump_test.cpp index 5eab10144c5c75643cb2302acf87caeb63d9006d..f9bba544de236ab3e7f06d128359db48fbc68f37 100644 --- a/ecmascript/tests/dump_test.cpp +++ b/ecmascript/tests/dump_test.cpp @@ -1037,11 +1037,17 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump) break; } case JSType::TS_NAMESPACE_TYPE: { - CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSNamespaceType::SIZE, 2U); + CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSNamespaceType::SIZE, 3U); JSHandle namespaceType = factory->NewTSNamespaceType(); DUMP_FOR_HANDLE(namespaceType) break; } + case JSType::TS_ENUM_TYPE: { + CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), TSEnumType::SIZE, 3U); + JSHandle enumType = factory->NewTSEnumType(); + DUMP_FOR_HANDLE(enumType) + break; + } case JSType::JS_API_ARRAY_LIST: { // 1 : 1 dump fileds number CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPIArrayList::SIZE, 1U); diff --git a/ecmascript/ts_types/global_ts_type_ref.h b/ecmascript/ts_types/global_ts_type_ref.h index 2e2309011834e1d55520c406d63dbfdd2b09be94..472c56639cbbf1daffeba765ebc0ee11ab8f2044 100644 --- a/ecmascript/ts_types/global_ts_type_ref.h +++ b/ecmascript/ts_types/global_ts_type_ref.h @@ -38,6 +38,7 @@ enum class TSTypeKind : uint8_t { // the following typekinds are not recorded in abc files and will be created at compile time ITERATOR_INSTANCE, NAMESPACE, + ENUM, UNKNOWN, TYPEKIND_FIRST = CLASS, diff --git a/ecmascript/ts_types/ts_manager.cpp b/ecmascript/ts_types/ts_manager.cpp index dee6cade6aa34dd4c589e6df81b4158d9e8fc922..b655b79c1511cc1acd8fc7791b8292cc3d6d8c84 100644 --- a/ecmascript/ts_types/ts_manager.cpp +++ b/ecmascript/ts_types/ts_manager.cpp @@ -176,14 +176,10 @@ GlobalTSTypeRef TSManager::GetPropType(GlobalTSTypeRef gt, JSHandleIsTSInterfaceType()) { JSHandle interfaceType(type); return TSInterfaceType::GetPropTypeGT(thread, interfaceType, propertyName); - } else if (type->IsTSNamespaceType()) { - JSHandle namespaceType(type); - return TSNamespaceType::GetPropTypeGT(thread, namespaceType, propertyName); } return GlobalTSTypeRef::Default(); } - GlobalTSTypeRef TSManager::GetIndexSignType(GlobalTSTypeRef objType, kungfu::GateType indexType) const { JSThread *thread = vm_->GetJSThread(); @@ -316,6 +312,8 @@ TSTypeKind TSManager::GetTypeKind(const GlobalTSTypeRef >) const return TSTypeKind::ITERATOR_INSTANCE; case JSType::TS_NAMESPACE_TYPE: return TSTypeKind::NAMESPACE; + case JSType::TS_ENUM_TYPE: + return TSTypeKind::ENUM; default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); @@ -635,13 +633,18 @@ GlobalTSTypeRef TSManager::CreateNamespaceType() return AddTSTypeToInferredTable(JSHandle(namespaceType)); } -void TSManager::AddNamespacePropType(kungfu::GateType objType, JSTaggedValue name, kungfu::GateType valueType) +GlobalTSTypeRef TSManager::CreateEnumType() +{ + JSHandle enumType = factory_->NewTSEnumType(); + return AddTSTypeToInferredTable(JSHandle(enumType)); +} + +void TSManager::AddIIFEObjPropType(kungfu::GateType objType, JSTaggedValue name, kungfu::GateType valueType) { JSHandle tsType = GetTSType(GlobalTSTypeRef(objType.Value())); - JSHandle namespaceType(tsType); JSHandle key(thread_, name); JSHandle value(thread_, JSTaggedValue(valueType.Value())); - TSNamespaceType::AddKeyAndValue(thread_, namespaceType, key, value); + TSObjectType::AddKeyAndValue(thread_, JSHandle(tsType), key, value); } GlobalTSTypeRef TSManager::GetClassType(GlobalTSTypeRef classInstanceGT) const @@ -1046,6 +1049,8 @@ std::string TSManager::GetTypeStr(kungfu::GateType gateType) const return "unknown"; case TSTypeKind::NAMESPACE: return "namespace"; + case TSTypeKind::ENUM: + return "enum"; default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); diff --git a/ecmascript/ts_types/ts_manager.h b/ecmascript/ts_types/ts_manager.h index 229b5954d1d00c77bf8e9e10ee1c357e52972fcf..bf6a8fda57506e7694e25497dfe045fe04754f67 100644 --- a/ecmascript/ts_types/ts_manager.h +++ b/ecmascript/ts_types/ts_manager.h @@ -369,7 +369,9 @@ public: GlobalTSTypeRef PUBLIC_API CreateNamespaceType(); - void AddNamespacePropType(kungfu::GateType objType, JSTaggedValue name, kungfu::GateType valueType); + GlobalTSTypeRef PUBLIC_API CreateEnumType(); + + void AddIIFEObjPropType(kungfu::GateType objType, JSTaggedValue name, kungfu::GateType valueType); inline bool IsUserDefinedClassTypeKind(const kungfu::GateType &gateType) const { @@ -382,18 +384,18 @@ public: return IsClassTypeKind(gt) && (!gt.IsBuiltinModule()); } - inline void StoreNamespaceType(const uint32_t methodOffset, const kungfu::GateType type) + inline void StoreIIFEObjType(const uint32_t methodOffset, const kungfu::GateType type) { methodOffsetToType_.insert(std::make_pair(methodOffset, type)); } - inline kungfu::GateType GetNamespaceObjType(const uint32_t methodOffset) const + inline kungfu::GateType GetIIFEObjType(const uint32_t methodOffset) const { - ASSERT(HasInferredNamespaceType(methodOffset)); + ASSERT(HasInferredIIFEObjType(methodOffset)); return methodOffsetToType_.at(methodOffset); } - inline bool HasInferredNamespaceType(const uint32_t methodOffset) const + inline bool HasInferredIIFEObjType(const uint32_t methodOffset) const { return methodOffsetToType_.find(methodOffset) != methodOffsetToType_.end(); } @@ -419,7 +421,8 @@ public: V(Import, TSTypeKind::IMPORT) \ V(Interface, TSTypeKind::INTERFACE) \ V(IteratorInstance, TSTypeKind::ITERATOR_INSTANCE) \ - V(Namespace, TSTypeKind::NAMESPACE) + V(Namespace, TSTypeKind::NAMESPACE) \ + V(Enum, TSTypeKind::ENUM) #define IS_TSTYPEKIND(NAME, TSTYPEKIND) \ inline bool PUBLIC_API Is##NAME##TypeKind(const kungfu::GateType &gateType) const \ diff --git a/ecmascript/ts_types/ts_type.cpp b/ecmascript/ts_types/ts_type.cpp index d8976d5fb7e7a150b4b8442db03cc0e44a8aded7..496814085381e490866b66c67775d9cea2b57563 100644 --- a/ecmascript/ts_types/ts_type.cpp +++ b/ecmascript/ts_types/ts_type.cpp @@ -219,6 +219,10 @@ GlobalTSTypeRef TSObjectType::GetPropTypeGT(JSThread *thread, JSHandle propName) { DISALLOW_GARBAGE_COLLECTION; + if (objectType->GetObjLayoutInfo().IsUndefined()) { + return GlobalTSTypeRef::Default(); + } + JSHandle layout(thread, objectType->GetObjLayoutInfo().GetTaggedObject()); uint32_t numOfProps = layout->GetNumOfProperties(); JSMutableHandle propKey(thread, JSTaggedValue::Undefined()); @@ -266,6 +270,17 @@ GlobalTSTypeRef TSObjectType::GetIndexSignType(JSThread *thread, const JSHandle< return GlobalTSTypeRef::Default(); } +void TSObjectType::AddKeyAndValue(const JSThread *thread, const JSHandle &enumType, + const JSHandle &key, const JSHandle &value) +{ + JSHandle propLayout(thread, enumType->GetObjLayoutInfo()); + if (propLayout->Find(key.GetTaggedValue())) { + return; + } + JSHandle newPropLayout = TSObjLayoutInfo::PushBack(thread, propLayout, key, value); + enumType->SetObjLayoutInfo(thread, newPropLayout.GetTaggedValue()); +} + GlobalTSTypeRef TSFunctionType::GetParameterTypeGT(int index) const { DISALLOW_GARBAGE_COLLECTION; @@ -363,44 +378,4 @@ GlobalTSTypeRef TSInterfaceType::GetIndexSignType(JSThread *thread, const JSHand } return GlobalTSTypeRef::Default(); } - - -void TSNamespaceType::AddKeyAndValue(const JSThread *thread, const JSHandle &namespaceType, - const JSHandle &key, const JSHandle &value) -{ - JSHandle propLayout(thread, namespaceType->GetPropertyType()); - if (propLayout->Find(key.GetTaggedValue())) { - return; - } - JSHandle newPropLayout = TSObjLayoutInfo::PushBack(thread, propLayout, key, value); - namespaceType->SetPropertyType(thread, newPropLayout.GetTaggedValue()); -} - -GlobalTSTypeRef TSNamespaceType::GetPropTypeGT(JSThread *thread, const JSHandle &namespaceType, - const JSHandle &propName) -{ - DISALLOW_GARBAGE_COLLECTION; - if (namespaceType->GetPropertyType().IsUndefined()) { - return GlobalTSTypeRef::Default(); - } - - JSHandle properties(thread, namespaceType->GetPropertyType()); - - if (properties->IsUndefined()) { - return GlobalTSTypeRef::Default(); - } - - JSHandle layout(thread, namespaceType->GetPropertyType().GetTaggedObject()); - uint32_t numOfProps = layout->GetNumOfProperties(); - JSMutableHandle propKey(thread, JSTaggedValue::Undefined()); - for (uint32_t i = 0; i < numOfProps; ++i) { - propKey.Update(layout->GetKey(i)); - if (!JSTaggedValue::Equal(thread, propName, propKey)) { - continue; - } - uint32_t gtRawData = static_cast(layout->GetTypeId(i).GetInt()); - return GlobalTSTypeRef(gtRawData); - } - return GlobalTSTypeRef::Default(); -} } // namespace panda::ecmascript diff --git a/ecmascript/ts_types/ts_type.h b/ecmascript/ts_types/ts_type.h index 4f526bc5dff3beecf3387b6f8df054bada8c4b66..f75662df93d60a8fd68bb4ae34efaceb0720ea3b 100644 --- a/ecmascript/ts_types/ts_type.h +++ b/ecmascript/ts_types/ts_type.h @@ -62,6 +62,9 @@ public: static GlobalTSTypeRef GetIndexSignType(JSThread *thread, const JSHandle &objectType, const uint32_t typeId); + static void AddKeyAndValue(const JSThread *thread, const JSHandle &objectType, + const JSHandle &key, const JSHandle &value); + ACCESSORS(ObjLayoutInfo, PROPERTIES_OFFSET, INDEX_SIGNS_OFFSET); ACCESSORS(IndexSigns, INDEX_SIGNS_OFFSET, SIZE); @@ -237,20 +240,19 @@ public: DECL_DUMP() }; -class TSNamespaceType : public TSType { +class TSNamespaceType : public TSObjectType { public: CAST_CHECK(TSNamespaceType, IsTSNamespaceType); - static constexpr size_t PROTOTYPE_TYPE_OFFSET = TSType::SIZE; - - ACCESSORS(PropertyType, PROTOTYPE_TYPE_OFFSET, SIZE); - - static void AddKeyAndValue(const JSThread *thread, const JSHandle &namespaceType, - const JSHandle &key, const JSHandle &value); - - static GlobalTSTypeRef GetPropTypeGT(JSThread *thread, const JSHandle &namespaceType, - const JSHandle &propName); + static constexpr size_t SIZE = TSObjectType::SIZE; + DECL_VISIT_OBJECT(TSType::SIZE, SIZE); + DECL_DUMP() +}; - DECL_VISIT_OBJECT(PROTOTYPE_TYPE_OFFSET, SIZE) +class TSEnumType : public TSObjectType { +public: + CAST_CHECK(TSEnumType, IsTSEnumType); + static constexpr size_t SIZE = TSObjectType::SIZE; + DECL_VISIT_OBJECT(TSType::SIZE, SIZE); DECL_DUMP() }; } // namespace panda::ecmascript diff --git a/ecmascript/ts_types/ts_type_accessor.h b/ecmascript/ts_types/ts_type_accessor.h index 08be69085a689e5d960bb21472b4ffee8cf696cd..7c4b35a221b49454ff90d79577fb2f0161cfcd96 100644 --- a/ecmascript/ts_types/ts_type_accessor.h +++ b/ecmascript/ts_types/ts_type_accessor.h @@ -29,7 +29,8 @@ namespace panda::ecmascript { V(Object, JSHandle) \ V(Interface, JSHandle) \ V(IteratorInstance, JSHandle) \ - V(Namespace, JSHandle) + V(Namespace, JSHandle) \ + V(Enum, JSHandle) #define CLASS_TYPE_BITFIELD_ACCESSOR_LIST(V) \ V(HasLinked) \ diff --git a/test/typeinfer/es2abc_feature/BUILD.gn b/test/typeinfer/es2abc_feature/BUILD.gn index 78543c85f450b6319914c50858408cfa1b3eb282..e0184930a4815f2af4e2579fdec3fd7cba4e3ee3 100644 --- a/test/typeinfer/es2abc_feature/BUILD.gn +++ b/test/typeinfer/es2abc_feature/BUILD.gn @@ -16,6 +16,9 @@ group("ark_typeinfer_es2abc_feature_test") { test_list = [ "arrow_function", "arrow_function_in_foreach", + "enum", + "enum_export", + "enum_expr", "indexsignature_class", "indexsignature_object", "member_variable_Initialization", diff --git a/test/typeinfer/es2abc_feature/enum/BUILD.gn b/test/typeinfer/es2abc_feature/enum/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..64a9788f3b0f19362d6456b852cda1c4beb59162 --- /dev/null +++ b/test/typeinfer/es2abc_feature/enum/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_typeinfer_test_action("enum") { + deps = [] + is_enable_global_typeinfer = true +} diff --git a/test/typeinfer/es2abc_feature/enum/enum.ts b/test/typeinfer/es2abc_feature/enum/enum.ts new file mode 100644 index 0000000000000000000000000000000000000000..b8e9d6b764da17667f910661f0b19703d810efc2 --- /dev/null +++ b/test/typeinfer/es2abc_feature/enum/enum.ts @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare function AssertType(value:any, type:string):void; + +enum Test1 { + A, + B, + C, +} + +AssertType(Test1, "enum"); +AssertType(Test1.A, "int"); +AssertType(Test1.B, "int"); +AssertType(Test1.C, "int"); + +enum Test2 { + A = 1.1, + B = 2.2, + C = 3.3, +} + +AssertType(Test2, "enum"); +AssertType(Test2.A, "double"); +AssertType(Test2.B, "double"); +AssertType(Test2.C, "double"); + +enum Test3 { + A = "a", + B = "b", + C = "c", +} + +AssertType(Test3, "enum"); +AssertType(Test3.A, "string"); +AssertType(Test3.B, "string"); +AssertType(Test3.C, "string"); + +function foo () { + AssertType(Test1, "enum"); + AssertType(Test1.A, "int"); + AssertType(Test1.B, "int"); + AssertType(Test1.C, "int"); + AssertType(Test2, "enum"); + AssertType(Test2.A, "double"); + AssertType(Test2.B, "double"); + AssertType(Test2.C, "double"); + AssertType(Test3, "enum"); + AssertType(Test3.A, "string"); + AssertType(Test3.B, "string"); + AssertType(Test3.C, "string"); +} + +foo(); diff --git a/test/typeinfer/es2abc_feature/enum_export/BUILD.gn b/test/typeinfer/es2abc_feature/enum_export/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..751620aaec056af1a0a339bfaaa7b1d04ffcd9c8 --- /dev/null +++ b/test/typeinfer/es2abc_feature/enum_export/BUILD.gn @@ -0,0 +1,20 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_typeinfer_test_action("enum_export") { + deps = [] + is_multi_file_tests = true + is_enable_global_typeinfer = true +} diff --git a/test/typeinfer/es2abc_feature/enum_export/enum_export.ts b/test/typeinfer/es2abc_feature/enum_export/enum_export.ts new file mode 100644 index 0000000000000000000000000000000000000000..8bfcc0d276895734f08f8cf3014226b916145fc8 --- /dev/null +++ b/test/typeinfer/es2abc_feature/enum_export/enum_export.ts @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare function AssertType(value:any, type:string):void; + +import {Test1} from "./export1" +import {Test2} from "./export2" + +AssertType(Test1, "enum"); +AssertType(Test1.A, "int"); +AssertType(Test1.B, "int"); +AssertType(Test1.C, "int"); +AssertType(Test2, "enum"); +AssertType(Test2.A, "string"); +AssertType(Test2.B, "string"); +AssertType(Test2.C, "string"); + +function foo () { + AssertType(Test1, "enum"); + AssertType(Test1.A, "int"); + AssertType(Test1.B, "int"); + AssertType(Test1.C, "int"); + AssertType(Test2, "enum"); + AssertType(Test2.A, "string"); + AssertType(Test2.B, "string"); + AssertType(Test2.C, "string"); +} + +foo(); diff --git a/test/typeinfer/es2abc_feature/enum_export/export1.ts b/test/typeinfer/es2abc_feature/enum_export/export1.ts new file mode 100644 index 0000000000000000000000000000000000000000..1dae7e83c424601f9a3af5582db7399d425591ea --- /dev/null +++ b/test/typeinfer/es2abc_feature/enum_export/export1.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare function AssertType(value:any, type:string):void; +export enum Test1 { + A, + B, + C, +} + +AssertType(Test1, "enum"); +AssertType(Test1.A, "int"); +AssertType(Test1.B, "int"); +AssertType(Test1.C, "int"); diff --git a/test/typeinfer/es2abc_feature/enum_export/export2.ts b/test/typeinfer/es2abc_feature/enum_export/export2.ts new file mode 100644 index 0000000000000000000000000000000000000000..069b37f0db68040f6a32e6e0479fca348628c7df --- /dev/null +++ b/test/typeinfer/es2abc_feature/enum_export/export2.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare function AssertType(value:any, type:string):void; +export enum Test2 { + A = "a", + B = "b", + C = "c", +} + +AssertType(Test2, "enum"); +AssertType(Test2.A, "string"); +AssertType(Test2.B, "string"); +AssertType(Test2.C, "string"); diff --git a/test/typeinfer/es2abc_feature/enum_expr/BUILD.gn b/test/typeinfer/es2abc_feature/enum_expr/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..384d262db041abb114460e86c045eb268cd45bd5 --- /dev/null +++ b/test/typeinfer/es2abc_feature/enum_expr/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_typeinfer_test_action("enum_expr") { + deps = [] + is_enable_global_typeinfer = true +} diff --git a/test/typeinfer/es2abc_feature/enum_expr/enum_expr.ts b/test/typeinfer/es2abc_feature/enum_expr/enum_expr.ts new file mode 100644 index 0000000000000000000000000000000000000000..57e94805160c9bc2f0efbd0576ea9cb7ed474a5f --- /dev/null +++ b/test/typeinfer/es2abc_feature/enum_expr/enum_expr.ts @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare function AssertType(value:any, type:string):void; + +enum Test1 { + A = 1 << 2, + B = 3 + 4 - 5 * 6, + C = "abc", + D = 123 | 456 & 789, +} + +AssertType(Test1, "enum"); +AssertType(Test1.A, "int"); +AssertType(Test1.B, "int"); +AssertType(Test1.C, "string"); +AssertType(Test1.D, "number"); + +enum Day { + SUNDAY = 0, + MONDAY = 1, + TUESDAY = 2, + WEDNESDAY = 3, + THURSDAY = 4, + FRIDAY = 5, + SATURDAY = 6, +} + +function foo(t:Day) { + switch (t) { + case Day.SUNDAY: { + AssertType(Day, "enum"); + AssertType(Day.SUNDAY, "int"); + } + case Day.MONDAY: { + AssertType(Day, "enum"); + AssertType(Day.MONDAY, "int"); + } + case Day.TUESDAY: { + AssertType(Day, "enum"); + AssertType(Day.TUESDAY, "int"); + } + case Day.WEDNESDAY: { + AssertType(Day, "enum"); + AssertType(Day.WEDNESDAY, "int"); + } + case Day.THURSDAY: { + AssertType(Day, "enum"); + AssertType(Day.THURSDAY, "int"); + } + case Day.FRIDAY: { + AssertType(Day, "enum"); + AssertType(Day.FRIDAY, "int"); + } + case Day.SATURDAY: { + AssertType(Day, "enum"); + AssertType(Day.SATURDAY, "int"); + } + default: { + AssertType(Day, "enum"); + } + } +} + +AssertType(Day, "enum"); +AssertType(Day.SUNDAY, "int"); +AssertType(Day.MONDAY, "int"); +AssertType(Day.TUESDAY, "int"); +AssertType(Day.WEDNESDAY, "int"); +AssertType(Day.THURSDAY, "int"); +AssertType(Day.FRIDAY, "int"); +AssertType(Day.SATURDAY, "int"); + +let t = Day.SUNDAY; +foo(t)