• 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/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