From 63f702ae40c4786b6267d9baa9073f4856740776 Mon Sep 17 00:00:00 2001 From: weng-xi Date: Tue, 25 Oct 2022 11:42:17 +0800 Subject: [PATCH] Set AOT code entry for literal object Signed-off-by: weng-xi Change-Id: I0c4d2e7579a845b3ec4cd8b9dac4057edf7e9397 --- ecmascript/aot_file_manager.cpp | 21 ++ ecmascript/aot_file_manager.h | 13 +- .../compiler/bytecode_circuit_builder.cpp | 34 ++- .../compiler/bytecode_circuit_builder.h | 16 +- ecmascript/compiler/circuit_builder-inl.h | 9 + ecmascript/compiler/circuit_builder.h | 1 + ecmascript/compiler/pass_manager.cpp | 4 +- ecmascript/compiler/slowpath_lowering.cpp | 30 ++- ecmascript/dfx/hprof/heap_snapshot.cpp | 2 + ecmascript/dump.cpp | 2 + ecmascript/global_env_constants.cpp | 2 + ecmascript/global_env_constants.h | 1 + ecmascript/js_hclass-inl.h | 1 + ecmascript/js_hclass.h | 10 +- ecmascript/js_tagged_value-inl.h | 5 + ecmascript/js_tagged_value.h | 1 + .../jspandafile/panda_file_translator.cpp | 2 +- ecmascript/jspandafile/program_object.h | 59 +++- ecmascript/mem/object_xray.h | 1 + ecmascript/object_factory.cpp | 13 + ecmascript/object_factory.h | 4 + ecmascript/tests/dump_test.cpp | 3 +- ecmascript/ts_types/ts_manager.cpp | 253 +++++++++++++++--- ecmascript/ts_types/ts_manager.h | 200 ++++++++++---- 24 files changed, 565 insertions(+), 122 deletions(-) diff --git a/ecmascript/aot_file_manager.cpp b/ecmascript/aot_file_manager.cpp index 1605f53671..0f0ccdade1 100644 --- a/ecmascript/aot_file_manager.cpp +++ b/ecmascript/aot_file_manager.cpp @@ -459,6 +459,27 @@ void AOTFileManager::SetAOTFuncEntry(const JSPandaFile *jsPandaFile, Method *met method->SetCodeEntryAndMarkAOT(codeEntry); } +void AOTFileManager::SetAOTFuncEntryForLiteral(const JSPandaFile *jsPandaFile, const TaggedArray *literal, + const AOTLiteralInfo *entryIndexes) +{ + size_t elementsLen = literal->GetLength(); + JSTaggedValue value = JSTaggedValue::Undefined(); + int pos = 0; + for (size_t i = 0; i < elementsLen; i++) { + value = literal->Get(i); + if (value.IsJSFunction()) { + JSTaggedValue index = entryIndexes->Get(pos++); + int entryIndex = index.GetInt(); + // -1 : this jsfunction is a large function + if (entryIndex == -1) { + continue; + } + SetAOTFuncEntry(jsPandaFile, JSFunction::Cast(value)->GetCallTarget(), + static_cast(entryIndex)); + } + } +} + kungfu::ArkStackMapParser* AOTFileManager::GetStackMapParser() const { return arkStackMapParser_; diff --git a/ecmascript/aot_file_manager.h b/ecmascript/aot_file_manager.h index 4d37146a83..6c97936551 100644 --- a/ecmascript/aot_file_manager.h +++ b/ecmascript/aot_file_manager.h @@ -149,7 +149,7 @@ public: struct FuncEntryDes { uint64_t codeAddr_; CallSignature::TargetKind kind_; - bool isMainFunc_; + bool isMainFunc_; uint32_t indexInKindOrMethodId_; uint32_t moduleIndex_; int fpDeltaPrevFrameSp_; @@ -392,6 +392,15 @@ private: std::vector asmStubTempHolder_ {}; }; +class AOTLiteralInfo : public TaggedArray { +public: + static AOTLiteralInfo *Cast(TaggedObject *object) + { + ASSERT(JSTaggedValue(object).IsTaggedArray()); + return static_cast(object); + } +}; + class AOTFileManager { public: explicit AOTFileManager(EcmaVM *vm); @@ -420,6 +429,8 @@ public: void UpdateJSMethods(JSHandle mainFunc, const JSPandaFile *jsPandaFile, std::string_view entryPoint); bool HasLoaded(const JSPandaFile *jsPandaFile) const; void SetAOTFuncEntry(const JSPandaFile *jsPandaFile, Method *method, uint32_t entryIndex); + void SetAOTFuncEntryForLiteral(const JSPandaFile *jsPandaFile, const TaggedArray *literal, + const AOTLiteralInfo *entryIndexes); void LoadSnapshotFile([[maybe_unused]]const std::string& filename); kungfu::ArkStackMapParser* GetStackMapParser() const; static JSTaggedValue GetAbsolutePath(JSThread *thread, JSTaggedValue relativePathVal); diff --git a/ecmascript/compiler/bytecode_circuit_builder.cpp b/ecmascript/compiler/bytecode_circuit_builder.cpp index 6455d02661..a0f3281879 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.cpp +++ b/ecmascript/compiler/bytecode_circuit_builder.cpp @@ -1054,12 +1054,12 @@ BytecodeInfo BytecodeCircuitBuilder::GetBytecodeInfo(const uint8_t *pc) } case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: { uint16_t imm = READ_INST_16_1(); - info.inputs.emplace_back(Immediate(imm)); + info.inputs.emplace_back(ConstDataId(ConstDataIDType::ObjectLiteralIDType, imm)); break; } case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: { uint16_t imm = READ_INST_16_2(); - info.inputs.emplace_back(Immediate(imm)); + info.inputs.emplace_back(ConstDataId(ConstDataIDType::ObjectLiteralIDType, imm)); break; } case EcmaOpcode::SETOBJECTWITHPROTO_IMM8_V8: { @@ -1074,12 +1074,12 @@ BytecodeInfo BytecodeCircuitBuilder::GetBytecodeInfo(const uint8_t *pc) } case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: { uint16_t imm = READ_INST_16_1(); - info.inputs.emplace_back(Immediate(imm)); + info.inputs.emplace_back(ConstDataId(ConstDataIDType::ArrayLiteralIDType, imm)); break; } case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: { uint16_t imm = READ_INST_16_2(); - info.inputs.emplace_back(Immediate(imm)); + info.inputs.emplace_back(ConstDataId(ConstDataIDType::ArrayLiteralIDType, imm)); break; } case EcmaOpcode::GETMODULENAMESPACE_IMM8: { @@ -1494,7 +1494,7 @@ BytecodeInfo BytecodeCircuitBuilder::GetBytecodeInfo(const uint8_t *pc) uint16_t length = READ_INST_16_5(); uint16_t v0 = READ_INST_8_7(); info.inputs.emplace_back(ConstDataId(ConstDataIDType::MethodIDType, methodId)); - info.inputs.emplace_back(Immediate(literaId)); + info.inputs.emplace_back(ConstDataId(ConstDataIDType::ClassLiteralIDType, literaId)); info.inputs.emplace_back(Immediate(length)); info.inputs.emplace_back(VirtualRegister(v0)); break; @@ -1505,7 +1505,7 @@ BytecodeInfo BytecodeCircuitBuilder::GetBytecodeInfo(const uint8_t *pc) uint16_t length = READ_INST_16_6(); uint16_t v0 = READ_INST_8_8(); info.inputs.emplace_back(ConstDataId(ConstDataIDType::MethodIDType, methodId)); - info.inputs.emplace_back(Immediate(literaId)); + info.inputs.emplace_back(ConstDataId(ConstDataIDType::ClassLiteralIDType, literaId)); info.inputs.emplace_back(Immediate(length)); info.inputs.emplace_back(VirtualRegister(v0)); break; @@ -1900,15 +1900,27 @@ std::vector BytecodeCircuitBuilder::CreateGateInList(const BytecodeInfo const auto &input = info.inputs[i]; if (std::holds_alternative(input)) { if (std::get(input).IsStringId()) { - tsManager_->AddStringIndex(std::get(input).GetId()); + tsManager_->AddIndexOrSkippedMethodID(CacheType::STRING, + std::get(input).GetId()); inList[i + length] = circuit_.GetConstantDataGate(std::get(input).CaculateBitField(), GateType::StringType()); + continue; } else if (std::get(input).IsMethodId()) { - tsManager_->AddMethodIndex(std::get(input).GetId()); - inList[i + length] = circuit_.GetConstantGate(MachineType::I64, + tsManager_->AddIndexOrSkippedMethodID(CacheType::METHOD, + std::get(input).GetId()); + } else if (std::get(input).IsClassLiteraId()) { + tsManager_->AddIndexOrSkippedMethodID(CacheType::CLASS_LITERAL, + std::get(input).GetId(), recordName_); + } else if (std::get(input).IsObjectLiteralID()) { + tsManager_->AddIndexOrSkippedMethodID(CacheType::OBJECT_LITERAL, + std::get(input).GetId(), recordName_); + } else if (std::get(input).IsArrayLiteralID()) { + tsManager_->AddIndexOrSkippedMethodID(CacheType::ARRAY_LITERAL, + std::get(input).GetId(), recordName_); + } + inList[i + length] = circuit_.GetConstantGate(MachineType::I64, std::get(input).GetId(), GateType::NJSValue()); - } } else if (std::holds_alternative(input)) { inList[i + length] = circuit_.GetConstantGate(MachineType::I64, std::get(input).GetValue(), @@ -2006,7 +2018,7 @@ GateRef BytecodeCircuitBuilder::NewConst(const BytecodeInfo &info) case EcmaOpcode::LDA_STR_ID16: { auto input = std::get(info.inputs.at(0)); if (input.IsStringId()) { - tsManager_->AddStringIndex(input.GetId()); + tsManager_->AddIndexOrSkippedMethodID(CacheType::STRING, input.GetId()); } gate = circuit_.GetConstantDataGate(input.CaculateBitField(), GateType::StringType()); break; diff --git a/ecmascript/compiler/bytecode_circuit_builder.h b/ecmascript/compiler/bytecode_circuit_builder.h index c13467966b..85d6d43df0 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.h +++ b/ecmascript/compiler/bytecode_circuit_builder.h @@ -147,6 +147,16 @@ public: return type_ == ConstDataIDType::ClassLiteralIDType; } + bool IsObjectLiteralID() const + { + return type_ == ConstDataIDType::ObjectLiteralIDType; + } + + bool IsArrayLiteralID() const + { + return type_ == ConstDataIDType::ArrayLiteralIDType; + } + BitField CaculateBitField() const { return (static_cast(type_) << TYPE_SHIFT) | id_; @@ -492,13 +502,14 @@ public: const CompilationConfig* cconfig, bool hasTypes, bool enableLog, - std::string name) + std::string name, + const CString &recordName) : tsManager_(tsManager), circuit_(cconfig->Is64Bit()), file_(jsPandaFile), pf_(jsPandaFile->GetPandaFile()), method_(methodLiteral), gateAcc_(&circuit_), argAcc_(&circuit_, method_, jsPandaFile), typeRecorder_(jsPandaFile, method_, tsManager), hasTypes_(hasTypes), enableLog_(enableLog), pcToBCOffset_(methodPCInfo.pcToBCOffset), byteCodeCurPrePc_(methodPCInfo.byteCodeCurPrePc), bytecodeBlockInfos_(methodPCInfo.bytecodeBlockInfos), - frameStateBuilder_(this, &circuit_, methodLiteral), methodName_(name) + frameStateBuilder_(this, &circuit_, methodLiteral), methodName_(name), recordName_(recordName) { } ~BytecodeCircuitBuilder() = default; @@ -681,6 +692,7 @@ private: std::map, kungfu::GateRef> resumeRegToRestore_; FrameStateBuilder frameStateBuilder_; std::string methodName_; + const CString &recordName_; }; } // namespace panda::ecmascript::kungfu #endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H diff --git a/ecmascript/compiler/circuit_builder-inl.h b/ecmascript/compiler/circuit_builder-inl.h index bd18893118..e94531de49 100644 --- a/ecmascript/compiler/circuit_builder-inl.h +++ b/ecmascript/compiler/circuit_builder-inl.h @@ -322,6 +322,15 @@ GateRef CircuitBuilder::TaggedIsBoolean(GateRef x) return BoolOr(TaggedIsFalse(x), TaggedIsTrue(x)); } +GateRef CircuitBuilder::IsAOTLiteralInfo(GateRef x) +{ + GateRef isHeapObj = TaggedIsHeapObject(x); + GateRef objType = GetObjectType(LoadHClass(x)); + GateRef isAOTLiteralInfoObj = Equal(objType, + Int32(static_cast(JSType::AOT_LITERAL_INFO))); + return LogicAnd(isHeapObj, isAOTLiteralInfoObj); +} + GateRef CircuitBuilder::TaggedGetInt(GateRef x) { x = ChangeTaggedPointerToInt64(x); diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index d53140e9fe..12cf97e54a 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -346,6 +346,7 @@ public: inline GateRef TaggedIsFalse(GateRef x); inline GateRef TaggedIsNull(GateRef x); inline GateRef TaggedIsBoolean(GateRef x); + inline GateRef IsAOTLiteralInfo(GateRef x); inline GateRef TaggedGetInt(GateRef x); inline GateRef ToTaggedInt(GateRef x); inline GateRef ToTaggedIntPtr(GateRef x); diff --git a/ecmascript/compiler/pass_manager.cpp b/ecmascript/compiler/pass_manager.cpp index ae648431d5..51f1c60164 100644 --- a/ecmascript/compiler/pass_manager.cpp +++ b/ecmascript/compiler/pass_manager.cpp @@ -57,7 +57,7 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat const std::string methodName(MethodLiteral::GetMethodName(jsPandaFile, method->GetMethodId())); if (FilterMethod(jsPandaFile, recordName, method, methodOffset, methodPCInfo)) { ++skippedMethodNum; - tsManager->AddSkippedMethodID(method->GetMethodId().GetOffset()); + tsManager->AddIndexOrSkippedMethodID(CacheType::SKIPPED_METHOD, method->GetMethodId().GetOffset()); LOG_COMPILER(INFO) << " method " << methodName << " has been skipped"; return; } @@ -73,7 +73,7 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat bool hasTyps = jsPandaFile->HasTSTypes(recordName); BytecodeCircuitBuilder builder(jsPandaFile, method, methodPCInfo, tsManager, - &cmpCfg, hasTyps, enableMethodLog && log_->OutputCIR(), fullName); + &cmpCfg, hasTyps, enableMethodLog && log_->OutputCIR(), fullName, recordName); builder.BytecodeToCircuit(); PassData data(builder.GetCircuit(), log_, enableMethodLog, fullName); PassRunner pipeline(&data); diff --git a/ecmascript/compiler/slowpath_lowering.cpp b/ecmascript/compiler/slowpath_lowering.cpp index b94657e5b5..a7f96a9d52 100644 --- a/ecmascript/compiler/slowpath_lowering.cpp +++ b/ecmascript/compiler/slowpath_lowering.cpp @@ -291,14 +291,34 @@ GateRef SlowPathLowering::GetObjectFromConstPool(GateRef glue, GateRef jsFunc, G } builder_.Bind(&cache); { - Label isNumber(&builder_); - builder_.Branch(builder_.TaggedIsNumber(cacheValue), &isNumber, &exit); - builder_.Bind(&isNumber); - { - if (type == ConstPoolType::METHOD) { + if (type == ConstPoolType::METHOD) { + Label isNumber(&builder_); + builder_.Branch(builder_.TaggedIsNumber(cacheValue), &isNumber, &exit); + builder_.Bind(&isNumber); + { result = LowerCallRuntime(glue, RTSTUB_ID(GetMethodFromCache), { constPool, builder_.Int32ToTaggedInt(index) }, true); + builder_.Jump(&exit); } + } else if (type == ConstPoolType::ARRAY_LITERAL) { + Label isAOTLiteralInfo(&builder_); + builder_.Branch(builder_.IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit); + builder_.Bind(&isAOTLiteralInfo); + { + result = LowerCallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), + { constPool, builder_.Int32ToTaggedInt(index), module }, true); + builder_.Jump(&exit); + } + } else if (type == ConstPoolType::OBJECT_LITERAL) { + Label isAOTLiteralInfo(&builder_); + builder_.Branch(builder_.IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit); + builder_.Bind(&isAOTLiteralInfo); + { + result = LowerCallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), + { constPool, builder_.Int32ToTaggedInt(index), module }, true); + builder_.Jump(&exit); + } + } else { builder_.Jump(&exit); } } diff --git a/ecmascript/dfx/hprof/heap_snapshot.cpp b/ecmascript/dfx/hprof/heap_snapshot.cpp index d4c912fae1..95ca9e12b3 100644 --- a/ecmascript/dfx/hprof/heap_snapshot.cpp +++ b/ecmascript/dfx/hprof/heap_snapshot.cpp @@ -213,6 +213,8 @@ CString *HeapSnapshot::GenerateNodeName(TaggedObject *entry) return GetArrayString(TaggedArray::Cast(entry), "ConstantPool["); case JSType::TAGGED_DICTIONARY: return GetArrayString(TaggedArray::Cast(entry), "TaggedDict["); + case JSType::AOT_LITERAL_INFO: + return GetArrayString(TaggedArray::Cast(entry), "AOTLiteralInfo["); case JSType::HCLASS: return GetString("HiddenClass"); case JSType::STRING: diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index 4d4655ac45..55d7ee5d90 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -422,6 +422,8 @@ CString JSHClass::DumpJSType(JSType type) return "CommonJSRequire"; case JSType::METHOD: return "Method"; + case JSType::AOT_LITERAL_INFO: + return "AOTLiteralInfo"; default: { CString ret = "unknown type "; return ret + static_cast(type); diff --git a/ecmascript/global_env_constants.cpp b/ecmascript/global_env_constants.cpp index ba42e934df..f19cf6f1fb 100644 --- a/ecmascript/global_env_constants.cpp +++ b/ecmascript/global_env_constants.cpp @@ -96,6 +96,8 @@ void GlobalEnvConstants::InitRootsClass([[maybe_unused]] JSThread *thread, JSHCl factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::TAGGED_ARRAY)); SetConstant(ConstantIndex::CONSTANT_POOL_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::CONSTANT_POOL)); + SetConstant(ConstantIndex::AOT_LITERAL_INFO_CLASS_INDEX, + factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::AOT_LITERAL_INFO)); InitGlobalConstantSpecial(thread); SetConstant(ConstantIndex::DICTIONARY_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::TAGGED_DICTIONARY)); diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index 705c5e43dc..1f1bd43789 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -112,6 +112,7 @@ class JSThread; V(JSTaggedValue, MethodClass, JS_METHOD_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, ClassPrototypeClass, CLASS_PROTOTYPE_HCLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, ClassConstructorClass, CLASS_CONSTRUCTOR_HCLASS_INDEX, ecma_roots_class) \ + V(JSTaggedValue, AOTLiteralInfoClass, AOT_LITERAL_INFO_CLASS_INDEX, ecma_roots_class) \ // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define GLOBAL_ENV_CONSTANT_SPECIAL(V) \ diff --git a/ecmascript/js_hclass-inl.h b/ecmascript/js_hclass-inl.h index 1f1242ceca..3df68b3c99 100644 --- a/ecmascript/js_hclass-inl.h +++ b/ecmascript/js_hclass-inl.h @@ -178,6 +178,7 @@ inline size_t JSHClass::SizeFromJSHClass(TaggedObject *header) case JSType::TAGGED_DICTIONARY: case JSType::LEXICAL_ENV: case JSType::CONSTANT_POOL: + case JSType::AOT_LITERAL_INFO: size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), reinterpret_cast(header)->GetLength()); break; diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index abca1a655c..d95ea91233 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -235,7 +235,9 @@ class ProtoChangeDetails; TS_CLASS_INSTANCE_TYPE, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \ TS_INTERFACE_TYPE, /* //////////////////////////////////////////////////////////////////////////-PADDING */ \ TS_ITERATOR_INSTANCE_TYPE, /* //////////////////////////////////////////////////////////////////-PADDING */ \ - TYPE_LAST = TS_ITERATOR_INSTANCE_TYPE, /* /////////////////////////////////////////////////////////-PADDING */ \ + \ + AOT_LITERAL_INFO, /* //////////////////////////////////////////////////////////////////////////////-PADDING */ \ + TYPE_LAST = AOT_LITERAL_INFO, /* //////////////////////////////////////////////////////////////////-PADDING */ \ \ JS_FUNCTION_FIRST = JS_FUNCTION, /* ///////////////////////////////////////////////////////////////-PADDING */ \ JS_FUNCTION_LAST = JS_ASYNC_AWAIT_STATUS_FUNCTION, /* //////////////////////////////////////////////-PADDING */\ @@ -470,6 +472,7 @@ public: case JSType::TAGGED_DICTIONARY: case JSType::LEXICAL_ENV: case JSType::CONSTANT_POOL: + case JSType::AOT_LITERAL_INFO: return true; default: return false; @@ -1260,6 +1263,11 @@ public: return GetObjectType() == JSType::TS_ITERATOR_INSTANCE_TYPE; } + inline bool IsAOTLiteralInfo() const + { + return GetObjectType() == JSType::AOT_LITERAL_INFO; + } + inline bool IsModuleRecord() const { JSType jsType = GetObjectType(); diff --git a/ecmascript/js_tagged_value-inl.h b/ecmascript/js_tagged_value-inl.h index de7e05c318..bdda667579 100644 --- a/ecmascript/js_tagged_value-inl.h +++ b/ecmascript/js_tagged_value-inl.h @@ -468,6 +468,11 @@ inline bool JSTaggedValue::IsConstantPool() const return IsHeapObject() && GetTaggedObject()->GetClass()->IsConstantPool(); } +inline bool JSTaggedValue::IsAOTLiteralInfo() const +{ + return IsHeapObject() && GetTaggedObject()->GetClass()->IsAOTLiteralInfo(); +} + inline bool JSTaggedValue::IsLinkedNode() const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsLinkedNode(); diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index 794421d65c..451d14c1d1 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -493,6 +493,7 @@ public: bool IsStringOrSymbol() const; bool IsTaggedArray() const; bool IsConstantPool() const; + bool IsAOTLiteralInfo() const; bool IsLinkedNode() const; bool IsRBTreeNode() const; bool IsNativePointer() const; diff --git a/ecmascript/jspandafile/panda_file_translator.cpp b/ecmascript/jspandafile/panda_file_translator.cpp index 9618d18189..2743494947 100644 --- a/ecmascript/jspandafile/panda_file_translator.cpp +++ b/ecmascript/jspandafile/panda_file_translator.cpp @@ -201,7 +201,7 @@ JSHandle PandaFileTranslator::ParseConstPool(EcmaVM *vm, const JSP auto string = factory->GetRawStringFromStringTable(foundStr.data, foundStr.utf16_length, foundStr.is_ascii, MemSpaceType::OLD_SPACE); constpool->SetObjectToCache(thread, value.GetConstpoolIndex(), JSTaggedValue(string)); - vm->GetTSManager()->AddStringIndex(value.GetConstpoolIndex()); + vm->GetTSManager()->AddIndexOrSkippedMethodID(CacheType::STRING, value.GetConstpoolIndex()); } else if (value.GetConstpoolType() == ConstPoolType::BASE_FUNCTION) { MethodLiteral *methodLiteral = jsPandaFile->FindMethodLiteral(it.first); ASSERT(methodLiteral != nullptr); diff --git a/ecmascript/jspandafile/program_object.h b/ecmascript/jspandafile/program_object.h index ce79cf2b66..80a5b56ed7 100644 --- a/ecmascript/jspandafile/program_object.h +++ b/ecmascript/jspandafile/program_object.h @@ -164,11 +164,14 @@ public: const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); auto val = taggedPool->Get(index); JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); - bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); - uint32_t entryIndex = 0; + // For AOT + bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); + bool hasEntryIndex = false; + uint32_t entryIndex = 0; if (isLoadedAOT && val.IsInt()) { entryIndex = static_cast(val.GetInt()); + hasEntryIndex = true; val = JSTaggedValue::Hole(); } @@ -186,7 +189,7 @@ public: JSHandle newConstpool = vm->FindOrCreateConstPool(jsPandaFile, id); method->SetConstantPool(thread, newConstpool); - if (isLoadedAOT) { + if (isLoadedAOT && hasEntryIndex) { vm->GetAOTFileManager()->SetAOTFuncEntry(jsPandaFile, *method, entryIndex); } @@ -202,11 +205,14 @@ public: { auto val = constpool->Get(index); JSPandaFile *jsPandaFile = constpool->GetJSPandaFile(); - bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); - uint32_t entryIndex = 0; + // For AOT + bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); + bool hasEntryIndex = false; + uint32_t entryIndex = 0; if (isLoadedAOT && val.IsInt()) { entryIndex = static_cast(val.GetInt()); + hasEntryIndex = true; val = JSTaggedValue::Hole(); } @@ -223,7 +229,7 @@ public: JSHandle newConstpool = vm->FindOrCreateConstPool(jsPandaFile, id); method->SetConstantPool(thread, newConstpool); - if (isLoadedAOT) { + if (isLoadedAOT && hasEntryIndex) { vm->GetAOTFileManager()->SetAOTFuncEntry(jsPandaFile, *method, entryIndex); } @@ -238,15 +244,27 @@ public: static JSTaggedValue GetClassLiteralFromCache(JSThread *thread, JSHandle constpool, uint32_t literal, CString entry) { + EcmaHandleScope handleScope(thread); auto val = constpool->Get(literal); - if (val.IsHole()) { - EcmaHandleScope handleScope(thread); + JSPandaFile *jsPandaFile = constpool->GetJSPandaFile(); - JSPandaFile *jsPandaFile = constpool->GetJSPandaFile(); + // For AOT + bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); + JSHandle entryIndexes(thread, JSTaggedValue::Undefined()); + if (isLoadedAOT && val.IsAOTLiteralInfo()) { + entryIndexes = JSHandle(thread, val); + val = JSTaggedValue::Hole(); + } + + if (val.IsHole()) { + EcmaVM *vm = thread->GetEcmaVM(); ASSERT(jsPandaFile->IsNewVersion()); panda_file::File::EntityId literalId = constpool->GetEntityId(literal); JSHandle literalArray = LiteralDataExtractor::GetDatasIgnoreType( thread, jsPandaFile, literalId, JSHandle(constpool), entry); + if (isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined()) { + vm->GetAOTFileManager()->SetAOTFuncEntryForLiteral(jsPandaFile, *literalArray, *entryIndexes); + } val = literalArray.GetTaggedValue(); constpool->Set(thread, literal, val); @@ -260,14 +278,23 @@ public: static JSTaggedValue GetLiteralFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index, CString entry) { static_assert(type == ConstPoolType::OBJECT_LITERAL || type == ConstPoolType::ARRAY_LITERAL); + EcmaHandleScope handleScope(thread); const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); - auto val = taggedPool->Get(index); - if (val.IsHole()) { - EcmaHandleScope handleScope(thread); + JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); + // For AOT + bool isLoadedAOT = jsPandaFile->IsLoadedAOT(); + JSHandle entryIndexes(thread, JSTaggedValue::Undefined()); + if (isLoadedAOT && val.IsAOTLiteralInfo()) { + entryIndexes = JSHandle(thread, val); + val = JSTaggedValue::Hole(); + } + + if (val.IsHole()) { + EcmaVM *vm = thread->GetEcmaVM(); JSHandle constpoolHandle(thread, constpool); - JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile(); + ASSERT(jsPandaFile->IsNewVersion()); panda_file::File::EntityId id = taggedPool->GetEntityId(index); @@ -291,6 +318,9 @@ public: valueHandle.Update(elements->Get(i + 1)); JSObject::DefinePropertyByLiteral(thread, obj, key, valueHandle); } + if (isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined()) { + vm->GetAOTFileManager()->SetAOTFuncEntryForLiteral(jsPandaFile, *properties, *entryIndexes); + } val = obj.GetTaggedValue(); break; } @@ -300,6 +330,9 @@ public: uint32_t length = literal->GetLength(); JSHandle arr(JSArray::ArrayCreate(thread, JSTaggedNumber(length))); arr->SetElements(thread, literal); + if (isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined()) { + vm->GetAOTFileManager()->SetAOTFuncEntryForLiteral(jsPandaFile, *literal, *entryIndexes); + } val = arr.GetTaggedValue(); break; } diff --git a/ecmascript/mem/object_xray.h b/ecmascript/mem/object_xray.h index 3385c6848a..683a84a403 100644 --- a/ecmascript/mem/object_xray.h +++ b/ecmascript/mem/object_xray.h @@ -330,6 +330,7 @@ public: case JSType::TAGGED_DICTIONARY: case JSType::TEMPLATE_MAP: case JSType::LEXICAL_ENV: + case JSType::AOT_LITERAL_INFO: TaggedArray::Cast(object)->VisitRangeSlot(visitor); break; case JSType::CONSTANT_POOL: diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index dda046dd48..35e5add4aa 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -122,6 +122,7 @@ #include "ecmascript/ts_types/ts_obj_layout_info.h" #include "ecmascript/ts_types/ts_type.h" #include "ecmascript/ts_types/ts_type_table.h" +#include "ecmascript/aot_file_manager.h" namespace panda::ecmascript { using Error = builtins::BuiltinsError; @@ -3812,4 +3813,16 @@ JSHandle ObjectFactory::NewAsyncGeneratorRequest() obj->SetCapability(thread_, JSTaggedValue::Undefined()); return obj; } + +JSHandle ObjectFactory::NewAOTLiteralInfo(uint32_t length, JSTaggedValue initVal) +{ + NewObjectHook(); + size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); + auto header = heap_->AllocateYoungOrHugeObject( + JSHClass::Cast(thread_->GlobalConstants()->GetAOTLiteralInfoClass().GetTaggedObject()), size); + + JSHandle aotLiteralInfo(thread_, header); + aotLiteralInfo->InitializeWithSpecialValue(initVal, length); + return aotLiteralInfo; +} } // namespace panda::ecmascript diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index 9edd625621..059c101257 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -164,6 +164,7 @@ class ProtoChangeDetails; class ProfileTypeInfo; class MachineCode; class ClassInfoExtractor; +class AOTLiteralInfo; enum class CompletionRecordType : uint8_t; enum class PrimitiveType : uint8_t; @@ -559,6 +560,9 @@ public: // ---------------------------------New objects used internally-------------------------------------- JSHandle NewJSStableArrayWithElements(const JSHandle &elements); + // ---------------------------------AOT snapshot----------------------------------------------------- + JSHandle NewAOTLiteralInfo(uint32_t length, JSTaggedValue initVal = JSTaggedValue::Hole()); + private: friend class GlobalEnv; friend class GlobalEnvConstants; diff --git a/ecmascript/tests/dump_test.cpp b/ecmascript/tests/dump_test.cpp index 1b6caa6e28..c3ef4f9791 100644 --- a/ecmascript/tests/dump_test.cpp +++ b/ecmascript/tests/dump_test.cpp @@ -787,7 +787,8 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump) break; } case JSType::TAGGED_ARRAY: - case JSType::LEXICAL_ENV: { + case JSType::LEXICAL_ENV: + case JSType::AOT_LITERAL_INFO: { JSHandle taggedArray = factory->NewTaggedArray(4); DUMP_FOR_HANDLE(taggedArray) break; diff --git a/ecmascript/ts_types/ts_manager.cpp b/ecmascript/ts_types/ts_manager.cpp index 5303192603..e28ebb2e3d 100644 --- a/ecmascript/ts_types/ts_manager.cpp +++ b/ecmascript/ts_types/ts_manager.cpp @@ -22,6 +22,7 @@ #include "ecmascript/ts_types/ts_type_table.h" #include "libpandafile/file-inl.h" #include "libpandafile/method_data_accessor-inl.h" +#include "ecmascript/aot_file_manager.h" namespace panda::ecmascript { void TSManager::DecodeTSTypes(const JSPandaFile *jsPandaFile) @@ -381,11 +382,7 @@ void TSManager::Iterate(const RootVisitor &v) { v(Root::ROOT_VM, ObjectSlot(reinterpret_cast(&globalModuleTable_))); v(Root::ROOT_VM, ObjectSlot(reinterpret_cast(&constantPoolInfos_))); - - uint64_t hclassCacheSize = hclassCache_.size(); - for (uint64_t i = 0; i < hclassCacheSize; i++) { - v(Root::ROOT_VM, ObjectSlot(reinterpret_cast(&(hclassCache_.data()[i])))); - } + currentABCInfo_.Iterate(v); } GlobalTSTypeRef TSManager::GetImportTypeTargetGT(GlobalTSTypeRef gt) const @@ -622,76 +619,149 @@ std::string TSManager::GetPrimitiveStr(const GlobalTSTypeRef >) const void TSManager::CreateConstantPoolInfos(size_t size) { - ObjectFactory *factory = vm_->GetFactory(); constantPoolInfosSize_ = 0; - constantPoolInfos_ = factory->NewTaggedArray(size * CONSTANTPOOL_INFOS_ITEM_SIZE).GetTaggedValue(); + constantPoolInfos_ = factory_->NewTaggedArray(size * CONSTANTPOOL_INFOS_ITEM_SIZE).GetTaggedValue(); } void TSManager::CollectConstantPoolInfo(const JSPandaFile* jsPandaFile) { - JSThread *thread = vm_->GetJSThread(); JSHandle constantPoolInfos = GetConstantPoolInfos(); ASSERT(constantPoolInfosSize_ < constantPoolInfos->GetLength()); std::string keyStr = std::to_string(jsPandaFile->GetFileUniqId()); JSHandle key = vm_->GetFactory()->NewFromStdString(keyStr); - constantPoolInfos->Set(thread, constantPoolInfosSize_++, key); + constantPoolInfos->Set(thread_, constantPoolInfosSize_++, key); auto value = GenerateConstantPoolInfo(jsPandaFile); - constantPoolInfos->Set(thread, constantPoolInfosSize_++, value); + constantPoolInfos->Set(thread_, constantPoolInfosSize_++, value); } JSTaggedValue TSManager::GenerateConstantPoolInfo(const JSPandaFile* jsPandaFile) { - ObjectFactory *factory = vm_->GetFactory(); - JSThread *thread = vm_->GetJSThread(); - JSHandle constantPool(thread, vm_->FindConstpool(jsPandaFile, 0)); - + JSHandle constantPool(thread_, vm_->FindConstpool(jsPandaFile, 0)); uint32_t constantPoolSize = constantPool->GetCacheLength(); - uint32_t hclassCacheSize = hclassCache_.size(); - JSHandle constantPoolInfo = factory->NewConstantPool(constantPoolSize + hclassCacheSize); + uint32_t hclassCacheSize = currentABCInfo_.GetHClassCacheSize(); + JSHandle constantPoolInfo = factory_->NewConstantPool(constantPoolSize + hclassCacheSize); LOG_COMPILER(INFO) << "snapshot: constantPoolSize: " << constantPoolSize; LOG_COMPILER(INFO) << "snapshot: hclassCacheSize: " << hclassCacheSize; - recordMethodInfos_.emplace_back(std::vector>{}); + snapshotRecordInfo_.InitNewRecordInfo(); + auto &recordMethodInfo = snapshotRecordInfo_.GetRecordMethodInfos().back(); + auto &recordLiteralInfo = snapshotRecordInfo_.GetRecordLiteralInfos().back(); - IterateConstantPoolCache(CacheType::STRING, [thread, constantPool, constantPoolInfo] (uint32_t index) { - auto string = ConstantPool::GetStringFromCache(thread, constantPool.GetTaggedValue(), index); - constantPoolInfo->SetObjectToCache(thread, index, string); + IterateConstantPoolCache(CacheType::STRING, [this, constantPool, constantPoolInfo] (uint32_t index) { + auto string = ConstantPool::GetStringFromCache(thread_, constantPool.GetTaggedValue(), index); + constantPoolInfo->SetObjectToCache(thread_, index, string); }); - IterateConstantPoolCache(CacheType::METHOD, [this, constantPool, jsPandaFile] (uint32_t index) { + IterateConstantPoolCache(CacheType::METHOD, [this, constantPool, jsPandaFile, &recordMethodInfo] (uint32_t index) { panda_file::File::IndexHeader *indexHeader = constantPool->GetIndexHeader(); auto pf = jsPandaFile->GetPandaFile(); Span indexs = pf->GetMethodIndex(indexHeader); panda_file::File::EntityId methodID = indexs[index]; - if (skippedMethodIDCache_.find(methodID.GetOffset()) == skippedMethodIDCache_.end()) { - recordMethodInfos_.back().emplace_back(std::make_pair(methodID.GetOffset(), index)); + if (!currentABCInfo_.IsSkippedMethod(methodID.GetOffset())) { + auto &methodInfos = recordMethodInfo.methodInfos_; + methodInfos.emplace_back(std::make_pair(index, methodID.GetOffset())); } }); - IterateHClassCaches([thread, constantPoolSize, constantPoolInfo] (JSTaggedType hclass, uint32_t index) { - constantPoolInfo->SetObjectToCache(thread, constantPoolSize + index, JSTaggedValue(hclass)); + IterateLiteralCaches(CacheType::CLASS_LITERAL, [this, constantPool, &recordLiteralInfo] + (std::pair item) { + const CString &recordName = item.first; + uint32_t index = item.second; + auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, constantPool, index, recordName); + JSHandle literalHandle(thread_, literalObj); + CollectLiteralInfo(literalHandle, index, recordLiteralInfo); + }); + + IterateLiteralCaches(CacheType::OBJECT_LITERAL, [this, jsPandaFile, constantPool, &recordLiteralInfo] + (std::pair item) { + const CString &recordName = item.first; + uint32_t index = item.second; + panda_file::File::EntityId id = constantPool->GetEntityId(index); + JSMutableHandle elements(thread_, JSTaggedValue::Undefined()); + JSMutableHandle properties(thread_, JSTaggedValue::Undefined()); + LiteralDataExtractor::ExtractObjectDatas( + thread_, jsPandaFile, id, elements, properties, JSHandle(constantPool), recordName); + CollectLiteralInfo(properties, index, recordLiteralInfo); + }); + + IterateLiteralCaches(CacheType::ARRAY_LITERAL, [this, jsPandaFile, constantPool, &recordLiteralInfo] + (std::pair item) { + const CString &recordName = item.first; + uint32_t index = item.second; + panda_file::File::EntityId id = constantPool->GetEntityId(index); + JSHandle literal = LiteralDataExtractor::GetDatasIgnoreType( + thread_, jsPandaFile, id, JSHandle(constantPool), recordName); + CollectLiteralInfo(literal, index, recordLiteralInfo); + }); + + IterateHClassCaches([this, constantPoolSize, constantPoolInfo] (JSTaggedType hclass, uint32_t index) { + constantPoolInfo->SetObjectToCache(thread_, constantPoolSize + index, JSTaggedValue(hclass)); }); return constantPoolInfo.GetTaggedValue(); } +void TSManager::CollectLiteralInfo(JSHandle array, uint32_t constantPoolIndex, + SnapshotRecordInfo::RecordLiteralInfo &recordLiteralInfo) +{ + JSMutableHandle valueHandle(thread_, JSTaggedValue::Undefined()); + uint32_t len = array->GetLength(); + SnapshotRecordInfo::RecordLiteralInfo::LiteralMethods methodIDs; + for (uint32_t i = 0; i < len; i++) { + valueHandle.Update(array->Get(i)); + if (valueHandle->IsJSFunction()) { + auto methodID = JSHandle(valueHandle)->GetCallTarget()->GetMethodId().GetOffset(); + if (currentABCInfo_.IsSkippedMethod(methodID)) { + methodIDs.emplace_back(std::make_pair(true, methodID)); + } else { + methodIDs.emplace_back(std::make_pair(false, methodID)); + } + } + } + recordLiteralInfo.literalInfos_.emplace_back(std::make_pair(constantPoolIndex, methodIDs)); +} + void TSManager::ResolveConstantPoolInfo(const std::map, uint32_t> &methodToEntryIndexMap) { + ObjectFactory *factory = vm_->GetFactory(); JSHandle constantPoolInfosHandle(thread_, constantPoolInfos_); JSMutableHandle currentCPInfo(thread_, JSTaggedValue::Undefined()); - uint32_t size = recordMethodInfos_.size(); + uint32_t size = snapshotRecordInfo_.GetSize(); + const auto &recordMethodInfos = snapshotRecordInfo_.GetRecordMethodInfos(); + const auto &recordLiteralInfos = snapshotRecordInfo_.GetRecordLiteralInfos(); + for (uint32_t i = 0; i < size; ++i) { JSTaggedValue constantPoolInfo = constantPoolInfosHandle->Get(i * CONSTANTPOOL_INFOS_ITEM_SIZE + 1); currentCPInfo.Update(constantPoolInfo); - const std::vector> &methodInfo = recordMethodInfos_[i]; - for (auto item: methodInfo) { + const SnapshotRecordInfo::RecordMethodInfo &recordMethodInfo = recordMethodInfos[i]; + for (auto item: recordMethodInfo.methodInfos_) { uint32_t moduleIndex = i; - uint32_t methodID = item.first; - uint32_t constantPoolIndex = item.second; + uint32_t constantPoolIndex = item.first; + uint32_t methodID = item.second; LOG_COMPILER(INFO) << "snapshot: resolve function method ID: " << methodID; uint32_t entryIndex = methodToEntryIndexMap.at(std::make_pair(moduleIndex, methodID)); currentCPInfo->SetObjectToCache(thread_, constantPoolIndex, JSTaggedValue(entryIndex)); } + const SnapshotRecordInfo::RecordLiteralInfo &recordLiteralInfo = recordLiteralInfos[i]; + for (auto item: recordLiteralInfo.literalInfos_) { + uint32_t moduleIndex = i; + uint32_t constantPoolIndex = item.first; + const SnapshotRecordInfo::RecordLiteralInfo::LiteralMethods &methodIDs = item.second; + uint32_t len = methodIDs.size(); + JSHandle aotLiteralInfo = factory->NewAOTLiteralInfo(len); + for (uint32_t pos = 0; pos < len; ++pos) { + bool isSkipped = methodIDs[pos].first; + uint32_t methodID = methodIDs[pos].second; + if (isSkipped) { + aotLiteralInfo->Set(thread_, pos, JSTaggedValue(-1)); + } else { + LOG_COMPILER(INFO) << "snapshot: resolve function method ID: " << methodID; + uint32_t entryIndex = methodToEntryIndexMap.at(std::make_pair(moduleIndex, methodID)); + aotLiteralInfo->Set(thread_, pos, JSTaggedValue(entryIndex)); + } + } + currentCPInfo->SetObjectToCache(thread_, constantPoolIndex, aotLiteralInfo.GetTaggedValue()); + } } } @@ -969,4 +1039,127 @@ JSHandle TSModuleTable::GenerateBuiltinsTypeTable(JSThread *thread) TSTypeTable::GenerateTypeTable(thread, jsPandaFile, builtinsRecordName, BUILTINS_TABLE_ID, vec); return builtinsTypeTable; } + +void ABCInfo::Iterate(const RootVisitor &v) +{ + uint64_t hclassCacheSize = hclassCache_.size(); + for (uint64_t i = 0; i < hclassCacheSize; i++) { + v(Root::ROOT_VM, ObjectSlot(reinterpret_cast(&(hclassCache_.data()[i])))); + } +} + +void ABCInfo::AddStringIndex(uint32_t index) +{ + if (stringIndexCache_.find(index) != stringIndexCache_.end()) { + return; + } + stringIndexCache_.insert(index); +} + +void ABCInfo::AddMethodIndex(uint32_t index) +{ + if (methodIndexCache_.find(index) != methodIndexCache_.end()) { + return; + } + methodIndexCache_.insert(index); +} + +void ABCInfo::AddSkippedMethodID(uint32_t methodID) +{ + if (skippedMethodIDCache_.find(methodID) != skippedMethodIDCache_.end()) { + return; + } + skippedMethodIDCache_.insert(methodID); +} + +void ABCInfo::AddClassLiteralIndex(const CString &recordName, uint32_t index) +{ + auto item = std::make_pair(recordName, index); + if (classLiteralCache_.find(item) != classLiteralCache_.end()) { + return; + } + classLiteralCache_.insert(item); +} + +void ABCInfo::AddObjectLiteralIndex(const CString &recordName, uint32_t index) +{ + auto item = std::make_pair(recordName, index); + if (objectLiteralCache_.find(item) != objectLiteralCache_.end()) { + return; + } + objectLiteralCache_.insert(item); +} + +void ABCInfo::AddArrayLiteralIndex(const CString &recordName, uint32_t index) +{ + auto item = std::make_pair(recordName, index); + if (arrayLiteralCache_.find(item) != arrayLiteralCache_.end()) { + return; + } + arrayLiteralCache_.insert(item); +} + +void ABCInfo::AddIndexOrSkippedMethodID(CacheType type, uint32_t index, const CString &recordName) +{ + switch (type) { + case CacheType::STRING: { + AddStringIndex(index); + break; + } + case CacheType::METHOD: { + AddMethodIndex(index); + break; + } + case CacheType::SKIPPED_METHOD: { + AddSkippedMethodID(index); + break; + } + case CacheType::CLASS_LITERAL: { + AddClassLiteralIndex(recordName, index); + break; + } + case CacheType::OBJECT_LITERAL: { + AddObjectLiteralIndex(recordName, index); + break; + } + case CacheType::ARRAY_LITERAL: { + AddArrayLiteralIndex(recordName, index); + break; + } + default: + UNREACHABLE(); + } +} + +const std::set& ABCInfo::GetStringOrMethodCache(CacheType type) const +{ + switch (type) { + case CacheType::STRING: { + return stringIndexCache_; + } + case CacheType::METHOD: { + return methodIndexCache_; + } + default: + UNREACHABLE(); + } +} + +const std::set>& ABCInfo::GetLiteralCache(CacheType type) const +{ + switch (type) { + case CacheType::CLASS_LITERAL: { + return classLiteralCache_; + } + case CacheType::OBJECT_LITERAL: { + return objectLiteralCache_; + } + case CacheType::ARRAY_LITERAL: { + return arrayLiteralCache_; + } + default: + UNREACHABLE(); + } +} + } // namespace panda::ecmascript diff --git a/ecmascript/ts_types/ts_manager.h b/ecmascript/ts_types/ts_manager.h index bb7976a20f..86b3f11e59 100644 --- a/ecmascript/ts_types/ts_manager.h +++ b/ecmascript/ts_types/ts_manager.h @@ -32,6 +32,120 @@ enum class MTableIdx : uint8_t { enum class CacheType : uint8_t { STRING = 0, METHOD, + SKIPPED_METHOD, + CLASS_LITERAL, + OBJECT_LITERAL, + ARRAY_LITERAL, +}; + +class ABCInfo { +public: + void PUBLIC_API AddIndexOrSkippedMethodID(CacheType type, uint32_t index, const CString &recordName); + + const std::set& GetStringOrMethodCache(CacheType type) const; + + const std::set>& GetLiteralCache(CacheType type) const; + + void Iterate(const RootVisitor &v); + + CVector& GetHClassCache() + { + return hclassCache_; + } + + void AddHClass(JSTaggedType hclass) + { + hclassCache_.emplace_back(hclass); + } + + bool IsSkippedMethod(uint32_t methodID) + { + if (skippedMethodIDCache_.find(methodID) == skippedMethodIDCache_.end()) { + return false; + } + return true; + } + + uint32_t GetHClassCacheSize() + { + return hclassCache_.size(); + } + + void ClearCaches() + { + stringIndexCache_.clear(); + methodIndexCache_.clear(); + skippedMethodIDCache_.clear(); + classLiteralCache_.clear(); + objectLiteralCache_.clear(); + arrayLiteralCache_.clear(); + hclassCache_.clear(); + } + +private: + void AddStringIndex(uint32_t index); + + void AddMethodIndex(uint32_t index); + + void AddSkippedMethodID(uint32_t methodID); + + void AddClassLiteralIndex(const CString &recordName, uint32_t index); + + void AddObjectLiteralIndex(const CString &recordName, uint32_t index); + + void AddArrayLiteralIndex(const CString &recordName, uint32_t index); + + // constantpool index + std::set stringIndexCache_ {}; + std::set methodIndexCache_ {}; + std::set skippedMethodIDCache_ {}; + + // (recordName, constantpool index) + std::set> classLiteralCache_ {}; + std::set> objectLiteralCache_ {}; + std::set> arrayLiteralCache_ {}; + + // store hclass of each abc which produced from static type info + CVector hclassCache_ {}; +}; + +class SnapshotRecordInfo { +public: + struct RecordLiteralInfo { + using LiteralMethods = std::vector>; + using LiteralInfo = std::pair; + std::vector literalInfos_; + }; + + struct RecordMethodInfo { + std::vector> methodInfos_; + }; + + void InitNewRecordInfo() + { + recordMethodInfos_.emplace_back(RecordMethodInfo{}); + recordLiteralInfos_.emplace_back(RecordLiteralInfo{}); + ++size_; + } + + uint32_t GetSize() + { + return size_; + } + + std::vector& GetRecordMethodInfos() + { + return recordMethodInfos_; + } + std::vector& GetRecordLiteralInfos() + { + return recordLiteralInfos_; + } + +private: + uint32_t size_ = 0; + std::vector recordMethodInfos_ {}; + std::vector recordLiteralInfos_ {}; }; class TSModuleTable : public TaggedArray { @@ -186,7 +300,7 @@ public: GlobalTSTypeRef PUBLIC_API GetOrCreateUnionType(CVector unionTypeVec); uint32_t PUBLIC_API GetFunctionTypeLength(GlobalTSTypeRef gt) const; - + GlobalTSTypeRef PUBLIC_API GetOrCreateTSIteratorInstanceType(TSRuntimeType runtimeType, GlobalTSTypeRef elementGt); GlobalTSTypeRef PUBLIC_API GetIteratorInstanceElementGt(GlobalTSTypeRef gt) const; @@ -274,36 +388,14 @@ public: JSHandle PUBLIC_API RestoreConstantPool(const JSPandaFile* pf); + void PUBLIC_API AddIndexOrSkippedMethodID(CacheType type, uint32_t index, const CString &recordName="") + { + currentABCInfo_.AddIndexOrSkippedMethodID(type, index, recordName); + } + void ClearCaches() { - stringIndexCache_.clear(); - methodIndexCache_.clear(); - skippedMethodIDCache_.clear(); - hclassCache_.clear(); - } - - void AddStringIndex(uint32_t index) - { - if (stringIndexCache_.find(index) != stringIndexCache_.end()) { - return; - } - stringIndexCache_.insert(index); - } - - void AddMethodIndex(uint32_t index) - { - if (methodIndexCache_.find(index) != methodIndexCache_.end()) { - return; - } - methodIndexCache_.insert(index); - } - - void AddSkippedMethodID(uint32_t methodID) - { - if (skippedMethodIDCache_.find(methodID) != skippedMethodIDCache_.end()) { - return; - } - skippedMethodIDCache_.insert(methodID); + currentABCInfo_.ClearCaches(); } EcmaVM *GetEcmaVM() const @@ -412,10 +504,14 @@ private: JSTaggedValue GenerateConstantPoolInfo(const JSPandaFile* jsPandaFile); + void CollectLiteralInfo(JSHandle array, uint32_t constantPoolIndex, + SnapshotRecordInfo::RecordLiteralInfo &recordLiteralInfo); + int BinarySearch(uint32_t target, uint32_t itemSize, bool findLeftBound = true); void AddHClassInCompilePhase(GlobalTSTypeRef gt, JSTaggedValue hclass, uint32_t constantPoolLen) { + CVector &hclassCache_ = currentABCInfo_.GetHClassCache(); hclassCache_.emplace_back(hclass.GetRawData()); classTypeIhcIndexMap_[gt] = constantPoolLen + hclassCache_.size() - 1; } @@ -423,29 +519,27 @@ private: template void IterateConstantPoolCache(CacheType type, const Callback &cb) { - switch (type) { - case CacheType::STRING: { - for (auto item: stringIndexCache_) { - cb(item); - } - break; - } - case CacheType::METHOD: { - for (auto item: methodIndexCache_) { - cb(item); - } - break; - } - default: - UNREACHABLE(); + const std::set &cache = currentABCInfo_.GetStringOrMethodCache(type); + for (auto item: cache) { + cb(item); + } + } + + template + void IterateLiteralCaches(CacheType type, const Callback &cb) + { + const std::set> &cache = currentABCInfo_.GetLiteralCache(type); + for (auto item: cache) { + cb(item); } } template void IterateHClassCaches(const Callback &cb) { - for (uint32_t i = 0; i < hclassCache_.size(); ++i) { - cb(hclassCache_[i], i); + const auto &hclassCache = currentABCInfo_.GetHClassCache(); + for (uint32_t i = 0; i < hclassCache.size(); ++i) { + cb(hclassCache[i], i); } } @@ -453,21 +547,17 @@ private: JSThread *thread_ {nullptr}; ObjectFactory *factory_ {nullptr}; JSTaggedValue globalModuleTable_ {JSTaggedValue::Hole()}; - JSTaggedValue constantPoolInfos_ {JSTaggedValue::Hole()}; - std::vector>> recordMethodInfos_ {}; - size_t constantPoolInfosSize_ {0}; // record the mapping relationship between classType and instance hclass index in the constant pool std::map classTypeIhcIndexMap_ {}; bool assertTypes_ {false}; bool printAnyTypes_ {false}; friend class EcmaVM; - // records the index in constantpool of the data that aot needs to serialize - std::set stringIndexCache_ {}; - std::set methodIndexCache_ {}; - std::set skippedMethodIDCache_ {}; - // store hclass of each abc which produced from static type info - CVector hclassCache_ {}; + // For snapshot + size_t constantPoolInfosSize_ {0}; + JSTaggedValue constantPoolInfos_ {JSTaggedValue::Hole()}; + ABCInfo currentABCInfo_ {}; + SnapshotRecordInfo snapshotRecordInfo_ {}; std::map, GlobalTSTypeRef> literalOffsetGTMap_ {}; };