mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 10:09:54 +00:00
AOT supports ld/stobjbyname for function object
Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I8GEHD Signed-off-by: weng-xi <wengxi1@huawei.com> Change-Id: I81b970dd66b62700aaeed3b39806ce0a7d1d92d0
This commit is contained in:
parent
91b7756e39
commit
40e3828c68
@ -97,6 +97,8 @@ void MethodSnapshotInfo::StoreDataToGlobalData(EcmaVM *vm, const JSPandaFile *js
|
||||
const std::set<uint32_t> &skippedMethods)
|
||||
{
|
||||
JSThread *thread = vm->GetJSThread();
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
PGOTypeManager *ptManager = thread->GetCurrentEcmaContext()->GetPTManager();
|
||||
for (auto item : info_) {
|
||||
const ItemData &data = item.second;
|
||||
JSHandle<ConstantPool> cp(thread,
|
||||
@ -106,10 +108,20 @@ void MethodSnapshotInfo::StoreDataToGlobalData(EcmaVM *vm, const JSPandaFile *js
|
||||
uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
|
||||
JSHandle<TaggedArray> snapshotCpArr(thread, globalData.GetCurSnapshotCpArray());
|
||||
JSHandle<ConstantPool> snapshotCp(thread, snapshotCpArr->Get(snapshotCpArrIdx));
|
||||
|
||||
PGOTypeLocation loc(jsPandaFile, data.methodOffset_, data.bcIndex_);
|
||||
ProfileType pt = ptManager->GetRootIdByLocation(loc);
|
||||
JSHandle<JSTaggedValue> ihc = JSHandle<JSTaggedValue>(thread, ptManager->QueryHClass(pt, pt));
|
||||
JSHandle<AOTLiteralInfo> aotLiteralInfo = factory->NewAOTLiteralInfo(1); // 1: only one method
|
||||
aotLiteralInfo->SetObjectToCache(thread, 0, JSTaggedValue(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE));
|
||||
if (!ihc->IsUndefined()) {
|
||||
aotLiteralInfo->SetIhc(ihc.GetTaggedValue());
|
||||
}
|
||||
if (skippedMethods.find(methodOffset) == skippedMethods.end()) {
|
||||
globalData.RecordReviseData(SnapshotReviseInfo::Type::METHOD,
|
||||
BaseReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
|
||||
snapshotCp->SetObjectToCache(thread, data.constantPoolIdx_, JSTaggedValue(methodOffset));
|
||||
aotLiteralInfo->SetObjectToCache(thread, 0, JSTaggedValue(methodOffset));
|
||||
snapshotCp->SetObjectToCache(thread, data.constantPoolIdx_, aotLiteralInfo.GetTaggedValue());
|
||||
globalData.RecordReviseData(
|
||||
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -140,8 +152,8 @@ void ClassLiteralSnapshotInfo::StoreDataToGlobalData(EcmaVM *vm, const JSPandaFi
|
||||
JSHandle<JSTaggedValue> chc = JSHandle<JSTaggedValue>(thread, ptManager->QueryHClass(ctorPt, ctorPt));
|
||||
|
||||
CollectLiteralInfo(vm, arrayHandle, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
|
||||
globalData.RecordReviseData(SnapshotReviseInfo::Type::LITERAL,
|
||||
BaseReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
|
||||
globalData.RecordReviseData(
|
||||
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,8 +186,8 @@ void ObjectLiteralSnapshotInfo::StoreDataToGlobalData(EcmaVM *vm, const JSPandaF
|
||||
JSHandle<JSTaggedValue> chc = JSHandle<JSTaggedValue>(thread, ptManager->QueryHClass(ctorPt, ctorPt));
|
||||
|
||||
CollectLiteralInfo(vm, properties, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
|
||||
globalData.RecordReviseData(SnapshotReviseInfo::Type::LITERAL,
|
||||
BaseReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
|
||||
globalData.RecordReviseData(
|
||||
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,8 +210,8 @@ void ArrayLiteralSnapshotInfo::StoreDataToGlobalData(EcmaVM *vm, const JSPandaFi
|
||||
JSHandle<JSTaggedValue> ihc = thread->GlobalConstants()->GetHandledUndefined();
|
||||
JSHandle<JSTaggedValue> chc = thread->GlobalConstants()->GetHandledUndefined();
|
||||
CollectLiteralInfo(vm, literal, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
|
||||
globalData.RecordReviseData(SnapshotReviseInfo::Type::LITERAL,
|
||||
BaseReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
|
||||
globalData.RecordReviseData(
|
||||
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,36 +20,16 @@
|
||||
#include "ecmascript/tagged_array-inl.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
JSHandle<ConstantPool> BaseReviseData::GetConstantPoolFromSnapshotData(JSThread *thread,
|
||||
const SnapshotGlobalData *globalData,
|
||||
uint32_t dataIdx, uint32_t cpArrayIdx)
|
||||
JSHandle<ConstantPool> ReviseData::GetConstantPoolFromSnapshotData(JSThread *thread,
|
||||
const SnapshotGlobalData *globalData,
|
||||
uint32_t dataIdx, uint32_t cpArrayIdx)
|
||||
{
|
||||
JSHandle<TaggedArray> data(thread, globalData->GetData());
|
||||
JSHandle<TaggedArray> cpArr(thread, data->Get(dataIdx + SnapshotGlobalData::CP_ARRAY_OFFSET));
|
||||
return JSHandle<ConstantPool>(thread, cpArr->Get(cpArrayIdx));
|
||||
}
|
||||
|
||||
void MethodReviseData::Resolve(JSThread *thread, const SnapshotGlobalData *globalData,
|
||||
const CMap<std::pair<std::string, uint32_t>, uint32_t> &methodToEntryIndexMap)
|
||||
{
|
||||
for (auto &item: data_) {
|
||||
JSHandle<ConstantPool> newCP = GetConstantPoolFromSnapshotData(thread, globalData,
|
||||
item.dataIdx_, item.cpArrayIdx_);
|
||||
JSTaggedValue val = newCP->GetObjectFromCache(item.constpoolIdx_);
|
||||
uint32_t methodOffset = static_cast<uint32_t>(val.GetInt());
|
||||
if (thread->GetEcmaVM()->GetJSOptions().IsEnableCompilerLogSnapshot()) {
|
||||
LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: " << methodOffset << ") ";
|
||||
}
|
||||
std::string name = globalData->GetFileNameByDataIdx(item.dataIdx_).c_str();
|
||||
AnFileInfo::FuncEntryIndexKey key = std::make_pair(name, methodOffset);
|
||||
if (methodToEntryIndexMap.find(key) != methodToEntryIndexMap.end()) {
|
||||
uint32_t entryIndex = methodToEntryIndexMap.at(key);
|
||||
newCP->SetObjectToCache(thread, item.constpoolIdx_, JSTaggedValue(entryIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LiteralReviseData::Resolve(JSThread *thread, const SnapshotGlobalData *globalData,
|
||||
void ReviseData::Resolve(JSThread *thread, const SnapshotGlobalData *globalData,
|
||||
const CMap<std::pair<std::string, uint32_t>, uint32_t> &methodToEntryIndexMap)
|
||||
{
|
||||
for (auto &item: data_) {
|
||||
|
@ -25,11 +25,7 @@ class SnapshotGlobalData;
|
||||
* The information that needs to be revised before saving the 'ai' file is recorded in SnapshotReviseData.
|
||||
* Currently, the revised information includes the entry index of each method in the 'an' file.
|
||||
*/
|
||||
#define REVISE_DATA_TYPE_LIST(V) \
|
||||
V(METHOD, Method) \
|
||||
V(LITERAL, Literal)
|
||||
|
||||
class BaseReviseData {
|
||||
class ReviseData {
|
||||
public:
|
||||
struct ItemData {
|
||||
uint32_t dataIdx_;
|
||||
@ -37,69 +33,42 @@ public:
|
||||
int32_t constpoolIdx_;
|
||||
};
|
||||
|
||||
BaseReviseData() = default;
|
||||
virtual ~BaseReviseData() = default;
|
||||
ReviseData() = default;
|
||||
virtual ~ReviseData() = default;
|
||||
|
||||
void Record(ItemData data)
|
||||
{
|
||||
data_.emplace_back(data);
|
||||
}
|
||||
|
||||
virtual void Resolve(JSThread *thread, const SnapshotGlobalData *globalData,
|
||||
const CMap<std::pair<std::string, uint32_t>, uint32_t> &methodToEntryIndexMap) = 0;
|
||||
void Resolve(JSThread *thread, const SnapshotGlobalData *globalData,
|
||||
const CMap<std::pair<std::string, uint32_t>, uint32_t> &methodToEntryIndexMap);
|
||||
|
||||
protected:
|
||||
JSHandle<ConstantPool> GetConstantPoolFromSnapshotData(JSThread *thread, const SnapshotGlobalData *globalData,
|
||||
uint32_t dataIdx, uint32_t cpArrayIdx);
|
||||
|
||||
using ReviseData = std::vector<ItemData>;
|
||||
ReviseData data_ {};
|
||||
std::vector<ItemData> data_;
|
||||
};
|
||||
|
||||
#define DEFINE_REVISE_CLASS(V, name) \
|
||||
class name##ReviseData final : public BaseReviseData { \
|
||||
public: \
|
||||
virtual void Resolve(JSThread *thread, const SnapshotGlobalData *globalData, \
|
||||
const CMap<std::pair<std::string, uint32_t>, uint32_t> &methodToEntryIndexMap) override; \
|
||||
};
|
||||
|
||||
REVISE_DATA_TYPE_LIST(DEFINE_REVISE_CLASS)
|
||||
#undef DEFINE_REVISE_CLASS
|
||||
|
||||
class SnapshotReviseInfo {
|
||||
public:
|
||||
enum class Type {
|
||||
#define DEFINE_TYPE(type, ...) type,
|
||||
REVISE_DATA_TYPE_LIST(DEFINE_TYPE)
|
||||
#undef DEFINE_TYPE
|
||||
};
|
||||
|
||||
SnapshotReviseInfo()
|
||||
{
|
||||
#define ADD_REVISE_DATA(V, name) \
|
||||
reviseData_.emplace_back(std::make_unique<name##ReviseData>());
|
||||
REVISE_DATA_TYPE_LIST(ADD_REVISE_DATA)
|
||||
#undef ADD_REVISE_DATA
|
||||
}
|
||||
SnapshotReviseInfo() = default;
|
||||
~SnapshotReviseInfo() = default;
|
||||
|
||||
void Record(Type type, BaseReviseData::ItemData data)
|
||||
void Record(ReviseData::ItemData data)
|
||||
{
|
||||
size_t reviseDataIdx = static_cast<size_t>(type);
|
||||
reviseData_.at(reviseDataIdx)->Record(data);
|
||||
reviseData_.Record(data);
|
||||
}
|
||||
|
||||
void ResolveData(JSThread *thread, const SnapshotGlobalData *globalData,
|
||||
const CMap<std::pair<std::string, uint32_t>, uint32_t> &methodToEntryIndexMap)
|
||||
{
|
||||
for (auto &data : reviseData_) {
|
||||
data->Resolve(thread, globalData, methodToEntryIndexMap);
|
||||
}
|
||||
reviseData_.Resolve(thread, globalData, methodToEntryIndexMap);
|
||||
}
|
||||
|
||||
private:
|
||||
CVector<std::unique_ptr<BaseReviseData>> reviseData_ {};
|
||||
ReviseData reviseData_ {};
|
||||
};
|
||||
#undef REVISE_DATA_TYPE_LIST
|
||||
|
||||
class SnapshotGlobalData {
|
||||
public:
|
||||
@ -141,9 +110,9 @@ public:
|
||||
|
||||
CString GetFileNameByDataIdx(uint32_t dataIdx) const;
|
||||
|
||||
void RecordReviseData(SnapshotReviseInfo::Type type, BaseReviseData::ItemData data)
|
||||
void RecordReviseData(ReviseData::ItemData data)
|
||||
{
|
||||
reviseInfo_.Record(type, data);
|
||||
reviseInfo_.Record(data);
|
||||
}
|
||||
|
||||
void ResolveSnapshotData(JSThread *thread,
|
||||
|
@ -462,6 +462,8 @@ namespace panda::ecmascript::kungfu {
|
||||
#define ASM_INTERPRETER_BC_LAYOUT_PROFILER_STUB_LIST(V) \
|
||||
APPEND_SUFFIX(HandleDefineclasswithbufferImm8Id16Id16Imm16V8, V) \
|
||||
APPEND_SUFFIX_IMM16(HandleDefineclasswithbufferImm16Id16Id16Imm16V8, V) \
|
||||
APPEND_SUFFIX(HandleDefinefuncImm8Id16Imm8, V) \
|
||||
APPEND_SUFFIX_IMM16(HandleDefinefuncImm16Id16Imm8, V) \
|
||||
APPEND_SUFFIX(HandleDefinegettersetterbyvalueV8V8V8V8, V) \
|
||||
APPEND_SUFFIX(HandleCreateobjectwithbufferImm8Id16, V) \
|
||||
APPEND_SUFFIX_IMM16(HandleCreateobjectwithbufferImm16Id16, V) \
|
||||
|
@ -438,6 +438,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsDefineFunc(EcmaOpcode opcode)
|
||||
{
|
||||
switch (opcode) {
|
||||
case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8:
|
||||
case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static uint8_t ReadByte(const uint8_t *pc)
|
||||
{
|
||||
@ -844,7 +855,7 @@ public:
|
||||
{
|
||||
return (idx <= end_) && (idx >= start_);
|
||||
}
|
||||
|
||||
|
||||
bool InRange() const
|
||||
{
|
||||
return (index_ <= end_) && (index_ >= start_);
|
||||
|
@ -697,9 +697,9 @@ GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, Ga
|
||||
Bind(&cache);
|
||||
{
|
||||
if (type == ConstPoolType::METHOD) {
|
||||
Label isInt(env_);
|
||||
Branch(TaggedIsInt(*result), &isInt, &exit);
|
||||
Bind(&isInt);
|
||||
Label isAOTLiteralInfo(env_);
|
||||
Branch(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
|
||||
Bind(&isAOTLiteralInfo);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
|
||||
{ constPool, Int32ToTaggedInt(index), module }, hirGate);
|
||||
|
@ -4253,7 +4253,7 @@ DECLARE_ASM_HANDLER(HandleDefinefuncImm8Id16Imm8)
|
||||
GateRef length = ReadInst8_3(pc);
|
||||
DEFVARIABLE(result, VariableType::JS_POINTER(),
|
||||
GetMethodFromConstPool(glue, constpool, GetModule(sp), ZExtInt16ToInt32(methodId)));
|
||||
result = CallRuntime(glue, RTSTUB_ID(DefineFunc), { *result });
|
||||
result = CallRuntime(glue, RTSTUB_ID(DefineFunc), { constpool, Int16ToTaggedInt(methodId), GetModule(sp) });
|
||||
Label notException(env);
|
||||
CHECK_EXCEPTION_WITH_JUMP(*result, ¬Exception);
|
||||
Bind(¬Exception);
|
||||
@ -4266,6 +4266,7 @@ DECLARE_ASM_HANDLER(HandleDefinefuncImm8Id16Imm8)
|
||||
SetLexicalEnvToFunction(glue, *result, envHandle);
|
||||
GateRef currentFunc = GetFunctionFromFrame(frame);
|
||||
SetHomeObjectToFunction(glue, *result, GetHomeObjectFromFunction(currentFunc));
|
||||
callback.ProfileDefineClass(*result);
|
||||
varAcc = *result;
|
||||
DISPATCH_WITH_ACC(DEFINEFUNC_IMM8_ID16_IMM8);
|
||||
}
|
||||
@ -4279,7 +4280,7 @@ DECLARE_ASM_HANDLER(HandleDefinefuncImm16Id16Imm8)
|
||||
GateRef length = ReadInst8_4(pc);
|
||||
DEFVARIABLE(result, VariableType::JS_POINTER(),
|
||||
GetMethodFromConstPool(glue, constpool, GetModule(sp), ZExtInt16ToInt32(methodId)));
|
||||
result = CallRuntime(glue, RTSTUB_ID(DefineFunc), { *result });
|
||||
result = CallRuntime(glue, RTSTUB_ID(DefineFunc), { constpool, Int16ToTaggedInt(methodId), GetModule(sp) });
|
||||
Label notException(env);
|
||||
CHECK_EXCEPTION_WITH_JUMP(*result, ¬Exception);
|
||||
Bind(¬Exception);
|
||||
@ -4293,6 +4294,7 @@ DECLARE_ASM_HANDLER(HandleDefinefuncImm16Id16Imm8)
|
||||
GateRef currentFunc = GetFunctionFromFrame(frame);
|
||||
SetHomeObjectToFunction(glue, *result, GetHomeObjectFromFunction(currentFunc));
|
||||
varAcc = *result;
|
||||
callback.ProfileDefineClass(*result);
|
||||
DISPATCH_WITH_ACC(DEFINEFUNC_IMM16_ID16_IMM8);
|
||||
}
|
||||
}
|
||||
|
@ -76,8 +76,9 @@ void PGOBCInfo::Record(const BytecodeInstruction &bcIns, int32_t bcIndex,
|
||||
} else if (Bytecodes::IsCallOp(opcode)) {
|
||||
Record(InfoDetail {recordName, methodOffset, bcIndex, bcOffset, 0}, Type::CALL_TARGET);
|
||||
} else if (Bytecodes::IsDefineClassWithBufferOp(opcode)) {
|
||||
auto cpIndex = bcIns.GetId().AsRawValue();
|
||||
Record(InfoDetail {recordName, methodOffset, bcIndex, bcOffset, cpIndex}, Type::CLASS);
|
||||
Record(InfoDetail {recordName, methodOffset, bcIndex, bcOffset, 0}, Type::CLASS);
|
||||
} else if (Bytecodes::IsDefineFunc(opcode)) {
|
||||
Record(InfoDetail {recordName, methodOffset, bcIndex, bcOffset, 0}, Type::FUNCTION);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -28,10 +28,11 @@ public:
|
||||
EMPTY_ARRAY,
|
||||
CALL_TARGET,
|
||||
CLASS,
|
||||
FUNCTION,
|
||||
|
||||
TYPE_NUM,
|
||||
TYPE_FIRST = OBJ_LITERAL,
|
||||
TYPE_LAST = CLASS,
|
||||
TYPE_LAST = FUNCTION,
|
||||
};
|
||||
|
||||
struct InfoDetail {
|
||||
|
@ -130,6 +130,57 @@ void ObjectLiteralParser::GenerateHClass(const PGOHClassGenerator &generator, co
|
||||
generator.GenerateHClass(rootSampleType);
|
||||
}
|
||||
|
||||
bool FunctionParser::RecordTypeInfo(const PGODefineOpType &defType, const PGOTypeLocation &loc)
|
||||
{
|
||||
auto rootType = defType.GetProfileType();
|
||||
auto ctorPt = defType.GetCtorPt();
|
||||
if (ctorPt.IsNone()) {
|
||||
return false;
|
||||
}
|
||||
PGOSampleType ctorSampleType(ctorPt);
|
||||
|
||||
auto protoPt = defType.GetProtoTypePt();
|
||||
if (protoPt.IsNone()) {
|
||||
return false;
|
||||
}
|
||||
PGOSampleType protoSampleType(protoPt);
|
||||
|
||||
ptManager_->RecordLocationToRootType(loc, rootType);
|
||||
auto ctorLoc = loc.ChangeType(PGOTypeLocation::Type::CONSTRUCTOR);
|
||||
ptManager_->RecordLocationToRootType(ctorLoc, ctorPt);
|
||||
|
||||
auto protoLoc = loc.ChangeType(PGOTypeLocation::Type::PROTOTYPE);
|
||||
ptManager_->RecordLocationToRootType(protoLoc, protoPt);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FunctionParser::GenerateHClass(const PGOHClassGenerator &generator, const PGOTypeLocation &loc)
|
||||
{
|
||||
auto thread = ptManager_->GetJSThread();
|
||||
[[maybe_unused]] EcmaHandleScope scope(thread);
|
||||
|
||||
auto rootType = ptManager_->GetRootIdByLocation(loc);
|
||||
PGOSampleType iSampleType(rootType);
|
||||
|
||||
auto ctorLoc = loc.ChangeType(PGOTypeLocation::Type::CONSTRUCTOR);
|
||||
auto ctorPt = ptManager_->GetRootIdByLocation(ctorLoc);
|
||||
PGOSampleType ctorSampleType(ctorPt);
|
||||
|
||||
auto protoLoc = loc.ChangeType(PGOTypeLocation::Type::PROTOTYPE);
|
||||
auto protoPt = ptManager_->GetRootIdByLocation(protoLoc);
|
||||
PGOSampleType protoSampleType(protoPt);
|
||||
|
||||
// testcase: propertyaccessor2.ts. protoSampleType not find desc
|
||||
if (generator.FindHClassLayoutDesc(ctorSampleType) && generator.FindHClassLayoutDesc(protoSampleType)) {
|
||||
generator.GenerateHClass(protoSampleType);
|
||||
|
||||
auto phValue = ptManager_->QueryHClass(protoPt, protoPt);
|
||||
JSHandle<JSHClass> phclass(thread, phValue);
|
||||
JSHandle<JSObject> prototype = thread->GetEcmaVM()->GetFactory()->NewJSObject(phclass);
|
||||
generator.GenerateIHClass(iSampleType, prototype);
|
||||
}
|
||||
}
|
||||
|
||||
PGOTypeParser::PGOTypeParser(const PGOProfilerDecoder &decoder, PGOTypeManager *ptManager)
|
||||
: decoder_(decoder), ptManager_(ptManager)
|
||||
{
|
||||
@ -137,6 +188,7 @@ PGOTypeParser::PGOTypeParser(const PGOProfilerDecoder &decoder, PGOTypeManager *
|
||||
parsers_.emplace_back(std::make_unique<EmptyArrayParser>(ptManager));
|
||||
parsers_.emplace_back(std::make_unique<ArrayLiteralParser>(ptManager));
|
||||
parsers_.emplace_back(std::make_unique<ObjectLiteralParser>(ptManager));
|
||||
parsers_.emplace_back(std::make_unique<FunctionParser>(ptManager));
|
||||
}
|
||||
|
||||
void PGOTypeParser::CreatePGOType(BytecodeInfoCollector &collector)
|
||||
|
@ -77,6 +77,14 @@ private:
|
||||
virtual void GenerateHClass(const PGOHClassGenerator &generator, const PGOTypeLocation &loc) override;
|
||||
};
|
||||
|
||||
class FunctionParser final : public BaseParser {
|
||||
public:
|
||||
FunctionParser(PGOTypeManager *ptManager) : BaseParser(ptManager, PGOBCInfo::Type::FUNCTION) {}
|
||||
private:
|
||||
virtual bool RecordTypeInfo(const PGODefineOpType &defType, const PGOTypeLocation &loc) override;
|
||||
virtual void GenerateHClass(const PGOHClassGenerator &generator, const PGOTypeLocation &loc) override;
|
||||
};
|
||||
|
||||
class PGOTypeParser {
|
||||
public:
|
||||
explicit PGOTypeParser(const PGOProfilerDecoder &decoder, PGOTypeManager *ptManager);
|
||||
|
@ -2504,14 +2504,16 @@ void SlowPathLowering::LowerDefineClassWithBuffer(GateRef gate)
|
||||
void SlowPathLowering::LowerDefineFunc(GateRef gate)
|
||||
{
|
||||
GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
|
||||
GateRef methodId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
|
||||
GateRef methodId = acc_.GetValueIn(gate, 0);
|
||||
GateRef length = acc_.GetValueIn(gate, 1);
|
||||
auto method = builder_.GetObjectFromConstPool(glue_, gate, jsFunc, methodId, ConstPoolType::METHOD);
|
||||
GateRef constPool = builder_.GetConstPoolFromFunction(jsFunc);
|
||||
GateRef module = builder_.GetModuleFromFunction(jsFunc);
|
||||
|
||||
Label defaultLabel(&builder_);
|
||||
Label successExit(&builder_);
|
||||
Label exceptionExit(&builder_);
|
||||
GateRef result = LowerCallRuntime(gate, RTSTUB_ID(DefineFunc), { method });
|
||||
GateRef result = LowerCallRuntime(gate, RTSTUB_ID(DefineFunc),
|
||||
{ constPool, builder_.ToTaggedInt(methodId), module });
|
||||
builder_.Branch(builder_.TaggedIsException(result), &exceptionExit, &defaultLabel);
|
||||
builder_.Bind(&defaultLabel);
|
||||
{
|
||||
|
@ -524,6 +524,37 @@ static void DumpPropertyKey(JSTaggedValue key, std::ostream &os)
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpAttr(const PropertyAttributes &attr, bool fastMode, std::ostream &os)
|
||||
{
|
||||
if (attr.IsAccessor()) {
|
||||
os << "(Accessor) ";
|
||||
}
|
||||
|
||||
os << "Attr(";
|
||||
if (attr.IsNoneAttributes()) {
|
||||
os << "NONE";
|
||||
}
|
||||
if (attr.IsWritable()) {
|
||||
os << "W";
|
||||
}
|
||||
if (attr.IsEnumerable()) {
|
||||
os << "E";
|
||||
}
|
||||
if (attr.IsConfigurable()) {
|
||||
os << "C";
|
||||
}
|
||||
os << ")";
|
||||
|
||||
os << " InlinedProps: " << attr.IsInlinedProps();
|
||||
|
||||
if (fastMode) {
|
||||
os << " Order: " << std::dec << attr.GetOffset();
|
||||
os << " SortedIndex: " << std::dec << attr.GetSortedIndex();
|
||||
} else {
|
||||
os << " Order: " << std::dec << attr.GetDictionaryOrder();
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpHClass(const JSHClass *jshclass, std::ostream &os, bool withDetail)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
@ -538,8 +569,18 @@ static void DumpHClass(const JSHClass *jshclass, std::ostream &os, bool withDeta
|
||||
attrs.DumpTaggedValue(os);
|
||||
os << "\n";
|
||||
if (withDetail && !attrs.IsNull()) {
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(attrs.GetTaggedObject());
|
||||
layoutInfo->Dump(os);
|
||||
LayoutInfo *layout = LayoutInfo::Cast(jshclass->GetLayout().GetTaggedObject());
|
||||
int element = static_cast<int>(jshclass->NumberOfProps());
|
||||
for (int i = 0; i < element; i++) {
|
||||
JSTaggedValue key = layout->GetKey(i);
|
||||
PropertyAttributes attr = layout->GetAttr(i);
|
||||
os << std::right << std::setw(DUMP_PROPERTY_OFFSET);
|
||||
os << "[" << i << "]: ";
|
||||
DumpPropertyKey(key, os);
|
||||
os << " : ";
|
||||
DumpAttr(attr, true, os);
|
||||
os << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
os << " - Transitions :" << std::setw(DUMP_TYPE_OFFSET);
|
||||
@ -609,37 +650,6 @@ static void DumpClass(TaggedObject *obj, std::ostream &os)
|
||||
DumpHClass(JSHClass::Cast(obj), os, true);
|
||||
}
|
||||
|
||||
static void DumpAttr(const PropertyAttributes &attr, bool fastMode, std::ostream &os)
|
||||
{
|
||||
if (attr.IsAccessor()) {
|
||||
os << "(Accessor) ";
|
||||
}
|
||||
|
||||
os << "Attr(";
|
||||
if (attr.IsNoneAttributes()) {
|
||||
os << "NONE";
|
||||
}
|
||||
if (attr.IsWritable()) {
|
||||
os << "W";
|
||||
}
|
||||
if (attr.IsEnumerable()) {
|
||||
os << "E";
|
||||
}
|
||||
if (attr.IsConfigurable()) {
|
||||
os << "C";
|
||||
}
|
||||
os << ")";
|
||||
|
||||
os << " InlinedProps: " << attr.IsInlinedProps();
|
||||
|
||||
if (fastMode) {
|
||||
os << " Order: " << std::dec << attr.GetOffset();
|
||||
os << " SortedIndex: " << std::dec << attr.GetSortedIndex();
|
||||
} else {
|
||||
os << " Order: " << std::dec << attr.GetDictionaryOrder();
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpObject(TaggedObject *obj, std::ostream &os)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
|
@ -42,6 +42,12 @@ void ICRuntime::UpdateLoadHandler(const ObjectOperator &op, JSHandle<JSTaggedVal
|
||||
}
|
||||
JSHandle<JSTaggedValue> handlerValue;
|
||||
JSHandle<JSHClass> hclass(GetThread(), receiver->GetTaggedObject()->GetClass());
|
||||
// When a transition occurs without the shadow property, AOT does not trigger the
|
||||
// notifyprototypechange behavior, so for the case where the property does not
|
||||
// exist and the Hclass is AOT, IC needs to be abandoned.
|
||||
if (hclass->IsTS() && !op.IsFound()) {
|
||||
return;
|
||||
}
|
||||
if (op.IsElement()) {
|
||||
if (!op.IsFound() && hclass->IsDictionaryElement()) {
|
||||
return;
|
||||
@ -201,7 +207,6 @@ JSTaggedValue LoadICRuntime::LoadValueMiss(JSHandle<JSTaggedValue> receiver, JSH
|
||||
icAccessor_.SetAsMega();
|
||||
return result.GetTaggedValue();
|
||||
}
|
||||
|
||||
UpdateLoadHandler(op, key, receiver);
|
||||
}
|
||||
|
||||
|
@ -4854,13 +4854,10 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
|
||||
uint16_t methodId = READ_INST_16_1();
|
||||
uint16_t length = READ_INST_8_3();
|
||||
LOG_INST() << "intrinsics::definefunc length: " << length;
|
||||
|
||||
auto constpool = GetConstantPool(sp);
|
||||
|
||||
auto module = GetEcmaModule(sp);
|
||||
Method *method = Method::Cast(GET_METHOD_FROM_CACHE(methodId).GetTaggedObject());
|
||||
ASSERT(method != nullptr);
|
||||
|
||||
auto res = SlowRuntimeStub::DefineFunc(thread, method);
|
||||
auto res = SlowRuntimeStub::DefineFunc(thread, constpool, methodId, module);
|
||||
JSFunction *jsFunc = JSFunction::Cast(res.GetTaggedObject());
|
||||
|
||||
jsFunc->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(length));
|
||||
@ -4881,10 +4878,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
|
||||
|
||||
auto constpool = GetConstantPool(sp);
|
||||
auto module = GetEcmaModule(sp);
|
||||
Method *method = Method::Cast(GET_METHOD_FROM_CACHE(methodId).GetTaggedObject());
|
||||
ASSERT(method != nullptr);
|
||||
|
||||
auto res = SlowRuntimeStub::DefineFunc(thread, method);
|
||||
auto res = SlowRuntimeStub::DefineFunc(thread, constpool, methodId, module);
|
||||
JSFunction *jsFunc = JSFunction::Cast(res.GetTaggedObject());
|
||||
|
||||
jsFunc->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(length));
|
||||
|
@ -264,7 +264,7 @@ JSTaggedValue InterpreterAssembly::Execute(EcmaRuntimeCallInfo *info)
|
||||
}
|
||||
auto acc = reinterpret_cast<InterpreterEntry>(entry)(thread->GetGlueAddr(),
|
||||
callTarget, method, method->GetCallField(), argc, argv);
|
||||
|
||||
|
||||
if (thread->IsEntryFrameDroppedTrue()) {
|
||||
thread->PendingEntryFrameDroppedState();
|
||||
return JSTaggedValue::Hole();
|
||||
@ -6644,11 +6644,7 @@ void InterpreterAssembly::HandleDefinefuncImm16Id16Imm8(
|
||||
LOG_INST() << "intrinsics::definefunc length: " << length;
|
||||
|
||||
constpool = GetConstantPool(sp);
|
||||
Method *method =
|
||||
Method::Cast(ConstantPool::GetMethodFromCache(thread, constpool, GetModule(sp), methodId).GetTaggedObject());
|
||||
ASSERT(method != nullptr);
|
||||
|
||||
auto res = SlowRuntimeStub::DefineFunc(thread, method);
|
||||
auto res = SlowRuntimeStub::DefineFunc(thread, constpool, methodId, GetModule(sp));
|
||||
JSFunction *jsFunc = JSFunction::Cast(res.GetTaggedObject());
|
||||
|
||||
jsFunc->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(length));
|
||||
@ -6671,12 +6667,9 @@ void InterpreterAssembly::HandleDefinefuncImm8Id16Imm8(
|
||||
uint16_t methodId = READ_INST_16_1();
|
||||
uint16_t length = READ_INST_8_3();
|
||||
LOG_INST() << "intrinsics::definefunc length: " << length;
|
||||
constpool = GetConstantPool(sp);
|
||||
Method *method =
|
||||
Method::Cast(ConstantPool::GetMethodFromCache(thread, constpool, GetModule(sp), methodId).GetTaggedObject());
|
||||
ASSERT(method != nullptr);
|
||||
|
||||
auto res = SlowRuntimeStub::DefineFunc(thread, method);
|
||||
constpool = GetConstantPool(sp);
|
||||
auto res = SlowRuntimeStub::DefineFunc(thread, constpool, methodId, GetModule(sp));
|
||||
JSFunction *jsFunc = JSFunction::Cast(res.GetTaggedObject());
|
||||
|
||||
jsFunc->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(length));
|
||||
|
@ -965,12 +965,14 @@ JSTaggedValue SlowRuntimeStub::StArraySpread(JSThread *thread, JSTaggedValue dst
|
||||
return RuntimeStubs::RuntimeStArraySpread(thread, dstHandle, index, srcHandle);
|
||||
}
|
||||
|
||||
JSTaggedValue SlowRuntimeStub::DefineFunc(JSThread *thread, Method *method)
|
||||
JSTaggedValue SlowRuntimeStub::DefineFunc(JSThread *thread, JSTaggedValue constPool, uint16_t methodId,
|
||||
JSTaggedValue module)
|
||||
{
|
||||
INTERPRETER_TRACE(thread, DefineFunc);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<Method> methodHandle(thread, method);
|
||||
return RuntimeStubs::RuntimeDefinefunc(thread, methodHandle);
|
||||
JSHandle<JSTaggedValue> constpoolHandle(thread, constPool);
|
||||
JSHandle<JSTaggedValue> moduleHandle(thread, module);
|
||||
return RuntimeStubs::RuntimeDefinefunc(thread, constpoolHandle, methodId, moduleHandle);
|
||||
}
|
||||
|
||||
JSTaggedValue SlowRuntimeStub::GetSuperConstructor(JSThread *thread, JSTaggedValue ctor)
|
||||
|
@ -142,7 +142,7 @@ public:
|
||||
static JSTaggedValue TryUpdateGlobalRecord(JSThread *thread, JSTaggedValue prop, JSTaggedValue value);
|
||||
static JSTaggedValue StArraySpread(JSThread *thread, JSTaggedValue dst, JSTaggedValue index, JSTaggedValue src);
|
||||
|
||||
static JSTaggedValue DefineFunc(JSThread *thread, Method *method);
|
||||
static JSTaggedValue DefineFunc(JSThread *thread, JSTaggedValue constPool, uint16_t methodId, JSTaggedValue module);
|
||||
|
||||
static JSTaggedValue GetSuperConstructor(JSThread *thread, JSTaggedValue ctor);
|
||||
static JSTaggedValue SuperCall(JSThread *thread, JSTaggedValue func, JSTaggedValue newTarget, uint16_t firstVRegIdx,
|
||||
|
@ -104,6 +104,10 @@ JSHClass *JSFunction::GetOrCreateInitialJSHClass(JSThread *thread, const JSHandl
|
||||
JSHandle<JSTaggedValue> proto;
|
||||
if (!fun->HasFunctionPrototype()) {
|
||||
proto = JSHandle<JSTaggedValue>::Cast(NewJSFunctionPrototype(thread, fun));
|
||||
if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(fun.GetTaggedType(),
|
||||
JSTaggedType(proto->GetTaggedObject()->GetClass()), pgo::ProfileType::Kind::PrototypeId);
|
||||
}
|
||||
} else {
|
||||
proto = JSHandle<JSTaggedValue>(thread, fun->GetProtoOrHClass());
|
||||
}
|
||||
@ -112,7 +116,7 @@ JSHClass *JSFunction::GetOrCreateInitialJSHClass(JSThread *thread, const JSHandl
|
||||
JSHandle<JSHClass> hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, proto);
|
||||
fun->SetProtoOrHClass(thread, hclass);
|
||||
if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileDefineIClass(fun.GetTaggedType(), hclass.GetTaggedType());
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(fun.GetTaggedType(), hclass.GetTaggedType());
|
||||
}
|
||||
return *hclass;
|
||||
}
|
||||
@ -121,7 +125,11 @@ JSTaggedValue JSFunction::PrototypeGetter(JSThread *thread, const JSHandle<JSObj
|
||||
{
|
||||
JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(self);
|
||||
if (!func->HasFunctionPrototype()) {
|
||||
NewJSFunctionPrototype(thread, func);
|
||||
JSHandle<JSTaggedValue> proto = JSHandle<JSTaggedValue>::Cast(NewJSFunctionPrototype(thread, func));
|
||||
if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(func.GetTaggedType(),
|
||||
JSTaggedType(proto->GetTaggedObject()->GetClass()), pgo::ProfileType::Kind::PrototypeId);
|
||||
}
|
||||
}
|
||||
return JSFunction::Cast(*self)->GetFunctionPrototype();
|
||||
}
|
||||
@ -141,6 +149,10 @@ bool JSFunction::PrototypeSetter(JSThread *thread, const JSHandle<JSObject> &sel
|
||||
func->SetProtoOrHClass(thread, newClass);
|
||||
} else {
|
||||
func->SetFunctionPrototype(thread, value.GetTaggedValue());
|
||||
if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(func.GetTaggedType(),
|
||||
JSTaggedType(value->GetTaggedObject()->GetClass()), pgo::ProfileType::Kind::PrototypeId);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -716,7 +728,7 @@ JSHandle<JSHClass> JSFunction::GetOrCreateDerivedJSHClass(JSThread *thread, JSHa
|
||||
derived->SetProtoOrHClass(thread, newJSHClass);
|
||||
|
||||
if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileDefineIClass(derived.GetTaggedType(),
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(derived.GetTaggedType(),
|
||||
newJSHClass.GetTaggedType());
|
||||
}
|
||||
|
||||
|
@ -223,8 +223,9 @@ public:
|
||||
bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
|
||||
bool hasEntryIndex = false;
|
||||
uint32_t entryIndex = 0;
|
||||
if (isLoadedAOT && val.IsInt()) {
|
||||
entryIndex = static_cast<uint32_t>(val.GetInt());
|
||||
if (isLoadedAOT && val.IsAOTLiteralInfo()) {
|
||||
JSHandle<AOTLiteralInfo> entryIndexes(thread, val);
|
||||
entryIndex = static_cast<uint32_t>(entryIndexes->GetObjectFromCache(0).GetInt()); // 0: only one method
|
||||
hasEntryIndex = true;
|
||||
val = JSTaggedValue::Hole();
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ void PGOProfiler::ProfileDefineClass(JSTaggedType ctor)
|
||||
}
|
||||
}
|
||||
|
||||
void PGOProfiler::ProfileDefineIClass(JSTaggedType ctor, JSTaggedType ihcValue)
|
||||
void PGOProfiler::ProfileClassRootHClass(JSTaggedType ctor, JSTaggedType rootHcValue, ProfileType::Kind kind)
|
||||
{
|
||||
if (!isEnable_) {
|
||||
return;
|
||||
@ -114,11 +114,11 @@ void PGOProfiler::ProfileDefineIClass(JSTaggedType ctor, JSTaggedType ihcValue)
|
||||
auto ctorMethod = Method::Cast(ctorMethodValue);
|
||||
auto entityId = ctorMethod->GetMethodId().GetOffset();
|
||||
|
||||
auto ihc = JSHClass::Cast(JSTaggedValue(ihcValue).GetTaggedObject());
|
||||
ihc->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
|
||||
if (GetProfileType(ihcValue, ihcValue).IsNone()) {
|
||||
ProfileType ihcProfileType(GetMethodAbcId(ctorFunc), entityId, ProfileType::Kind::ClassId, true);
|
||||
InsertProfileType(ihcValue, ihcValue, ihcProfileType);
|
||||
auto rootHc = JSHClass::Cast(JSTaggedValue(rootHcValue).GetTaggedObject());
|
||||
rootHc->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
|
||||
if (GetProfileType(rootHcValue, rootHcValue).IsNone()) {
|
||||
ProfileType ihcProfileType(GetMethodAbcId(ctorFunc), entityId, kind, true);
|
||||
InsertProfileType(rootHcValue, rootHcValue, ihcProfileType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,6 +605,16 @@ void PGOProfiler::ProfileBytecode(ApEntityId abcId, const CString &recordName, J
|
||||
DumpDefineClass(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo);
|
||||
break;
|
||||
}
|
||||
case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: {
|
||||
uint8_t slotId = READ_INST_8_0();
|
||||
DumpDefineClass(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo);
|
||||
break;
|
||||
}
|
||||
case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: {
|
||||
uint16_t slotId = READ_INST_16_0();
|
||||
DumpDefineClass(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo);
|
||||
break;
|
||||
}
|
||||
case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
|
||||
case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
|
||||
case EcmaOpcode::CREATEEMPTYARRAY_IMM8: {
|
||||
@ -971,12 +981,14 @@ void PGOProfiler::DumpDefineClass(ApEntityId abcId, const CString &recordName, E
|
||||
objDefType.SetCtorPt(ctorType);
|
||||
recordInfos_->AddRootLayout(ctorRootHClass, ctorType);
|
||||
|
||||
auto prototypeObj = JSObject::Cast(protoOrHClass);
|
||||
auto prototypeHClass = prototypeObj->GetClass();
|
||||
auto prototypeRootHClass = JSTaggedType(JSHClass::FindRootHClass(prototypeHClass));
|
||||
auto prototypeType = GetProfileType(prototypeRootHClass, prototypeRootHClass);
|
||||
objDefType.SetProtoTypePt(prototypeType);
|
||||
recordInfos_->AddRootLayout(prototypeRootHClass, prototypeType);
|
||||
if (protoOrHClass.IsJSObject()) {
|
||||
auto prototypeObj = JSObject::Cast(protoOrHClass);
|
||||
auto prototypeHClass = prototypeObj->GetClass();
|
||||
auto prototypeRootHClass = JSTaggedType(JSHClass::FindRootHClass(prototypeHClass));
|
||||
auto prototypeType = GetProfileType(prototypeRootHClass, prototypeRootHClass);
|
||||
objDefType.SetProtoTypePt(prototypeType);
|
||||
recordInfos_->AddRootLayout(prototypeRootHClass, prototypeType);
|
||||
}
|
||||
|
||||
recordInfos_->AddDefine(recordType, methodId, bcOffset, objDefType);
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ public:
|
||||
void ProfileDefineClass(JSTaggedType ctor);
|
||||
void ProfileDefineGetterSetter(
|
||||
JSHClass *receverHClass, JSHClass *holderHClass, const JSHandle<JSTaggedValue> &func, int32_t pcOffset);
|
||||
void ProfileDefineIClass(JSTaggedType ctor, JSTaggedType ihcValue);
|
||||
void ProfileClassRootHClass(JSTaggedType ctor, JSTaggedType rootHcValue,
|
||||
ProfileType::Kind kind = ProfileType::Kind::ClassId);
|
||||
void UpdateProfileType(JSHClass *oldHClass, JSHClass *newHClass);
|
||||
|
||||
void SetSaveTimestamp(std::chrono::system_clock::time_point timestamp)
|
||||
|
@ -1877,10 +1877,36 @@ JSTaggedValue RuntimeStubs::RuntimeNewObjRange(JSThread *thread, const JSHandle<
|
||||
return tagged;
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeDefinefunc(JSThread *thread, const JSHandle<Method> &methodHandle)
|
||||
JSTaggedValue RuntimeStubs::RuntimeDefinefunc(JSThread *thread, const JSHandle<JSTaggedValue> &constpool,
|
||||
uint16_t methodId, const JSHandle<JSTaggedValue> &module)
|
||||
{
|
||||
JSHandle<ConstantPool> constpoolHandle = JSHandle<ConstantPool>::Cast(constpool);
|
||||
JSMutableHandle<JSTaggedValue> ihc(thread, JSTaggedValue::Undefined());
|
||||
JSTaggedValue val = constpoolHandle->GetObjectFromCache(methodId);
|
||||
if (val.IsAOTLiteralInfo()) {
|
||||
JSHandle<AOTLiteralInfo> aotLiteralInfo(thread, val);
|
||||
ihc.Update(aotLiteralInfo->GetIhc());
|
||||
}
|
||||
JSTaggedValue method = ConstantPool::GetMethodFromCache(thread, constpool.GetTaggedValue(),
|
||||
module.GetTaggedValue(), methodId);
|
||||
const JSHandle<Method> methodHandle(thread, method);
|
||||
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
return factory->NewJSFunction(methodHandle).GetTaggedValue();
|
||||
JSHandle<JSFunction> result = factory->NewJSFunction(methodHandle);
|
||||
if (!ihc->IsUndefined()) {
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHandle<JSTaggedValue> parentPrototype = env->GetObjectFunctionPrototype();
|
||||
result->SetProtoOrHClass(thread, ihc);
|
||||
JSHandle<JSObject> clsPrototype(thread, result->GetFunctionPrototype());
|
||||
clsPrototype->GetClass()->SetPrototype(thread, parentPrototype);
|
||||
JSHClass::EnableProtoChangeMarker(thread,
|
||||
JSHandle<JSHClass>(thread, result->GetFunctionPrototype().GetTaggedObject()->GetClass()));
|
||||
}
|
||||
|
||||
if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileDefineClass(result.GetTaggedValue().GetRawData());
|
||||
}
|
||||
return result.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeCreateRegExpWithLiteral(JSThread *thread,
|
||||
@ -2080,7 +2106,7 @@ JSTaggedValue RuntimeStubs::RuntimeDefineGetterSetterByValue(JSThread *thread, c
|
||||
method->SetFunctionKind(FunctionKind::SETTER_FUNCTION);
|
||||
desc.SetSetter(setter);
|
||||
}
|
||||
|
||||
|
||||
JSObject::DefineOwnProperty(thread, obj, propKey, desc);
|
||||
auto holderTraHClass = obj->GetJSHClass();
|
||||
if (receiverHClass != holderTraHClass) {
|
||||
@ -2670,11 +2696,32 @@ JSTaggedValue RuntimeStubs::RuntimeNotifyConcurrentResult(JSThread *thread, JSTa
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
bool RuntimeStubs::IsNeedNotifyHclassChangedForAotTransition(JSThread *thread, const JSHandle<JSHClass> &hclass,
|
||||
JSTaggedValue key)
|
||||
{
|
||||
JSMutableHandle<JSObject> protoHandle(thread, hclass->GetPrototype());
|
||||
while (true) {
|
||||
if (!protoHandle.GetTaggedValue().IsHeapObject()) {
|
||||
break;
|
||||
}
|
||||
JSHClass *protoHclass = protoHandle->GetJSHClass();
|
||||
if (JSHClass::FindPropertyEntry(thread, protoHclass, key) != -1) {
|
||||
return true;
|
||||
}
|
||||
protoHandle.Update(protoHclass->GetPrototype());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeUpdateHClass(JSThread *thread,
|
||||
const JSHandle<JSHClass> &oldhclass, const JSHandle<JSHClass> &newhclass, JSTaggedValue key)
|
||||
{
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
JSHClass::NotifyHclassChanged(thread, oldhclass, newhclass, key);
|
||||
if (IsNeedNotifyHclassChangedForAotTransition(thread, oldhclass, key)) {
|
||||
JSHClass::NotifyHclassChanged(thread, oldhclass, newhclass, key);
|
||||
}
|
||||
JSHClass::EnablePHCProtoChangeMarker(thread, newhclass);
|
||||
JSHClass::RefreshUsers(thread, oldhclass, newhclass);
|
||||
#endif
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
@ -1890,8 +1890,10 @@ DEF_RUNTIME_STUBS(NewObjRange)
|
||||
DEF_RUNTIME_STUBS(DefineFunc)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(DefineFunc);
|
||||
JSHandle<Method> method = GetHArg<Method>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
return RuntimeDefinefunc(thread, method).GetRawData();
|
||||
JSHandle<JSTaggedValue> constpool = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
JSTaggedValue methodId = GetArg(argv, argc, 1); // 1: means the first parameter
|
||||
JSHandle<JSTaggedValue> module = GetHArg<JSTaggedValue>(argv, argc, 2); // 2: means the second parameter
|
||||
return RuntimeDefinefunc(thread, constpool, static_cast<uint16_t>(methodId.GetInt()), module).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(CreateRegExpWithLiteral)
|
||||
|
@ -646,7 +646,8 @@ private:
|
||||
static inline JSTaggedValue RuntimeNewObjRange(JSThread *thread, const JSHandle<JSTaggedValue> &func,
|
||||
const JSHandle<JSTaggedValue> &newTarget, uint16_t firstArgIdx,
|
||||
uint16_t length);
|
||||
static inline JSTaggedValue RuntimeDefinefunc(JSThread *thread, const JSHandle<Method> &methodHandle);
|
||||
static inline JSTaggedValue RuntimeDefinefunc(JSThread *thread, const JSHandle<JSTaggedValue> &constpool,
|
||||
uint16_t methodId, const JSHandle<JSTaggedValue> &module);
|
||||
static inline JSTaggedValue RuntimeCreateRegExpWithLiteral(JSThread *thread, const JSHandle<JSTaggedValue> &pattern,
|
||||
uint8_t flags);
|
||||
static inline JSTaggedValue RuntimeThrowIfSuperNotCorrectCall(JSThread *thread, uint16_t index,
|
||||
@ -724,6 +725,8 @@ private:
|
||||
const JSHandle<JSTaggedValue> &value);
|
||||
static inline JSTaggedValue RuntimeNotifyConcurrentResult(JSThread *thread, JSTaggedValue result,
|
||||
JSTaggedValue hint);
|
||||
static inline bool IsNeedNotifyHclassChangedForAotTransition(JSThread *thread, const JSHandle<JSHClass> &hclass,
|
||||
JSTaggedValue key);
|
||||
static inline JSTaggedValue RuntimeUpdateHClass(JSThread *thread, const JSHandle<JSHClass> &oldhclass,
|
||||
const JSHandle<JSHClass> &newhclass, JSTaggedValue key);
|
||||
static inline JSTaggedValue RuntimeNotifyDebuggerStatement(JSThread *thread);
|
||||
|
@ -187,6 +187,8 @@ group("ark_aot_ts_test") {
|
||||
"pgo_forof_set",
|
||||
"pgo_forof_string",
|
||||
"pgo_forof_typed_array",
|
||||
"pgo_function_operation",
|
||||
"pgo_function_prototype",
|
||||
"pgo_objectliteral_operation",
|
||||
"pgo_call_deopt",
|
||||
"poplexenv",
|
||||
|
@ -13,3 +13,4 @@
|
||||
|
||||
5
|
||||
5
|
||||
foo
|
||||
|
@ -94,3 +94,9 @@ function getPrototypeOf(a)
|
||||
|
||||
getPrototypeOf(A);
|
||||
getPrototypeOf(B);
|
||||
|
||||
A.prototype.foo = function() {
|
||||
print("foo");
|
||||
}
|
||||
|
||||
a.foo();
|
||||
|
@ -13,3 +13,4 @@
|
||||
|
||||
5
|
||||
5
|
||||
foo
|
||||
|
20
test/aottest/pgo_function_operation/BUILD.gn
Normal file
20
test/aottest/pgo_function_operation/BUILD.gn
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_aot_test_action("pgo_function_operation") {
|
||||
deps = []
|
||||
is_only_typed_path = true
|
||||
is_enable_pgo = true
|
||||
}
|
21
test/aottest/pgo_function_operation/expect_output.txt
Normal file
21
test/aottest/pgo_function_operation/expect_output.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
1
|
||||
2
|
||||
foo
|
||||
bar
|
||||
undefined
|
||||
bar
|
||||
1
|
||||
1
|
21
test/aottest/pgo_function_operation/pgo_expect_output.txt
Normal file
21
test/aottest/pgo_function_operation/pgo_expect_output.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
1
|
||||
2
|
||||
foo
|
||||
bar
|
||||
undefined
|
||||
bar
|
||||
1
|
||||
1
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
declare function print(arg:any):string;
|
||||
|
||||
function A() {
|
||||
this.x = 1;
|
||||
}
|
||||
|
||||
A.prototype.foo = function() {
|
||||
print("foo");
|
||||
}
|
||||
|
||||
A.prototype.bar = function() {
|
||||
print("bar");
|
||||
}
|
||||
|
||||
let a = new A();
|
||||
print(a.x);
|
||||
a.x =2;
|
||||
print(a.x);
|
||||
a.foo();
|
||||
a.bar();
|
||||
|
||||
|
||||
function B() {
|
||||
this.x = 1;
|
||||
}
|
||||
|
||||
function foo(b) {
|
||||
print(b.bar);
|
||||
}
|
||||
|
||||
let b = new B();
|
||||
foo(b);
|
||||
|
||||
B.prototype.bar = "bar";
|
||||
foo(b);
|
||||
|
||||
|
||||
|
||||
for(let i = 0; i<2; ++i) {
|
||||
function C() {
|
||||
this.x = 1;
|
||||
}
|
||||
let c = new C();
|
||||
print(c.x);
|
||||
}
|
||||
|
20
test/aottest/pgo_function_prototype/BUILD.gn
Normal file
20
test/aottest/pgo_function_prototype/BUILD.gn
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_aot_test_action("pgo_function_prototype") {
|
||||
deps = []
|
||||
is_only_typed_path = true
|
||||
is_enable_pgo = true
|
||||
}
|
14
test/aottest/pgo_function_prototype/expect_output.txt
Normal file
14
test/aottest/pgo_function_prototype/expect_output.txt
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
1
|
14
test/aottest/pgo_function_prototype/pgo_expect_output.txt
Normal file
14
test/aottest/pgo_function_prototype/pgo_expect_output.txt
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
1
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
declare function print(arg:any):string;
|
||||
|
||||
function B() {
|
||||
this.x = 1;
|
||||
}
|
||||
|
||||
B.prototype = {}
|
||||
|
||||
let b = new B();
|
||||
print(b.x);
|
Loading…
Reference in New Issue
Block a user