AOT support multi constantpool

Signed-off-by: weng-xi <wengxi1@huawei.com>
Change-Id: Icb3db9b97825b94ae5e506286c59549d237fbdf1
This commit is contained in:
weng-xi 2022-12-08 15:42:13 +08:00
parent 3fdadf7bf6
commit bf8e23a221
35 changed files with 64734 additions and 273 deletions

View File

@ -351,7 +351,9 @@ bool AnFileDataManager::UnsafeLoadDataFromBinaryBuffer(const CString &filename)
void AnFileInfo::Iterate(const RootVisitor &v)
{
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&snapshotConstantPool_)));
for (auto iter : deserializedCPs_) {
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&deserializedCPs_.at(iter.first))));
}
}
void AnFileInfo::Save(const std::string &filename)
@ -410,6 +412,27 @@ void AnFileInfo::RewriteRelcateTextSection([[maybe_unused]] const char* symbol,
#endif
}
JSHandle<JSTaggedValue> AnFileInfo::GetDeserializedConstantPool(int32_t cpID) const
{
auto iter = deserializedCPs_.find(cpID);
if (iter == deserializedCPs_.end()) {
LOG_COMPILER(ERROR) << "can not find deserialized constantpool in anFileInfo, constantPoolID is " << cpID;
UNREACHABLE();
}
return JSHandle<JSTaggedValue>(uintptr_t(&iter->second));
}
void PUBLIC_API AnFileInfo::SetDeserializedConstantPool(JSThread *thread, JSTaggedValue snapshotCPList)
{
JSHandle<TaggedArray> cpList(thread, snapshotCPList);
uint32_t len = cpList->GetLength();
for (uint32_t pos = 0; pos < len; pos += DESERIALIZED_CP_LIST_ITEM_SIZE) {
int32_t constantPoolID = cpList->Get(pos).GetInt();
JSTaggedValue cp = cpList->Get(pos + 1);
deserializedCPs_.insert({constantPoolID, cp});
}
}
bool AnFileInfo::Load(const std::string &filename)
{
AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
@ -701,15 +724,15 @@ bool AOTFileManager::RewriteDataSection(uintptr_t dataSec, size_t size,
return true;
}
void AOTFileManager::AddSnapshotConstantPool(JSTaggedValue snapshotConstantPool)
void AOTFileManager::AddDeserializedConstantPool(JSTaggedValue deserializedCPList)
{
// There is no system library currently, so the length of anFileInfos_ should be 1
ASSERT(anFileInfos_.size() == 1);
AnFileInfo &anFileInfo = anFileInfos_.back();
anFileInfo.SetSnapshotConstantPool(snapshotConstantPool);
anFileInfo.SetDeserializedConstantPool(vm_->GetJSThread(), deserializedCPList);
}
JSHandle<JSTaggedValue> AOTFileManager::GetSnapshotConstantPool(const JSPandaFile *jsPandaFile)
JSHandle<JSTaggedValue> AOTFileManager::GetDeserializedConstantPool(const JSPandaFile *jsPandaFile, int32_t cpID)
{
// In some appilication, only the main vm will load '.an' file currently
// return the constantpool with HOLE value when other worker try to obtain the
@ -719,7 +742,7 @@ JSHandle<JSTaggedValue> AOTFileManager::GetSnapshotConstantPool(const JSPandaFil
}
uint32_t anFileInfoIndex = jsPandaFile->GetAOTFileInfoIndex();
const AnFileInfo &anFileInfo = anFileInfos_[anFileInfoIndex];
return anFileInfo.GetSnapshotConstantPool();
return anFileInfo.GetDeserializedConstantPool(cpID);
}
AOTFileManager::~AOTFileManager()

View File

@ -369,20 +369,16 @@ public:
void RewriteRelcateDeoptHandler(EcmaVM *vm);
JSHandle<JSTaggedValue> PUBLIC_API GetSnapshotConstantPool() const
{
return JSHandle<JSTaggedValue>(uintptr_t(&snapshotConstantPool_));
}
JSHandle<JSTaggedValue> GetDeserializedConstantPool(int32_t cpID) const;
void PUBLIC_API SetSnapshotConstantPool(JSTaggedValue snapshotConstantPool)
{
snapshotConstantPool_ = snapshotConstantPool;
}
void SetDeserializedConstantPool(JSThread *thread, JSTaggedValue snapshotCPList);
private:
static constexpr uint8_t DESERIALIZED_CP_LIST_ITEM_SIZE = 2;
void RewriteRelcateTextSection(const char* symbol, uintptr_t patchAddr);
std::unordered_map<uint32_t, uint64_t> mainEntryMap_ {};
JSTaggedValue snapshotConstantPool_ {JSTaggedValue::Hole()};
CMap<int32_t, JSTaggedValue> deserializedCPs_ {};
std::shared_ptr<const AnFileDataManager::AnFileData> data_ {nullptr};
bool isLoad_ {false};
};
@ -496,8 +492,8 @@ public:
static JSTaggedValue GetAbsolutePath(JSThread *thread, JSTaggedValue relativePathVal);
static bool GetAbsolutePath(const CString &relativePathCstr, CString &absPathCstr);
bool RewriteDataSection(uintptr_t dataSec, size_t size, uintptr_t newData, size_t newSize);
void AddSnapshotConstantPool(JSTaggedValue snapshotConstantPool);
JSHandle<JSTaggedValue> GetSnapshotConstantPool(const JSPandaFile *jsPandaFile);
void AddDeserializedConstantPool(JSTaggedValue deserializedCPList);
JSHandle<JSTaggedValue> GetDeserializedConstantPool(const JSPandaFile *jsPandaFile, int32_t cpID);
private:
const StubFileInfo& GetStubFileInfo() const

View File

