mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
!3915 Support typeinfer for generic types [PART_1]
Merge pull request !3915 from huoqingyi/typeliteral
This commit is contained in:
commit
8a32f45414
1
BUILD.gn
1
BUILD.gn
@ -625,6 +625,7 @@ ecma_source = [
|
||||
"ecmascript/jspandafile/class_info_extractor.cpp",
|
||||
"ecmascript/jspandafile/debug_info_extractor.cpp",
|
||||
"ecmascript/jspandafile/literal_data_extractor.cpp",
|
||||
"ecmascript/jspandafile/type_literal_extractor.cpp",
|
||||
"ecmascript/jspandafile/accessor/module_data_accessor.cpp",
|
||||
"ecmascript/jspandafile/panda_file_translator.cpp",
|
||||
"ecmascript/jspandafile/js_pandafile_executor.cpp",
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "ecmascript/base/path_helper.h"
|
||||
#include "ecmascript/compiler/type_recorder.h"
|
||||
#include "ecmascript/interpreter/interpreter-inl.h"
|
||||
#include "ecmascript/jspandafile/type_literal_extractor.h"
|
||||
#include "ecmascript/ts_types/ts_type_parser.h"
|
||||
#include "libpandafile/code_data_accessor.h"
|
||||
|
||||
@ -79,7 +80,7 @@ void BytecodeInfoCollector::ProcessClasses()
|
||||
cda.EnumerateMethods([this, methods, &methodIdx, pf, &processedInsns,
|
||||
&recordNames, &methodPcInfos, &recordName] (panda_file::MethodDataAccessor &mda) {
|
||||
auto methodId = mda.GetMethodId();
|
||||
CollectFunctionTypeId(vm_->GetJSThread(), methodId);
|
||||
CollectFunctionTypeId(methodId);
|
||||
|
||||
// Generate all constpool
|
||||
vm_->FindOrCreateConstPool(jsPandaFile_, methodId);
|
||||
@ -142,99 +143,50 @@ void BytecodeInfoCollector::CollectClassLiteralInfo(const MethodLiteral *method,
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectFunctionTypeId(JSThread *thread, panda_file::File::EntityId fieldId)
|
||||
void BytecodeInfoCollector::CollectFunctionTypeId(panda_file::File::EntityId fieldId)
|
||||
{
|
||||
const panda_file::File *pf = jsPandaFile_->GetPandaFile();
|
||||
panda_file::MethodDataAccessor mda(*pf, fieldId);
|
||||
mda.EnumerateAnnotations([this, fieldId, pf, thread] (panda_file::File::EntityId annotationId) {
|
||||
panda_file::AnnotationDataAccessor ada(*pf, annotationId);
|
||||
auto *annotationName = reinterpret_cast<const char *>(jsPandaFile_->GetStringData(ada.GetClassId()).data);
|
||||
ASSERT(annotationName != nullptr);
|
||||
if (::strcmp("L_ESTypeAnnotation;", annotationName) != 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t length = ada.GetCount();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
panda_file::AnnotationDataAccessor::Elem adae = ada.GetElement(i);
|
||||
auto *elemName = reinterpret_cast<const char *>(jsPandaFile_->GetStringData(adae.GetNameId()).data);
|
||||
ASSERT(elemName != nullptr);
|
||||
if (::strcmp("_TypeOfInstruction", elemName) != 0) {
|
||||
continue;
|
||||
uint32_t offset = fieldId.GetOffset();
|
||||
TypeAnnotationExtractor annoExtractor(jsPandaFile_, offset);
|
||||
annoExtractor.EnumerateInstsAndTypes(
|
||||
[this, offset](const int32_t bcOffset, const uint32_t typeId) {
|
||||
if (bcOffset == TypeRecorder::METHOD_ANNOTATION_FUNCTION_TYPE_OFFSET) {
|
||||
bytecodeInfo_.SetFunctionTypeIDAndMethodOffset(typeId, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
panda_file::ScalarValue sv = adae.GetScalarValue();
|
||||
panda_file::File::EntityId literalOffset(sv.GetValue());
|
||||
JSHandle<TaggedArray> typeOfInstruction =
|
||||
LiteralDataExtractor::GetTypeLiteral(thread, jsPandaFile_, literalOffset);
|
||||
|
||||
for (uint32_t j = 0; j < typeOfInstruction->GetLength(); j = j + 2) { // + 2 means bcOffset and typeId
|
||||
int32_t bcOffset = typeOfInstruction->Get(j).GetInt();
|
||||
uint32_t typeId = static_cast<uint32_t>(typeOfInstruction->Get(j + 1).GetInt());
|
||||
if (bcOffset == TypeRecorder::METHOD_ANNOTATION_FUNCTION_TYPE_OFFSET) {
|
||||
bytecodeInfo_.SetFunctionTypeIDAndMethodOffset(typeId, fieldId.GetOffset());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::IterateLiteral(const MethodLiteral *method,
|
||||
std::vector<uint32_t> &classOffsetVector)
|
||||
{
|
||||
const panda_file::File *pf = jsPandaFile_->GetPandaFile();
|
||||
panda_file::File::EntityId fieldId = method->GetMethodId();
|
||||
uint32_t defineMethodOffset = fieldId.GetOffset();
|
||||
panda_file::MethodDataAccessor methodDataAccessor(*pf, fieldId);
|
||||
|
||||
methodDataAccessor.EnumerateAnnotations([&](panda_file::File::EntityId annotation_id) {
|
||||
panda_file::AnnotationDataAccessor ada(*pf, annotation_id);
|
||||
std::string annotationName = std::string(utf::Mutf8AsCString(pf->GetStringData(ada.GetClassId()).data));
|
||||
if (annotationName.compare("L_ESTypeAnnotation;") != 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t length = ada.GetCount();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
panda_file::AnnotationDataAccessor::Elem adae = ada.GetElement(i);
|
||||
std::string elemName = std::string(utf::Mutf8AsCString(pf->GetStringData(adae.GetNameId()).data));
|
||||
if (elemName.compare("_TypeOfInstruction") != 0) {
|
||||
continue;
|
||||
TypeAnnotationExtractor annoExtractor(jsPandaFile_, defineMethodOffset);
|
||||
std::map<int32_t, uint32_t> offsetTypeMap;
|
||||
annoExtractor.EnumerateInstsAndTypes(
|
||||
[this, &offsetTypeMap, defineMethodOffset](const int32_t bcOffset, const uint32_t typeOffset) {
|
||||
if (classDefBCIndexes_.find(bcOffset) != classDefBCIndexes_.end() ||
|
||||
classDefBCIndexes_.find(bcOffset - 1) != classDefBCIndexes_.end()) { // for getter setter
|
||||
bytecodeInfo_.SetClassTypeOffsetAndDefMethod(typeOffset, defineMethodOffset);
|
||||
}
|
||||
|
||||
panda_file::ScalarValue sv = adae.GetScalarValue();
|
||||
panda_file::File::EntityId literalOffset(sv.GetValue());
|
||||
JSHandle<TaggedArray> typeOfInstruction =
|
||||
LiteralDataExtractor::GetTypeLiteral(vm_->GetJSThread(), jsPandaFile_, literalOffset);
|
||||
std::map<int32_t, uint32_t> offsetTypeMap;
|
||||
for (uint32_t j = 0; j < typeOfInstruction->GetLength(); j = j + 2) { // 2: Two parsing once
|
||||
int32_t bcOffset = typeOfInstruction->Get(j).GetInt();
|
||||
uint32_t typeOffset = static_cast<uint32_t>(typeOfInstruction->Get(j + 1).GetInt());
|
||||
if (classDefBCIndexes_.find(bcOffset) != classDefBCIndexes_.end() ||
|
||||
classDefBCIndexes_.find(bcOffset - 1) != classDefBCIndexes_.end()) { // for getter setter
|
||||
bytecodeInfo_.SetClassTypeOffsetAndDefMethod(typeOffset, defineMethodOffset);
|
||||
}
|
||||
if (bcOffset != TypeRecorder::METHOD_ANNOTATION_THIS_TYPE_OFFSET &&
|
||||
typeOffset > TSTypeParser::USER_DEFINED_TYPE_OFFSET) {
|
||||
offsetTypeMap.insert(std::make_pair(bcOffset, typeOffset));
|
||||
}
|
||||
if (bcOffset != TypeRecorder::METHOD_ANNOTATION_THIS_TYPE_OFFSET &&
|
||||
typeOffset > TSTypeParser::USER_DEFINED_TYPE_OFFSET) {
|
||||
offsetTypeMap.insert(std::make_pair(bcOffset, typeOffset));
|
||||
}
|
||||
});
|
||||
|
||||
for (auto item : offsetTypeMap) {
|
||||
uint32_t typeOffset = item.second;
|
||||
StoreClassTypeOffset(typeOffset, classOffsetVector);
|
||||
}
|
||||
|
||||
for (auto item : offsetTypeMap) {
|
||||
uint32_t typeOffset = item.second;
|
||||
StoreClassTypeOffset(typeOffset, classOffsetVector);
|
||||
}
|
||||
}
|
||||
});
|
||||
classDefBCIndexes_.clear();
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::StoreClassTypeOffset(const uint32_t typeOffset, std::vector<uint32_t> &classOffsetVector)
|
||||
{
|
||||
panda_file::File::EntityId offset(typeOffset);
|
||||
JSHandle<TaggedArray> literal =
|
||||
LiteralDataExtractor::GetTypeLiteral(vm_->GetJSThread(), jsPandaFile_, offset);
|
||||
int typeKind = literal->Get(0).GetInt();
|
||||
if (typeKind != static_cast<int>(TSTypeKind::CLASS)) {
|
||||
TypeLiteralExtractor typeLiteralExtractor(jsPandaFile_, typeOffset);
|
||||
if (typeLiteralExtractor.GetTypeKind() != TSTypeKind::CLASS) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -566,26 +518,12 @@ void BytecodeInfoCollector::CollectExportIndexs(const CString &recordName, uint3
|
||||
bool BytecodeInfoCollector::CheckExportName(const CString &recordName, const JSHandle<EcmaString> &exportStr)
|
||||
{
|
||||
auto tsManager = vm_->GetTSManager();
|
||||
// To compare with the exportTable, we need to parse the literalbuffer in abc TypeAnnotation.
|
||||
// If the exportTable already exist, we will use it directly. OtherWise, we will parse and store it.
|
||||
// In type system parser at a later stage, we will also use these arrays to avoid duplicate parsing.
|
||||
if (tsManager->HasResolvedExportTable(jsPandaFile_, recordName)) {
|
||||
JSTaggedValue exportTypeTable = tsManager->GetResolvedExportTable(jsPandaFile_, recordName);
|
||||
JSHandle<TaggedArray> table(vm_->GetJSThread(), exportTypeTable);
|
||||
return IsEffectiveExportName(exportStr, table);
|
||||
}
|
||||
JSHandle<TaggedArray> newResolvedTable = tsManager->GenerateExportTableFromLiteral(jsPandaFile_, recordName);
|
||||
return IsEffectiveExportName(exportStr, newResolvedTable);
|
||||
}
|
||||
|
||||
bool BytecodeInfoCollector::IsEffectiveExportName(const JSHandle<EcmaString> &exportNameStr,
|
||||
const JSHandle<TaggedArray> &exportTypeTable)
|
||||
{
|
||||
JSHandle<TaggedArray> exportTypeTable = tsManager->GetExportTableFromLiteral(jsPandaFile_, recordName);
|
||||
uint32_t length = exportTypeTable->GetLength();
|
||||
for (uint32_t i = 0; i < length; i = i + 2) { // 2: skip a pair of key and value
|
||||
EcmaString *valueString = EcmaString::Cast(exportTypeTable->Get(i).GetTaggedObject());
|
||||
uint32_t typeId = static_cast<uint32_t>(exportTypeTable->Get(i + 1).GetInt());
|
||||
if (EcmaStringAccessor::StringsAreEqual(*exportNameStr, valueString) && typeId != 0) {
|
||||
if (EcmaStringAccessor::StringsAreEqual(*exportStr, valueString) && typeId != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -715,13 +715,10 @@ private:
|
||||
void IterateLiteral(const MethodLiteral *method, std::vector<uint32_t> &classOffsetVector);
|
||||
void StoreClassTypeOffset(const uint32_t typeOffset, std::vector<uint32_t> &classOffsetVector);
|
||||
void CollectClassLiteralInfo(const MethodLiteral *method, const std::vector<std::string> &classNameVec);
|
||||
void CollectFunctionTypeId(JSThread *thread, panda_file::File::EntityId fieldId);
|
||||
void CollectFunctionTypeId(panda_file::File::EntityId fieldId);
|
||||
void CollectImportIndexs(uint32_t methodOffset, uint32_t index);
|
||||
void CollectExportIndexs(const CString &recordName, uint32_t index);
|
||||
bool CheckExportName(const CString &recordName,
|
||||
const JSHandle<EcmaString> &exportStr);
|
||||
bool IsEffectiveExportName(const JSHandle<EcmaString> &exportNameStr,
|
||||
const JSHandle<TaggedArray> &exportTypeTable);
|
||||
bool CheckExportName(const CString &recordName, const JSHandle<EcmaString> &exportStr);
|
||||
void CollectRecordReferenceREL();
|
||||
void CollectRecordImportInfo(const CString &recordName);
|
||||
void CollectRecordExportInfo(const CString &recordName);
|
||||
|
@ -15,12 +15,10 @@
|
||||
|
||||
#include "ecmascript/compiler/type_recorder.h"
|
||||
|
||||
#include "ecmascript/jspandafile/literal_data_extractor.h"
|
||||
#include "ecmascript/jspandafile/type_literal_extractor.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_loader.h"
|
||||
#include "ecmascript/ts_types/ts_type_parser.h"
|
||||
|
||||
#include "libpandafile/method_data_accessor-inl.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
TypeRecorder::TypeRecorder(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral,
|
||||
TSManager *tsManager, const CString &recordName, PGOProfilerLoader *loader)
|
||||
@ -38,60 +36,34 @@ TypeRecorder::TypeRecorder(const JSPandaFile *jsPandaFile, const MethodLiteral *
|
||||
void TypeRecorder::LoadTypes(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral,
|
||||
TSManager *tsManager, const CString &recordName)
|
||||
{
|
||||
JSThread *thread = tsManager->GetThread();
|
||||
TSTypeParser typeParser(tsManager);
|
||||
const panda_file::File *pf = jsPandaFile->GetPandaFile();
|
||||
panda_file::File::EntityId fieldId = methodLiteral->GetMethodId();
|
||||
panda_file::MethodDataAccessor mda(*pf, fieldId);
|
||||
mda.EnumerateAnnotations([&](panda_file::File::EntityId annotationId) {
|
||||
panda_file::AnnotationDataAccessor ada(*pf, annotationId);
|
||||
auto *annotationName = reinterpret_cast<const char *>(jsPandaFile->GetStringData(ada.GetClassId()).data);
|
||||
ASSERT(annotationName != nullptr);
|
||||
if (::strcmp("L_ESTypeAnnotation;", annotationName) != 0) {
|
||||
TypeAnnotationExtractor annoExtractor(jsPandaFile, fieldId.GetOffset());
|
||||
GlobalTSTypeRef thisGT;
|
||||
GlobalTSTypeRef funcGT;
|
||||
annoExtractor.EnumerateInstsAndTypes([this, &typeParser, &jsPandaFile, &recordName, &thisGT,
|
||||
&funcGT](const int32_t bcOffset, const uint32_t typeId) {
|
||||
GlobalTSTypeRef gt = typeParser.CreateGT(jsPandaFile, recordName, typeId);
|
||||
if (gt.IsDefault()) {
|
||||
return;
|
||||
}
|
||||
uint32_t length = ada.GetCount();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
panda_file::AnnotationDataAccessor::Elem adae = ada.GetElement(i);
|
||||
auto *elemName = reinterpret_cast<const char *>(jsPandaFile->GetStringData(adae.GetNameId()).data);
|
||||
ASSERT(elemName != nullptr);
|
||||
if (::strcmp("_TypeOfInstruction", elemName) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
panda_file::ScalarValue sv = adae.GetScalarValue();
|
||||
panda_file::File::EntityId literalOffset(sv.GetValue());
|
||||
JSHandle<TaggedArray> typeOfInstruction =
|
||||
LiteralDataExtractor::GetTypeLiteral(thread, jsPandaFile, literalOffset);
|
||||
|
||||
GlobalTSTypeRef thisGT = GlobalTSTypeRef::Default();
|
||||
GlobalTSTypeRef funcGT = GlobalTSTypeRef::Default();
|
||||
for (uint32_t j = 0; j < typeOfInstruction->GetLength(); j = j + 2) { // + 2 means bcOffset and typeId
|
||||
int32_t bcOffset = typeOfInstruction->Get(j).GetInt();
|
||||
uint32_t typeId = static_cast<uint32_t>(typeOfInstruction->Get(j + 1).GetInt());
|
||||
GlobalTSTypeRef gt = typeParser.CreateGT(jsPandaFile, recordName, typeId);
|
||||
if (gt.IsDefault()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The type of a function is recorded as (-1, funcTypeId). If the function is a member of a class,
|
||||
// the type of the class or its instance is is recorded as (-2, classTypeId). If it is a static
|
||||
// member, the type id refers to the type of the class; otherwise, it links to the type of the
|
||||
// instances of the class.
|
||||
if (bcOffset == METHOD_ANNOTATION_THIS_TYPE_OFFSET) {
|
||||
thisGT = gt;
|
||||
continue;
|
||||
}
|
||||
if (bcOffset == METHOD_ANNOTATION_FUNCTION_TYPE_OFFSET) {
|
||||
funcGT = gt;
|
||||
continue;
|
||||
}
|
||||
auto type = GateType(gt);
|
||||
bcOffsetGtMap_.emplace(bcOffset, type);
|
||||
}
|
||||
LoadArgTypes(tsManager, funcGT, thisGT);
|
||||
// The type of a function is recorded as (-1, funcTypeId). If the function is a member of a class,
|
||||
// the type of the class or its instance is is recorded as (-2, classTypeId). If it is a static
|
||||
// member, the type id refers to the type of the class; otherwise, it links to the type of the
|
||||
// instances of the class.
|
||||
if (bcOffset == METHOD_ANNOTATION_THIS_TYPE_OFFSET) {
|
||||
thisGT = gt;
|
||||
return;
|
||||
}
|
||||
if (bcOffset == METHOD_ANNOTATION_FUNCTION_TYPE_OFFSET) {
|
||||
funcGT = gt;
|
||||
return;
|
||||
}
|
||||
auto type = GateType(gt);
|
||||
bcOffsetGtMap_.emplace(bcOffset, type);
|
||||
});
|
||||
LoadArgTypes(tsManager, funcGT, thisGT);
|
||||
}
|
||||
|
||||
void TypeRecorder::LoadTypesFromPGO(const MethodLiteral *methodLiteral, const CString &recordName)
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "ecmascript/jspandafile/method_literal.h"
|
||||
#include "ecmascript/mem/c_containers.h"
|
||||
|
||||
#include "libpandafile/file.h"
|
||||
#include "libpandafile/file-inl.h"
|
||||
#include "libpandafile/file_items.h"
|
||||
#include "libpandafile/literal_data_accessor.h"
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "ecmascript/ecma_string.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile.h"
|
||||
#include "ecmascript/module/js_module_manager.h"
|
||||
#include "ecmascript/patch/quick_fix_manager.h"
|
||||
#include "ecmascript/tagged_array-inl.h"
|
||||
@ -445,46 +444,4 @@ JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread,
|
||||
});
|
||||
return literals;
|
||||
}
|
||||
|
||||
// use for parsing specific literal which record TS type info
|
||||
JSHandle<TaggedArray> LiteralDataExtractor::GetTypeLiteral(JSThread *thread, const JSPandaFile *jsPandaFile,
|
||||
EntityId offset)
|
||||
{
|
||||
LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
uint32_t num = lda.GetLiteralValsNum(offset) / 2; // 2: half
|
||||
JSHandle<TaggedArray> literals = factory->NewOldSpaceTaggedArray(num);
|
||||
uint32_t pos = 0;
|
||||
lda.EnumerateLiteralVals(
|
||||
offset, [literals, &pos, factory, thread, jsPandaFile](const LiteralValue &value, const LiteralTag &tag) {
|
||||
JSTaggedValue jt = JSTaggedValue::Null();
|
||||
switch (tag) {
|
||||
case LiteralTag::INTEGER: {
|
||||
jt = JSTaggedValue(base::bit_cast<int32_t>(std::get<uint32_t>(value)));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::LITERALARRAY: {
|
||||
ASSERT(std::get<uint32_t>(value) > LITERALARRAY_VALUE_LOW_BOUNDARY);
|
||||
jt = JSTaggedValue(std::get<uint32_t>(value));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::BUILTINTYPEINDEX: {
|
||||
jt = JSTaggedValue(std::get<uint8_t>(value));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::STRING: {
|
||||
StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
|
||||
EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::OLD_SPACE);
|
||||
jt = JSTaggedValue(str);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_FULL(FATAL) << "type literal should not exist LiteralTag: " << static_cast<uint8_t>(tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
literals->Set(thread, pos++, jt);
|
||||
});
|
||||
return literals;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -16,7 +16,7 @@
|
||||
#ifndef ECMASCRIPT_JSPANDAFILE_LITERAL_DATA_EXTRACTOR_H
|
||||
#define ECMASCRIPT_JSPANDAFILE_LITERAL_DATA_EXTRACTOR_H
|
||||
|
||||
#include "ecmascript/jspandafile/panda_file_translator.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile.h"
|
||||
#include "ecmascript/js_tagged_value-inl.h"
|
||||
#include "libpandafile/literal_data_accessor-inl.h"
|
||||
|
||||
@ -57,9 +57,6 @@ public:
|
||||
|
||||
static void PUBLIC_API GetMethodOffsets(const JSPandaFile *jsPandaFile, EntityId id,
|
||||
std::vector<uint32_t> &methodOffsets);
|
||||
|
||||
static JSHandle<TaggedArray> PUBLIC_API GetTypeLiteral(JSThread *thread, const JSPandaFile *jsPandaFile,
|
||||
EntityId offset);
|
||||
private:
|
||||
static JSHandle<TaggedArray> EnumerateLiteralVals(JSThread *thread, panda_file::LiteralDataAccessor &lda,
|
||||
const JSPandaFile *jsPandaFile, size_t index, JSHandle<ConstantPool> constpool,
|
||||
|
@ -26,10 +26,9 @@
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/tagged_array.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
#include "ecmascript/ts_types/ts_type_table.h"
|
||||
#include "libpandabase/utils/utf.h"
|
||||
|
||||
#include "libpandafile/class_data_accessor-inl.h"
|
||||
#include "libpandabase/utils/utf.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
template<class T, class... Args>
|
||||
|
@ -17,14 +17,12 @@
|
||||
#define ECMASCRIPT_JSPANDAFILE_PANDA_FILE_TRANSLATOR_H
|
||||
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/jspandafile/bytecode_inst/old_instruction.h"
|
||||
#include "ecmascript/jspandafile/constpool_value.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile.h"
|
||||
|
||||
#include "libpandabase/utils/bit_field.h"
|
||||
#include "libpandafile/code_data_accessor-inl.h"
|
||||
#include "libpandafile/file-inl.h"
|
||||
|
||||
#include "ecmascript/jspandafile/bytecode_inst/old_instruction.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class Program;
|
||||
|
248
ecmascript/jspandafile/type_literal_extractor.cpp
Normal file
248
ecmascript/jspandafile/type_literal_extractor.cpp
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/jspandafile/type_literal_extractor.h"
|
||||
|
||||
#include "libpandafile/literal_data_accessor-inl.h"
|
||||
#include "libpandafile/method_data_accessor-inl.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
using LiteralTag = panda_file::LiteralTag;
|
||||
using LiteralValue = panda_file::LiteralDataAccessor::LiteralValue;
|
||||
using StringData = panda_file::StringData;
|
||||
using EntityId = panda_file::File::EntityId;
|
||||
using LiteralDataAccessor = panda_file::LiteralDataAccessor;
|
||||
|
||||
static constexpr const char *TYPE_ANNO_RECORD_NAME = "L_ESTypeAnnotation;";
|
||||
|
||||
static bool IsLegalOffset(uint32_t offset)
|
||||
{
|
||||
return offset != 0U;
|
||||
}
|
||||
|
||||
static uint32_t GetMethodAnnoOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset, const char *annoName)
|
||||
{
|
||||
const panda_file::File &pf = *jsPandaFile->GetPandaFile();
|
||||
EntityId methodId(methodOffset);
|
||||
panda_file::MethodDataAccessor mda(pf, methodId);
|
||||
|
||||
uint32_t annoOffset = 0;
|
||||
mda.EnumerateAnnotations([&jsPandaFile, &annoName, &pf, &annoOffset](EntityId annotationId) {
|
||||
panda_file::AnnotationDataAccessor ada(pf, annotationId);
|
||||
auto *annotationName = reinterpret_cast<const char *>(jsPandaFile->GetStringData(ada.GetClassId()).data);
|
||||
ASSERT(annotationName != nullptr);
|
||||
if (::strcmp(TYPE_ANNO_RECORD_NAME, annotationName) != 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t length = ada.GetCount();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
panda_file::AnnotationDataAccessor::Elem adae = ada.GetElement(i);
|
||||
auto *elemName = reinterpret_cast<const char *>(jsPandaFile->GetStringData(adae.GetNameId()).data);
|
||||
ASSERT(elemName != nullptr);
|
||||
|
||||
if (::strcmp(annoName, elemName) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
panda_file::ScalarValue sv = adae.GetScalarValue();
|
||||
annoOffset = sv.GetValue();
|
||||
}
|
||||
});
|
||||
return annoOffset;
|
||||
}
|
||||
|
||||
TypeLiteralExtractor::TypeLiteralExtractor(const JSPandaFile *jsPandaFile, const uint32_t typeOffset)
|
||||
: typeOffset_(typeOffset)
|
||||
{
|
||||
ProcessTypeLiteral(jsPandaFile, typeOffset);
|
||||
}
|
||||
|
||||
void TypeLiteralExtractor::ProcessTypeLiteral(const JSPandaFile *jsPandaFile, const uint32_t typeOffset)
|
||||
{
|
||||
EntityId literalId(typeOffset);
|
||||
LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
|
||||
bool isFirst = true;
|
||||
lda.EnumerateLiteralVals(literalId,
|
||||
[this, &jsPandaFile, &isFirst](const LiteralValue &value, const LiteralTag &tag) {
|
||||
if (isFirst) {
|
||||
uint32_t kindValue = std::get<uint32_t>(value);
|
||||
if (UNLIKELY(!IsVaildKind(kindValue))) {
|
||||
LOG_COMPILER(FATAL) << "Load type literal failure.";
|
||||
return;
|
||||
}
|
||||
kind_ = static_cast<TSTypeKind>(std::get<uint32_t>(value));
|
||||
isFirst = false;
|
||||
return;
|
||||
}
|
||||
switch (tag) {
|
||||
case LiteralTag::INTEGER: {
|
||||
uint32_t valueValue = std::get<uint32_t>(value);
|
||||
if (static_cast<int32_t>(valueValue) < 0) {
|
||||
isGenerics_ = true;
|
||||
}
|
||||
array_.emplace_back(valueValue);
|
||||
break;
|
||||
}
|
||||
case LiteralTag::LITERALARRAY: {
|
||||
array_.emplace_back(std::get<uint32_t>(value));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::BUILTINTYPEINDEX: {
|
||||
array_.emplace_back(static_cast<uint32_t>(std::get<uint8_t>(value)));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::STRING: {
|
||||
StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
|
||||
CString stringValue = utf::Mutf8AsCString(sd.data);
|
||||
array_.emplace_back(stringValue);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_COMPILER(FATAL) << "TypeLiteral should not exist LiteralTag: " << static_cast<uint32_t>(tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TypeSummaryExtractor::TypeSummaryExtractor(const JSPandaFile *jsPandaFile, const CString &recordName)
|
||||
{
|
||||
ProcessTypeSummary(jsPandaFile, jsPandaFile->GetTypeSummaryOffset(recordName));
|
||||
}
|
||||
|
||||
void TypeSummaryExtractor::ProcessTypeSummary(const JSPandaFile *jsPandaFile, const uint32_t summaryOffset)
|
||||
{
|
||||
EntityId summaryId(summaryOffset);
|
||||
LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
|
||||
bool isFirstIndex = true;
|
||||
lda.EnumerateLiteralVals(summaryId,
|
||||
[this, &isFirstIndex, &jsPandaFile](const LiteralValue &value, const LiteralTag &tag) {
|
||||
switch (tag) {
|
||||
case LiteralTag::LITERALARRAY: {
|
||||
typeOffsets_.emplace_back(std::get<uint32_t>(value));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::BUILTINTYPEINDEX: {
|
||||
typeOffsets_.emplace_back(static_cast<uint32_t>(std::get<uint8_t>(value)));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::INTEGER: {
|
||||
if (isFirstIndex) {
|
||||
numOfTypes_ = std::get<uint32_t>(value);
|
||||
typeOffsets_.emplace_back(numOfTypes_);
|
||||
isFirstIndex = false;
|
||||
} else {
|
||||
numOfRedirects_ = std::get<uint32_t>(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LiteralTag::STRING: {
|
||||
StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
|
||||
CString stringValue = utf::Mutf8AsCString(sd.data);
|
||||
reDirects_.emplace_back(stringValue);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_COMPILER(FATAL) << "TypeSummary should not exist LiteralTag: " << static_cast<uint32_t>(tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
ASSERT(typeOffsets_.size() == numOfTypes_ + 1);
|
||||
ASSERT(reDirects_.size() == numOfRedirects_);
|
||||
}
|
||||
|
||||
TypeAnnotationExtractor::TypeAnnotationExtractor(const JSPandaFile *jsPandaFile, const uint32_t methodOffset)
|
||||
{
|
||||
ProcessTypeAnnotation(jsPandaFile, methodOffset);
|
||||
}
|
||||
|
||||
void TypeAnnotationExtractor::ProcessTypeAnnotation(const JSPandaFile *jsPandaFile, const uint32_t methodOffset)
|
||||
{
|
||||
uint32_t annoOffset = GetMethodAnnoOffset(jsPandaFile, methodOffset, TYPE_ANNO_ELEMENT_NAME);
|
||||
if (!IsLegalOffset(annoOffset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityId annoId(annoOffset);
|
||||
LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
|
||||
lda.EnumerateLiteralVals(annoId, [this](const LiteralValue &value, const LiteralTag &tag) {
|
||||
switch (tag) {
|
||||
case LiteralTag::INTEGER: {
|
||||
int32_t valueValue = base::bit_cast<int32_t>(std::get<uint32_t>(value));
|
||||
bcOffsets_.emplace_back(valueValue);
|
||||
break;
|
||||
}
|
||||
case LiteralTag::LITERALARRAY: {
|
||||
typeIds_.emplace_back(std::get<uint32_t>(value));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::BUILTINTYPEINDEX: {
|
||||
typeIds_.emplace_back(static_cast<uint32_t>(std::get<uint8_t>(value)));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_COMPILER(FATAL) << "TypeAnnotation should not exist LiteralTag: " << static_cast<uint32_t>(tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
ASSERT(bcOffsets_.size() == typeIds_.size());
|
||||
}
|
||||
|
||||
ExportTypeTableExtractor::ExportTypeTableExtractor(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
bool isBuiltinTable)
|
||||
{
|
||||
ProcessExportTable(jsPandaFile, recordName, isBuiltinTable);
|
||||
}
|
||||
|
||||
void ExportTypeTableExtractor::ProcessExportTable(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
bool isBuiltinTable)
|
||||
{
|
||||
const char *name = isBuiltinTable ? DECLARED_SYMBOL_TYPES : EXPORTED_SYMBOL_TYPES;
|
||||
uint32_t methodOffset = jsPandaFile->GetMainMethodIndex(recordName);
|
||||
uint32_t annoOffset = GetMethodAnnoOffset(jsPandaFile, methodOffset, name);
|
||||
if (!IsLegalOffset(annoOffset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityId annoId(annoOffset);
|
||||
LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
|
||||
lda.EnumerateLiteralVals(annoId, [this, &jsPandaFile](const LiteralValue &value, const LiteralTag &tag) {
|
||||
switch (tag) {
|
||||
case LiteralTag::LITERALARRAY: {
|
||||
typeIds_.emplace_back(std::get<uint32_t>(value));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::BUILTINTYPEINDEX: {
|
||||
typeIds_.emplace_back(static_cast<uint32_t>(std::get<uint8_t>(value)));
|
||||
break;
|
||||
}
|
||||
case LiteralTag::STRING: {
|
||||
StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
|
||||
exportVars_.emplace_back(utf::Mutf8AsCString(sd.data));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_COMPILER(FATAL) << "TypeExportTable should not exist LiteralTag: " << static_cast<uint32_t>(tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
ASSERT(exportVars_.size() == typeIds_.size());
|
||||
}
|
||||
} // namespace panda::ecmascript
|
207
ecmascript/jspandafile/type_literal_extractor.h
Normal file
207
ecmascript/jspandafile/type_literal_extractor.h
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_JSPANDAFILE_TYPE_LITERAL_EXTRACTOR_H
|
||||
#define ECMASCRIPT_JSPANDAFILE_TYPE_LITERAL_EXTRACTOR_H
|
||||
|
||||
#include "ecmascript/jspandafile/js_pandafile.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class TypeLiteralExtractor {
|
||||
using TypeLiteralValue = std::variant<uint32_t, CString>;
|
||||
|
||||
public:
|
||||
explicit TypeLiteralExtractor(const JSPandaFile *jsPandaFile, const uint32_t typeOffset);
|
||||
~TypeLiteralExtractor() = default;
|
||||
NO_COPY_SEMANTIC(TypeLiteralExtractor);
|
||||
NO_MOVE_SEMANTIC(TypeLiteralExtractor);
|
||||
|
||||
inline bool IsVaildTypeLiteral() const
|
||||
{
|
||||
return !array_.empty();
|
||||
}
|
||||
|
||||
inline TSTypeKind GetTypeKind() const
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
|
||||
inline bool IsGenerics() const
|
||||
{
|
||||
return isGenerics_;
|
||||
}
|
||||
|
||||
inline void SetGenerics()
|
||||
{
|
||||
isGenerics_ = true;
|
||||
}
|
||||
|
||||
inline uint32_t GetIntValue(const uint32_t index) const
|
||||
{
|
||||
ASSERT(index < array_.size());
|
||||
auto t = array_[index];
|
||||
ASSERT(std::holds_alternative<uint32_t>(t));
|
||||
return std::get<uint32_t>(t);
|
||||
}
|
||||
|
||||
inline const CString &GetStringValue(const uint32_t index) const
|
||||
{
|
||||
ASSERT(index < array_.size());
|
||||
const auto &t = array_[index];
|
||||
ASSERT(std::holds_alternative<CString>(t));
|
||||
return std::get<CString>(t);
|
||||
}
|
||||
|
||||
inline uint32_t GetTypeOffset() const
|
||||
{
|
||||
return typeOffset_;
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateElements(const uint32_t numIndex, const Callback &callback)
|
||||
{
|
||||
ASSERT(numIndex < array_.size());
|
||||
uint32_t length = std::get<uint32_t>(array_[numIndex]);
|
||||
ASSERT(numIndex + length < array_.size());
|
||||
for (uint32_t i = 1; i <= length; i++) {
|
||||
uint32_t value = GetIntValue(numIndex + i);
|
||||
callback(value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateProperties(const uint32_t numIndex, const uint32_t gap, const Callback &callback)
|
||||
{
|
||||
ASSERT(numIndex < array_.size());
|
||||
ASSERT(gap >= VALUE_OFFSET);
|
||||
uint32_t length = std::get<uint32_t>(array_[numIndex]);
|
||||
ASSERT(numIndex + length * gap < array_.size());
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
uint32_t keyIndex = numIndex + i * gap + KEY_OFFSET;
|
||||
uint32_t valueIndex = numIndex + i * gap + VALUE_OFFSET;
|
||||
const CString &key = GetStringValue(keyIndex);
|
||||
uint32_t value = GetIntValue(valueIndex);
|
||||
callback(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr uint32_t KEY_OFFSET = 1;
|
||||
static constexpr uint32_t VALUE_OFFSET = 2;
|
||||
|
||||
inline bool IsVaildKind(const uint32_t kindValue) const
|
||||
{
|
||||
return (static_cast<uint32_t>(TSTypeKind::TYPEKIND_FIRST) <= kindValue) &&
|
||||
(kindValue <= static_cast<uint32_t>(TSTypeKind::TYPEKIND_LAST));
|
||||
}
|
||||
|
||||
void ProcessTypeLiteral(const JSPandaFile *jsPandaFile, const uint32_t typeOffset);
|
||||
|
||||
std::vector<TypeLiteralValue> array_;
|
||||
uint32_t typeOffset_ { 0 };
|
||||
TSTypeKind kind_ { TSTypeKind::UNKNOWN };
|
||||
bool isGenerics_ { false };
|
||||
};
|
||||
|
||||
class TypeSummaryExtractor {
|
||||
public:
|
||||
explicit TypeSummaryExtractor(const JSPandaFile *jsPandaFile, const CString &recordName);
|
||||
~TypeSummaryExtractor() = default;
|
||||
NO_COPY_SEMANTIC(TypeSummaryExtractor);
|
||||
NO_MOVE_SEMANTIC(TypeSummaryExtractor);
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateTypeOffsets(const uint32_t lastIndex, const Callback &callback)
|
||||
{
|
||||
ASSERT(lastIndex < typeOffsets_.size());
|
||||
for (uint32_t i = 0; i <= lastIndex; i++) {
|
||||
callback(typeOffsets_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
inline uint32_t GetNumOfTypes() const
|
||||
{
|
||||
return numOfTypes_;
|
||||
}
|
||||
|
||||
private:
|
||||
void ProcessTypeSummary(const JSPandaFile *jsPandaFile, const uint32_t summaryOffset);
|
||||
|
||||
std::vector<uint32_t> typeOffsets_ {};
|
||||
std::vector<CString> reDirects_ {};
|
||||
uint32_t numOfTypes_ { 0 };
|
||||
uint32_t numOfRedirects_ { 0 };
|
||||
};
|
||||
|
||||
class TypeAnnotationExtractor {
|
||||
public:
|
||||
explicit TypeAnnotationExtractor(const JSPandaFile *jsPandaFile, const uint32_t methodOffset);
|
||||
~TypeAnnotationExtractor() = default;
|
||||
NO_COPY_SEMANTIC(TypeAnnotationExtractor);
|
||||
NO_MOVE_SEMANTIC(TypeAnnotationExtractor);
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateInstsAndTypes(const Callback &callback)
|
||||
{
|
||||
ASSERT(bcOffsets_.size() == typeIds_.size());
|
||||
uint32_t length = bcOffsets_.size();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
callback(bcOffsets_[i], typeIds_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr const char *TYPE_ANNO_ELEMENT_NAME = "_TypeOfInstruction";
|
||||
|
||||
void ProcessTypeAnnotation(const JSPandaFile *jsPandaFile, const uint32_t methodOffset);
|
||||
|
||||
std::vector<int32_t> bcOffsets_ {};
|
||||
std::vector<uint32_t> typeIds_ {};
|
||||
};
|
||||
|
||||
class ExportTypeTableExtractor {
|
||||
public:
|
||||
explicit ExportTypeTableExtractor(const JSPandaFile *jsPandaFile, const CString &recordName, bool isBuiltinTable);
|
||||
~ExportTypeTableExtractor() = default;
|
||||
NO_COPY_SEMANTIC(ExportTypeTableExtractor);
|
||||
NO_MOVE_SEMANTIC(ExportTypeTableExtractor);
|
||||
|
||||
inline uint32_t GetLength() const
|
||||
{
|
||||
ASSERT(exportVars_.size() == typeIds_.size());
|
||||
return exportVars_.size() + typeIds_.size();
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateModuleTypes(const Callback &callback)
|
||||
{
|
||||
ASSERT(exportVars_.size() == typeIds_.size());
|
||||
uint32_t length = exportVars_.size();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
callback(exportVars_[i], typeIds_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr const char *DECLARED_SYMBOL_TYPES = "declaredSymbolTypes";
|
||||
static constexpr const char *EXPORTED_SYMBOL_TYPES = "exportedSymbolTypes";
|
||||
|
||||
void ProcessExportTable(const JSPandaFile *jsPandaFile, const CString &recordName, bool isBuiltinTable);
|
||||
|
||||
std::vector<CString> exportVars_ {};
|
||||
std::vector<uint32_t> typeIds_ {};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_JSPANDAFILE_TYPE_LITERAL_EXTRACTOR_H
|
@ -20,12 +20,9 @@
|
||||
#include "libpandabase/utils/bit_field.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
/*
|
||||
* To maintain consistency with the frontend, ITERATOR_INSTANCE should always be at
|
||||
* the end of TSTypeKind, because there is no ITERATOR_INSTANCE in the frontend.
|
||||
*/
|
||||
enum class TSTypeKind : int {
|
||||
enum class TSTypeKind : uint8_t {
|
||||
PRIMITIVE = 0,
|
||||
// the following typekinds are recorded in abc files and are consistent with the corresponding values
|
||||
CLASS,
|
||||
CLASS_INSTANCE,
|
||||
FUNCTION,
|
||||
@ -33,9 +30,17 @@ enum class TSTypeKind : int {
|
||||
ARRAY,
|
||||
OBJECT,
|
||||
IMPORT,
|
||||
INTERFACE_KIND,
|
||||
INTERFACE,
|
||||
BUILTININST,
|
||||
GENERICINST,
|
||||
INDEXSIG,
|
||||
|
||||
// the following typekinds are not recorded in abc files and will be created at compile time
|
||||
ITERATOR_INSTANCE,
|
||||
UNKNOWN
|
||||
UNKNOWN,
|
||||
|
||||
TYPEKIND_FIRST = CLASS,
|
||||
TYPEKIND_LAST = INDEXSIG,
|
||||
};
|
||||
|
||||
enum class TSPrimitiveType : int {
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "ecmascript/jspandafile/js_pandafile_manager.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/subtyping_operator.h"
|
||||
#include "ecmascript/ts_types/ts_type_parser.h"
|
||||
#include "ecmascript/ts_types/ts_type_table_generator.h"
|
||||
#include "ecmascript/vtable.h"
|
||||
|
||||
@ -235,7 +234,7 @@ TSTypeKind TSManager::GetTypeKind(const GlobalTSTypeRef >) const
|
||||
case JSType::TS_OBJECT_TYPE:
|
||||
return TSTypeKind::OBJECT;
|
||||
case JSType::TS_INTERFACE_TYPE:
|
||||
return TSTypeKind::INTERFACE_KIND;
|
||||
return TSTypeKind::INTERFACE;
|
||||
case JSType::TS_ITERATOR_INSTANCE_TYPE:
|
||||
return TSTypeKind::ITERATOR_INSTANCE;
|
||||
default:
|
||||
@ -909,7 +908,7 @@ std::string TSManager::GetTypeStr(kungfu::GateType gateType) const
|
||||
return "object";
|
||||
case TSTypeKind::IMPORT:
|
||||
return "import";
|
||||
case TSTypeKind::INTERFACE_KIND:
|
||||
case TSTypeKind::INTERFACE:
|
||||
return "interface";
|
||||
case TSTypeKind::ITERATOR_INSTANCE:
|
||||
return "iterator_instance";
|
||||
@ -1220,12 +1219,36 @@ kungfu::GateType TSManager::TryNarrowUnionType(kungfu::GateType gateType)
|
||||
return gateType;
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> TSManager::GetExportTableFromLiteral(const JSPandaFile *jsPandaFile, const CString &recordName)
|
||||
{
|
||||
// To compare with the exportTable, we need to parse the literalbuffer in abc TypeAnnotation.
|
||||
// If the exportTable already exist, we will use it directly. OtherWise, we will parse and store it.
|
||||
// In type system parser at a later stage, we will also use these arrays to avoid duplicate parsing.
|
||||
if (HasResolvedExportTable(jsPandaFile, recordName)) {
|
||||
JSTaggedValue exportTypeTable = GetResolvedExportTable(jsPandaFile, recordName);
|
||||
JSHandle<TaggedArray> table(vm_->GetJSThread(), exportTypeTable);
|
||||
return table;
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> typeOfExportedSymbols = GenerateExportTableFromLiteral(jsPandaFile, recordName);
|
||||
AddResolvedExportTable(jsPandaFile, recordName, typeOfExportedSymbols.GetTaggedValue());
|
||||
return typeOfExportedSymbols;
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> TSManager::GenerateExportTableFromLiteral(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName)
|
||||
{
|
||||
TSTypeParser parser(this);
|
||||
JSHandle<TaggedArray> typeOfExportedSymbols = parser.GetExportDataFromRecord(jsPandaFile, recordName);
|
||||
AddResolvedExportTable(jsPandaFile, recordName, typeOfExportedSymbols.GetTaggedValue());
|
||||
bool isBuiltinTable = (std::strcmp(recordName.c_str(), TSTypeTable::BUILTINS_TABLE_NAME) == 0);
|
||||
ExportTypeTableExtractor exTableExtractor(jsPandaFile, recordName, isBuiltinTable);
|
||||
uint32_t length = exTableExtractor.GetLength();
|
||||
JSHandle<TaggedArray> typeOfExportedSymbols = factory_->NewOldSpaceTaggedArray(length);
|
||||
uint32_t index = 0;
|
||||
exTableExtractor.EnumerateModuleTypes(
|
||||
[this, &typeOfExportedSymbols, &index](const CString &name, const uint32_t typeId) {
|
||||
JSHandle<EcmaString> str = factory_->NewFromUtf8(name);
|
||||
typeOfExportedSymbols->Set(thread_, index++, JSTaggedValue(str.GetTaggedValue()));
|
||||
typeOfExportedSymbols->Set(thread_, index++, JSTaggedValue(typeId));
|
||||
});
|
||||
return typeOfExportedSymbols;
|
||||
}
|
||||
|
||||
@ -1285,12 +1308,11 @@ void TSManager::GenerateBuiltinSummary()
|
||||
SetBuiltinPandaFile(jsPandaFile.get());
|
||||
CString builtinsRecordName(TSTypeTable::BUILTINS_TABLE_NAME);
|
||||
SetBuiltinRecordName(builtinsRecordName);
|
||||
panda_file::File::EntityId summaryOffset(jsPandaFile->GetTypeSummaryOffset(builtinsRecordName));
|
||||
JSHandle<TaggedArray> builtinOffsets =
|
||||
LiteralDataExtractor::GetTypeLiteral(thread_, jsPandaFile.get(), summaryOffset);
|
||||
for (uint32_t i = 0; i <= static_cast<uint32_t>(BuiltinTypeId::NUM_OF_BUILTIN_TYPES); i++) {
|
||||
builtinOffsets_.emplace_back(static_cast<uint32_t>(builtinOffsets->Get(i).GetInt()));
|
||||
}
|
||||
TypeSummaryExtractor summExtractor(jsPandaFile.get(), builtinsRecordName);
|
||||
summExtractor.EnumerateTypeOffsets(static_cast<uint32_t>(BuiltinTypeId::NUM_OF_BUILTIN_TYPES),
|
||||
[this](const uint32_t typeOffset) {
|
||||
builtinOffsets_.emplace_back(typeOffset);
|
||||
});
|
||||
}
|
||||
|
||||
void TSManager::PrintNumOfTypes() const
|
||||
|
@ -16,12 +16,13 @@
|
||||
#ifndef ECMASCRIPT_TS_TYPES_TS_MANAGER_H
|
||||
#define ECMASCRIPT_TS_TYPES_TS_MANAGER_H
|
||||
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_tagged_value-inl.h"
|
||||
#include "ecmascript/ts_types/global_ts_type_ref.h"
|
||||
#include "ecmascript/ts_types/ts_obj_layout_info.h"
|
||||
#include "ecmascript/compiler/bytecode_info_collector.h"
|
||||
#include "ecmascript/compiler/compilation_driver.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_tagged_value-inl.h"
|
||||
#include "ecmascript/jspandafile/type_literal_extractor.h"
|
||||
#include "ecmascript/ts_types/global_ts_type_ref.h"
|
||||
#include "ecmascript/ts_types/ts_obj_layout_info.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
enum class MTableIdx : uint8_t {
|
||||
@ -411,7 +412,7 @@ public:
|
||||
V(Array, TSTypeKind::ARRAY) \
|
||||
V(Object, TSTypeKind::OBJECT) \
|
||||
V(Import, TSTypeKind::IMPORT) \
|
||||
V(Interface, TSTypeKind::INTERFACE_KIND) \
|
||||
V(Interface, TSTypeKind::INTERFACE) \
|
||||
V(IteratorInstance, TSTypeKind::ITERATOR_INSTANCE) \
|
||||
|
||||
#define IS_TSTYPEKIND(NAME, TSTYPEKIND) \
|
||||
@ -440,7 +441,11 @@ public:
|
||||
bool isImportType = false)
|
||||
{
|
||||
auto key = std::make_pair(jsPandaFile, offset);
|
||||
literalOffsetGTMap_.emplace(key, gt);
|
||||
if (literalOffsetGTMap_.find(key) != literalOffsetGTMap_.end()) {
|
||||
literalOffsetGTMap_[key] = gt;
|
||||
} else {
|
||||
literalOffsetGTMap_.emplace(key, gt);
|
||||
}
|
||||
if (!isImportType) {
|
||||
auto value = std::make_pair(recordName, offset);
|
||||
gtLiteralOffsetMap_.emplace(gt, value);
|
||||
@ -693,7 +698,7 @@ public:
|
||||
|
||||
kungfu::GateType TryNarrowUnionType(kungfu::GateType gateType);
|
||||
|
||||
JSHandle<TaggedArray> GenerateExportTableFromLiteral(const JSPandaFile *jsPandaFile, const CString &recordName);
|
||||
JSHandle<TaggedArray> GetExportTableFromLiteral(const JSPandaFile *jsPandaFile, const CString &recordName);
|
||||
|
||||
private:
|
||||
NO_COPY_SEMANTIC(TSManager);
|
||||
@ -701,6 +706,8 @@ private:
|
||||
|
||||
GlobalTSTypeRef AddTSTypeToTypeTable(const JSHandle<TSType> &type, int tableId) const;
|
||||
|
||||
JSHandle<TaggedArray> GenerateExportTableFromLiteral(const JSPandaFile *jsPandaFile, const CString &recordName);
|
||||
|
||||
GlobalTSTypeRef FindUnionInTypeTable(JSHandle<TSTypeTable> table, JSHandle<TSUnionType> unionType) const;
|
||||
|
||||
GlobalTSTypeRef FindIteratorInstanceInInferTable(GlobalTSTypeRef kindGt, GlobalTSTypeRef elementGt) const;
|
||||
|
@ -77,7 +77,6 @@ class TSClassType : public TSType {
|
||||
public:
|
||||
CAST_CHECK(TSClassType, IsTSClassType);
|
||||
|
||||
static constexpr size_t FIELD_LENGTH = 4; // every field record name, typeIndex, accessFlag, readonly
|
||||
static constexpr size_t INSTANCE_TYPE_OFFSET = TSType::SIZE;
|
||||
|
||||
static GlobalTSTypeRef GetPropTypeGT(JSThread *thread, JSHandle<TSClassType> classType,
|
||||
@ -149,9 +148,6 @@ class TSInterfaceType : public TSType {
|
||||
public:
|
||||
CAST_CHECK(TSInterfaceType, IsTSInterfaceType);
|
||||
|
||||
// every field record name, typeIndex, accessFlag, readonly
|
||||
static constexpr size_t FIELD_LENGTH = 4;
|
||||
|
||||
static GlobalTSTypeRef GetPropTypeGT(JSThread *thread, JSHandle<TSInterfaceType> classInstanceType,
|
||||
JSHandle<JSTaggedValue> propName);
|
||||
|
||||
|
@ -17,13 +17,16 @@
|
||||
|
||||
#include "ecmascript/base/path_helper.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile_manager.h"
|
||||
#include "ecmascript/jspandafile/literal_data_extractor.h"
|
||||
#include "ecmascript/jspandafile/type_literal_extractor.h"
|
||||
#include "ecmascript/module/js_module_manager.h"
|
||||
|
||||
#include "libpandafile/annotation_data_accessor.h"
|
||||
#include "libpandafile/class_data_accessor-inl.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
// For each property of one class, object or interface, it's name and typeIndex are recorded in order,
|
||||
// and if it is a field, then accessFlag and readonly of this property will be additionally recorded.
|
||||
static constexpr uint32_t FIELD_LENGTH = 4;
|
||||
static constexpr uint32_t METHOD_LENGTH = 2;
|
||||
static constexpr uint32_t INDEX_OCCUPIED_OFFSET = 1;
|
||||
|
||||
TSTypeParser::TSTypeParser(TSManager *tsManager)
|
||||
: tsManager_(tsManager), vm_(tsManager->GetEcmaVM()),
|
||||
thread_(vm_->GetJSThread()), factory_(vm_->GetFactory()),
|
||||
@ -72,14 +75,13 @@ GlobalTSTypeRef TSTypeParser::ParseBuiltinObjType(uint32_t typeId)
|
||||
|
||||
GlobalTSTypeRef TSTypeParser::ParseType(const JSPandaFile *jsPandaFile, const CString &recordName, uint32_t typeId)
|
||||
{
|
||||
panda_file::File::EntityId offset(typeId);
|
||||
JSHandle<TaggedArray> literal = LiteralDataExtractor::GetTypeLiteral(thread_, jsPandaFile, offset);
|
||||
if (literal->GetLength() == 0) { // typeLiteral maybe hole in d.abc
|
||||
return GetAndStoreGT(jsPandaFile, typeId, recordName);
|
||||
TypeLiteralExtractor typeLiteralExtractor(jsPandaFile, typeId);
|
||||
if (!typeLiteralExtractor.IsVaildTypeLiteral()) { // typeLiteral maybe hole in d.abc
|
||||
return GlobalTSTypeRef::Default();
|
||||
}
|
||||
TSTypeKind kind = static_cast<TSTypeKind>(literal->Get(TYPE_KIND_INDEX_IN_LITERAL).GetInt());
|
||||
if (kind == TSTypeKind::IMPORT) {
|
||||
return ResolveImportType(jsPandaFile, recordName, literal, typeId);
|
||||
|
||||
if (typeLiteralExtractor.GetTypeKind() == TSTypeKind::IMPORT) {
|
||||
return ResolveImportType(jsPandaFile, recordName, &typeLiteralExtractor);
|
||||
}
|
||||
|
||||
uint32_t moduleId = tableGenerator_.TryGetModuleId(recordName);
|
||||
@ -100,7 +102,7 @@ GlobalTSTypeRef TSTypeParser::ParseType(const JSPandaFile *jsPandaFile, const CS
|
||||
|
||||
table->SetNumberOfTypes(thread_, localId);
|
||||
GlobalTSTypeRef gt = GetAndStoreGT(jsPandaFile, typeId, recordName, moduleId, localId);
|
||||
JSHandle<JSTaggedValue> type = ParseNonImportType(jsPandaFile, recordName, literal, kind, typeId);
|
||||
JSHandle<JSTaggedValue> type = ParseNonImportType(jsPandaFile, recordName, &typeLiteralExtractor);
|
||||
if (UNLIKELY(type->IsUndefined())) {
|
||||
return GetAndStoreGT(jsPandaFile, typeId, recordName);
|
||||
}
|
||||
@ -111,9 +113,11 @@ GlobalTSTypeRef TSTypeParser::ParseType(const JSPandaFile *jsPandaFile, const CS
|
||||
}
|
||||
|
||||
GlobalTSTypeRef TSTypeParser::ResolveImportType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
JSHandle<TaggedArray> literal, uint32_t typeId)
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
JSHandle<EcmaString> importVarNamePath(thread_, literal->Get(IMPORT_PATH_OFFSET_IN_LITERAL)); // #A#./A
|
||||
uint32_t typeId = typeLiteralExtractor->GetTypeOffset();
|
||||
JSHandle<EcmaString> importVarNamePath =
|
||||
factory_->NewFromUtf8(typeLiteralExtractor->GetStringValue(DEFAULT_INDEX));
|
||||
JSHandle<EcmaString> relativePath = GenerateImportRelativePath(importVarNamePath);
|
||||
CString cstringRelativePath = ConvertToString(*relativePath);
|
||||
// skip @ohos:|@app:|@native: prefixed imports
|
||||
@ -135,7 +139,7 @@ GlobalTSTypeRef TSTypeParser::ResolveImportType(const JSPandaFile *jsPandaFile,
|
||||
|
||||
uint32_t moduleId = tableGenerator_.TryGetModuleId(entryPoint);
|
||||
if (UNLIKELY(!GlobalTSTypeRef::IsVaildModuleId(moduleId))) {
|
||||
LOG_COMPILER(DEBUG) << "The maximum number of TSTypeTables is reached. All TSTypes in the recored "
|
||||
LOG_COMPILER(DEBUG) << "The maximum number of TSTypeTables is reached. All TSTypes in the record "
|
||||
<< entryPoint << " will not be parsed and will be treated as any.";
|
||||
return GetAndStoreGT(jsPandaFile, typeId, recordName);
|
||||
}
|
||||
@ -150,40 +154,43 @@ GlobalTSTypeRef TSTypeParser::ResolveImportType(const JSPandaFile *jsPandaFile,
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> TSTypeParser::ParseNonImportType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
JSHandle<TaggedArray> literal, TSTypeKind kind, uint32_t typeId)
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
auto kind = typeLiteralExtractor->GetTypeKind();
|
||||
switch (kind) {
|
||||
case TSTypeKind::CLASS: {
|
||||
JSHandle<TSClassType> classType = ParseClassType(jsPandaFile, recordName, literal, typeId);
|
||||
JSHandle<TSClassType> classType = ParseClassType(jsPandaFile, recordName, typeLiteralExtractor);
|
||||
return JSHandle<JSTaggedValue>(classType);
|
||||
}
|
||||
case TSTypeKind::CLASS_INSTANCE: {
|
||||
JSHandle<TSClassInstanceType> classInstanceType = ParseClassInstanceType(jsPandaFile, recordName, literal);
|
||||
JSHandle<TSClassInstanceType> classInstanceType =
|
||||
ParseClassInstanceType(jsPandaFile, recordName, typeLiteralExtractor);
|
||||
return JSHandle<JSTaggedValue>(classInstanceType);
|
||||
}
|
||||
case TSTypeKind::INTERFACE_KIND: {
|
||||
JSHandle<TSInterfaceType> interfaceType = ParseInterfaceType(jsPandaFile, recordName, literal);
|
||||
case TSTypeKind::INTERFACE: {
|
||||
JSHandle<TSInterfaceType> interfaceType = ParseInterfaceType(jsPandaFile, recordName, typeLiteralExtractor);
|
||||
return JSHandle<JSTaggedValue>(interfaceType);
|
||||
}
|
||||
case TSTypeKind::UNION: {
|
||||
JSHandle<TSUnionType> unionType = ParseUnionType(jsPandaFile, recordName, literal);
|
||||
JSHandle<TSUnionType> unionType = ParseUnionType(jsPandaFile, recordName, typeLiteralExtractor);
|
||||
return JSHandle<JSTaggedValue>(unionType);
|
||||
}
|
||||
case TSTypeKind::FUNCTION: {
|
||||
JSHandle<TSFunctionType> functionType = ParseFunctionType(jsPandaFile, recordName, literal, typeId);
|
||||
JSHandle<TSFunctionType> functionType =
|
||||
ParseFunctionType(jsPandaFile, recordName, typeLiteralExtractor);
|
||||
return JSHandle<JSTaggedValue>(functionType);
|
||||
}
|
||||
case TSTypeKind::ARRAY: {
|
||||
JSHandle<TSArrayType> arrayType = ParseArrayType(jsPandaFile, recordName, literal);
|
||||
JSHandle<TSArrayType> arrayType = ParseArrayType(jsPandaFile, recordName, typeLiteralExtractor);
|
||||
return JSHandle<JSTaggedValue>(arrayType);
|
||||
}
|
||||
case TSTypeKind::OBJECT: {
|
||||
JSHandle<TSObjectType> objectType = ParseObjectType(jsPandaFile, recordName, literal);
|
||||
JSHandle<TSObjectType> objectType = ParseObjectType(jsPandaFile, recordName, typeLiteralExtractor);
|
||||
return JSHandle<JSTaggedValue>(objectType);
|
||||
}
|
||||
default: {
|
||||
LOG_COMPILER(DEBUG) << "Do not support parse types with kind " << static_cast<uint32_t>(kind) << ". "
|
||||
<< "Please check whether the type literal " << typeId
|
||||
<< "Please check whether the type literal " << typeLiteralExtractor->GetTypeOffset()
|
||||
<< " recorded in the record " << recordName << " is correct.";
|
||||
return thread_->GlobalConstants()->GetHandledUndefined();
|
||||
}
|
||||
@ -191,20 +198,228 @@ JSHandle<JSTaggedValue> TSTypeParser::ParseNonImportType(const JSPandaFile *jsPa
|
||||
}
|
||||
|
||||
JSHandle<TSClassType> TSTypeParser::ParseClassType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal, uint32_t typeId)
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
JSHandle<TSClassType> classType = factory_->NewTSClassType();
|
||||
ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::CLASS);
|
||||
ClassLiteralInfo classLitInfo(typeLiteralExtractor);
|
||||
uint32_t numNonStaticFieldsIndex = classLitInfo.numNonStaticFieldsIndex;
|
||||
uint32_t numNonStaticMethodsIndex = classLitInfo.numNonStaticMethodsIndex;
|
||||
uint32_t numStaticFieldsIndex = classLitInfo.numStaticFieldsIndex;
|
||||
uint32_t numStaticMethodsIndex = classLitInfo.numStaticMethodsIndex;
|
||||
|
||||
std::string className = tsManager_->GetClassNameByOffset(jsPandaFile, typeId);
|
||||
JSHandle<TSClassType> classType = factory_->NewTSClassType();
|
||||
SetClassName(classType, jsPandaFile, typeLiteralExtractor);
|
||||
SetSuperClassType(classType, jsPandaFile, recordName, typeLiteralExtractor);
|
||||
|
||||
// resolve instance type
|
||||
uint32_t numFields = typeLiteralExtractor->GetIntValue(numNonStaticFieldsIndex);
|
||||
JSHandle<TSObjectType> instanceType = factory_->NewTSObjectType(numFields);
|
||||
FillPropTypes(jsPandaFile, recordName, instanceType, typeLiteralExtractor, numNonStaticFieldsIndex, FIELD_LENGTH);
|
||||
classType->SetInstanceType(thread_, instanceType);
|
||||
|
||||
// resolve prototype type
|
||||
uint32_t numNonStatic = typeLiteralExtractor->GetIntValue(numNonStaticMethodsIndex);
|
||||
JSHandle<TSObjectType> prototypeType = factory_->NewTSObjectType(numNonStatic);
|
||||
FillPropTypes(jsPandaFile, recordName, prototypeType, typeLiteralExtractor,
|
||||
numNonStaticMethodsIndex, METHOD_LENGTH);
|
||||
classType->SetPrototypeType(thread_, prototypeType);
|
||||
|
||||
// resolve constructor type
|
||||
uint32_t numStaticFields = typeLiteralExtractor->GetIntValue(numStaticFieldsIndex);
|
||||
uint32_t numStaticMethods = typeLiteralExtractor->GetIntValue(numStaticMethodsIndex);
|
||||
uint32_t numStatic = numStaticFields + numStaticMethods;
|
||||
JSHandle<TSObjectType> constructorType = factory_->NewTSObjectType(numStatic);
|
||||
FillPropTypes(jsPandaFile, recordName, constructorType, typeLiteralExtractor, numStaticFieldsIndex, FIELD_LENGTH);
|
||||
FillPropTypes(jsPandaFile, recordName, constructorType, typeLiteralExtractor,
|
||||
numStaticMethodsIndex, METHOD_LENGTH);
|
||||
classType->SetConstructorType(thread_, constructorType);
|
||||
return classType;
|
||||
}
|
||||
|
||||
JSHandle<TSClassInstanceType> TSTypeParser::ParseClassInstanceType(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::CLASS_INSTANCE);
|
||||
JSHandle<TSClassInstanceType> classInstanceType = factory_->NewTSClassInstanceType();
|
||||
// classTypeId is stored in the first position
|
||||
uint32_t classTypeId = typeLiteralExtractor->GetIntValue(DEFAULT_INDEX);
|
||||
auto classGT = CreateGT(jsPandaFile, recordName, classTypeId);
|
||||
classInstanceType->SetClassGT(classGT);
|
||||
return classInstanceType;
|
||||
}
|
||||
|
||||
JSHandle<TSInterfaceType> TSTypeParser::ParseInterfaceType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::INTERFACE);
|
||||
JSHandle<TSInterfaceType> interfaceType = factory_->NewTSInterfaceType();
|
||||
InterfaceLiteralInfo interfaceLitInfo(typeLiteralExtractor);
|
||||
uint32_t numFieldsIndex = interfaceLitInfo.numFieldsIndex;
|
||||
uint32_t numMethodsIndex = interfaceLitInfo.numMethodsIndex;
|
||||
|
||||
// resolve extends of interface
|
||||
uint32_t numExtends = typeLiteralExtractor->GetIntValue(InterfaceLiteralInfo::NUM_EXTENDS_INDEX);
|
||||
JSHandle<TaggedArray> extendsId = factory_->NewTaggedArray(numExtends);
|
||||
uint32_t extendsIndex = 0;
|
||||
typeLiteralExtractor->EnumerateElements(InterfaceLiteralInfo::NUM_EXTENDS_INDEX,
|
||||
[this, &jsPandaFile, &recordName, &extendsIndex, &extendsId](const uint32_t literalValue) {
|
||||
auto extendGT = CreateGT(jsPandaFile, recordName, literalValue);
|
||||
extendsId->Set(thread_, extendsIndex++, JSTaggedValue(extendGT.GetType()));
|
||||
});
|
||||
interfaceType->SetExtends(thread_, extendsId);
|
||||
|
||||
uint32_t numFields = typeLiteralExtractor->GetIntValue(numFieldsIndex);
|
||||
uint32_t numMethods = typeLiteralExtractor->GetIntValue(numMethodsIndex);
|
||||
uint32_t totalFields = numFields + numMethods;
|
||||
JSHandle<TSObjectType> fieldsType = factory_->NewTSObjectType(totalFields);
|
||||
FillPropTypes(jsPandaFile, recordName, fieldsType, typeLiteralExtractor, numFieldsIndex, FIELD_LENGTH);
|
||||
FillInterfaceMethodTypes(jsPandaFile, recordName, fieldsType, typeLiteralExtractor, numMethodsIndex);
|
||||
interfaceType->SetFields(thread_, fieldsType);
|
||||
return interfaceType;
|
||||
}
|
||||
|
||||
JSHandle<TSUnionType> TSTypeParser::ParseUnionType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::UNION);
|
||||
// the number of union types is stored in the first position
|
||||
uint32_t numOfUnionMembers = typeLiteralExtractor->GetIntValue(DEFAULT_INDEX);
|
||||
JSHandle<TSUnionType> unionType = factory_->NewTSUnionType(numOfUnionMembers);
|
||||
|
||||
JSHandle<TaggedArray> components(thread_, unionType->GetComponents());
|
||||
uint32_t index = 0;
|
||||
typeLiteralExtractor->EnumerateElements(DEFAULT_INDEX,
|
||||
[this, &jsPandaFile, &recordName, &index, &components](const uint32_t literalValue) {
|
||||
auto componentGT = CreateGT(jsPandaFile, recordName, literalValue);
|
||||
components->Set(thread_, index++, JSTaggedValue(componentGT.GetType()));
|
||||
});
|
||||
unionType->SetComponents(thread_, components);
|
||||
return unionType;
|
||||
}
|
||||
|
||||
JSHandle<TSFunctionType> TSTypeParser::ParseFunctionType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::FUNCTION);
|
||||
FunctionLiteralInfo functionLitInfo(typeLiteralExtractor);
|
||||
uint32_t numParasIndex = functionLitInfo.numParasIndex;
|
||||
uint32_t returnTypeIndex = functionLitInfo.returnTypeIndex;
|
||||
|
||||
uint32_t length = typeLiteralExtractor->GetIntValue(numParasIndex);
|
||||
JSHandle<TSFunctionType> functionType = factory_->NewTSFunctionType(length);
|
||||
|
||||
SetFunctionThisType(functionType, jsPandaFile, recordName, typeLiteralExtractor);
|
||||
JSHandle<TaggedArray> parameterTypes(thread_, functionType->GetParameterTypes());
|
||||
uint32_t index = 0;
|
||||
typeLiteralExtractor->EnumerateElements(numParasIndex,
|
||||
[this, &jsPandaFile, &recordName, &index, ¶meterTypes](const uint32_t literalValue) {
|
||||
auto parameterGT = CreateGT(jsPandaFile, recordName, literalValue);
|
||||
if (tsManager_->IsClassTypeKind(parameterGT)) {
|
||||
parameterGT = tsManager_->CreateClassInstanceType(parameterGT);
|
||||
}
|
||||
parameterTypes->Set(thread_, index++, JSTaggedValue(parameterGT.GetType()));
|
||||
});
|
||||
functionType->SetParameterTypes(thread_, parameterTypes);
|
||||
|
||||
JSHandle<JSTaggedValue> functionName(
|
||||
factory_->NewFromUtf8(typeLiteralExtractor->GetStringValue(FunctionLiteralInfo::NAME_INDEX)));
|
||||
functionType->SetName(thread_, functionName);
|
||||
|
||||
uint32_t returntypeId = typeLiteralExtractor->GetIntValue(returnTypeIndex);
|
||||
auto returnGT = CreateGT(jsPandaFile, recordName, returntypeId);
|
||||
functionType->SetReturnGT(returnGT);
|
||||
|
||||
uint32_t bitField = typeLiteralExtractor->GetIntValue(FunctionLiteralInfo::BITFIELD_INDEX);
|
||||
functionType->SetBitField(bitField);
|
||||
|
||||
StoreMethodOffset(functionType, typeLiteralExtractor);
|
||||
return functionType;
|
||||
}
|
||||
|
||||
JSHandle<TSArrayType> TSTypeParser::ParseArrayType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::ARRAY);
|
||||
JSHandle<TSArrayType> arrayType = factory_->NewTSArrayType();
|
||||
// the type of elements of array is stored in the first position
|
||||
auto elemetnGT = CreateGT(jsPandaFile, recordName, typeLiteralExtractor->GetIntValue(DEFAULT_INDEX));
|
||||
if (tsManager_->IsClassTypeKind(elemetnGT)) {
|
||||
elemetnGT = tsManager_->CreateClassInstanceType(elemetnGT);
|
||||
}
|
||||
arrayType->SetElementGT(elemetnGT);
|
||||
return arrayType;
|
||||
}
|
||||
|
||||
JSHandle<TSObjectType> TSTypeParser::ParseObjectType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::OBJECT);
|
||||
// the number of properties of object is stored in the first position
|
||||
uint32_t length = typeLiteralExtractor->GetIntValue(DEFAULT_INDEX);
|
||||
JSHandle<TSObjectType> objectType = factory_->NewTSObjectType(length);
|
||||
FillPropTypes(jsPandaFile, recordName, objectType, typeLiteralExtractor, DEFAULT_INDEX, METHOD_LENGTH);
|
||||
return objectType;
|
||||
}
|
||||
|
||||
void TSTypeParser::FillPropTypes(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
const JSHandle<TSObjectType> &objectType,
|
||||
TypeLiteralExtractor *typeLiteralExtractor,
|
||||
const uint32_t numOfFieldIndex,
|
||||
const uint32_t gap)
|
||||
{
|
||||
JSHandle<TSObjLayoutInfo> layout(thread_, objectType->GetObjLayoutInfo());
|
||||
JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
|
||||
typeLiteralExtractor->EnumerateProperties(numOfFieldIndex, gap,
|
||||
[this, &key, &jsPandaFile, &recordName, &layout](const CString &literalKey, const uint32_t literalValue) {
|
||||
JSHandle<JSTaggedValue> propName(factory_->NewFromUtf8(literalKey));
|
||||
key.Update(propName.GetTaggedValue());
|
||||
ASSERT(key->IsString());
|
||||
auto gt = CreateGT(jsPandaFile, recordName, literalValue);
|
||||
if (tsManager_->IsClassTypeKind(gt)) {
|
||||
gt = tsManager_->CreateClassInstanceType(gt);
|
||||
}
|
||||
layout->AddKeyAndType(thread_, key.GetTaggedValue(), JSTaggedValue(gt.GetType()));
|
||||
});
|
||||
}
|
||||
|
||||
void TSTypeParser::FillInterfaceMethodTypes(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
const JSHandle<TSObjectType> &objectType,
|
||||
TypeLiteralExtractor *typeLiteralExtractor,
|
||||
const uint32_t numExtends)
|
||||
{
|
||||
JSHandle<TSObjLayoutInfo> layout(thread_, objectType->GetObjLayoutInfo());
|
||||
JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
|
||||
typeLiteralExtractor->EnumerateElements(numExtends,
|
||||
[this, &jsPandaFile, &recordName, &layout, &key](const uint32_t literalValue) {
|
||||
auto gt = CreateGT(jsPandaFile, recordName, literalValue);
|
||||
if (tsManager_->IsFunctionTypeKind(gt)) {
|
||||
JSHandle<JSTaggedValue> tsType = tsManager_->GetTSType(gt);
|
||||
ASSERT(tsType->IsTSFunctionType());
|
||||
JSHandle<TSFunctionType> functionType(tsType);
|
||||
key.Update(functionType->GetName());
|
||||
};
|
||||
layout->AddKeyAndType(thread_, key.GetTaggedValue(), JSTaggedValue(gt.GetType()));
|
||||
});
|
||||
}
|
||||
|
||||
void TSTypeParser::SetClassName(const JSHandle<TSClassType> &classType,
|
||||
const JSPandaFile *jsPandaFile,
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
std::string className = tsManager_->GetClassNameByOffset(jsPandaFile, typeLiteralExtractor->GetTypeOffset());
|
||||
JSHandle<EcmaString> classEcmaString = factory_->NewFromStdString(className);
|
||||
classType->SetName(thread_, classEcmaString.GetTaggedValue());
|
||||
}
|
||||
|
||||
uint32_t index = 0;
|
||||
ASSERT(static_cast<TSTypeKind>(literal->Get(index).GetInt()) == TSTypeKind::CLASS);
|
||||
|
||||
const uint32_t ignoreLength = 2; // 2: ignore accessFlag and readonly
|
||||
index += ignoreLength;
|
||||
int extendsTypeId = literal->Get(index++).GetInt();
|
||||
void TSTypeParser::SetSuperClassType(const JSHandle<TSClassType> &classType,
|
||||
const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
uint32_t extendsTypeId = typeLiteralExtractor->GetIntValue(ClassLiteralInfo::SUPER_CLASS_INDEX);
|
||||
if (TSClassType::IsBaseClassType(extendsTypeId)) {
|
||||
classType->SetHasLinked(true);
|
||||
} else {
|
||||
@ -214,284 +429,32 @@ JSHandle<TSClassType> TSTypeParser::ParseClassType(const JSPandaFile *jsPandaFil
|
||||
classType->SetHasLinked(true);
|
||||
}
|
||||
}
|
||||
|
||||
// ignore implement
|
||||
uint32_t numImplement = literal->Get(index++).GetInt();
|
||||
index += numImplement;
|
||||
|
||||
// resolve instance type
|
||||
uint32_t numFields = static_cast<uint32_t>(literal->Get(index++).GetInt());
|
||||
|
||||
JSHandle<TSObjectType> instanceType = factory_->NewTSObjectType(numFields);
|
||||
JSHandle<TSObjLayoutInfo> instanceTypeInfo(thread_, instanceType->GetObjLayoutInfo());
|
||||
ASSERT(instanceTypeInfo->GetPropertiesCapacity() == numFields);
|
||||
FillPropertyTypes(jsPandaFile, recordName, instanceTypeInfo, literal, 0, numFields, index, true);
|
||||
classType->SetInstanceType(thread_, instanceType);
|
||||
|
||||
// resolve prototype type
|
||||
uint32_t numNonStatic = literal->Get(index++).GetInt();
|
||||
JSHandle<TSObjectType> prototypeType = factory_->NewTSObjectType(numNonStatic);
|
||||
|
||||
JSHandle<TSObjLayoutInfo> nonStaticTypeInfo(thread_, prototypeType->GetObjLayoutInfo());
|
||||
ASSERT(nonStaticTypeInfo->GetPropertiesCapacity() == static_cast<uint32_t>(numNonStatic));
|
||||
FillPropertyTypes(jsPandaFile, recordName, nonStaticTypeInfo, literal, 0, numNonStatic, index, false);
|
||||
classType->SetPrototypeType(thread_, prototypeType);
|
||||
|
||||
// resolve constructor type
|
||||
// static include fields and methods, which the former takes up 4 spaces and the latter takes up 2 spaces.
|
||||
uint32_t numStaticFields = literal->Get(index++).GetInt();
|
||||
uint32_t numStaticMethods = literal->Get(index + numStaticFields * TSClassType::FIELD_LENGTH).GetInt();
|
||||
uint32_t numStatic = numStaticFields + numStaticMethods;
|
||||
// new function type when support it
|
||||
JSHandle<TSObjectType> constructorType = factory_->NewTSObjectType(numStatic);
|
||||
|
||||
JSHandle<TSObjLayoutInfo> staticTypeInfo(thread_, constructorType->GetObjLayoutInfo());
|
||||
ASSERT(staticTypeInfo->GetPropertiesCapacity() == static_cast<uint32_t>(numStatic));
|
||||
FillPropertyTypes(jsPandaFile, recordName, staticTypeInfo, literal, 0, numStaticFields, index, true);
|
||||
index++; // jmp over numStaticMethods
|
||||
// static methods
|
||||
FillPropertyTypes(jsPandaFile, recordName, staticTypeInfo, literal, numStaticFields, numStatic, index, false);
|
||||
classType->SetConstructorType(thread_, constructorType);
|
||||
return classType;
|
||||
}
|
||||
|
||||
JSHandle<TSClassInstanceType> TSTypeParser::ParseClassInstanceType(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal)
|
||||
void TSTypeParser::SetFunctionThisType(const JSHandle<TSFunctionType> &functionType,
|
||||
const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
ASSERT(static_cast<TSTypeKind>(literal->Get(TYPE_KIND_INDEX_IN_LITERAL).GetInt()) ==
|
||||
TSTypeKind::CLASS_INSTANCE);
|
||||
JSHandle<TSClassInstanceType> classInstanceType = factory_->NewTSClassInstanceType();
|
||||
uint32_t classTypeId = static_cast<uint32_t>(literal->Get(TSClassInstanceType::CREATE_CLASS_OFFSET).GetInt());
|
||||
auto classGT = CreateGT(jsPandaFile, recordName, classTypeId);
|
||||
classInstanceType->SetClassGT(classGT);
|
||||
return classInstanceType;
|
||||
}
|
||||
|
||||
JSHandle<TSInterfaceType> TSTypeParser::ParseInterfaceType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
JSHandle<TSInterfaceType> interfaceType = factory_->NewTSInterfaceType();
|
||||
ASSERT(static_cast<TSTypeKind>(literal->Get(index).GetInt()) == TSTypeKind::INTERFACE_KIND);
|
||||
|
||||
index++;
|
||||
// resolve extends of interface
|
||||
uint32_t numExtends = literal->Get(index++).GetInt();
|
||||
JSHandle<TaggedArray> extendsId = factory_->NewTaggedArray(numExtends);
|
||||
JSMutableHandle<JSTaggedValue> extendsType(thread_, JSTaggedValue::Undefined());
|
||||
for (uint32_t extendsIndex = 0; extendsIndex < numExtends; extendsIndex++) {
|
||||
auto typeId = literal->Get(index++).GetInt();
|
||||
auto extendGT = CreateGT(jsPandaFile, recordName, typeId);
|
||||
extendsType.Update(JSTaggedValue(extendGT.GetType()));
|
||||
extendsId->Set(thread_, extendsIndex, extendsType);
|
||||
}
|
||||
interfaceType->SetExtends(thread_, extendsId);
|
||||
|
||||
// resolve fields and methods of interface
|
||||
uint32_t numFields = static_cast<uint32_t>(literal->Get(index++).GetInt());
|
||||
// field takes up 4 spaces and method takes up 2 spaces.
|
||||
uint32_t numMethods = static_cast<uint32_t>(literal->Get(index +
|
||||
numFields * TSInterfaceType::FIELD_LENGTH).GetInt());
|
||||
uint32_t totalFields = numFields + numMethods;
|
||||
|
||||
JSHandle<TSObjectType> fieldsType = factory_->NewTSObjectType(totalFields);
|
||||
JSHandle<TSObjLayoutInfo> fieldsTypeInfo(thread_, fieldsType->GetObjLayoutInfo());
|
||||
ASSERT(fieldsTypeInfo->GetPropertiesCapacity() == static_cast<uint32_t>(totalFields));
|
||||
FillPropertyTypes(jsPandaFile, recordName, fieldsTypeInfo, literal, 0, numFields, index, true);
|
||||
index++; // jmp over numMethod
|
||||
FillInterfaceMethodTypes(jsPandaFile, recordName, fieldsTypeInfo, literal, numFields, totalFields, index);
|
||||
interfaceType->SetFields(thread_, fieldsType);
|
||||
return interfaceType;
|
||||
}
|
||||
|
||||
JSHandle<TSUnionType> TSTypeParser::ParseUnionType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal)
|
||||
{
|
||||
uint32_t literalIndex = 0;
|
||||
ASSERT(static_cast<TSTypeKind>(literal->Get(literalIndex).GetInt()) == TSTypeKind::UNION);
|
||||
literalIndex++;
|
||||
uint32_t numOfUnionMembers = literal->Get(literalIndex++).GetInt();
|
||||
|
||||
JSHandle<TSUnionType> unionType = factory_->NewTSUnionType(numOfUnionMembers);
|
||||
JSHandle<TaggedArray> components(thread_, unionType->GetComponents());
|
||||
for (uint32_t index = 0; index < numOfUnionMembers; ++index) {
|
||||
uint32_t componentTypeId = literal->Get(literalIndex++).GetInt();
|
||||
auto componentGT = CreateGT(jsPandaFile, recordName, componentTypeId);
|
||||
components->Set(thread_, index, JSTaggedValue(componentGT.GetType()));
|
||||
}
|
||||
unionType->SetComponents(thread_, components);
|
||||
return unionType;
|
||||
}
|
||||
|
||||
JSHandle<TSFunctionType> TSTypeParser::ParseFunctionType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal, uint32_t functionId)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
ASSERT(static_cast<TSTypeKind>(literal->Get(index).GetInt()) == TSTypeKind::FUNCTION);
|
||||
index++;
|
||||
|
||||
int32_t bitField = literal->Get(index++).GetInt();
|
||||
|
||||
JSHandle<JSTaggedValue> functionName(thread_, literal->Get(index++));
|
||||
bool hasThisType = static_cast<bool>(literal->Get(index++).GetInt());
|
||||
int32_t thisTypeId = 0;
|
||||
if (hasThisType) {
|
||||
thisTypeId = literal->Get(index++).GetInt();
|
||||
}
|
||||
|
||||
int32_t length = literal->Get(index++).GetInt();
|
||||
JSHandle<TSFunctionType> functionType = factory_->NewTSFunctionType(length);
|
||||
JSHandle<TaggedArray> parameterTypes(thread_, functionType->GetParameterTypes());
|
||||
JSMutableHandle<JSTaggedValue> parameterTypeRef(thread_, JSTaggedValue::Undefined());
|
||||
for (int32_t i = 0; i < length; ++i) {
|
||||
auto typeId = literal->Get(index++).GetInt();
|
||||
auto parameterGT = CreateGT(jsPandaFile, recordName, typeId);
|
||||
if (tsManager_->IsClassTypeKind(parameterGT)) {
|
||||
parameterGT = tsManager_->CreateClassInstanceType(parameterGT);
|
||||
}
|
||||
parameterTypeRef.Update(JSTaggedValue(parameterGT.GetType()));
|
||||
parameterTypes->Set(thread_, i, parameterTypeRef);
|
||||
}
|
||||
int32_t returntypeId = literal->Get(index++).GetInt();
|
||||
|
||||
functionType->SetName(thread_, functionName);
|
||||
bool hasThisType = static_cast<bool>(typeLiteralExtractor->GetIntValue(FunctionLiteralInfo::HAS_THIS_TYPE_INDEX));
|
||||
if (hasThisType) {
|
||||
// if hasThisType is true, then the next position will store typeId of this
|
||||
uint32_t thisTypeId = typeLiteralExtractor->GetIntValue(FunctionLiteralInfo::HAS_THIS_TYPE_INDEX + 1);
|
||||
auto thisGT = CreateGT(jsPandaFile, recordName, thisTypeId);
|
||||
functionType->SetThisGT(thisGT);
|
||||
}
|
||||
}
|
||||
|
||||
functionType->SetParameterTypes(thread_, parameterTypes);
|
||||
auto returnGT = CreateGT(jsPandaFile, recordName, returntypeId);
|
||||
functionType->SetReturnGT(returnGT);
|
||||
functionType->SetBitField(bitField);
|
||||
auto bcInfoCollector = tsManager_->GetBytecodeInfoCollector();
|
||||
if (bcInfoCollector != nullptr) {
|
||||
auto &bcInfo = bcInfoCollector->GetBytecodeInfo();
|
||||
uint32_t methodOffset = bcInfo.IterateFunctionTypeIDAndMethodOffset(functionId);
|
||||
void TSTypeParser::StoreMethodOffset(const JSHandle<TSFunctionType> &functionType,
|
||||
TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
if (bcInfo_ != nullptr) {
|
||||
uint32_t typeOffset = typeLiteralExtractor->GetTypeOffset();
|
||||
uint32_t methodOffset = bcInfo_->IterateFunctionTypeIDAndMethodOffset(typeOffset);
|
||||
if (methodOffset != 0) {
|
||||
functionType->SetMethodOffset(methodOffset);
|
||||
}
|
||||
}
|
||||
return functionType;
|
||||
}
|
||||
|
||||
JSHandle<TSArrayType> TSTypeParser::ParseArrayType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
ASSERT(static_cast<TSTypeKind>(literal->Get(index).GetInt()) == TSTypeKind::ARRAY);
|
||||
index++;
|
||||
JSHandle<JSTaggedValue> elementTypeId(thread_, literal->Get(index++));
|
||||
ASSERT(elementTypeId->IsInt());
|
||||
JSHandle<TSArrayType> arrayType = factory_->NewTSArrayType();
|
||||
auto elemetnGT = CreateGT(jsPandaFile, recordName, elementTypeId->GetInt());
|
||||
if (tsManager_->IsClassTypeKind(elemetnGT)) {
|
||||
elemetnGT = tsManager_->CreateClassInstanceType(elemetnGT);
|
||||
}
|
||||
arrayType->SetElementGT(elemetnGT);
|
||||
return arrayType;
|
||||
}
|
||||
|
||||
JSHandle<TSObjectType> TSTypeParser::ParseObjectType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
ASSERT(static_cast<TSTypeKind>(literal->Get(index).GetInt()) == TSTypeKind::OBJECT);
|
||||
index++;
|
||||
uint32_t length = literal->Get(index++).GetInt();
|
||||
JSHandle<TSObjectType> objectType = factory_->NewTSObjectType(length);
|
||||
JSHandle<TSObjLayoutInfo> propertyTypeInfo(thread_, objectType->GetObjLayoutInfo());
|
||||
ASSERT(propertyTypeInfo->GetPropertiesCapacity() == static_cast<uint32_t>(length));
|
||||
FillPropertyTypes(jsPandaFile, recordName, propertyTypeInfo, literal, 0, length, index, false);
|
||||
objectType->SetObjLayoutInfo(thread_, propertyTypeInfo);
|
||||
return objectType;
|
||||
}
|
||||
|
||||
void TSTypeParser::FillPropertyTypes(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
JSHandle<TSObjLayoutInfo> &layout, const JSHandle<TaggedArray> &literal,
|
||||
uint32_t startIndex, uint32_t lastIndex, uint32_t &index, bool isField)
|
||||
{
|
||||
JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> value(thread_, JSTaggedValue::Undefined());
|
||||
for (uint32_t fieldIndex = startIndex; fieldIndex < lastIndex; ++fieldIndex) {
|
||||
key.Update(literal->Get(index++));
|
||||
ASSERT(key->IsString());
|
||||
auto gt = CreateGT(jsPandaFile, recordName, literal->Get(index++).GetInt());
|
||||
if (tsManager_->IsClassTypeKind(gt)) {
|
||||
gt = tsManager_->CreateClassInstanceType(gt);
|
||||
}
|
||||
value.Update(JSTaggedValue(gt.GetType()));
|
||||
layout->AddKeyAndType(thread_, key.GetTaggedValue(), value.GetTaggedValue());
|
||||
if (isField) {
|
||||
index += 2; // 2: ignore accessFlag and readonly
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TSTypeParser::FillInterfaceMethodTypes(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
JSHandle<TSObjLayoutInfo> &layout, const JSHandle<TaggedArray> &literal,
|
||||
uint32_t startIndex, uint32_t lastIndex, uint32_t &index)
|
||||
{
|
||||
JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> value(thread_, JSTaggedValue::Undefined());
|
||||
for (uint32_t methodIndex = startIndex; methodIndex < lastIndex; ++methodIndex) {
|
||||
auto gt = CreateGT(jsPandaFile, recordName, literal->Get(index++).GetInt());
|
||||
value.Update(JSTaggedValue(gt.GetType()));
|
||||
|
||||
if (tsManager_->IsFunctionTypeKind(gt)) {
|
||||
JSHandle<JSTaggedValue> tsType = tsManager_->GetTSType(gt);
|
||||
ASSERT(tsType->IsTSFunctionType());
|
||||
|
||||
JSHandle<TSFunctionType> functionType(tsType);
|
||||
key.Update(functionType->GetName());
|
||||
};
|
||||
|
||||
layout->AddKeyAndType(thread_, key.GetTaggedValue(), value.GetTaggedValue());
|
||||
}
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> TSTypeParser::GetExportDataFromRecord(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName)
|
||||
{
|
||||
const panda_file::File &pf = *jsPandaFile->GetPandaFile();
|
||||
panda_file::File::EntityId methodId(jsPandaFile->GetMainMethodIndex(recordName));
|
||||
panda_file::MethodDataAccessor mda(pf, methodId);
|
||||
|
||||
const char *symbolTypes;
|
||||
auto *fileName = pf.GetFilename().c_str();
|
||||
if (::strcmp(TSTypeTable::BUILTINS_TABLE_NAME, fileName) == 0) {
|
||||
symbolTypes = DECLARED_SYMBOL_TYPES;
|
||||
} else {
|
||||
symbolTypes = EXPORTED_SYMBOL_TYPES;
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> typeOfExportedSymbols(thread_, thread_->GlobalConstants()->GetEmptyArray());
|
||||
mda.EnumerateAnnotations([&](panda_file::File::EntityId annotationId) {
|
||||
panda_file::AnnotationDataAccessor ada(pf, annotationId);
|
||||
auto *annotationName = reinterpret_cast<const char *>(jsPandaFile->GetStringData(ada.GetClassId()).data);
|
||||
ASSERT(annotationName != nullptr);
|
||||
if (::strcmp("L_ESTypeAnnotation;", annotationName) != 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t length = ada.GetCount();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
panda_file::AnnotationDataAccessor::Elem adae = ada.GetElement(i);
|
||||
auto *elemName = reinterpret_cast<const char *>(jsPandaFile->GetStringData(adae.GetNameId()).data);
|
||||
ASSERT(elemName != nullptr);
|
||||
|
||||
if (::strcmp(symbolTypes, elemName) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
panda_file::ScalarValue sv = adae.GetScalarValue();
|
||||
panda_file::File::EntityId literalOffset(sv.GetValue());
|
||||
typeOfExportedSymbols = LiteralDataExtractor::GetTypeLiteral(thread_, jsPandaFile, literalOffset);
|
||||
// typeOfExprotedSymbols: "symbol0", "type0", "symbol1", "type1" ...
|
||||
}
|
||||
});
|
||||
|
||||
return typeOfExportedSymbols;
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> TSTypeParser::GenerateExportTableFromRecord(const JSPandaFile *jsPandaFile,
|
||||
@ -501,24 +464,15 @@ JSHandle<JSTaggedValue> TSTypeParser::GenerateExportTableFromRecord(const JSPand
|
||||
JSHandle<JSTaggedValue> exportValeTable = TSTypeTable::GetExportValueTable(thread_, table);
|
||||
if (exportValeTable->IsUndefined()) {
|
||||
// Read export-data from annotation of the .abc File
|
||||
JSHandle<TaggedArray> exportTable;
|
||||
if (tsManager_->HasResolvedExportTable(jsPandaFile, recordName)) {
|
||||
JSTaggedValue resolvedTable = tsManager_->GetResolvedExportTable(jsPandaFile, recordName);
|
||||
exportTable = JSHandle<TaggedArray>::Cast(JSHandle<JSTaggedValue>(thread_, resolvedTable));
|
||||
} else {
|
||||
exportTable = GetExportDataFromRecord(jsPandaFile, recordName);
|
||||
}
|
||||
JSHandle<TaggedArray> exportTable = tsManager_->GetExportTableFromLiteral(jsPandaFile, recordName);
|
||||
uint32_t length = exportTable->GetLength();
|
||||
|
||||
// Replace typeIds with GT
|
||||
JSTaggedValue target;
|
||||
for (uint32_t i = 1; i < length; i += 2) { // 2: skip a pair of key and value
|
||||
target = exportTable->Get(i);
|
||||
JSTaggedValue target = exportTable->Get(i);
|
||||
// Create GT based on typeId, and wrapped it into a JSTaggedValue
|
||||
uint32_t typeId = static_cast<uint32_t>(target.GetInt());
|
||||
GlobalTSTypeRef typeGT = CreateGT(jsPandaFile, recordName, typeId);
|
||||
GlobalTSTypeRef gt = CreateGT(jsPandaFile, recordName, typeId);
|
||||
// Set the wrapped GT to exportTable
|
||||
exportTable->Set(thread_, i, JSTaggedValue(typeGT.GetType()));
|
||||
exportTable->Set(thread_, i, JSTaggedValue(gt.GetType()));
|
||||
}
|
||||
TSTypeTable::SetExportValueTable(thread_, table, exportTable);
|
||||
return JSHandle<JSTaggedValue>(exportTable);
|
||||
@ -591,4 +545,35 @@ GlobalTSTypeRef TSTypeParser::IterateStarExport(JSHandle<EcmaString> target, con
|
||||
}
|
||||
return GlobalTSTypeRef::Default();
|
||||
}
|
||||
|
||||
static uint32_t CalculateNextNumIndex(const TypeLiteralExtractor *typeLiteralExtractor,
|
||||
uint32_t startIndex = 0,
|
||||
uint32_t gap = 1)
|
||||
{
|
||||
return startIndex + INDEX_OCCUPIED_OFFSET + (typeLiteralExtractor->GetIntValue(startIndex) * gap);
|
||||
}
|
||||
|
||||
ClassLiteralInfo::ClassLiteralInfo(const TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::CLASS);
|
||||
numNonStaticFieldsIndex = CalculateNextNumIndex(typeLiteralExtractor, NUM_IMPLEMENTS_INDEX);
|
||||
numNonStaticMethodsIndex = CalculateNextNumIndex(typeLiteralExtractor, numNonStaticFieldsIndex, FIELD_LENGTH);
|
||||
numStaticFieldsIndex = CalculateNextNumIndex(typeLiteralExtractor, numNonStaticMethodsIndex, METHOD_LENGTH);
|
||||
numStaticMethodsIndex = CalculateNextNumIndex(typeLiteralExtractor, numStaticFieldsIndex, FIELD_LENGTH);
|
||||
}
|
||||
|
||||
InterfaceLiteralInfo::InterfaceLiteralInfo(const TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::INTERFACE);
|
||||
numFieldsIndex = CalculateNextNumIndex(typeLiteralExtractor, NUM_EXTENDS_INDEX);
|
||||
numMethodsIndex = CalculateNextNumIndex(typeLiteralExtractor, numFieldsIndex, FIELD_LENGTH);
|
||||
}
|
||||
|
||||
FunctionLiteralInfo::FunctionLiteralInfo(const TypeLiteralExtractor *typeLiteralExtractor)
|
||||
{
|
||||
ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::FUNCTION);
|
||||
numParasIndex = HAS_THIS_TYPE_INDEX + INDEX_OCCUPIED_OFFSET +
|
||||
typeLiteralExtractor->GetIntValue(HAS_THIS_TYPE_INDEX);
|
||||
returnTypeIndex = CalculateNextNumIndex(typeLiteralExtractor, numParasIndex);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -36,17 +36,11 @@ public:
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API CreateGT(const JSPandaFile *jsPandaFile, const CString &recordName, uint32_t typeId);
|
||||
|
||||
JSHandle<TaggedArray> GetExportDataFromRecord(const JSPandaFile *jsPandaFile, const CString &recordName);
|
||||
|
||||
static constexpr size_t USER_DEFINED_TYPE_OFFSET = 100;
|
||||
|
||||
private:
|
||||
static constexpr size_t TYPE_KIND_INDEX_IN_LITERAL = 0;
|
||||
static constexpr size_t BUILDIN_TYPE_OFFSET = 20;
|
||||
static constexpr size_t IMPORT_PATH_OFFSET_IN_LITERAL = 1;
|
||||
|
||||
static constexpr const char* DECLARED_SYMBOL_TYPES = "declaredSymbolTypes";
|
||||
static constexpr const char* EXPORTED_SYMBOL_TYPES = "exportedSymbolTypes";
|
||||
static constexpr size_t DEFAULT_INDEX = 0;
|
||||
|
||||
inline GlobalTSTypeRef GetAndStoreGT(const JSPandaFile *jsPandaFile, uint32_t typeId, const CString &recordName,
|
||||
uint32_t moduleId = 0, uint32_t localId = 0)
|
||||
@ -76,45 +70,60 @@ private:
|
||||
GlobalTSTypeRef ParseBuiltinObjType(uint32_t typeId);
|
||||
|
||||
GlobalTSTypeRef ResolveImportType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
JSHandle<TaggedArray> literal, uint32_t typeId);
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
JSHandle<JSTaggedValue> ParseNonImportType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
JSHandle<TaggedArray> literal, TSTypeKind kind, uint32_t typeId);
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
JSHandle<TSClassType> ParseClassType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal, uint32_t typeId);
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
JSHandle<TSClassInstanceType> ParseClassInstanceType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal);
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
JSHandle<TSInterfaceType> ParseInterfaceType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal);
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
JSHandle<TSUnionType> ParseUnionType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal);
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
JSHandle<TSFunctionType> ParseFunctionType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal, uint32_t functionId);
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
JSHandle<TSArrayType> ParseArrayType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal);
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
JSHandle<TSObjectType> ParseObjectType(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TaggedArray> &literal);
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
void FillPropertyTypes(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
JSHandle<TSObjLayoutInfo> &layout,
|
||||
const JSHandle<TaggedArray> &literal,
|
||||
uint32_t startIndex, uint32_t lastIndex,
|
||||
uint32_t &index, bool isField);
|
||||
void FillPropTypes(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
const JSHandle<TSObjectType> &objectType,
|
||||
TypeLiteralExtractor *typeLiteralExtractor,
|
||||
const uint32_t numOfFieldIndex,
|
||||
const uint32_t gap);
|
||||
|
||||
void FillInterfaceMethodTypes(const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
JSHandle<TSObjLayoutInfo> &layout,
|
||||
const JSHandle<TaggedArray> &literal,
|
||||
uint32_t startIndex, uint32_t lastIndex,
|
||||
uint32_t &index);
|
||||
const JSHandle<TSObjectType> &objectType,
|
||||
TypeLiteralExtractor *typeLiteralExtractor,
|
||||
const uint32_t numExtends);
|
||||
|
||||
void SetClassName(const JSHandle<TSClassType> &classType,
|
||||
const JSPandaFile *jsPandaFile,
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
void SetSuperClassType(const JSHandle<TSClassType> &classType,
|
||||
const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
void SetFunctionThisType(const JSHandle<TSFunctionType> &functionType,
|
||||
const JSPandaFile *jsPandaFile,
|
||||
const CString &recordName,
|
||||
TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
void StoreMethodOffset(const JSHandle<TSFunctionType> &functionType, TypeLiteralExtractor *typeLiteralExtractor);
|
||||
|
||||
JSHandle<JSTaggedValue> GenerateExportTableFromRecord(const JSPandaFile *jsPandaFile, const CString &recordName,
|
||||
const JSHandle<TSTypeTable> &table);
|
||||
@ -137,5 +146,40 @@ private:
|
||||
TSTypeTableGenerator tableGenerator_;
|
||||
kungfu::BCInfo *bcInfo_ {nullptr};
|
||||
};
|
||||
|
||||
struct ClassLiteralInfo {
|
||||
explicit ClassLiteralInfo(const TypeLiteralExtractor *typeLiteralExtractor);
|
||||
~ClassLiteralInfo() = default;
|
||||
|
||||
static constexpr uint32_t SUPER_CLASS_INDEX = 1;
|
||||
static constexpr uint32_t NUM_IMPLEMENTS_INDEX = 2;
|
||||
|
||||
uint32_t numNonStaticFieldsIndex {0};
|
||||
uint32_t numNonStaticMethodsIndex {0};
|
||||
uint32_t numStaticFieldsIndex {0};
|
||||
uint32_t numStaticMethodsIndex {0};
|
||||
};
|
||||
|
||||
struct InterfaceLiteralInfo {
|
||||
explicit InterfaceLiteralInfo(const TypeLiteralExtractor *typeLiteralExtractor);
|
||||
~InterfaceLiteralInfo() = default;
|
||||
|
||||
static constexpr uint32_t NUM_EXTENDS_INDEX = 0;
|
||||
|
||||
uint32_t numFieldsIndex {0};
|
||||
uint32_t numMethodsIndex {0};
|
||||
};
|
||||
|
||||
struct FunctionLiteralInfo {
|
||||
explicit FunctionLiteralInfo(const TypeLiteralExtractor *typeLiteralExtractor);
|
||||
~FunctionLiteralInfo() = default;
|
||||
|
||||
static constexpr uint32_t BITFIELD_INDEX = 0;
|
||||
static constexpr uint32_t NAME_INDEX = 1;
|
||||
static constexpr uint32_t HAS_THIS_TYPE_INDEX = 2;
|
||||
|
||||
uint32_t numParasIndex {0};
|
||||
uint32_t returnTypeIndex {0};
|
||||
};
|
||||
} // panda::ecmascript
|
||||
#endif // ECMASCRIPT_TS_TYPES_TS_TYPE_PARSER_H
|
||||
|
@ -55,16 +55,8 @@ JSHandle<TSTypeTable> TSTypeTableGenerator::GetOrGenerateTSTypeTable(const JSPan
|
||||
return tsManager_->GetTSTypeTable(moduleId);
|
||||
}
|
||||
JSHandle<EcmaString> recordNameStr = factory_->NewFromUtf8(recordName);
|
||||
// read type summary literal
|
||||
// struct of summaryLiteral: {numTypes, literalOffset0, literalOffset1, ...}
|
||||
panda_file::File::EntityId summaryOffset(jsPandaFile->GetTypeSummaryOffset(recordName));
|
||||
JSHandle<TaggedArray> summaryLiteral =
|
||||
LiteralDataExtractor::GetTypeLiteral(thread_, jsPandaFile, summaryOffset);
|
||||
uint32_t numIdx = static_cast<uint32_t>(BuiltinTypeId::NUM_INDEX_IN_SUMMARY);
|
||||
uint32_t numTypes = static_cast<uint32_t>(summaryLiteral->Get(numIdx).GetInt());
|
||||
|
||||
// Initialize a empty TSTypeTable with length of (numTypes + RESERVE_TABLE_LENGTH)
|
||||
JSHandle<TSTypeTable> table = AddTypeTable(recordNameStr, numTypes);
|
||||
TypeSummaryExtractor summExtractor(jsPandaFile, recordName);
|
||||
JSHandle<TSTypeTable> table = AddTypeTable(recordNameStr, summExtractor.GetNumOfTypes());
|
||||
return table;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user