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