@ -51,6 +51,9 @@ void BytecodeInfoCollector::ProcessClasses()
auto methodId = mda.GetMethodId();
ASSERT(codeId.has_value());
// Generate all constpool
vm_->FindOrCreateConstPool(jsPandaFile_, methodId);
MethodLiteral *methodLiteral = methods + (methodIdx++);
panda_file::CodeDataAccessor codeDataAccessor(*pf, codeId.value());
uint32_t codeSize = codeDataAccessor.GetCodeSize();
@ -339,7 +342,7 @@ void BytecodeInfoCollector::CollectConstantPoolIndexInfoFromBC(const BytecodeIns
case BytecodeInstruction::Opcode::STGLOBALVAR_IMM16_ID16:
case BytecodeInstruction::Opcode::LDBIGINT_ID16: {
auto index = bcIns.GetId().AsRawValue();
AddConstantPoolIndexToBCInfo(ConstantPoolIndexType::STRING, index);
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::STRING, index, methodOffset);
break;
}
case BytecodeInstruction::Opcode::DEFINEFUNC_IMM8_ID16_IMM8:
@ -347,33 +350,33 @@ void BytecodeInfoCollector::CollectConstantPoolIndexInfoFromBC(const BytecodeIns
case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM8_ID16_IMM8:
case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM16_ID16_IMM8: {
auto index = bcIns.GetId().AsRawValue();
AddConstantPoolIndexToBCInfo(ConstantPoolIndexType::METHOD, index);
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, index, methodOffset);
break;
}
case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
auto index = bcIns.GetId().AsRawValue();
AddConstantPoolIndexToBCInfo(ConstantPoolIndexType::OBJECT_LITERAL, index, methodOffset);
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::OBJECT_LITERAL, index, methodOffset);
break;
}
case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM16_ID16: {
auto index = bcIns.GetId().AsRawValue();
AddConstantPoolIndexToBCInfo(ConstantPoolIndexType::ARRAY_LITERAL, index, methodOffset);
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::ARRAY_LITERAL, index, methodOffset);
break;
}
case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: {
auto methodIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
AddConstantPoolIndexToBCInfo(ConstantPoolIndexType::METHOD, methodIndex);
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, methodIndex, methodOffset);
auto literalIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
AddConstantPoolIndexToBCInfo(ConstantPoolIndexType::CLASS_LITERAL, literalIndex, methodOffset);
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::CLASS_LITERAL, literalIndex, methodOffset);
break;
}
case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
auto methodIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
AddConstantPoolIndexToBCInfo(ConstantPoolIndexType::METHOD, methodIndex);
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, methodIndex, methodOffset);
auto literalIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
AddConstantPoolIndexToBCInfo(ConstantPoolIndexType::CLASS_LITERAL, literalIndex, methodOffset);
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::CLASS_LITERAL, literalIndex, methodOffset);
break;
}
default:
@ -422,32 +425,12 @@ uint32_t LexEnvManager::GetTargetLexEnv(uint32_t methodId, uint32_t level) const
return offset;
}
void ConstantPoolIndexInfo::AddConstantPoolIndex(ConstantPoolIndexType type, uint32_t index, uint32_t methodOffset)
void ConstantPoolInfo::AddIndexToCPItem(ItemType type, uint32_t index, uint32_t methodOffset)
{
switch (type) {
case ConstantPoolIndexType::STRING: {
stringIndex_.insert(index);
break;
}
case ConstantPoolIndexType::METHOD: {
methodIndex_.insert(index);
break;
}
case ConstantPoolIndexType::CLASS_LITERAL: {
classLiteralIndex_.insert(std::make_pair(index, methodOffset));
break;
}
case ConstantPoolIndexType::OBJECT_LITERAL: {
objectLiteralIndex_.insert(std::make_pair(index, methodOffset));
break;
}
case ConstantPoolIndexType::ARRAY_LITERAL: {
arrayLiteralIndex_.insert(std::make_pair(index, methodOffset));
break;
}
default:
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
Item &item = GetCPItem(type);
if (item.find(index) != item.end()) {
return;
}
item.insert({index, ItemData {index, methodOffset, nullptr}});
}
} // namespace panda::ecmascript::kungfu

View File

