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