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