• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "ecmascript/ts_types/ts_type_table_generator.h"
17 
18 #include "ecmascript/jspandafile/js_pandafile_manager.h"
19 #include "ecmascript/jspandafile/type_literal_extractor.h"
20 
21 namespace panda::ecmascript {
GenerateDefaultTSTypeTables()22 void TSTypeTableGenerator::GenerateDefaultTSTypeTables()
23 {
24     JSHandle<EcmaString> primitiveTableName = factory_->NewFromASCII(TSTypeTable::PRIMITIVE_TABLE_NAME);
25     AddTypeTable(primitiveTableName);
26 
27     GenerateBuiltinsTypeTable();
28 
29     JSHandle<EcmaString> inferTableName = factory_->NewFromASCII(TSTypeTable::INFER_TABLE_NAME);
30     AddTypeTable(inferTableName);
31 
32     JSHandle<EcmaString> runtimeTableName = factory_->NewFromASCII(TSTypeTable::RUNTIME_TABLE_NAME);
33     AddTypeTable(runtimeTableName);
34 
35     InitRuntimeTypeTable();
36 
37     JSHandle<EcmaString> genericsTableName = factory_->NewFromASCII(TSTypeTable::GENERICS_TABLE_NAME);
38     AddTypeTable(genericsTableName);
39 }
40 
GenerateBuiltinsTypeTable()41 void TSTypeTableGenerator::GenerateBuiltinsTypeTable()
42 {
43     JSHandle<EcmaString> builtinsTableName = factory_->NewFromASCII(TSTypeTable::BUILTINS_TABLE_NAME);
44     if (LIKELY(tsManager_->IsBuiltinsDTSEnabled())) {
45         tsManager_->GenerateBuiltinSummary();
46         uint32_t numOfTypes = tsManager_->GetBuiltinOffset(static_cast<uint32_t>(BuiltinTypeId::NUM_INDEX_IN_SUMMARY));
47         AddTypeTable(builtinsTableName, numOfTypes);
48     } else {
49         AddTypeTable(builtinsTableName);
50     }
51 }
52 
GetOrGenerateTSTypeTable(const JSPandaFile * jsPandaFile,const CString & recordName,uint32_t moduleId)53 JSHandle<TSTypeTable> TSTypeTableGenerator::GetOrGenerateTSTypeTable(const JSPandaFile *jsPandaFile,
54                                                                      const CString &recordName,
55                                                                      uint32_t moduleId)
56 {
57     if (UNLIKELY(moduleId != static_cast<uint32_t>(GetNextModuleId()))) {
58         return tsManager_->GetTSTypeTable(moduleId);
59     }
60     JSHandle<EcmaString> recordNameStr = factory_->NewFromUtf8(recordName);
61     // when PGO is enabled, no matter whether the abc file is a '.js' or a '.ts' file, it may contain PGO GT
62     uint32_t typeNum = tsManager_->GetPGOGTCountByRecordName(recordName);
63     if (jsPandaFile->HasTSTypes(recordName)) {
64         // only '.ts' file has type literal and can get number of type from it
65         TypeSummaryExtractor summExtractor(jsPandaFile, recordName);
66         typeNum += summExtractor.GetNumOfTypes();
67     }
68     JSHandle<TSTypeTable> table = AddTypeTable(recordNameStr, typeNum);
69     return table;
70 }
71 
TryGetModuleId(const CString & recordName) const72 uint32_t TSTypeTableGenerator::TryGetModuleId(const CString &recordName) const
73 {
74     JSHandle<EcmaString> recordNameStr = factory_->NewFromUtf8(recordName);
75     int moduleIdBaseOnFile = GetTSModuleTable()->GetGlobalModuleID(thread_, recordNameStr);
76     if (moduleIdBaseOnFile != TSModuleTable::NOT_FOUND) {
77         return moduleIdBaseOnFile;
78     }
79     return static_cast<uint32_t>(GetNextModuleId());
80 }
81 
TryGetLocalId(const JSHandle<TSTypeTable> & table) const82 uint32_t TSTypeTableGenerator::TryGetLocalId(const JSHandle<TSTypeTable> &table) const
83 {
84     return table->GetNumberOfTypes() + 1;
85 }
86 
AddTypeTable(const JSHandle<EcmaString> & recordNameStr,uint32_t numTypes)87 JSHandle<TSTypeTable> TSTypeTableGenerator::AddTypeTable(const JSHandle<EcmaString> &recordNameStr,
88                                                          uint32_t numTypes)
89 {
90     JSHandle<TSTypeTable> typeTable = factory_->NewTSTypeTable(numTypes);
91 
92     JSHandle<TSModuleTable> table = GetTSModuleTable();
93     int numberOfTSTypeTable = table->GetNumberOfTSTypeTables();
94     if (TSModuleTable::GetTSTypeTableOffset(numberOfTSTypeTable) > table->GetLength()) {
95         table = JSHandle<TSModuleTable>(TaggedArray::SetCapacity(thread_, JSHandle<TaggedArray>(table),
96             table->GetLength() * TSModuleTable::INCREASE_CAPACITY_RATE));
97     }
98     // add ts type table
99     table->SetNumberOfTSTypeTables(thread_, numberOfTSTypeTable + 1);
100     table->Set(thread_, TSModuleTable::GetModuleRequestOffset(numberOfTSTypeTable), recordNameStr);
101     table->Set(thread_, TSModuleTable::GetSortIdOffset(numberOfTSTypeTable), JSTaggedValue(numberOfTSTypeTable));
102     table->Set(thread_, TSModuleTable::GetTSTypeTableOffset(numberOfTSTypeTable), typeTable);
103     tsManager_->SetTSModuleTable(table);
104     return typeTable;
105 }
106 
InitRuntimeTypeTable()107 void TSTypeTableGenerator::InitRuntimeTypeTable()
108 {
109     JSHandle<TSTypeTable> runtimeTable = tsManager_->GetRuntimeTable();
110 
111     // add IteratorResult GT
112     JSHandle<JSTaggedValue> valueString = thread_->GlobalConstants()->GetHandledValueString();
113     JSHandle<JSTaggedValue> doneString = thread_->GlobalConstants()->GetHandledDoneString();
114     std::vector<JSHandle<JSTaggedValue>> prop { valueString, doneString };
115     std::vector<GlobalTSTypeRef> propType { GlobalTSTypeRef::Default(), kungfu::GateType::BooleanType().GetGTRef() };
116 
117     JSHandle<TSObjectType> iteratorResultType = factory_->NewTSObjectType(prop.size());
118     JSHandle<TSTypeTable> newRuntimeTable = TSTypeTable::PushBackTypeToTable(thread_,
119         runtimeTable, JSHandle<TSType>(iteratorResultType));
120     GlobalTSTypeRef iteratorResultGt(static_cast<uint32_t>(ModuleTableIdx::RUNTIME),
121                                      newRuntimeTable->GetNumberOfTypes());
122     iteratorResultType->SetGT(iteratorResultGt);
123 
124     JSHandle<TSObjLayoutInfo> layoutInfo(thread_, iteratorResultType->GetObjLayoutInfo());
125     FillLayoutTypes(layoutInfo, prop, propType);
126 
127     // add IteratorFunction GT
128     JSHandle<TSFunctionType> iteratorFunctionType = factory_->NewTSFunctionType(0);
129     newRuntimeTable = TSTypeTable::PushBackTypeToTable(thread_, runtimeTable, JSHandle<TSType>(iteratorFunctionType));
130     GlobalTSTypeRef functiontGt(static_cast<uint32_t>(ModuleTableIdx::RUNTIME),
131                                                       newRuntimeTable->GetNumberOfTypes());
132     iteratorFunctionType->SetGT(functiontGt);
133     iteratorFunctionType->SetReturnGT(iteratorResultGt);
134 
135     // add TSIterator GT
136     JSHandle<JSTaggedValue> nextString = thread_->GlobalConstants()->GetHandledNextString();
137     JSHandle<JSTaggedValue> throwString = thread_->GlobalConstants()->GetHandledThrowString();
138     JSHandle<JSTaggedValue> returnString = thread_->GlobalConstants()->GetHandledReturnString();
139     std::vector<JSHandle<JSTaggedValue>> iteratorProp { nextString, throwString, returnString };
140     std::vector<GlobalTSTypeRef> iteratorPropType { functiontGt, functiontGt, functiontGt };
141 
142     JSHandle<TSObjectType> iteratorType = factory_->NewTSObjectType(iteratorProp.size());
143     newRuntimeTable = TSTypeTable::PushBackTypeToTable(thread_, runtimeTable, JSHandle<TSType>(iteratorType));
144     GlobalTSTypeRef iteratorGt(static_cast<uint32_t>(ModuleTableIdx::RUNTIME), newRuntimeTable->GetNumberOfTypes());
145     iteratorType->SetGT(iteratorGt);
146 
147     JSHandle<TSObjLayoutInfo> iteratorLayoutInfo(thread_, iteratorType->GetObjLayoutInfo());
148     FillLayoutTypes(iteratorLayoutInfo, iteratorProp, iteratorPropType);
149 
150     tsManager_->SetRuntimeTable(newRuntimeTable);
151 }
152 
FillLayoutTypes(const JSHandle<TSObjLayoutInfo> & layout,const std::vector<JSHandle<JSTaggedValue>> & prop,const std::vector<GlobalTSTypeRef> & propType)153 void TSTypeTableGenerator::FillLayoutTypes(const JSHandle<TSObjLayoutInfo> &layout,
154                                            const std::vector<JSHandle<JSTaggedValue>> &prop,
155                                            const std::vector<GlobalTSTypeRef> &propType)
156 {
157     JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
158     JSMutableHandle<JSTaggedValue> value(thread_, JSTaggedValue::Undefined());
159     for (uint32_t index = 0; index < prop.size(); index++) {
160         key.Update(prop[index]);
161         ASSERT(key->IsString());
162         value.Update(JSTaggedValue(propType[index].GetType()));
163         layout->AddProperty(thread_, key.GetTaggedValue(), value.GetTaggedValue());
164     }
165 }
166 }  // namespace panda::ecmascript
167