mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-30 13:40:51 +00:00
Feat(Aot): Part4 Load hclass info from ap for aot compiler
Issue: #I7EGRC Change-Id: I2493cc4f22b5579f28a93433845481febf17effc Signed-off-by: yingguofeng@huawei.com <yingguofeng@huawei.com>
This commit is contained in:
parent
a54b399699
commit
fb20da0b8f
@ -459,6 +459,8 @@ namespace panda::ecmascript::kungfu {
|
||||
APPEND_SUFFIX(HandleDefineclasswithbufferImm8Id16Id16Imm16V8, V) \
|
||||
APPEND_SUFFIX(HandleDefineclasswithbufferImm16Id16Id16Imm16V8, V) \
|
||||
APPEND_SUFFIX(HandleDefinegettersetterbyvalueV8V8V8V8, V) \
|
||||
APPEND_SUFFIX(HandleCreateobjectwithbufferImm8Id16, V) \
|
||||
APPEND_SUFFIX(HandleCreateobjectwithbufferImm16Id16, V) \
|
||||
APPEND_SUFFIX(HandleLdobjbynameImm8Id16, V) \
|
||||
APPEND_SUFFIX(HandleLdobjbynameImm16Id16, V) \
|
||||
APPEND_SUFFIX(HandleLdthisbynameImm16Id16, V) \
|
||||
|
@ -1444,6 +1444,26 @@ DEF_CALL_SIGNATURE(ProfileDefineClass)
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(ProfileCreateObject)
|
||||
{
|
||||
// 4: 4 input parameters
|
||||
CallSignature defineProfInstruction(
|
||||
"ProfileCreateObject", 0, 5, ArgumentsOrder::DEFAULT_ORDER, VariableType::VOID());
|
||||
*callSign = defineProfInstruction;
|
||||
// 4: 4 input parameters
|
||||
std::array<VariableType, 5> params = { // 4 : 4 input parameters
|
||||
VariableType::NATIVE_POINTER(),
|
||||
VariableType::JS_ANY(),
|
||||
VariableType::INT32(),
|
||||
VariableType::JS_ANY(),
|
||||
VariableType::JS_ANY(),
|
||||
};
|
||||
callSign->SetVariadicArgs(true);
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(true);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(ProfileOpType)
|
||||
{
|
||||
// 4: 4 input parameters
|
||||
|
@ -417,6 +417,7 @@ private:
|
||||
V(Comment) \
|
||||
V(ProfileCall) \
|
||||
V(ProfileDefineClass) \
|
||||
V(ProfileCreateObject) \
|
||||
V(ProfileOpType) \
|
||||
V(ProfileObjLayout) \
|
||||
V(FatalPrint) \
|
||||
|
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <initializer_list>
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/compiler/access_object_stub_builder.h"
|
||||
#include "ecmascript/compiler/bc_call_signature.h"
|
||||
@ -59,11 +60,12 @@ void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc
|
||||
GateRef acc, GateRef hotnessCounter, \
|
||||
[[maybe_unused]] ProfileOperation callback)
|
||||
|
||||
#define REGISTER_PROFILE_CALL_BACK() \
|
||||
ProfileOperation callback([this, glue, sp, pc, profileTypeInfo](GateRef value, OperationType type) { \
|
||||
ProfilerStubBuilder profiler(this); \
|
||||
profiler.PGOProfiler(glue, pc, GetFunctionFromFrame(GetFrame(sp)), profileTypeInfo, value, type); \
|
||||
});
|
||||
#define REGISTER_PROFILE_CALL_BACK() \
|
||||
ProfileOperation callback( \
|
||||
[this, glue, sp, pc, profileTypeInfo](const std::initializer_list<GateRef> &values, OperationType type) { \
|
||||
ProfilerStubBuilder profiler(this); \
|
||||
profiler.PGOProfiler(glue, pc, GetFunctionFromFrame(GetFrame(sp)), profileTypeInfo, values, type); \
|
||||
});
|
||||
|
||||
#define REGISTER_NULL_CALL_BACK() ProfileOperation callback;
|
||||
|
||||
@ -3851,6 +3853,7 @@ DECLARE_ASM_HANDLER(HandleCreateobjectwithbufferImm8Id16)
|
||||
GateRef result = GetObjectLiteralFromConstPool(glue, constpool, imm, module);
|
||||
GateRef currentEnv = GetEnvFromFrame(GetFrame(sp));
|
||||
GateRef res = CallRuntime(glue, RTSTUB_ID(CreateObjectHavingMethod), { result, currentEnv });
|
||||
callback.ProfileCreateObject(result, res);
|
||||
CHECK_EXCEPTION_WITH_ACC(res, INT_PTR(CREATEOBJECTWITHBUFFER_IMM8_ID16));
|
||||
}
|
||||
|
||||
@ -3862,6 +3865,7 @@ DECLARE_ASM_HANDLER(HandleCreateobjectwithbufferImm16Id16)
|
||||
GateRef result = GetObjectLiteralFromConstPool(glue, constpool, imm, module);
|
||||
GateRef currentEnv = GetEnvFromFrame(GetFrame(sp));
|
||||
GateRef res = CallRuntime(glue, RTSTUB_ID(CreateObjectHavingMethod), { result, currentEnv });
|
||||
callback.ProfileCreateObject(result, res);
|
||||
CHECK_EXCEPTION_WITH_ACC(res, INT_PTR(CREATEOBJECTWITHBUFFER_IMM16_ID16));
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define ECMASCRIPT_COMPILER_PROFILER_OPERATION_H
|
||||
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "ecmascript/compiler/gate_meta_data.h"
|
||||
|
||||
@ -25,6 +26,7 @@ enum class OperationType : uint8_t {
|
||||
CALL,
|
||||
OPERATION_TYPE,
|
||||
DEFINE_CLASS,
|
||||
CREATE_OBJECT,
|
||||
STORE_LAYOUT,
|
||||
LOAD_LAYOUT,
|
||||
};
|
||||
@ -33,7 +35,7 @@ enum class OperationType : uint8_t {
|
||||
callback.ProfileCombineOpType( \
|
||||
*curType, type, [this](GateRef curType, GateRef type) -> GateRef { return Int32Or(curType, type); });
|
||||
|
||||
using Callback = std::function<void(GateRef, OperationType)>;
|
||||
using Callback = std::function<void(const std::initializer_list<GateRef> &, OperationType)>;
|
||||
class ProfileOperation {
|
||||
public:
|
||||
ProfileOperation() : callback_(nullptr) {}
|
||||
@ -47,14 +49,14 @@ public:
|
||||
inline void ProfileCall(GateRef func) const
|
||||
{
|
||||
if (callback_) {
|
||||
callback_(func, OperationType::CALL);
|
||||
callback_({ func }, OperationType::CALL);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ProfileOpType(GateRef type) const
|
||||
{
|
||||
if (callback_) {
|
||||
callback_(type, OperationType::OPERATION_TYPE);
|
||||
callback_({ type }, OperationType::OPERATION_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,28 +65,35 @@ public:
|
||||
{
|
||||
if (callback_) {
|
||||
GateRef ret = combine(curType, type);
|
||||
callback_(ret, OperationType::OPERATION_TYPE);
|
||||
callback_({ ret }, OperationType::OPERATION_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ProfileDefineClass(GateRef constructor) const
|
||||
{
|
||||
if (callback_) {
|
||||
callback_(constructor, OperationType::DEFINE_CLASS);
|
||||
callback_({ constructor }, OperationType::DEFINE_CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ProfileCreateObject(GateRef originObj, GateRef newObj) const
|
||||
{
|
||||
if (callback_) {
|
||||
callback_({ originObj, newObj }, OperationType::CREATE_OBJECT);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ProfileObjLayoutByStore(GateRef object) const
|
||||
{
|
||||
if (callback_) {
|
||||
callback_(object, OperationType::STORE_LAYOUT);
|
||||
callback_({ object }, OperationType::STORE_LAYOUT);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ProfileObjLayoutByLoad(GateRef object) const
|
||||
{
|
||||
if (callback_) {
|
||||
callback_(object, OperationType::LOAD_LAYOUT);
|
||||
callback_({ object }, OperationType::LOAD_LAYOUT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,24 +19,27 @@
|
||||
#include "ecmascript/compiler/stub_builder-inl.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void ProfilerStubBuilder::PGOProfiler(
|
||||
GateRef glue, GateRef pc, GateRef func, GateRef profileTypeInfo, GateRef value, OperationType type)
|
||||
void ProfilerStubBuilder::PGOProfiler(GateRef glue, GateRef pc, GateRef func, GateRef profileTypeInfo,
|
||||
const std::vector<GateRef> &values, OperationType type)
|
||||
{
|
||||
switch (type) {
|
||||
case OperationType::CALL:
|
||||
ProfileCall(glue, value);
|
||||
ProfileCall(glue, values[0]);
|
||||
break;
|
||||
case OperationType::OPERATION_TYPE:
|
||||
ProfileOpType(glue, pc, func, profileTypeInfo, value);
|
||||
ProfileOpType(glue, pc, func, profileTypeInfo, values[0]);
|
||||
break;
|
||||
case OperationType::DEFINE_CLASS:
|
||||
ProfileDefineClass(glue, pc, func, value);
|
||||
ProfileDefineClass(glue, pc, func, values[0]);
|
||||
break;
|
||||
case OperationType::CREATE_OBJECT:
|
||||
ProfileCreateObject(glue, pc, func, values[0], values[1]);
|
||||
break;
|
||||
case OperationType::STORE_LAYOUT:
|
||||
ProfileObjLayout(glue, pc, func, value, Int32(1));
|
||||
ProfileObjLayout(glue, pc, func, values[0], Int32(1));
|
||||
break;
|
||||
case OperationType::LOAD_LAYOUT:
|
||||
ProfileObjLayout(glue, pc, func, value, Int32(0));
|
||||
ProfileObjLayout(glue, pc, func, values[0], Int32(0));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -107,6 +110,21 @@ void ProfilerStubBuilder::ProfileDefineClass(GateRef glue, GateRef pc, GateRef f
|
||||
env->SubCfgExit();
|
||||
}
|
||||
|
||||
void ProfilerStubBuilder::ProfileCreateObject(GateRef glue, GateRef pc, GateRef func, GateRef originObj, GateRef newObj)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label subEntry(env);
|
||||
env->SubCfgEntry(&subEntry);
|
||||
|
||||
GateRef method = Load(VariableType::JS_ANY(), func, IntPtr(JSFunctionBase::METHOD_OFFSET));
|
||||
GateRef firstPC =
|
||||
Load(VariableType::NATIVE_POINTER(), method, IntPtr(Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
|
||||
GateRef offset = TruncPtrToInt32(PtrSub(pc, firstPC));
|
||||
CallNGCRuntime(glue, RTSTUB_ID(ProfileCreateObject), { glue, func, offset, originObj, newObj });
|
||||
|
||||
env->SubCfgExit();
|
||||
}
|
||||
|
||||
void ProfilerStubBuilder::ProfileObjLayout(GateRef glue, GateRef pc, GateRef func, GateRef object, GateRef store)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
@ -29,11 +29,12 @@ public:
|
||||
NO_COPY_SEMANTIC(ProfilerStubBuilder);
|
||||
void GenerateCircuit() override {}
|
||||
|
||||
void PGOProfiler(
|
||||
GateRef glue, GateRef pc, GateRef func, GateRef profileTypeInfo, GateRef value, OperationType type);
|
||||
void PGOProfiler(GateRef glue, GateRef pc, GateRef func, GateRef profileTypeInfo,
|
||||
const std::vector<GateRef> &values, OperationType type);
|
||||
void ProfileCall(GateRef glue, GateRef func);
|
||||
void ProfileOpType(GateRef glue, GateRef pc, GateRef func, GateRef profileTypeInfo, GateRef type);
|
||||
void ProfileDefineClass(GateRef glue, GateRef pc, GateRef func, GateRef constructor);
|
||||
void ProfileCreateObject(GateRef glue, GateRef pc, GateRef func, GateRef originObj, GateRef newObj);
|
||||
void ProfileObjLayout(GateRef glue, GateRef pc, GateRef func, GateRef object, GateRef store);
|
||||
|
||||
GateRef UpdateTrackTypeInPropAttr(GateRef attr, GateRef value, ProfileOperation callback);
|
||||
|
@ -40,9 +40,16 @@ void TSHClassGenerator::GenerateTSHClasses() const
|
||||
}
|
||||
}
|
||||
|
||||
void TSHClassGenerator::UpdateTSHClassFromPGO(JSHClass *hclass, const PGOHClassLayoutDesc &desc) const
|
||||
void TSHClassGenerator::UpdateTSHClassFromPGO(const kungfu::GateType &type, const PGOHClassLayoutDesc &desc) const
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
auto hclassValue = tsManager_->GetTSHClass(type);
|
||||
if (!hclassValue.IsJSHClass()) {
|
||||
return;
|
||||
}
|
||||
|
||||
tsManager_->InsertPtToGtMap(desc.GetClassType(), type);
|
||||
auto hclass = JSHClass::Cast(hclassValue.GetTaggedObject());
|
||||
const JSThread *thread = tsManager_->GetThread();
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
|
||||
int element = layoutInfo->NumberOfElements();
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
~TSHClassGenerator() = default;
|
||||
|
||||
void GenerateTSHClasses() const;
|
||||
void UpdateTSHClassFromPGO(JSHClass *hclass, const PGOHClassLayoutDesc &desc) const;
|
||||
void UpdateTSHClassFromPGO(const kungfu::GateType &type, const PGOHClassLayoutDesc &desc) const;
|
||||
|
||||
private:
|
||||
void RecursiveGenerate(const JSHandle<TSClassType> &classType) const;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "ecmascript/jspandafile/type_literal_extractor.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_layout.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_type.h"
|
||||
#include "ecmascript/ts_types/ts_type_parser.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
@ -166,26 +167,23 @@ PGOSampleType TypeRecorder::GetOrUpdatePGOType(TSManager *tsManager, int32_t off
|
||||
if (!decoder_->GetHClassLayoutDesc(iter, &desc)) {
|
||||
return PGOSampleType::NoneClassType();
|
||||
}
|
||||
auto hclassValue = tsManager->GetTSHClass(type);
|
||||
if (hclassValue.IsJSHClass()) {
|
||||
auto hclass = JSHClass::Cast(hclassValue.GetTaggedObject());
|
||||
TSHClassGenerator generator(tsManager);
|
||||
generator.UpdateTSHClassFromPGO(hclass, *desc);
|
||||
}
|
||||
TSHClassGenerator generator(tsManager);
|
||||
generator.UpdateTSHClassFromPGO(type, *desc);
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
if (bcOffsetPGORwTypeMap_.find(offset) != bcOffsetPGORwTypeMap_.end()) {
|
||||
auto defineType = bcOffsetPGORwTypeMap_.at(offset);
|
||||
// pass mono first
|
||||
if (defineType.GetCount() == 1) {
|
||||
return PGOSampleType(defineType.GetType(0));
|
||||
}
|
||||
}
|
||||
return PGOSampleType::NoneType();
|
||||
}
|
||||
|
||||
PGORWOpType TypeRecorder::GetRwOpType(int32_t offset) const
|
||||
{
|
||||
if (bcOffsetPGORwTypeMap_.find(offset) != bcOffsetPGORwTypeMap_.end()) {
|
||||
return bcOffsetPGORwTypeMap_.at(offset);
|
||||
}
|
||||
return PGORWOpType();
|
||||
}
|
||||
|
||||
bool TypeRecorder::TypeNeedFilter(GlobalTSTypeRef gt) const
|
||||
{
|
||||
return gt.IsDefault() || gt.IsGenericsModule();
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
|
||||
GateType GetType(const int32_t offset) const;
|
||||
PGOSampleType GetOrUpdatePGOType(TSManager *tsManager, int32_t offset, const GateType &type) const;
|
||||
PGORWOpType GetRwOpType(int32_t offset) const;
|
||||
GateType GetArgType(const uint32_t argIndex) const;
|
||||
GateType UpdateType(const int32_t offset, const GateType &type) const;
|
||||
|
||||
|
@ -695,7 +695,7 @@ void JSHClass::CopyTSInheritInfo(const JSThread *thread, const JSHandle<JSHClass
|
||||
newHClass->SetVTable(thread, copyVtable);
|
||||
}
|
||||
|
||||
bool JSHClass::DumpForProfile(const JSHClass *hclass, PGOHClassLayoutDesc &desc, PGOObjLayoutKind kind)
|
||||
bool JSHClass::DumpForProfile(const JSHClass *hclass, PGOHClassLayoutDesc &desc, PGOObjKind kind)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
if (hclass->IsDictionaryMode()) {
|
||||
|
@ -1670,7 +1670,7 @@ public:
|
||||
DECL_DUMP()
|
||||
|
||||
static CString DumpJSType(JSType type);
|
||||
static bool DumpForProfile(const JSHClass *hclass, PGOHClassLayoutDesc &desc, PGOObjLayoutKind kind);
|
||||
static bool DumpForProfile(const JSHClass *hclass, PGOHClassLayoutDesc &desc, PGOObjKind kind);
|
||||
|
||||
DECL_VISIT_OBJECT(PROTOTYPE_OFFSET, BIT_FIELD_OFFSET);
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "ecmascript/jspandafile/literal_data_extractor.h"
|
||||
#include "ecmascript/module/js_module_manager.h"
|
||||
#include "ecmascript/patch/quick_fix_manager.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler.h"
|
||||
|
||||
#include "libpandafile/class_data_accessor-inl.h"
|
||||
#include "libpandafile/index_accessor.h"
|
||||
@ -286,6 +287,9 @@ public:
|
||||
valueHandle.Update(elements->Get(i + 1));
|
||||
JSObject::DefinePropertyByLiteral(thread, obj, key, valueHandle);
|
||||
}
|
||||
|
||||
PGOProfiler *profiler = thread->GetEcmaVM()->GetPGOProfiler();
|
||||
profiler->InsertLiteralId(JSTaggedType(obj->GetJSHClass()), id);
|
||||
val = obj.GetTaggedValue();
|
||||
break;
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ bool LayoutInfo::IsUninitializedProperty(const JSHandle<JSObject> object, uint32
|
||||
return val.IsHole();
|
||||
}
|
||||
|
||||
void LayoutInfo::DumpFieldIndexForProfile(int index, PGOHClassLayoutDesc &desc, PGOObjLayoutKind kind)
|
||||
void LayoutInfo::DumpFieldIndexForProfile(int index, PGOHClassLayoutDesc &desc, PGOObjKind kind)
|
||||
{
|
||||
auto key = GetKey(index);
|
||||
if (key.IsString()) {
|
||||
|
@ -86,7 +86,7 @@ public:
|
||||
void GetAllEnumKeys(const JSThread *thread, int end, int offset, TaggedArray *keyArray, uint32_t *keys,
|
||||
const JSHandle<JSObject> object);
|
||||
|
||||
void DumpFieldIndexForProfile(int index, PGOHClassLayoutDesc &desc, PGOObjLayoutKind kind);
|
||||
void DumpFieldIndexForProfile(int index, PGOHClassLayoutDesc &desc, PGOObjKind kind);
|
||||
DECL_DUMP()
|
||||
|
||||
private:
|
||||
|
@ -122,10 +122,53 @@ void PGOProfiler::ProfileDefineClass(JSThread *thread, JSTaggedType func, int32_
|
||||
}
|
||||
auto prototypeObj = JSObject::Cast(prototype);
|
||||
auto prototypeHClass = JSTaggedType(prototypeObj->GetClass());
|
||||
recordInfos_->AddLayout(currentType, prototypeHClass, PGOObjLayoutKind::PROTOTYPE);
|
||||
recordInfos_->AddLayout(currentType, prototypeHClass, PGOObjKind::PROTOTYPE);
|
||||
|
||||
auto ctorHClass = JSTaggedType(ctorFunction->GetJSHClass());
|
||||
recordInfos_->AddLayout(currentType, ctorHClass, PGOObjLayoutKind::CONSTRUCTOR);
|
||||
recordInfos_->AddLayout(currentType, ctorHClass, PGOObjKind::CONSTRUCTOR);
|
||||
}
|
||||
}
|
||||
|
||||
void PGOProfiler::ProfileCreateObject(JSTaggedType func, int32_t offset, JSTaggedType originObj, JSTaggedType newObj)
|
||||
{
|
||||
if (!isEnable_) {
|
||||
return;
|
||||
}
|
||||
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
JSTaggedValue funcValue(func);
|
||||
if (funcValue.IsJSFunction()) {
|
||||
JSFunction *funcFunction = JSFunction::Cast(funcValue);
|
||||
JSTaggedValue recordNameValue = funcFunction->GetRecordName();
|
||||
if (recordNameValue.IsHole()) {
|
||||
return;
|
||||
}
|
||||
CString recordName = ConvertToString(recordNameValue);
|
||||
|
||||
auto method = funcFunction->GetMethod();
|
||||
if (!method.IsMethod()) {
|
||||
return;
|
||||
}
|
||||
auto jsMethod = Method::Cast(method);
|
||||
auto funcMethodId = jsMethod->GetMethodId();
|
||||
|
||||
auto originObjValue = JSTaggedValue(originObj);
|
||||
auto newObjValue = JSTaggedValue(newObj);
|
||||
if (!originObjValue.IsJSObject() || !newObjValue.IsJSObject()) {
|
||||
return;
|
||||
}
|
||||
auto originHclass = JSObject::Cast(originObjValue)->GetJSHClass();
|
||||
auto iter = literalIds_.find(JSTaggedType(originHclass));
|
||||
if (iter == literalIds_.end()) {
|
||||
return;
|
||||
}
|
||||
auto newHClass = JSObject::Cast(newObjValue) ->GetJSHClass();
|
||||
InsertLiteralId(JSTaggedType(newHClass), iter->second);
|
||||
|
||||
auto currentType = PGOSampleType::CreateClassType(iter->second.GetOffset());
|
||||
auto superType = PGOSampleType::CreateClassType(0);
|
||||
recordInfos_->AddDefine(recordName, funcMethodId, offset, currentType, superType);
|
||||
recordInfos_->AddLayout(currentType, JSTaggedType(newHClass), PGOObjKind::LOCAL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,13 +196,20 @@ void PGOProfiler::ProfileObjLayout(JSThread *thread, JSTaggedType func, int32_t
|
||||
auto holder = JSTaggedValue(object);
|
||||
auto hclass = holder.GetTaggedObject()->GetClass();
|
||||
auto ctor = JSTaggedValue::Undefined();
|
||||
PGOObjLayoutKind kind = PGOObjLayoutKind::LOCAL;
|
||||
PGOObjKind kind = PGOObjKind::LOCAL;
|
||||
if (hclass->IsClassPrototype()) {
|
||||
ctor = JSObject::GetCtorFromPrototype(thread, holder);
|
||||
kind = PGOObjLayoutKind::PROTOTYPE;
|
||||
kind = PGOObjKind::PROTOTYPE;
|
||||
} else if (hclass->IsClassConstructor()) {
|
||||
ctor = holder;
|
||||
kind = PGOObjLayoutKind::CONSTRUCTOR;
|
||||
kind = PGOObjKind::CONSTRUCTOR;
|
||||
} else if (hclass->IsLiteral()) {
|
||||
auto iter = literalIds_.find(JSTaggedType(hclass));
|
||||
if (iter != literalIds_.end()) {
|
||||
PGOObjectInfo info(ClassType(iter->second.GetOffset()), kind);
|
||||
recordInfos_->AddObjectInfo(recordName, jsMethod->GetMethodId(), offset, info);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
auto prototype = hclass->GetProto();
|
||||
ctor = JSObject::GetCtorFromPrototype(thread, prototype);
|
||||
@ -173,12 +223,27 @@ void PGOProfiler::ProfileObjLayout(JSThread *thread, JSTaggedType func, int32_t
|
||||
}
|
||||
auto ctorJSMethod = Method::Cast(ctorMethod);
|
||||
auto methodId = ctorJSMethod->GetMethodId();
|
||||
PGOSampleType type = PGOSampleType::CreateClassType(methodId.GetOffset());
|
||||
recordInfos_->AddType(recordName, jsMethod->GetMethodId(), offset, type);
|
||||
PGOObjectInfo info(ClassType(methodId.GetOffset()), kind);
|
||||
recordInfos_->AddObjectInfo(recordName, jsMethod->GetMethodId(), offset, info);
|
||||
if (store) {
|
||||
PGOSampleType type = PGOSampleType::CreateClassType(methodId.GetOffset());
|
||||
recordInfos_->AddLayout(type, JSTaggedType(hclass), kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PGOProfiler::InsertLiteralId(JSTaggedType hclass, EntityId literalId)
|
||||
{
|
||||
if (!isEnable_) {
|
||||
return;
|
||||
}
|
||||
auto iter = literalIds_.find(hclass);
|
||||
if (iter != literalIds_.end()) {
|
||||
if (!(iter->second == literalId)) {
|
||||
literalIds_.erase(iter);
|
||||
}
|
||||
}
|
||||
literalIds_.emplace(hclass, literalId);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -30,6 +30,7 @@ public:
|
||||
|
||||
void ProfileCall(JSTaggedType value, SampleMode mode = SampleMode::CALL_MODE);
|
||||
void ProfileOpType(JSTaggedType func, int32_t offset, uint32_t type);
|
||||
void ProfileCreateObject(JSTaggedType func, int32_t offset, JSTaggedType originObj, JSTaggedType newObj);
|
||||
void ProfileDefineClass(JSThread *thread, JSTaggedType func, int32_t offset, JSTaggedType ctor);
|
||||
void ProfileObjLayout(JSThread *thread, JSTaggedType func, int32_t offset, JSTaggedType object, bool store);
|
||||
void SetSaveTimestamp(std::chrono::system_clock::time_point timestamp)
|
||||
@ -37,6 +38,8 @@ public:
|
||||
saveTimestamp_ = timestamp;
|
||||
}
|
||||
|
||||
void InsertLiteralId(JSTaggedType hclass, EntityId literalId);
|
||||
|
||||
private:
|
||||
static constexpr uint32_t MERGED_EVERY_COUNT = 20;
|
||||
static constexpr auto MERGED_MIN_INTERVAL = std::chrono::milliseconds(15);
|
||||
@ -69,6 +72,7 @@ private:
|
||||
bool isEnable_ {false};
|
||||
uint32_t methodCount_ {0};
|
||||
std::chrono::system_clock::time_point saveTimestamp_;
|
||||
CMap<JSTaggedType, EntityId> literalIds_;
|
||||
std::unique_ptr<PGORecordDetailInfos> recordInfos_;
|
||||
friend class PGOProfilerManager;
|
||||
};
|
||||
|
@ -243,7 +243,7 @@ void PGOMethodTypeSet::SkipFromBinary(void **buffer)
|
||||
}
|
||||
}
|
||||
|
||||
bool PGOMethodTypeSet::ParseFromBinary(void **buffer)
|
||||
bool PGOMethodTypeSet::ParseFromBinary(void **buffer, PGOProfilerHeader *const header)
|
||||
{
|
||||
uint32_t size = base::ReadBuffer<uint32_t>(buffer, sizeof(uint32_t));
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
@ -252,7 +252,7 @@ bool PGOMethodTypeSet::ParseFromBinary(void **buffer)
|
||||
scalarOpTypeInfos_.emplace(*reinterpret_cast<ScalarOpTypeInfo *>(typeInfo));
|
||||
} else if (typeInfo->GetInfoType() == InfoType::DEFINE_CLASS_TYPE) {
|
||||
objDefOpTypeInfos_.emplace(*reinterpret_cast<ObjDefOpTypeInfo *>(typeInfo));
|
||||
} else if (typeInfo->GetInfoType() == InfoType::USE_HCLASS_TYPE) {
|
||||
} else if (header->SupportUseHClassType() && typeInfo->GetInfoType() == InfoType::USE_HCLASS_TYPE) {
|
||||
rwScalarOpTypeInfos_.emplace(*reinterpret_cast<RWScalarOpTypeInfo *>(typeInfo));
|
||||
}
|
||||
}
|
||||
@ -488,7 +488,7 @@ void PGOMethodTypeSet::RWScalarOpTypeInfo::ProcessToText(std::string &text) cons
|
||||
text += TYPE_SEPARATOR + SPACE;
|
||||
}
|
||||
isFirst = false;
|
||||
text += type_.GetType(i).GetTypeString();
|
||||
text += type_.GetObjectInfo(i).GetInfoString();
|
||||
}
|
||||
text += (SPACE + ARRAY_END);
|
||||
}
|
||||
@ -547,6 +547,14 @@ bool PGOMethodInfoMap::AddType(Chunk *chunk, PGOMethodId methodId, int32_t offse
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PGOMethodInfoMap::AddObjectInfo(Chunk *chunk, PGOMethodId methodId, int32_t offset, const PGOObjectInfo &info)
|
||||
{
|
||||
auto typeInfoSet = GetOrInsertMethodTypeSet(chunk, methodId);
|
||||
ASSERT(typeInfoSet != nullptr);
|
||||
typeInfoSet->AddObjectInfo(offset, info);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PGOMethodInfoMap::AddDefine(
|
||||
Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType)
|
||||
{
|
||||
@ -625,7 +633,7 @@ bool PGOMethodInfoMap::ParseFromBinary(Chunk *chunk, uint32_t threshold, void **
|
||||
}
|
||||
if (header->SupportType()) {
|
||||
auto typeInfoSet = chunk->New<PGOMethodTypeSet>();
|
||||
typeInfoSet->ParseFromBinary(buffer);
|
||||
typeInfoSet->ParseFromBinary(buffer, header);
|
||||
methodTypeInfos_.emplace(info->GetMethodId(), typeInfoSet);
|
||||
}
|
||||
}
|
||||
@ -802,7 +810,7 @@ bool PGOMethodIdSet::ParseFromBinary(uint32_t threshold, void **buffer, PGOProfi
|
||||
<< ELEMENT_SEPARATOR << std::to_string(static_cast<int>(info->GetSampleMode()))
|
||||
<< ELEMENT_SEPARATOR << info->GetMethodName();
|
||||
if (header->SupportType()) {
|
||||
methodInfo.GetPGOMethodTypeSet().ParseFromBinary(buffer);
|
||||
methodInfo.GetPGOMethodTypeSet().ParseFromBinary(buffer, header);
|
||||
}
|
||||
}
|
||||
|
||||
@ -850,6 +858,14 @@ bool PGORecordDetailInfos::AddType(const CString &recordName, PGOMethodId method
|
||||
return curMethodInfos->AddType(chunk_.get(), methodId, offset, type);
|
||||
}
|
||||
|
||||
bool PGORecordDetailInfos::AddObjectInfo(
|
||||
const CString &recordName, EntityId methodId, int32_t offset, const PGOObjectInfo &info)
|
||||
{
|
||||
auto curMethodInfos = GetMethodInfoMap(recordName);
|
||||
ASSERT(curMethodInfos != nullptr);
|
||||
return curMethodInfos->AddObjectInfo(chunk_.get(), methodId, offset, info);
|
||||
}
|
||||
|
||||
bool PGORecordDetailInfos::AddDefine(
|
||||
const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType)
|
||||
{
|
||||
@ -867,7 +883,7 @@ bool PGORecordDetailInfos::AddDefine(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PGORecordDetailInfos::AddLayout(PGOSampleType type, JSTaggedType hclass, PGOObjLayoutKind kind)
|
||||
bool PGORecordDetailInfos::AddLayout(PGOSampleType type, JSTaggedType hclass, PGOObjKind kind)
|
||||
{
|
||||
auto hclassObject = JSHClass::Cast(JSTaggedValue(hclass).GetTaggedObject());
|
||||
PGOHClassLayoutDesc descInfo(type.GetClassType());
|
||||
|
@ -52,59 +52,47 @@ static constexpr size_t ALIGN_SIZE = 4;
|
||||
using PGOMethodId = EntityId;
|
||||
|
||||
/**
|
||||
* |----PGOProfilerHeader
|
||||
* |--------MAGIC
|
||||
* |--------VERSION
|
||||
* |--------SECTION_NUMBER
|
||||
* |--------PANDA_FILE_INFO_SECTION_INFO
|
||||
* |------------offset
|
||||
* |------------size (reserve)
|
||||
* |------------number
|
||||
* |--------RECORD_INFO_SECTION_INFO
|
||||
* |------------offset
|
||||
* |------------size (reserve)
|
||||
* |------------number
|
||||
* |----PGOPandaFileInfos
|
||||
* |--------SIZE
|
||||
* |--------CHECK_SUM
|
||||
* |--------...
|
||||
* |----PGORecordDetailInfos
|
||||
* |--------PGOMethodInfoMap
|
||||
* |------------PGOMethodInfo
|
||||
* |----------------size
|
||||
* |----------------id
|
||||
* |----------------count
|
||||
* |----------------mode
|
||||
* |----------------methodName
|
||||
* |----------------methodChecksum
|
||||
* |----------------...
|
||||
* |------------PGOMethodTypeSet
|
||||
* |----------------ScalarOpTypeInfo
|
||||
* |--------------------size
|
||||
* |--------------------offset
|
||||
* |--------------------type
|
||||
* |----------------...
|
||||
* |----------------PGOHClassLayoutDescInner
|
||||
* |--------------------size
|
||||
* |--------------------offset
|
||||
* |--------------------type
|
||||
* |--------------------count
|
||||
* |--------------------PGOLayoutDescInfo
|
||||
* |------------------------size
|
||||
* |------------------------type
|
||||
* |------------------------key
|
||||
* |--------------------...
|
||||
* |----------------...
|
||||
* |----PGORecordSimpleInfos
|
||||
* |--------PGOMethodIdSet
|
||||
* |------------id
|
||||
* |------------...
|
||||
|----PGOProfilerHeader
|
||||
|--------MAGIC(8)
|
||||
|------------{ 'P', 'A', 'N', 'D', 'A', '\0', '\0', '\0' }
|
||||
|--------VERSION(4)
|
||||
|------------{ '0', '0', '0', '0' }
|
||||
|--------SECTION_NUMBER(4)
|
||||
|------------{ 3 }
|
||||
|--------PANDA_FILE_INFO_SECTION_INFO(12)
|
||||
|------------{ offset, size (reserve), number1 }
|
||||
|--------RECORD_INFO_SECTION_INFO(12)
|
||||
|------------{ offset, size (reserve), number2 }
|
||||
|--------LAYOUT_DESC_SECTION_INFO(12)
|
||||
|------------{ offset, size (reserve), number3 }
|
||||
|
|
||||
|----Section1: PGOPandaFileInfos(number1)
|
||||
|--------[{ size, CHECK_SUM }, { size, CHECK_SUM }, ...]
|
||||
|
|
||||
|----Section2: PGORecordDetailInfos(number2)
|
||||
|--------[ PGOMethodInfoMap(number4)
|
||||
|------------{ offset, size, number4 }
|
||||
|------------[ PGOMethodInfo(size1)
|
||||
|----------------{ size1, entityId, count, mode, methodName, [{ size, offset, type }, { size, offset, type }, ...]},
|
||||
|------------ PGOMethodInfo(size1)
|
||||
|----------------{ size1, entityId, count, mode, methodName, [{ size, offset, type }, { size, offset, type }, ...]},
|
||||
|--------------... ]
|
||||
|-------- PGOMethodInfoMap()
|
||||
|--------... ]
|
||||
|
|
||||
|----Section3: PGHClassLayoutDescs(number3)
|
||||
|--------{ offset, size, number5 }
|
||||
|--------[ PGOHClassLayoutDescInner(size)
|
||||
|------------{ size, type, superType, count, ptCount, ctorCount, [{ size, handle, key }, { size, heandle, key }, ...]}
|
||||
|-------- PGOHClassLayoutDescInner(size)
|
||||
|------------{ size, type, superType, count, ptCount, ctorCount, [{ size, handle, key }, { size, heandle, key }, ...]}
|
||||
*/
|
||||
class PGOProfilerHeader : public base::FileHeader {
|
||||
public:
|
||||
static constexpr VersionType TYPE_MINI_VERSION = {0, 0, 0, 2};
|
||||
static constexpr VersionType METHOD_CHECKSUM_MINI_VERSION = {0, 0, 0, 4};
|
||||
static constexpr std::array<uint8_t, VERSION_SIZE> LAST_VERSION = {0, 0, 0, 4};
|
||||
static constexpr VersionType USE_HCLASS_TYPE_MINI_VERSION = {0, 0, 0, 5};
|
||||
static constexpr std::array<uint8_t, VERSION_SIZE> LAST_VERSION = {0, 0, 0, 5};
|
||||
static constexpr size_t SECTION_SIZE = 3;
|
||||
static constexpr size_t PANDA_FILE_SECTION_INDEX = 0;
|
||||
static constexpr size_t RECORD_INFO_SECTION_INDEX = 1;
|
||||
@ -176,6 +164,11 @@ public:
|
||||
return InternalVerifyVersion(METHOD_CHECKSUM_MINI_VERSION);
|
||||
}
|
||||
|
||||
bool SupportUseHClassType() const
|
||||
{
|
||||
return InternalVerifyVersion(USE_HCLASS_TYPE_MINI_VERSION);
|
||||
}
|
||||
|
||||
NO_COPY_SEMANTIC(PGOProfilerHeader);
|
||||
NO_MOVE_SEMANTIC(PGOProfilerHeader);
|
||||
|
||||
@ -395,26 +388,22 @@ public:
|
||||
|
||||
void AddType(uint32_t offset, PGOSampleType type)
|
||||
{
|
||||
if (type.IsClassType()) {
|
||||
AddClassType(offset, type);
|
||||
auto result = scalarOpTypeInfos_.find(ScalarOpTypeInfo(offset, type));
|
||||
if (result != scalarOpTypeInfos_.end()) {
|
||||
auto combineType = result->GetType().CombineType(type);
|
||||
const_cast<ScalarOpTypeInfo &>(*result).SetType(combineType);
|
||||
} else {
|
||||
auto result = scalarOpTypeInfos_.find(ScalarOpTypeInfo(offset, type));
|
||||
if (result != scalarOpTypeInfos_.end()) {
|
||||
auto combineType = result->GetType().CombineType(type);
|
||||
const_cast<ScalarOpTypeInfo &>(*result).SetType(combineType);
|
||||
} else {
|
||||
scalarOpTypeInfos_.emplace(offset, type);
|
||||
}
|
||||
scalarOpTypeInfos_.emplace(offset, type);
|
||||
}
|
||||
}
|
||||
|
||||
void AddClassType(uint32_t offset, PGOSampleType type)
|
||||
void AddObjectInfo(uint32_t offset, const PGOObjectInfo &info)
|
||||
{
|
||||
auto result = rwScalarOpTypeInfos_.find(RWScalarOpTypeInfo(offset));
|
||||
if (result != rwScalarOpTypeInfos_.end()) {
|
||||
const_cast<RWScalarOpTypeInfo &>(*result).AddClassType(type);
|
||||
const_cast<RWScalarOpTypeInfo &>(*result).AddObjectInfo(info);
|
||||
} else {
|
||||
rwScalarOpTypeInfos_.emplace(offset, type);
|
||||
rwScalarOpTypeInfos_.emplace(offset, info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,7 +436,7 @@ public:
|
||||
void Merge(const PGOMethodTypeSet *info);
|
||||
static void SkipFromBinary(void **buffer);
|
||||
|
||||
bool ParseFromBinary(void **buffer);
|
||||
bool ParseFromBinary(void **buffer, PGOProfilerHeader *const header);
|
||||
bool ProcessToBinary(std::stringstream &stream) const;
|
||||
|
||||
bool ParseFromText(const std::string &typeString);
|
||||
@ -490,10 +479,10 @@ private:
|
||||
public:
|
||||
explicit RWScalarOpTypeInfo(uint32_t offset)
|
||||
: TypeInfoHeader(InfoType::USE_HCLASS_TYPE, offset) {};
|
||||
RWScalarOpTypeInfo(uint32_t offset, PGOSampleType type)
|
||||
RWScalarOpTypeInfo(uint32_t offset, PGOObjectInfo info)
|
||||
: TypeInfoHeader(sizeof(RWScalarOpTypeInfo), InfoType::USE_HCLASS_TYPE, offset)
|
||||
{
|
||||
type_.AddClassType(type.GetClassType());
|
||||
type_.AddObjectInfo(info);
|
||||
}
|
||||
|
||||
bool operator<(const RWScalarOpTypeInfo &right) const
|
||||
@ -511,10 +500,9 @@ private:
|
||||
type_.Merge(type.type_);
|
||||
}
|
||||
|
||||
void AddClassType(const PGOSampleType &type)
|
||||
void AddObjectInfo(const PGOObjectInfo &info)
|
||||
{
|
||||
ASSERT(type.IsClassType());
|
||||
type_.AddClassType(type.GetClassType());
|
||||
type_.AddObjectInfo(info);
|
||||
}
|
||||
|
||||
PGORWOpType GetType() const
|
||||
@ -761,6 +749,7 @@ public:
|
||||
|
||||
bool AddMethod(Chunk *chunk, Method *jsMethod, SampleMode mode);
|
||||
bool AddType(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type);
|
||||
bool AddObjectInfo(Chunk *chunk, PGOMethodId methodId, int32_t offset, const PGOObjectInfo &info);
|
||||
bool AddDefine(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType);
|
||||
void Merge(Chunk *chunk, PGOMethodInfoMap *methodInfos);
|
||||
|
||||
@ -883,9 +872,10 @@ public:
|
||||
// If it is a new method, return true.
|
||||
bool AddMethod(const CString &recordName, Method *jsMethod, SampleMode mode);
|
||||
bool AddType(const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type);
|
||||
bool AddObjectInfo(const CString &recordName, PGOMethodId methodId, int32_t offset, const PGOObjectInfo &info);
|
||||
bool AddDefine(
|
||||
const CString &recordName, PGOMethodId methodId, int32_t offset, PGOSampleType type, PGOSampleType superType);
|
||||
bool AddLayout(PGOSampleType type, JSTaggedType hclass, PGOObjLayoutKind kind);
|
||||
bool AddLayout(PGOSampleType type, JSTaggedType hclass, PGOObjKind kind);
|
||||
void Merge(const PGORecordDetailInfos &recordInfos);
|
||||
|
||||
void ParseFromBinary(void *buffer, PGOProfilerHeader *const header);
|
||||
|
@ -16,16 +16,16 @@
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_layout.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
void PGOHClassLayoutDesc::UpdateKeyAndDesc(const CString &key, const PGOHandler &handler, PGOObjLayoutKind kind)
|
||||
void PGOHClassLayoutDesc::UpdateKeyAndDesc(const CString &key, const PGOHandler &handler, PGOObjKind kind)
|
||||
{
|
||||
switch (kind) {
|
||||
case PGOObjLayoutKind::LOCAL:
|
||||
case PGOObjKind::LOCAL:
|
||||
UpdateKeyAndDesc(key, handler, layoutDesc_);
|
||||
break;
|
||||
case PGOObjLayoutKind::PROTOTYPE:
|
||||
case PGOObjKind::PROTOTYPE:
|
||||
UpdateKeyAndDesc(key, handler, ptLayoutDesc_);
|
||||
break;
|
||||
case PGOObjLayoutKind::CONSTRUCTOR:
|
||||
case PGOObjKind::CONSTRUCTOR:
|
||||
UpdateKeyAndDesc(key, handler, ctorLayoutDesc_);
|
||||
break;
|
||||
default:
|
||||
@ -47,13 +47,13 @@ bool PGOHClassLayoutDesc::FindDescWithKey(const CString &key, PGOHandler &handle
|
||||
void PGOHClassLayoutDesc::Merge(const PGOHClassLayoutDesc &from)
|
||||
{
|
||||
for (const auto &iter : from.layoutDesc_) {
|
||||
UpdateKeyAndDesc(iter.first, iter.second, PGOObjLayoutKind::LOCAL);
|
||||
UpdateKeyAndDesc(iter.first, iter.second, PGOObjKind::LOCAL);
|
||||
}
|
||||
for (const auto &iter : from.ptLayoutDesc_) {
|
||||
UpdateKeyAndDesc(iter.first, iter.second, PGOObjLayoutKind::PROTOTYPE);
|
||||
UpdateKeyAndDesc(iter.first, iter.second, PGOObjKind::PROTOTYPE);
|
||||
}
|
||||
for (const auto &iter : from.ctorLayoutDesc_) {
|
||||
UpdateKeyAndDesc(iter.first, iter.second, PGOObjLayoutKind::CONSTRUCTOR);
|
||||
UpdateKeyAndDesc(iter.first, iter.second, PGOObjKind::CONSTRUCTOR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,11 +82,6 @@ private:
|
||||
|
||||
using PropertyDesc = std::pair<CString, PGOHandler>;
|
||||
using LayoutDesc = CVector<PropertyDesc>;
|
||||
enum class PGOObjLayoutKind {
|
||||
LOCAL,
|
||||
PROTOTYPE,
|
||||
CONSTRUCTOR,
|
||||
};
|
||||
|
||||
class PGOHClassLayoutDesc {
|
||||
public:
|
||||
@ -154,7 +149,7 @@ public:
|
||||
ctorLayoutDesc_.emplace_back(key, handler);
|
||||
}
|
||||
|
||||
void UpdateKeyAndDesc(const CString &key, const PGOHandler &handler, PGOObjLayoutKind kind);
|
||||
void UpdateKeyAndDesc(const CString &key, const PGOHandler &handler, PGOObjKind kind);
|
||||
|
||||
bool FindDescWithKey(const CString &key, PGOHandler &handler) const;
|
||||
|
||||
|
@ -293,45 +293,99 @@ private:
|
||||
std::variant<Type, ClassType> type_;
|
||||
};
|
||||
|
||||
enum class PGOObjKind {
|
||||
LOCAL,
|
||||
PROTOTYPE,
|
||||
CONSTRUCTOR,
|
||||
};
|
||||
|
||||
class PGOObjectInfo {
|
||||
public:
|
||||
PGOObjectInfo() : type_(ClassType()), objKind_(PGOObjKind::LOCAL) {}
|
||||
PGOObjectInfo(ClassType type, PGOObjKind kind) : type_(type), objKind_(PGOObjKind::LOCAL)
|
||||
{
|
||||
if (kind == PGOObjKind::CONSTRUCTOR) {
|
||||
objKind_ = kind;
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetInfoString() const
|
||||
{
|
||||
std::string result = type_.GetTypeString();
|
||||
result += "(";
|
||||
if (objKind_ == PGOObjKind::CONSTRUCTOR) {
|
||||
result += "c";
|
||||
} else {
|
||||
result += "l";
|
||||
}
|
||||
result += ")";
|
||||
return result;
|
||||
}
|
||||
|
||||
ClassType GetClassType() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
bool IsNone() const
|
||||
{
|
||||
return type_.IsNone();
|
||||
}
|
||||
|
||||
bool InConstructor() const
|
||||
{
|
||||
return objKind_ == PGOObjKind::CONSTRUCTOR;
|
||||
}
|
||||
|
||||
bool operator<(const PGOObjectInfo &right) const
|
||||
{
|
||||
return type_ < right.type_ || objKind_ < right.objKind_;
|
||||
}
|
||||
|
||||
bool operator==(const PGOObjectInfo &right) const
|
||||
{
|
||||
return type_ == right.type_ && objKind_ == right.objKind_;
|
||||
}
|
||||
|
||||
private:
|
||||
ClassType type_ { ClassType() };
|
||||
PGOObjKind objKind_ { PGOObjKind::LOCAL };
|
||||
};
|
||||
|
||||
class PGORWOpType : public PGOType {
|
||||
public:
|
||||
PGORWOpType() : PGOType(TypeKind::RW_OP_TYPE) {};
|
||||
explicit PGORWOpType(const PGOSampleType &type) : PGOType(TypeKind::RW_OP_TYPE), count_(0)
|
||||
{
|
||||
ASSERT(type.IsClassType());
|
||||
AddClassType(type.GetClassType());
|
||||
}
|
||||
PGORWOpType() : PGOType(TypeKind::RW_OP_TYPE), count_(0) {};
|
||||
|
||||
void Merge(const PGORWOpType &type)
|
||||
{
|
||||
for (int i = 0; i < type.count_; i++) {
|
||||
AddClassType(type.type_[i]);
|
||||
AddObjectInfo(type.infos_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void AddClassType(const ClassType &type)
|
||||
void AddObjectInfo(const PGOObjectInfo &info)
|
||||
{
|
||||
if (type.IsNone()) {
|
||||
if (info.IsNone()) {
|
||||
return;
|
||||
}
|
||||
int32_t count = 0;
|
||||
for (; count < count_; count++) {
|
||||
if (type_[count] == type) {
|
||||
if (infos_[count] == info) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (count < 4) { // 4 : Class type
|
||||
type_[count] = type;
|
||||
if (count < POLY_CASE_NUM) {
|
||||
infos_[count] = info;
|
||||
count_++;
|
||||
} else {
|
||||
LOG_ECMA(DEBUG) << "Class type exceeds 4, discard";
|
||||
}
|
||||
}
|
||||
|
||||
ClassType GetType(int32_t index) const
|
||||
PGOObjectInfo GetObjectInfo(int32_t index) const
|
||||
{
|
||||
ASSERT(index < count_);
|
||||
return type_[index];
|
||||
return infos_[index];
|
||||
}
|
||||
|
||||
int32_t GetCount() const
|
||||
@ -340,8 +394,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int POLY_CASE_NUM = 4;
|
||||
int count_ = 0;
|
||||
ClassType type_[4];
|
||||
PGOObjectInfo infos_[POLY_CASE_NUM];
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_PGO_PROFILER_TYPE_H
|
||||
|
@ -406,6 +406,13 @@ void RuntimeStubs::ProfileDefineClass(uintptr_t argGlue, uintptr_t func, int32_t
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileDefineClass(thread, func, offset, ctor);
|
||||
}
|
||||
|
||||
void RuntimeStubs::ProfileCreateObject(
|
||||
uintptr_t argGlue, JSTaggedType func, int32_t offset, JSTaggedType originObj, JSTaggedType newObj)
|
||||
{
|
||||
auto thread = JSThread::GlueToJSThread(argGlue);
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileCreateObject(func, offset, originObj, newObj);
|
||||
}
|
||||
|
||||
void RuntimeStubs::ProfileObjLayout(uintptr_t argGlue, uintptr_t func, int32_t offset, uintptr_t object, int32_t store)
|
||||
{
|
||||
auto thread = JSThread::GlueToJSThread(argGlue);
|
||||
|
@ -98,6 +98,7 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
|
||||
V(DebugPrintInstruction) \
|
||||
V(ProfileCall) \
|
||||
V(ProfileDefineClass) \
|
||||
V(ProfileCreateObject) \
|
||||
V(ProfileOpType) \
|
||||
V(ProfileObjLayout) \
|
||||
V(Comment) \
|
||||
@ -354,6 +355,8 @@ public:
|
||||
static void Comment(uintptr_t argStr);
|
||||
static void ProfileCall(uintptr_t argGlue, uintptr_t func);
|
||||
static void ProfileDefineClass(uintptr_t argGlue, uintptr_t func, int32_t offset, uintptr_t ctor);
|
||||
static void ProfileCreateObject(
|
||||
uintptr_t argGlue, JSTaggedType func, int32_t offset, JSTaggedType originObj, JSTaggedType newObj);
|
||||
static void ProfileOpType(uintptr_t argGlue, uintptr_t func, int32_t offset, int32_t type);
|
||||
static void ProfileObjLayout(uintptr_t argGlue, uintptr_t func, int32_t offset, uintptr_t object, int32_t store);
|
||||
static void FatalPrint(int fmtMessageId, ...);
|
||||
|
@ -709,6 +709,11 @@ public:
|
||||
return collectedGT_;
|
||||
}
|
||||
|
||||
inline void InsertPtToGtMap(ClassType pgoType, const kungfu::GateType &gateType)
|
||||
{
|
||||
ptToGtMap_.emplace(pgoType, gateType);
|
||||
}
|
||||
|
||||
void PrintNumOfTypes() const;
|
||||
|
||||
void PrintTypeInfo(const JSPandaFile *jsPandaFile) const;
|
||||
@ -808,6 +813,7 @@ private:
|
||||
JSThread *thread_ {nullptr};
|
||||
ObjectFactory *factory_ {nullptr};
|
||||
JSTaggedValue globalModuleTable_ {JSTaggedValue::Hole()};
|
||||
CMap<ClassType, const kungfu::GateType> ptToGtMap_ {};
|
||||
std::map<GlobalTSTypeRef, IHClassData> gtIhcMap_ {};
|
||||
std::map<GlobalTSTypeRef, IHClassData> gtConstructorhcMap_ {};
|
||||
bool assertTypes_ {false};
|
||||
|
Loading…
Reference in New Issue
Block a user