@ -192,59 +192,41 @@ private:
LexicalEnvStatus status_ { LexicalEnvStatus::VIRTUAL_LEXENV };
};
enum class ConstantPoolIndexType : uint8_t {
STRING,
METHOD,
CLASS_LITERAL,
OBJECT_LITERAL,
ARRAY_LITERAL,
};
class ConstantPoolIndexInfo {
class ConstantPoolInfo {
public:
const std::set<uint32_t>& GetStringOrMethodIndexSet(ConstantPoolIndexType type)
enum ItemType {
STRING = 0,
METHOD,
CLASS_LITERAL,
OBJECT_LITERAL,
ARRAY_LITERAL,
ITEM_TYPE_NUM,
ITEM_TYPE_FIRST = STRING,
ITEM_TYPE_LAST = ARRAY_LITERAL,
};
struct ItemData {
uint32_t index {0};
uint32_t outerMethodOffset {0};
CString *recordName {nullptr};
};
// key:constantpool index, value:ItemData
using Item = std::unordered_map<uint32_t, ItemData>;
ConstantPoolInfo() : items_(ItemType::ITEM_TYPE_NUM, Item{}) {}
Item& GetCPItem(ItemType type)
{
switch (type) {
case ConstantPoolIndexType::STRING: {
return stringIndex_;
}
case ConstantPoolIndexType::METHOD: {
return methodIndex_;
}
default:
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
ASSERT(ItemType::ITEM_TYPE_FIRST <= type && type <= ItemType::ITEM_TYPE_LAST);
return items_[type];
}
const std::set<std::pair<uint32_t, uint32_t>>& GetLiteralIndexSet(ConstantPoolIndexType type)
{
switch (type) {
case ConstantPoolIndexType::CLASS_LITERAL: {
return classLiteralIndex_;
}
case ConstantPoolIndexType::OBJECT_LITERAL: {
return objectLiteralIndex_;
}
case ConstantPoolIndexType::ARRAY_LITERAL: {
return arrayLiteralIndex_;
}
default:
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
}
void AddConstantPoolIndex(ConstantPoolIndexType type, uint32_t index, uint32_t methodOffset = 0);
void AddIndexToCPItem(ItemType type, uint32_t index, uint32_t methodOffset);
private:
std::set<uint32_t> stringIndex_ {};
std::set<uint32_t> methodIndex_ {};
// literal need to record methodOffset (constantpool index, methodOffset)
std::set<std::pair<uint32_t, uint32_t>> classLiteralIndex_ {};
std::set<std::pair<uint32_t, uint32_t>> objectLiteralIndex_ {};
std::set<std::pair<uint32_t, uint32_t>> arrayLiteralIndex_ {};
std::vector<Item> items_;
};
class BCInfo {
@ -287,26 +269,19 @@ public:
return skippedMethods_.size();
}
void AddConstantPoolIndex(ConstantPoolIndexType type, uint32_t index, uint32_t methodOffset = 0)
void AddIndexToCPInfo(ConstantPoolInfo::ItemType type, uint32_t index, uint32_t methodOffset)
{
cpIndexInfo_.AddConstantPoolIndex(type, index, methodOffset);
cpInfo_.AddIndexToCPItem(type, index, methodOffset);
}
template <class Callback>
void IterateStringOrMethodIndex(ConstantPoolIndexType type, const Callback &cb)
void IterateConstantPoolInfo(ConstantPoolInfo::ItemType type, const Callback &cb)
{
const auto &indexSet = cpIndexInfo_.GetStringOrMethodIndexSet(type);
for (uint32_t index : indexSet) {
cb(index);
}
}
template <class Callback>
void IterateLiteralIndex(ConstantPoolIndexType type, const Callback &cb)
{
const auto &indexSet = cpIndexInfo_.GetLiteralIndexSet(type);
for (const auto &item : indexSet) {
cb(item.first, methodOffsetToRecordName_[item.second]);
auto &item = cpInfo_.GetCPItem(type);
for (auto &iter : item) {
ConstantPoolInfo::ItemData &data = iter.second;
data.recordName = &methodOffsetToRecordName_[data.outerMethodOffset];
cb(data);
}
}
@ -355,7 +330,7 @@ private:
std::unordered_map<uint32_t, MethodInfo> methodList_ {};
std::unordered_map<uint32_t, CString> methodOffsetToRecordName_ {};
std::set<uint32_t> skippedMethods_ {};
ConstantPoolIndexInfo cpIndexInfo_;
ConstantPoolInfo cpInfo_;
PGOProfilerLoader &pfLoader_;
size_t maxMethodSize_;
};
@ -393,9 +368,9 @@ private:
class BytecodeInfoCollector {
public:
explicit BytecodeInfoCollector(JSPandaFile *jsPandaFile, PGOProfilerLoader &profilerLoader,
explicit BytecodeInfoCollector(EcmaVM *vm, JSPandaFile *jsPandaFile, PGOProfilerLoader &profilerLoader,
size_t maxAotMethodSize)
: jsPandaFile_(jsPandaFile), bytecodeInfo_(profilerLoader, maxAotMethodSize)
: vm_(vm), jsPandaFile_(jsPandaFile), bytecodeInfo_(profilerLoader, maxAotMethodSize)
{
ProcessClasses();
}
@ -403,7 +378,7 @@ public:
NO_COPY_SEMANTIC(BytecodeInfoCollector);
NO_MOVE_SEMANTIC(BytecodeInfoCollector);
BCInfo &GetBytecodeInfo()
BCInfo& GetBytecodeInfo()
{
return bytecodeInfo_;
}
@ -413,16 +388,15 @@ public:
return bytecodeInfo_.IsSkippedMethod(methodOffset);
}
template <class Callback>
void IterateStringOrMethodIndex(ConstantPoolIndexType type, const Callback &cb)
const JSPandaFile* GetJSPandaFile()
{
bytecodeInfo_.IterateStringOrMethodIndex(type, cb);
return jsPandaFile_;
}
template <class Callback>
void IterateLiteralIndex(ConstantPoolIndexType type, const Callback &cb)
void IterateConstantPoolInfo(ConstantPoolInfo::ItemType type, const Callback &cb)
{
bytecodeInfo_.IterateLiteralIndex(type, cb);
bytecodeInfo_.IterateConstantPoolInfo(type, cb);
}
private:
@ -431,9 +405,10 @@ private:
return methodInfoIndex_++;
}
void AddConstantPoolIndexToBCInfo(ConstantPoolIndexType type, uint32_t index, uint32_t methodOffset = 0)
void AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType type,
uint32_t index, uint32_t methodOffset)
{
bytecodeInfo_.AddConstantPoolIndex(type, index, methodOffset);
bytecodeInfo_.AddIndexToCPInfo(type, index, methodOffset);
}
const CString GetEntryFunName(const std::string_view &entryPoint) const;
@ -448,6 +423,7 @@ private:
void CollectMethodInfoFromBC(const BytecodeInstruction &bcIns, const MethodLiteral *method);
void CollectConstantPoolIndexInfoFromBC(const BytecodeInstruction &bcIns, const MethodLiteral *method);
EcmaVM *vm_;
JSPandaFile *jsPandaFile_ {nullptr};
BCInfo bytecodeInfo_;
size_t methodInfoIndex_ {0};

View File

@ -35,8 +35,8 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
}
profilerLoader_.LoadProfiler(profilerIn, hotnessThreshold_);
BytecodeInfoCollector bcInfoCollector(jsPandaFile, profilerLoader_, maxAotMethodSize_);
ResolveModuleAndConstPool(jsPandaFile, fileName);
BytecodeInfoCollector bcInfoCollector(vm_, jsPandaFile, profilerLoader_, maxAotMethodSize_);
ResolveModule(jsPandaFile, fileName);
auto aotModule = new LLVMModule(fileName, triple_);
auto aotModuleAssembler = new LLVMAssembler(aotModule->GetModule(),
LOptions(optLevel_, true, relocMode_));
@ -58,6 +58,8 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
auto jsPandaFile = info.GetJSPandaFile();
auto cmpCfg = info.GetCompilerConfig();
auto tsManager = info.GetTSManager();
// note: TSManager need to set current constantpool before all pass
tsManager->SetCurConstantPool(jsPandaFile, methodOffset);
if (log_->CertainMethod()) {
enableMethodLog = logList_->IncludesMethod(fileName, methodName);
@ -126,11 +128,8 @@ JSPandaFile *PassManager::CreateAndVerifyJSPandaFile(const CString &fileName)
return jsPandaFile;
}
void PassManager::ResolveModuleAndConstPool(const JSPandaFile *jsPandaFile, const std::string &fileName)
void PassManager::ResolveModule(const JSPandaFile *jsPandaFile, const std::string &fileName)
{
JSThread *thread = vm_->GetJSThread();
JSHandle<Program> program;
const auto &recordInfo = jsPandaFile->GetJSRecordInfo();
ModuleManager *moduleManager = vm_->GetModuleManager();
for (auto info: recordInfo) {
@ -138,13 +137,6 @@ void PassManager::ResolveModuleAndConstPool(const JSPandaFile *jsPandaFile, cons
if (jsPandaFile->IsModule(recordName)) {
moduleManager->HostResolveImportedModuleWithMerge(fileName.c_str(), recordName);
}
program = PandaFileTranslator::GenerateProgram(vm_, jsPandaFile, recordName);
}
JSHandle<JSFunction> mainFunc(thread, program->GetMainFunction());
JSHandle<Method> method(thread, mainFunc->GetMethod());
JSHandle<JSTaggedValue> constPool(thread, method->GetConstantPool());
TSManager *tsManager = vm_->GetTSManager();
tsManager->InitSnapshotConstantPool(constPool.GetTaggedValue());
}
} // namespace panda::ecmascript::kungfu

View File

@ -114,7 +114,7 @@ public:
private:
JSPandaFile *CreateAndVerifyJSPandaFile(const CString &fileName);
void ResolveModuleAndConstPool(const JSPandaFile *jsPandaFile, const std::string &fileName);
void ResolveModule(const JSPandaFile *jsPandaFile, const std::string &fileName);
bool EnableTypeLowering() const
{

View File

@ -2963,9 +2963,9 @@ void SlowPathLowering::LowerDefineClassWithBuffer(GateRef gate, GateRef glue, Ga
result = LowerCallRuntime(glue, RTSTUB_ID(CreateClassWithBuffer), args, true);
builder_.Branch(builder_.IsSpecial(*result, JSTaggedValue::VALUE_EXCEPTION), &isException, &isNotException);
} else {
GlobalTSTypeRef gt = type.GetGTRef();
const std::map<GlobalTSTypeRef, uint32_t> &classTypeIhcIndexMap = tsManager_->GetClassTypeIhcIndexMap();
GateRef ihcIndex = builder_.Int32((classTypeIhcIndexMap.at(gt)));
int index = tsManager_->GetHClassIndexByClassGateType(type);
ASSERT(index != -1);
GateRef ihcIndex = builder_.Int32(index);
GateRef ihclass = builder_.GetObjectFromConstPool(glue, jsFunc, ihcIndex, ConstPoolType::CLASS_LITERAL);
auto args = { proto, lexicalEnv, constpool,

View File

@ -761,14 +761,14 @@ void TSTypeLowering::LowerTypedLdObjByName(GateRef gate)
DISALLOW_GARBAGE_COLLECTION;
uint16_t propIndex = ConstDataId(acc_.GetBitField(acc_.GetValueIn(gate, 1))).GetId();
auto thread = tsManager_->GetEcmaVM()->GetJSThread();
JSHandle<ConstantPool> constantPool(tsManager_->GetSnapshotConstantPool());
JSHandle<ConstantPool> constantPool(tsManager_->GetConstantPool());
auto prop = ConstantPool::GetStringFromCache(thread, constantPool.GetTaggedValue(), propIndex);
// 3: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 3);
GateRef receiver = acc_.GetValueIn(gate, 2); // 2: acc or this object
GateType receiverType = acc_.GetGateType(receiver);
int hclassIndex = tsManager_->GetHClassIndex(receiverType);
int hclassIndex = tsManager_->GetHClassIndexByInstanceGateType(receiverType);
if (hclassIndex == -1) { // slowpath
acc_.DeleteGuardAndFrameState(gate);
return;
@ -804,7 +804,7 @@ void TSTypeLowering::LowerTypedStObjByName(GateRef gate, bool isThis)
DISALLOW_GARBAGE_COLLECTION;
uint16_t propIndex = ConstDataId(acc_.GetBitField(acc_.GetValueIn(gate, 1))).GetId();
auto thread = tsManager_->GetEcmaVM()->GetJSThread();
JSHandle<ConstantPool> constantPool(tsManager_->GetSnapshotConstantPool());
JSHandle<ConstantPool> constantPool(tsManager_->GetConstantPool());
auto prop = ConstantPool::GetStringFromCache(thread, constantPool.GetTaggedValue(), propIndex);
GateRef receiver = Circuit::NullGate();
@ -821,7 +821,7 @@ void TSTypeLowering::LowerTypedStObjByName(GateRef gate, bool isThis)
value = acc_.GetValueIn(gate, 3); // 3: acc
}
GateType receiverType = acc_.GetGateType(receiver);
int hclassIndex = tsManager_->GetHClassIndex(receiverType);
int hclassIndex = tsManager_->GetHClassIndexByInstanceGateType(receiverType);
if (hclassIndex == -1) { // slowpath
acc_.DeleteGuardAndFrameState(gate);
return;
@ -967,7 +967,7 @@ void TSTypeLowering::LowerTypedNewObjRange(GateRef gate, GateRef glue)
return;
}
int hclassIndex = tsManager_->GetHClassIndexByClassGT(ctorType);
int hclassIndex = tsManager_->GetHClassIndexByClassGateType(ctorType);
// guard maybe not a GUARD
GateRef guard = acc_.GetDep(gate);

View File

@ -655,7 +655,7 @@ bool TypeInfer::InferLdStr(GateRef gate)
bool TypeInfer::GetObjPropWithName(GateRef gate, GateType objType, uint64_t index)
{
auto thread = tsManager_->GetEcmaVM()->GetJSThread();
JSHandle<ConstantPool> constantPool(tsManager_->GetSnapshotConstantPool());
JSHandle<ConstantPool> constantPool(tsManager_->GetConstantPool());
JSTaggedValue name = ConstantPool::GetStringFromCache(thread, constantPool.GetTaggedValue(), index);
auto type = GetPropType(objType, name);
if (tsManager_->IsGetterSetterFunc(type)) {
@ -796,7 +796,7 @@ bool TypeInfer::GetSuperProp(GateRef gate, uint64_t index, bool isString)
GlobalTSTypeRef type = GlobalTSTypeRef::Default();
bool isStatic = tsManager_->IsStaticFunc(funcType.GetGTRef());
auto propType = isStatic ? PropertyType::STATIC : PropertyType::NORMAL;
JSHandle<ConstantPool> constantPool(tsManager_->GetSnapshotConstantPool());
JSHandle<ConstantPool> constantPool(tsManager_->GetConstantPool());
type = isString ? tsManager_->GetSuperPropType(classType.GetGTRef(),
ConstantPool::GetStringFromCache(thread, constantPool.GetTaggedValue(), index), propType) :
tsManager_->GetSuperPropType(classType.GetGTRef(), index, propType);
@ -1026,10 +1026,10 @@ void TypeInfer::TypeCheck(GateRef gate) const
}
auto funcName = gateAccessor_.GetValueIn(func, 1);
auto thread = tsManager_->GetEcmaVM()->GetJSThread();
JSHandle<ConstantPool> constantPool(tsManager_->GetSnapshotConstantPool());
JSHandle<ConstantPool> constantPool(tsManager_->GetConstantPool());
uint16_t funcNameStrId = ConstDataId(gateAccessor_.GetBitField(funcName)).GetId();
ConstantPool::GetStringFromCache(thread, constantPool.GetTaggedValue(), funcNameStrId);
auto funcNameString = constantPool->GetStdStringByIdx(gateAccessor_.GetBitField(funcName));
auto funcNameString = constantPool->GetStdStringByIdx(funcNameStrId);
if (funcNameString == "AssertType") {
GateRef expectedGate = gateAccessor_.GetValueIn(gate, 1);
uint16_t strId = ConstDataId(gateAccessor_.GetBitField(expectedGate)).GetId();

View File

@ -405,7 +405,8 @@ public:
std::optional<std::reference_wrapper<CMap<int32_t, JSTaggedValue>>> FindConstpools(
const JSPandaFile *jsPandaFile);
JSHandle<ConstantPool> FindOrCreateConstPool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id);
JSHandle<ConstantPool> PUBLIC_API FindOrCreateConstPool(const JSPandaFile *jsPandaFile,
panda_file::File::EntityId id);
void StoreBCOffsetInfo(const std::string& methodName, int32_t bcOffset)
{

View File

@ -24,8 +24,9 @@ std::string ConstantPool::GetStdStringByIdx(size_t index) const
return EcmaStringAccessor(str).ToStdString(StringConvertedUsage::LOGICOPERATION);
}
JSHandle<ConstantPool> ConstantPool::RestoreConstantPool(EcmaVM *vm, const JSPandaFile *jsPandaFile)
JSHandle<ConstantPool> ConstantPool::GetDeserializedConstantPool(EcmaVM *vm, const JSPandaFile *jsPandaFile,
int32_t cpID)
{
return JSHandle<ConstantPool>(vm->GetAOTFileManager()->GetSnapshotConstantPool(jsPandaFile));
return JSHandle<ConstantPool>(vm->GetAOTFileManager()->GetDeserializedConstantPool(jsPandaFile, cpID));
}
}

View File

@ -78,7 +78,9 @@ public:
bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
if (isLoadedAOT) {
#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
constpool = RestoreConstantPool(vm, jsPandaFile);
panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), id);
int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
constpool = GetDeserializedConstantPool(vm, jsPandaFile, index);
#else
LOG_FULL(FATAL) << "Aot don't support Windows and MacOS platform";
UNREACHABLE();
@ -398,7 +400,7 @@ private:
return JSTaggedValue::TaggedTypeSize() * GetLength() + DATA_OFFSET;
}
static JSHandle<ConstantPool> RestoreConstantPool(EcmaVM *vm, const JSPandaFile *jsPandaFile);
static JSHandle<ConstantPool> GetDeserializedConstantPool(EcmaVM *vm, const JSPandaFile *jsPandaFile, int32_t cpID);
};
} // namespace ecmascript
} // namespace panda

