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/literal_data_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
GenerateBuiltinsTypeTable()38 void TSTypeTableGenerator::GenerateBuiltinsTypeTable()
39 {
40 JSHandle<EcmaString> builtinsTableName = factory_->NewFromASCII(TSTypeTable::BUILTINS_TABLE_NAME);
41 if (LIKELY(tsManager_->IsBuiltinsDTSEnabled())) {
42 tsManager_->GenerateBuiltinSummary();
43 uint32_t numOfTypes = tsManager_->GetBuiltinOffset(static_cast<uint32_t>(BuiltinTypeId::NUM_INDEX_IN_SUMMARY));
44 AddTypeTable(builtinsTableName, numOfTypes);
45 } else {
46 AddTypeTable(builtinsTableName);
47 }
48 }
49
GetOrGenerateTSTypeTable(const JSPandaFile * jsPandaFile,const CString & recordName,uint32_t moduleId)50 JSHandle<TSTypeTable> TSTypeTableGenerator::GetOrGenerateTSTypeTable(const JSPandaFile *jsPandaFile,
51 const CString &recordName,
52 uint32_t moduleId)
53 {
54 if (UNLIKELY(moduleId != static_cast<uint32_t>(GetNextModuleId()))) {
55 return tsManager_->GetTSTypeTable(moduleId);
56 }
57 JSHandle<EcmaString> recordNameStr = factory_->NewFromUtf8(recordName);
58 // read type summary literal
59 // struct of summaryLiteral: {numTypes, literalOffset0, literalOffset1, ...}
60 panda_file::File::EntityId summaryOffset(jsPandaFile->GetTypeSummaryOffset(recordName));
61 JSHandle<TaggedArray> summaryLiteral =
62 LiteralDataExtractor::GetTypeLiteral(thread_, jsPandaFile, summaryOffset);
63 uint32_t numIdx = static_cast<uint32_t>(BuiltinTypeId::NUM_INDEX_IN_SUMMARY);
64 uint32_t numTypes = static_cast<uint32_t>(summaryLiteral->Get(numIdx).GetInt());
65
66 // Initialize a empty TSTypeTable with length of (numTypes + RESERVE_TABLE_LENGTH)
67 JSHandle<TSTypeTable> table = AddTypeTable(recordNameStr, numTypes);
68 return table;
69 }
70
TryGetModuleId(const CString & recordName) const71 uint32_t TSTypeTableGenerator::TryGetModuleId(const CString &recordName) const
72 {
73 JSHandle<EcmaString> recordNameStr = factory_->NewFromUtf8(recordName);
74 int moduleIdBaseOnFile = GetTSModuleTable()->GetGlobalModuleID(thread_, recordNameStr);
75 if (moduleIdBaseOnFile != TSModuleTable::NOT_FOUND) {
76 return moduleIdBaseOnFile;
77 }
78 return static_cast<uint32_t>(GetNextModuleId());
79 }
80
TryGetLocalId(const JSHandle<TSTypeTable> & table) const81 uint32_t TSTypeTableGenerator::TryGetLocalId(const JSHandle<TSTypeTable> &table) const
82 {
83 return table->GetNumberOfTypes() + 1;
84 }
85
AddTypeTable(const JSHandle<EcmaString> & recordNameStr,uint32_t numTypes)86 JSHandle<TSTypeTable> TSTypeTableGenerator::AddTypeTable(const JSHandle<EcmaString> &recordNameStr,
87 uint32_t numTypes)
88 {
89 JSHandle<TSTypeTable> typeTable = factory_->NewTSTypeTable(numTypes);
90
91 JSHandle<TSModuleTable> table = GetTSModuleTable();
92 int numberOfTSTypeTable = table->GetNumberOfTSTypeTables();
93 if (TSModuleTable::GetTSTypeTableOffset(numberOfTSTypeTable) > table->GetLength()) {
94 table = JSHandle<TSModuleTable>(TaggedArray::SetCapacity(thread_, JSHandle<TaggedArray>(table),
95 table->GetLength() * TSModuleTable::INCREASE_CAPACITY_RATE));
96 }
97 // add ts type table
98 table->SetNumberOfTSTypeTables(thread_, numberOfTSTypeTable + 1);
99 table->Set(thread_, TSModuleTable::GetModuleRequestOffset(numberOfTSTypeTable), recordNameStr);
100 table->Set(thread_, TSModuleTable::GetSortIdOffset(numberOfTSTypeTable), JSTaggedValue(numberOfTSTypeTable));
101 table->Set(thread_, TSModuleTable::GetTSTypeTableOffset(numberOfTSTypeTable), typeTable);
102 tsManager_->SetTSModuleTable(table);
103 return typeTable;
104 }
105
InitRuntimeTypeTable()106 void TSTypeTableGenerator::InitRuntimeTypeTable()
107 {
108 JSHandle<TSTypeTable> runtimeTable = tsManager_->GetTSTypeTable(TSModuleTable::RUNTIME_TABLE_ID);
109
110 // add IteratorResult GT
111 JSHandle<JSTaggedValue> valueString = thread_->GlobalConstants()->GetHandledValueString();
112 JSHandle<JSTaggedValue> doneString = thread_->GlobalConstants()->GetHandledDoneString();
113 std::vector<JSHandle<JSTaggedValue>> prop { valueString, doneString };
114 std::vector<GlobalTSTypeRef> propType { GlobalTSTypeRef::Default(), kungfu::GateType::BooleanType().GetGTRef() };
115
116 JSHandle<TSObjectType> iteratorResultType = factory_->NewTSObjectType(prop.size());
117 JSHandle<TSTypeTable> newRuntimeTable = TSTypeTable::PushBackTypeToTable(thread_,
118 runtimeTable, JSHandle<TSType>(iteratorResultType));
119 GlobalTSTypeRef iteratorResultGt(TSModuleTable::RUNTIME_TABLE_ID, newRuntimeTable->GetNumberOfTypes());
120 iteratorResultType->SetGT(iteratorResultGt);
121
122 JSHandle<TSObjLayoutInfo> layoutInfo(thread_, iteratorResultType->GetObjLayoutInfo());
123 FillLayoutTypes(layoutInfo, prop, propType);
124
125 // add IteratorFunction GT
126 JSHandle<TSFunctionType> iteratorFunctionType = factory_->NewTSFunctionType(0);
127 newRuntimeTable = TSTypeTable::PushBackTypeToTable(thread_, runtimeTable, JSHandle<TSType>(iteratorFunctionType));
128 GlobalTSTypeRef functiontGt(TSModuleTable::RUNTIME_TABLE_ID, newRuntimeTable->GetNumberOfTypes());
129 iteratorFunctionType->SetGT(functiontGt);
130 iteratorFunctionType->SetReturnGT(iteratorResultGt);
131
132 // add TSIterator GT
133 JSHandle<JSTaggedValue> nextString = thread_->GlobalConstants()->GetHandledNextString();
134 JSHandle<JSTaggedValue> throwString = thread_->GlobalConstants()->GetHandledThrowString();
135 JSHandle<JSTaggedValue> returnString = thread_->GlobalConstants()->GetHandledReturnString();
136 std::vector<JSHandle<JSTaggedValue>> iteratorProp { nextString, throwString, returnString };
137 std::vector<GlobalTSTypeRef> iteratorPropType { functiontGt, functiontGt, functiontGt };
138
139 JSHandle<TSObjectType> iteratorType = factory_->NewTSObjectType(iteratorProp.size());
140 newRuntimeTable = TSTypeTable::PushBackTypeToTable(thread_, runtimeTable, JSHandle<TSType>(iteratorType));
141 GlobalTSTypeRef iteratorGt(TSModuleTable::RUNTIME_TABLE_ID, newRuntimeTable->GetNumberOfTypes());
142 iteratorType->SetGT(iteratorGt);
143
144 JSHandle<TSObjLayoutInfo> iteratorLayoutInfo(thread_, iteratorType->GetObjLayoutInfo());
145 FillLayoutTypes(iteratorLayoutInfo, iteratorProp, iteratorPropType);
146
147 tsManager_->SetTSTypeTable(newRuntimeTable, TSModuleTable::RUNTIME_TABLE_ID);
148 }
149
FillLayoutTypes(const JSHandle<TSObjLayoutInfo> & layout,const std::vector<JSHandle<JSTaggedValue>> & prop,const std::vector<GlobalTSTypeRef> & propType)150 void TSTypeTableGenerator::FillLayoutTypes(const JSHandle<TSObjLayoutInfo> &layout,
151 const std::vector<JSHandle<JSTaggedValue>> &prop,
152 const std::vector<GlobalTSTypeRef> &propType)
153 {
154 JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
155 JSMutableHandle<JSTaggedValue> value(thread_, JSTaggedValue::Undefined());
156 for (uint32_t index = 0; index < prop.size(); index++) {
157 key.Update(prop[index]);
158 ASSERT(key->IsString());
159 value.Update(JSTaggedValue(propType[index].GetType()));
160 layout->AddKeyAndType(thread_, key.GetTaggedValue(), value.GetTaggedValue());
161 }
162 }
163 } // namespace panda::ecmascript
164