From ca9bc147ebde8a7d048290fe3122f28d672e4939 Mon Sep 17 00:00:00 2001 From: huoqingyi Date: Fri, 17 Feb 2023 00:07:46 +0800 Subject: [PATCH] Decouple generating TSHClasses from parsing TSTypes In the process of parsing one TSType (at that point the TSType has not yet been generated), if we try to get it to do something, then the program crashes. We need to fix it. Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I6FP5J Tests: typeinfer test, aot test Change-Id: I319cdfcc2a072450a4925eb15e51bf1fba4d7ce8 Signed-off-by: huoqingyi --- ecmascript/compiler/type_recorder.cpp | 1 + ecmascript/ts_types/ts_manager.cpp | 24 +++++++++++++++-- ecmascript/ts_types/ts_manager.h | 10 +++++++ ecmascript/ts_types/ts_type.cpp | 4 ++- ecmascript/ts_types/ts_type_parser.cpp | 17 +----------- ecmascript/ts_types/ts_type_parser.h | 2 -- test/typeinfer/BUILD.gn | 1 + test/typeinfer/superclass/BUILD.gn | 19 +++++++++++++ test/typeinfer/superclass/superclass.ts | 36 +++++++++++++++++++++++++ 9 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 test/typeinfer/superclass/BUILD.gn create mode 100644 test/typeinfer/superclass/superclass.ts diff --git a/ecmascript/compiler/type_recorder.cpp b/ecmascript/compiler/type_recorder.cpp index db4e9dd314..f69cfabda7 100644 --- a/ecmascript/compiler/type_recorder.cpp +++ b/ecmascript/compiler/type_recorder.cpp @@ -30,6 +30,7 @@ TypeRecorder::TypeRecorder(const JSPandaFile *jsPandaFile, const MethodLiteral * return; } LoadTypes(jsPandaFile, methodLiteral, tsManager, recordName); + tsManager->GenerateTSHClasses(); } void TypeRecorder::LoadTypes(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral, diff --git a/ecmascript/ts_types/ts_manager.cpp b/ecmascript/ts_types/ts_manager.cpp index 072267cc8b..8f92878b98 100644 --- a/ecmascript/ts_types/ts_manager.cpp +++ b/ecmascript/ts_types/ts_manager.cpp @@ -653,13 +653,33 @@ void TSManager::GenerateTSHClass(JSHandle classType) gtIhcMap_.insert({gt, IHClassData(JSTaggedValue(ihc).GetRawData())}); } +void TSManager::GenerateTSHClasses() +{ + for (const auto > : collectedTypeOffsets_) { + JSHandle tsType = GetTSType(gt); + if (tsType->IsUndefined()) { + continue; + } + ASSERT(tsType->IsTSClassType()); + JSHandle classType(tsType); + if (!classType->GetHasLinked()) { + RecursivelyMergeClassField(classType); + } + if (IsUserDefinedClassTypeKind(gt)) { + GenerateTSHClass(classType); + } + } + collectedTypeOffsets_.clear(); +} + JSHandle TSManager::GetTSType(const GlobalTSTypeRef >) const { uint32_t moduleId = gt.GetModuleId(); uint32_t localId = gt.GetLocalId(); - if (moduleId == TSModuleTable::BUILTINS_TABLE_ID && !IsBuiltinsDTSEnabled()) { - return JSHandle(thread_, JSTaggedValue::Undefined()); + if ((moduleId == TSModuleTable::BUILTINS_TABLE_ID && !IsBuiltinsDTSEnabled()) || + (moduleId == TSModuleTable::PRIMITIVE_TABLE_ID)) { + return thread_->GlobalConstants()->GetHandledUndefined(); } JSHandle mTable = GetTSModuleTable(); diff --git a/ecmascript/ts_types/ts_manager.h b/ecmascript/ts_types/ts_manager.h index acc1506a5d..ab8e58f675 100644 --- a/ecmascript/ts_types/ts_manager.h +++ b/ecmascript/ts_types/ts_manager.h @@ -365,6 +365,8 @@ public: void GenerateTSHClass(JSHandle classType); + void GenerateTSHClasses(); + JSHandle GetTSType(const GlobalTSTypeRef >) const; std::string PUBLIC_API GetTypeStr(kungfu::GateType gateType) const; @@ -648,6 +650,13 @@ public: return name; } + inline void CollectTypeOffsets(GlobalTSTypeRef classGT) + { + if (IsClassTypeKind(classGT)) { + collectedTypeOffsets_.insert(classGT); + } + } + private: NO_COPY_SEMANTIC(TSManager); NO_MOVE_SEMANTIC(TSManager); @@ -735,6 +744,7 @@ private: CString builtinsRecordName_ {""}; std::map localModuleVarGtMap_{}; kungfu::CompilationDriver *cmpDriver_ {nullptr}; + std::set collectedTypeOffsets_ {}; // use for storing types that need to generate hclasses friend class EcmaVM; diff --git a/ecmascript/ts_types/ts_type.cpp b/ecmascript/ts_types/ts_type.cpp index ab34fb1fb6..d5ac1e4170 100644 --- a/ecmascript/ts_types/ts_type.cpp +++ b/ecmascript/ts_types/ts_type.cpp @@ -355,7 +355,9 @@ GlobalTSTypeRef TSInterfaceType::GetPropTypeGT(JSThread *thread, JSHandle(extendsValue.GetInt()); GlobalTSTypeRef extendsGT = GlobalTSTypeRef(gtRawData); JSHandle extendsType = tsManager->GetTSType(extendsGT); - + if (extendsType->IsUndefined()) { + return GlobalTSTypeRef::Default(); + } ASSERT(extendsType->IsTSType()); if (extendsType->IsTSClassType()) { diff --git a/ecmascript/ts_types/ts_type_parser.cpp b/ecmascript/ts_types/ts_type_parser.cpp index 0f70f6e2c7..6870a2dcf7 100644 --- a/ecmascript/ts_types/ts_type_parser.cpp +++ b/ecmascript/ts_types/ts_type_parser.cpp @@ -72,8 +72,7 @@ GlobalTSTypeRef TSTypeParser::ParseType(const JSPandaFile *jsPandaFile, const CS GlobalTSTypeRef gt = GetGT(jsPandaFile, table, moduleId, typeId, recordName); JSHandle type = ParseNonImportType(jsPandaFile, recordName, literal, kind, typeId); SetTSType(table, type, gt); - - GenerateTSHClass(type); + tsManager_->CollectTypeOffsets(gt); // collect types that need to generate hclasses return gt; } @@ -396,20 +395,6 @@ void TSTypeParser::FillInterfaceMethodTypes(const JSPandaFile *jsPandaFile, cons } } -void TSTypeParser::GenerateTSHClass(JSHandle type) -{ - if (type->IsTSClassType()) { - JSHandle classType(type); - if (!classType->GetHasLinked()) { - tsManager_->RecursivelyMergeClassField(classType); - } - auto gt = classType->GetGT(); - if (tsManager_->IsUserDefinedClassTypeKind(gt)) { - tsManager_->GenerateTSHClass(classType); - } - } -} - JSHandle TSTypeParser::GetExportDataFromRecord(const JSPandaFile *jsPandaFile, const CString &recordName) { diff --git a/ecmascript/ts_types/ts_type_parser.h b/ecmascript/ts_types/ts_type_parser.h index 5cc4d88b52..a07b57060f 100644 --- a/ecmascript/ts_types/ts_type_parser.h +++ b/ecmascript/ts_types/ts_type_parser.h @@ -102,8 +102,6 @@ private: uint32_t startIndex, uint32_t lastIndex, uint32_t &index); - void GenerateTSHClass(JSHandle type); - JSHandle GetExportDataFromRecord(const JSPandaFile *jsPandaFile, const CString &recordName); JSHandle GenerateExportTableFromRecord(const JSPandaFile *jsPandaFile, const CString &recordName); diff --git a/test/typeinfer/BUILD.gn b/test/typeinfer/BUILD.gn index bc3d70a4e5..7b755a0496 100644 --- a/test/typeinfer/BUILD.gn +++ b/test/typeinfer/BUILD.gn @@ -92,6 +92,7 @@ group("ark_typeinfer_test") { "stlettoglobalrecord:stlettoglobalrecordAotTypeInferAction", "sub2dyn:sub2dynAotTypeInferAction", "supercall:supercallAotTypeInferAction", + "superclass:superclassAotTypeInferAction", "throwdyn_1:throwdyn_1AotTypeInferAction", "throwdyn_2:throwdyn_2AotTypeInferAction", "tryldglobalbyname:tryldglobalbynameAotTypeInferAction", diff --git a/test/typeinfer/superclass/BUILD.gn b/test/typeinfer/superclass/BUILD.gn new file mode 100644 index 0000000000..2b57e9ab5b --- /dev/null +++ b/test/typeinfer/superclass/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("superclass") { + deps = [] + is_disable_type_lowering = true +} diff --git a/test/typeinfer/superclass/superclass.ts b/test/typeinfer/superclass/superclass.ts new file mode 100644 index 0000000000..2a3077b4f8 --- /dev/null +++ b/test/typeinfer/superclass/superclass.ts @@ -0,0 +1,36 @@ +/* + * 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; + +class A { + foo():B { + let v = new B(); + AssertType(v, "B"); + return v; + } +} + +class B extends A {} + +let a = new A(); +let b = a.foo(); +let c = new B(); +let d = c.foo(); + +AssertType(a, "A"); +AssertType(b, "B"); +AssertType(c, "B"); +AssertType(d, "B");