View File

@ -38,8 +38,8 @@ namespace panda::ecmascript {
void Snapshot::Serialize(const CString &fileName)
{
TSManager *tsManager = vm_->GetTSManager();
JSHandle<ConstantPool> root(tsManager->GetSnapshotConstantPool());
Serialize(root.GetTaggedValue().GetTaggedObject(), nullptr, fileName);
JSTaggedValue root = tsManager->GetSnapshotCPList();
Serialize(root.GetTaggedObject(), nullptr, fileName);
}
void Snapshot::Serialize(TaggedObject *objectHeader, const panda_file::File *pf, const CString &fileName)

View File

@ -1394,8 +1394,8 @@ void SnapshotProcessor::HandleRootObject(SnapshotType type, uintptr_t rootObject
}
case SnapshotType::AI: {
JSTaggedValue item = JSTaggedValue(rootObjectAddr);
if (!isRootObjRelocate_ && item.IsConstantPool()) {
vm_->GetAOTFileManager()->AddSnapshotConstantPool(item);
if (!isRootObjRelocate_ && item.IsTaggedArray()) {
vm_->GetAOTFileManager()->AddDeserializedConstantPool(item);
isRootObjRelocate_ = true;
}
break;

View File

@ -132,25 +132,64 @@ bool TSManager::IsDuplicatedKey(JSHandle<TSObjLayoutInfo> extendLayout, JSTagged
return false;
}
int TSManager::GetHClassIndex(const kungfu::GateType &gateType)
int TSManager::GetHClassIndexByInstanceGateType(const kungfu::GateType &gateType)
{
// make sure already setting correct curCP_ and curCPID_ before calling this method
if (!IsClassInstanceTypeKind(gateType)) {
return -1;
}
GlobalTSTypeRef instanceGT = gateType.GetGTRef();
GlobalTSTypeRef classGT = GetClassType(instanceGT);
auto it = classTypeIhcIndexMap_.find(classGT);
if (it == classTypeIhcIndexMap_.end()) {
return GetHClassIndex(classGT);
}
int TSManager::GetHClassIndexByClassGateType(const kungfu::GateType &gateType)
{
// make sure already setting correct curCP_ and curCPID_ before calling this method
if (!IsClassTypeKind(gateType)) {
return -1;
}
GlobalTSTypeRef classGT = gateType.GetGTRef();
return GetHClassIndex(classGT);
}
int TSManager::GetHClassIndex(GlobalTSTypeRef classGT)
{
// make sure already setting correct curCP_ and curCPID_ before calling this method
auto iter = gtIhcMap_.find(classGT);
if (iter == gtIhcMap_.end()) {
return -1;
} else {
return it->second;
std::unordered_map<int32_t, uint32_t> &cpIndexMap = iter->second.GetCPIndexMap();
auto indexIter = cpIndexMap.find(curCPID_);
if (indexIter == cpIndexMap.end()) {
// This ihc is used in the current constantpool, but has not yet been recorded
return RecordIhcToVecAndIndexMap(iter->second);
}
return indexIter->second;
}
}
uint32_t TSManager::RecordIhcToVecAndIndexMap(IHClassData &ihcData)
{
// make sure already setting correct curCP_ and curCPID_ before calling this method
JSHandle<ConstantPool> constantPool(GetConstantPool());
CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(curCPID_);
hcVec.emplace_back(ihcData.GetIHC());
uint32_t index = constantPool->GetCacheLength() + hcVec.size() - 1;
std::unordered_map<int32_t, uint32_t> &cpIndexMap = ihcData.GetCPIndexMap();
cpIndexMap[curCPID_] = index;
return index;
}
JSTaggedValue TSManager::GetHClassFromCache(uint32_t index)
{
JSHandle<ConstantPool> constantPool(GetSnapshotConstantPool());
return JSTaggedValue(hclassCache_[index - constantPool->GetCacheLength()]);
// make sure already setting correct curCP_ and curCPID_ before calling this method
JSHandle<ConstantPool> constantPool(GetConstantPool());
const CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(curCPID_);
return JSTaggedValue(hcVec[index - constantPool->GetCacheLength()]);
}
int TSManager::GetPropertyOffset(JSTaggedValue hclass, JSTaggedValue key)
@ -428,10 +467,10 @@ GlobalTSTypeRef TSManager::GetOrCreateUnionType(CVector<GlobalTSTypeRef> unionTy
void TSManager::Iterate(const RootVisitor &v)
{
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&globalModuleTable_)));
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&snapshotConstantPool_)));
uint64_t hclassCacheSize = hclassCache_.size();
for (uint64_t i = 0; i < hclassCacheSize; i++) {
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&(hclassCache_.data()[i]))));
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&curCP_)));
snapshotData_.Iterate(v);
for (auto iter : gtIhcMap_) {
iter.second.Iterate(v);
}
}
@ -594,9 +633,8 @@ GlobalTSTypeRef TSManager::GetArrayParameterTypeGT(GlobalTSTypeRef gt) const
return arrayType->GetElementGT();
}
void TSManager::GenerateStaticHClass(const JSPandaFile *jsPandaFile, JSHandle<TSClassType> classType)
void TSManager::GenerateStaticHClass(JSHandle<TSClassType> classType)
{
JSHandle<ConstantPool> constPool(thread_, vm_->FindConstpool(jsPandaFile, 0));
JSHandle<TSObjectType> instanceType(thread_, classType->GetInstanceType());
JSHClass *ihc = TSObjectType::GetOrCreateHClass(thread_, instanceType, TSObjectTypeKind::INSTANCE);
JSHandle<TSObjectType> prototypeType(thread_, classType->GetPrototypeType());
@ -606,7 +644,7 @@ void TSManager::GenerateStaticHClass(const JSPandaFile *jsPandaFile, JSHandle<TS
ihc->SetProto(thread_, prototype);
GlobalTSTypeRef gt = classType->GetGT();
AddHClassInCompilePhase(gt, JSTaggedValue(ihc), constPool->GetCacheLength());
gtIhcMap_.insert({gt, IHClassData(JSTaggedValue(ihc).GetRawData())});
}
JSHandle<JSTaggedValue> TSManager::GetTSType(const GlobalTSTypeRef &gt) const
@ -731,69 +769,170 @@ std::string TSManager::GetPrimitiveStr(const GlobalTSTypeRef &gt) const
}
}
void TSManager::SetCurConstantPool(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
{
curCPID_ = GetOldConstantPoolIDByMethodOffset(jsPandaFile, methodOffset);
curCP_ = vm_->FindConstpool(jsPandaFile, curCPID_);
}
int32_t TSManager::GetOldConstantPoolIDByMethodOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
{
panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(),
panda_file::File::EntityId(methodOffset));
return static_cast<int32_t>(indexAccessor.GetHeaderIndex());
}
JSHandle<ConstantPool> TSManager::GetSnapshotConstantPool(uint32_t cpListIndex)
{
JSHandle<TaggedArray> snapshotCPList = JSHandle<TaggedArray>(thread_, snapshotData_.GetSnapshotCPList());
return JSHandle<ConstantPool>(thread_, snapshotCPList->Get(cpListIndex));
}
void TSManager::ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector *bcInfoCollector)
{
JSHandle<ConstantPool> cp(thread_, snapshotConstantPool_);
uint32_t constantPoolSize = cp->GetCacheLength();
uint32_t hclassCacheSize = hclassCache_.size();
auto jsPandaFile = cp->GetJSPandaFile();
if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolSize: " << constantPoolSize;
LOG_COMPILER(INFO) << "[aot-snapshot] hclassCacheSize: " << hclassCacheSize;
}
JSHandle<ConstantPool> newConstantPool = factory_->NewConstantPool(constantPoolSize + hclassCacheSize);
const CMap<int32_t, JSTaggedValue> &oldCPValues = vm_->FindConstpools(
bcInfoCollector->GetJSPandaFile()).value();
std::map<int32_t, uint32_t> cpListIndexMap;
bcInfoCollector->IterateStringOrMethodIndex(kungfu::ConstantPoolIndexType::STRING, [this, newConstantPool]
(uint32_t index) {
JSTaggedValue str = ConstantPool::GetStringFromCache(thread_, snapshotConstantPool_, index);
newConstantPool->SetObjectToCache(thread_, index, str);
GenerateSnapshotConstantPoolList(cpListIndexMap, oldCPValues);
FillSnapshotConstantPoolList(cpListIndexMap, bcInfoCollector);
AddHClassToSnapshotConstantPoolList(cpListIndexMap, bcInfoCollector);
}
void TSManager::GenerateSnapshotConstantPoolList(std::map<int32_t, uint32_t> &cpListIndexMap,
const CMap<int32_t, JSTaggedValue> &oldCPValues)
{
// 2: each item need store (constantPoolID, constantpool)
JSHandle<TaggedArray> snapshotCPList = factory_->NewTaggedArray(oldCPValues.size() *
SnapshotData::SNAPSHOT_CP_LIST_ITEM_SIZE);
snapshotData_.SetSnapshotCPList(snapshotCPList.GetTaggedValue());
JSMutableHandle<ConstantPool> oldCP(thread_->GlobalConstants()->GetHandledUndefined());
uint32_t pos = 0;
for (auto &iter : oldCPValues) {
int32_t oldCPID = iter.first;
oldCP.Update(iter.second);
uint32_t cpSize = oldCP->GetCacheLength();
const CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(oldCPID);
uint32_t hcVecSize = hcVec.size();
if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolID: " << oldCPID;
LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolSize: " << cpSize;
LOG_COMPILER(INFO) << "[aot-snapshot] hclassSize: " << hcVecSize;
}
JSHandle<ConstantPool> newCp = factory_->NewConstantPool(cpSize + hcVecSize);
snapshotCPList->Set(thread_, pos++, JSTaggedValue(oldCPID));
cpListIndexMap[oldCPID] = pos;
snapshotCPList->Set(thread_, pos++, newCp.GetTaggedValue());
}
}
void TSManager::FillSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
kungfu::BytecodeInfoCollector *bcInfoCollector)
{
const JSPandaFile *jsPandaFile = bcInfoCollector->GetJSPandaFile();
bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::STRING,
[this, jsPandaFile, &cpListIndexMap] (const kungfu::ConstantPoolInfo::ItemData &data) {
int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
JSTaggedValue oldCP = vm_->FindConstpool(jsPandaFile, oldCPID);
JSTaggedValue str = ConstantPool::GetStringFromCache(thread_, oldCP, data.index);
uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
newCP->SetObjectToCache(thread_, data.index, str);
});
bcInfoCollector->IterateStringOrMethodIndex(kungfu::ConstantPoolIndexType::METHOD,
[this, newConstantPool, cp, bcInfoCollector, jsPandaFile] (uint32_t index) {
panda_file::File::IndexHeader *indexHeader = cp->GetIndexHeader();
auto pf = jsPandaFile->GetPandaFile();
Span<const panda_file::File::EntityId> indexs = pf->GetMethodIndex(indexHeader);
uint32_t methodOffset = indexs[index].GetOffset();
bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::METHOD,
[this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
panda_file::File::IndexHeader *indexHeader = oldCP->GetIndexHeader();
Span<const panda_file::File::EntityId> indexs = jsPandaFile->GetPandaFile()->GetMethodIndex(indexHeader);
uint32_t methodOffset = indexs[data.index].GetOffset();
uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
if (!bcInfoCollector->IsSkippedMethod(methodOffset)) {
recordMethodIndex_.emplace_back(index);
newConstantPool->SetObjectToCache(thread_, index, JSTaggedValue(methodOffset));
snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::METHOD,
std::make_pair(cpListIndex, data.index));
newCP->SetObjectToCache(thread_, data.index, JSTaggedValue(methodOffset));
}
});
bcInfoCollector->IterateLiteralIndex(kungfu::ConstantPoolIndexType::CLASS_LITERAL,
[this, newConstantPool, cp, bcInfoCollector] (uint32_t index, const CString &recordName) {
auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, cp, index, recordName);
bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::CLASS_LITERAL,
[this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, oldCP, data.index, *data.recordName);
JSHandle<TaggedArray> literalHandle(thread_, literalObj);
CollectLiteralInfo(literalHandle, index, newConstantPool, bcInfoCollector);
recordLiteralIndex_.emplace_back(index);
uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
CollectLiteralInfo(literalHandle, data.index, newCP, bcInfoCollector);
snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
std::make_pair(cpListIndex, data.index));
});
bcInfoCollector->IterateLiteralIndex(kungfu::ConstantPoolIndexType::OBJECT_LITERAL,
[this, newConstantPool, cp, bcInfoCollector, jsPandaFile] (uint32_t index, const CString &recordName) {
panda_file::File::EntityId id = cp->GetEntityId(index);
bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::OBJECT_LITERAL,
[this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
panda_file::File::EntityId id = oldCP->GetEntityId(data.index);
JSMutableHandle<TaggedArray> elements(thread_, JSTaggedValue::Undefined());
JSMutableHandle<TaggedArray> properties(thread_, JSTaggedValue::Undefined());
LiteralDataExtractor::ExtractObjectDatas(thread_, jsPandaFile,
id, elements, properties, cp, recordName);
CollectLiteralInfo(properties, index, newConstantPool, bcInfoCollector);
recordLiteralIndex_.emplace_back(index);
LiteralDataExtractor::ExtractObjectDatas(thread_, jsPandaFile, id, elements,
properties, oldCP, *data.recordName);
uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
CollectLiteralInfo(properties, data.index, newCP, bcInfoCollector);
snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
std::make_pair(cpListIndex, data.index));
});
bcInfoCollector->IterateLiteralIndex(kungfu::ConstantPoolIndexType::ARRAY_LITERAL,
[this, newConstantPool, cp, bcInfoCollector, jsPandaFile] (uint32_t index, const CString &recordName) {
panda_file::File::EntityId id = cp->GetEntityId(index);
bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::ARRAY_LITERAL,
[this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
panda_file::File::EntityId id = oldCP->GetEntityId(data.index);
JSHandle<TaggedArray> literal = LiteralDataExtractor::GetDatasIgnoreType(
thread_, jsPandaFile, id, cp, recordName);
CollectLiteralInfo(literal, index, newConstantPool, bcInfoCollector);
recordLiteralIndex_.emplace_back(index);
thread_, jsPandaFile, id, oldCP, *data.recordName);
uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
CollectLiteralInfo(literal, data.index, newCP, bcInfoCollector);
snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
std::make_pair(cpListIndex, data.index));
});
}
for (uint32_t i = 0; i < hclassCacheSize; ++i) {
newConstantPool->SetObjectToCache(thread_, constantPoolSize + i, JSTaggedValue(hclassCache_[i]));
void TSManager::AddHClassToSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
kungfu::BytecodeInfoCollector *bcInfoCollector)
{
const JSPandaFile *jsPandaFile = bcInfoCollector->GetJSPandaFile();
JSMutableHandle<ConstantPool> oldCP(thread_->GlobalConstants()->GetHandledUndefined());
JSMutableHandle<ConstantPool> newCP(thread_->GlobalConstants()->GetHandledUndefined());
for (auto &iter : cpListIndexMap) {
int32_t oldCPID = iter.first;
oldCP.Update(vm_->FindConstpool(jsPandaFile, oldCPID));
uint32_t constantPoolSize = oldCP->GetCacheLength();
uint32_t cpListIndex = iter.second;
newCP.Update(GetSnapshotConstantPool(cpListIndex));
const CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(oldCPID);
uint32_t hcVecSize = hcVec.size();
for (uint32_t i = 0; i < hcVecSize; ++i) {
newCP->SetObjectToCache(thread_, constantPoolSize + i, JSTaggedValue(hcVec[i]));
}
}
snapshotConstantPool_ = newConstantPool.GetTaggedValue();
}
void TSManager::CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constantPoolIndex,
@ -827,20 +966,28 @@ void TSManager::CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constan
void TSManager::ResolveSnapshotConstantPool(const std::map<uint32_t, uint32_t> &methodToEntryIndexMap)
{
JSHandle<ConstantPool> snapshotConstantPool(GetSnapshotConstantPool());
auto &recordMethodInfo = snapshotData_.GetRecordInfo(SnapshotData::RecordType::METHOD);
for (auto &item: recordMethodInfo) {
uint32_t cpListIndex = item.first;
uint32_t methodIndex = item.second;
JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
for (auto item: recordMethodIndex_) {
JSTaggedValue val = snapshotConstantPool->GetObjectFromCache(item);
JSTaggedValue val = newCP->GetObjectFromCache(methodIndex);
uint32_t methodOffset = static_cast<uint32_t>(val.GetInt());
if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: " << methodOffset << ") ";
}
uint32_t entryIndex = methodToEntryIndexMap.at(methodOffset);
snapshotConstantPool->SetObjectToCache(thread_, item, JSTaggedValue(entryIndex));
newCP->SetObjectToCache(thread_, methodIndex, JSTaggedValue(entryIndex));
}
for (auto item: recordLiteralIndex_) {
JSTaggedValue val = snapshotConstantPool->GetObjectFromCache(item);
auto &recordLiteralInfo = snapshotData_.GetRecordInfo(SnapshotData::RecordType::LITERAL);
for (auto &item: recordLiteralInfo) {
uint32_t cpListIndex = item.first;
uint32_t literalIndex = item.second;
JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
JSTaggedValue val = newCP->GetObjectFromCache(literalIndex);
AOTLiteralInfo *aotLiteralInfo = AOTLiteralInfo::Cast(val.GetTaggedObject());
uint32_t aotLiteralInfoLen = aotLiteralInfo->GetLength();
for (uint32_t i = 0; i < aotLiteralInfoLen; ++i) {

View File

@ -362,30 +362,17 @@ public:
return CString(fileName);
}
const std::map<GlobalTSTypeRef, uint32_t> &GetClassTypeIhcIndexMap() const
{
return classTypeIhcIndexMap_;
}
void GenerateStaticHClass(const JSPandaFile *jsPandaFile, JSHandle<TSClassType> classType);
void GenerateStaticHClass(JSHandle<TSClassType> classType);
JSHandle<JSTaggedValue> GetTSType(const GlobalTSTypeRef &gt) const;
std::string PUBLIC_API GetTypeStr(kungfu::GateType gateType) const;
int GetHClassIndexByClassGT(const kungfu::GateType &gateType) const
{
if (!IsClassTypeKind(gateType)) {
return -1;
}
GlobalTSTypeRef classGT = gateType.GetGTRef();
auto it = classTypeIhcIndexMap_.find(classGT);
if (it == classTypeIhcIndexMap_.end()) {
return -1;
} else {
return it->second;
}
}
int PUBLIC_API GetHClassIndexByInstanceGateType(const kungfu::GateType &gateType);
int PUBLIC_API GetHClassIndexByClassGateType(const kungfu::GateType &gateType);
JSTaggedValue PUBLIC_API GetHClassFromCache(uint32_t index);
inline bool IsUserDefinedClassTypeKind(const kungfu::GateType &gateType) const
{
@ -501,27 +488,16 @@ public:
(l == static_cast<uint32_t>(TSRuntimeType::ITERATOR_RESULT));
}
int PUBLIC_API GetHClassIndex(const kungfu::GateType &gateType);
JSTaggedValue PUBLIC_API GetHClassFromCache(uint32_t index);
// not consider [[prototype]] properties and accessor, -1: not find
int PUBLIC_API GetPropertyOffset(JSTaggedValue hclass, JSTaggedValue key);
void PUBLIC_API InitSnapshotConstantPool(JSTaggedValue constantPool)
void PUBLIC_API SetCurConstantPool(const JSPandaFile *jsPandaFile, uint32_t methodOffset);
JSHandle<JSTaggedValue> PUBLIC_API GetConstantPool() const
{
snapshotConstantPool_ = constantPool;
return JSHandle<JSTaggedValue>(uintptr_t(&curCP_));
}
JSHandle<JSTaggedValue> PUBLIC_API GetSnapshotConstantPool() const
{
return JSHandle<JSTaggedValue>(uintptr_t(&snapshotConstantPool_));
}
void PUBLIC_API ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector *bcInfoCollector);
void PUBLIC_API ResolveSnapshotConstantPool(const std::map<uint32_t, uint32_t> &methodToEntryIndexMap);
bool PUBLIC_API IsBuiltin(kungfu::GateType funcType) const;
bool PUBLIC_API IsBuiltinMath(kungfu::GateType funcType) const;
@ -538,6 +514,99 @@ public:
return builtinsRecordName_;
}
class IHClassData {
public:
IHClassData(JSTaggedType ihc) : ihc_(ihc) {}
void Iterate(const RootVisitor &v)
{
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&ihc_)));
}
std::unordered_map<int32_t, uint32_t>& GetCPIndexMap()
{
return cpIndexMap_;
}
JSTaggedType GetIHC() const
{
return ihc_;
}
private:
JSTaggedType ihc_ {0};
std::unordered_map<int32_t, uint32_t> cpIndexMap_ {};
};
// for snapshot
class SnapshotData {
public:
enum RecordType {
METHOD = 0,
LITERAL,
RECORD_TYPE_NUM,
RECORD_TYPE_FIRST = METHOD,
RECORD_TYPE_LAST = LITERAL,
};
static constexpr uint8_t SNAPSHOT_CP_LIST_ITEM_SIZE = 2;
using RecordData = std::vector<std::pair<uint32_t, uint32_t>>;
SnapshotData() : recordInfo_(RecordType::RECORD_TYPE_NUM, RecordData{}) {}
void Iterate(const RootVisitor &v)
{
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&snapshotCPList_)));
}
void SetSnapshotCPList(JSTaggedValue snapshotCPList)
{
snapshotCPList_ = snapshotCPList;
}
JSTaggedValue GetSnapshotCPList() const
{
return snapshotCPList_;
}
CVector<JSTaggedType>& GetSnapshotHCVector(int32_t cpID)
{
return snapshotHCs_[cpID];
}
void AddIndexInfoToRecordInfo(RecordType type, std::pair<uint32_t, uint32_t> indexInfo)
{
ASSERT(RECORD_TYPE_FIRST <= type && type <= RECORD_TYPE_LAST);
recordInfo_[type].emplace_back(indexInfo);
}
const RecordData& GetRecordInfo(RecordType type)
{
ASSERT(RECORD_TYPE_FIRST <= type && type <= RECORD_TYPE_LAST);
return recordInfo_[type];
}
private:
JSTaggedValue snapshotCPList_ {JSTaggedValue::Hole()};
// key: constantpoolnum, value: store hclass which produced from static type info
CMap<int32_t, CVector<JSTaggedType>> snapshotHCs_ {};
// used to record the data that needs to be modified into the aot code entry index
std::vector<RecordData> recordInfo_ {};
};
JSTaggedValue PUBLIC_API GetSnapshotCPList() const
{
return snapshotData_.GetSnapshotCPList();
}
void PUBLIC_API ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector *bcInfoCollector);
void PUBLIC_API ResolveSnapshotConstantPool(const std::map<uint32_t, uint32_t> &methodToEntryIndexMap);
private:
NO_COPY_SEMANTIC(TSManager);
NO_MOVE_SEMANTIC(TSManager);
@ -558,11 +627,9 @@ private:
std::string GetPrimitiveStr(const GlobalTSTypeRef &gt) const;
void AddHClassInCompilePhase(GlobalTSTypeRef gt, JSTaggedValue hclass, uint32_t constantPoolLen)
{
hclassCache_.emplace_back(hclass.GetRawData());
classTypeIhcIndexMap_[gt] = constantPoolLen + hclassCache_.size() - 1;
}
int GetHClassIndex(GlobalTSTypeRef classGT);
uint32_t RecordIhcToVecAndIndexMap(IHClassData &ihcData);
void CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constantPoolIndex,
JSHandle<ConstantPool> snapshotConstantPool,
@ -578,31 +645,43 @@ private:
builtinsRecordName_ = builtinsRecordName;
}
// for snapshot
int32_t GetOldConstantPoolIDByMethodOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset);
void GenerateSnapshotConstantPoolList(std::map<int32_t, uint32_t> &cpListIndexMap,
const CMap<int32_t, JSTaggedValue> &oldCPValues);
void FillSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
kungfu::BytecodeInfoCollector *bcInfoCollector);
void AddHClassToSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
kungfu::BytecodeInfoCollector *bcInfoCollector);
JSHandle<ConstantPool> GetSnapshotConstantPool(uint32_t cpListIndex);
EcmaVM *vm_ {nullptr};
JSThread *thread_ {nullptr};
ObjectFactory *factory_ {nullptr};
JSTaggedValue globalModuleTable_ {JSTaggedValue::Hole()};
// record the mapping relationship between classType and instance hclass index in the constant pool
std::map<GlobalTSTypeRef, uint32_t> classTypeIhcIndexMap_ {};
std::map<GlobalTSTypeRef, IHClassData> gtIhcMap_ {};
bool assertTypes_ {false};
bool printAnyTypes_ {false};
friend class EcmaVM;
// store hclass of each abc which produced from static type info
CVector<JSTaggedType> hclassCache_ {};
// when the passmanager iterates each method, the curCP_ and curCPID_ should be updated
// so that subsequent passes (type_infer, ts_type_lowering) can obtain the correct constpool.
JSTaggedValue curCP_ {JSTaggedValue::Hole()};
int32_t curCPID_ {0};
// This constantpool is generated by pass_manager in AOT phase
// which can be used directly in each pass stage of AOT, such as type_infer and ts_type_lowring
// Finally it will be serialized into the '.ai' file, and used in runtime.
JSTaggedValue snapshotConstantPool_ {JSTaggedValue::Hole()};
std::vector<uint32_t> recordMethodIndex_ {};
std::vector<uint32_t> recordLiteralIndex_ {};
// for snapshot
SnapshotData snapshotData_ {};
std::map<std::pair<const JSPandaFile *, uint32_t>, GlobalTSTypeRef> literalOffsetGTMap_ {};
std::vector<uint32_t> builtinOffsets_ {};
JSPandaFile *builtinPandaFile_ {nullptr};
CString builtinsRecordName_ {""};
std::map<LocalModuleInfo, GlobalTSTypeRef> localModuleVarGtMap_{};
friend class EcmaVM;
};
} // namespace panda::ecmascript

View File

@ -72,7 +72,7 @@ GlobalTSTypeRef TSTypeParser::ParseType(const JSPandaFile *jsPandaFile, const CS
JSHandle<JSTaggedValue> type = ParseNonImportType(jsPandaFile, recordName, literal, kind);
SetTSType(table, type, gt);
GenerateStaticHClass(jsPandaFile, type);
GenerateStaticHClass(type);
return gt;
}
@ -379,7 +379,7 @@ void TSTypeParser::FillInterfaceMethodTypes(const JSPandaFile *jsPandaFile, cons
}
}
void TSTypeParser::GenerateStaticHClass(const JSPandaFile *jsPandaFile, JSHandle<JSTaggedValue> type)
void TSTypeParser::GenerateStaticHClass(JSHandle<JSTaggedValue> type)
{
if (type->IsTSClassType()) {
JSHandle<TSClassType> classType(type);
@ -388,7 +388,7 @@ void TSTypeParser::GenerateStaticHClass(const JSPandaFile *jsPandaFile, JSHandle
}
auto gt = classType->GetGT();
if (tsManager_->IsUserDefinedClassTypeKind(gt)) {
tsManager_->GenerateStaticHClass(jsPandaFile, classType);
tsManager_->GenerateStaticHClass(classType);
}
}
}

View File

@ -101,7 +101,7 @@ private:
uint32_t startIndex, uint32_t lastIndex,
uint32_t &index);
void GenerateStaticHClass(const JSPandaFile *jsPandaFile, JSHandle<JSTaggedValue> type);
void GenerateStaticHClass(JSHandle<JSTaggedValue> type);
JSHandle<TaggedArray> GetExportDataFromRecord(const JSPandaFile *jsPandaFile, const CString &recordName);

View File

@ -161,4 +161,8 @@ group("ark_aot_test") {
"builtins_stub:builtins_stubAotAction",
]
}
if (!is_debug) {
deps += [ "aot_multi_constantpool_test:aot_multi_constantpool_test" ]
}
}

View File

@ -0,0 +1,23 @@
# Copyright (c) 2022 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.
group("aot_multi_constantpool_test") {
testonly = true
deps = [
"multi_constantpool_class:multi_constantpool_classAotAction",
"multi_constantpool_closure:multi_constantpool_closureAotAction",
"multi_constantpool_constructor:multi_constantpool_constructorAotAction",
"multi_constantpool_func:multi_constantpool_funcAotAction",
"multi_constantpool_funccall:multi_constantpool_funccallAotAction",
]
}

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_test_action("multi_constantpool_class") {
deps = []
is_disable_type_lowering = false
}

View File

@ -0,0 +1,15 @@
# Copyright (c) 2022 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.
base foo
base foo2

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_test_action("multi_constantpool_closure") {
deps = []
is_disable_type_lowering = false
}

View File

@ -0,0 +1,16 @@
# Copyright (c) 2022 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.
base: 65536
base: 65488
base: -1

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_test_action("multi_constantpool_constructor") {
deps = []
is_disable_type_lowering = false
}

View File

@ -0,0 +1,14 @@
# Copyright (c) 2022 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.
foo: base

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_test_action("multi_constantpool_func") {
deps = []
is_disable_type_lowering = false
}

View File

@ -0,0 +1,15 @@
# Copyright (c) 2022 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.
base foo
base foo2

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_test_action("multi_constantpool_funccall") {
deps = []
is_disable_type_lowering = false
}

View File

@ -0,0 +1,15 @@
# Copyright (c) 2022 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.
base foo
base foo2