mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-26 19:50:55 +00:00
<Perf>(interpreter): Optimization PGO profile
1、Delete field VTable and Super in hclass. 2、Opt dump hclass transition tree. 3、Opt profileType of hclass. 4、Class function supports ProfileTypeInfoCell. Issue: #IA9QT3 Change-Id: I3d296f19433878c16f70d0260a3e77ce58ba9a3f Signed-off-by: yingguofeng@huawei.com <yingguofeng@huawei.com>
This commit is contained in:
parent
3d15b0df15
commit
b5eedbb873
@ -123,18 +123,6 @@ JSTaggedValue BuiltinsArkTools::GetHClass(EcmaRuntimeCallInfo *info)
|
||||
return JSTaggedValue(hclass);
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::HasTSSubtyping(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
JSThread *thread = info->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
|
||||
ASSERT(info->GetArgsNumber() == 1);
|
||||
JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
|
||||
JSHClass *hclass = object->GetTaggedObject()->GetClass();
|
||||
return GetTaggedBoolean(hclass->HasTSSubtyping());
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::IsSlicedString(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
|
@ -30,7 +30,6 @@
|
||||
V("forceFullGC", ForceFullGC, 0, INVALID) \
|
||||
V("getHClass", GetHClass, 1, INVALID) \
|
||||
V("getLexicalEnv", GetLexicalEnv, 1, INVALID) \
|
||||
V("hasTSSubtyping", HasTSSubtyping, 1, INVALID) \
|
||||
V("isSlicedString", IsSlicedString, 1, INVALID) \
|
||||
V("hiddenStackSourceFile", HiddenStackSourceFile, 0, INVALID) \
|
||||
V("hintGC", HintGC, 0, INVALID) \
|
||||
@ -174,8 +173,6 @@ public:
|
||||
|
||||
static JSTaggedValue GetHClass(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue HasTSSubtyping(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue IsSlicedString(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue IsNotHoleProperty(EcmaRuntimeCallInfo *info);
|
||||
|
@ -2290,6 +2290,21 @@ DEF_CALL_SIGNATURE(FindElementWithCache)
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(UpdateFieldType)
|
||||
{
|
||||
// 2 : 2 input parameters
|
||||
CallSignature index("UpdateFieldType", 0, 2, ArgumentsOrder::DEFAULT_ORDER, VariableType::INT32());
|
||||
*callSign = index;
|
||||
// 2 : 2 input parameters
|
||||
std::array<VariableType, 2> params = {
|
||||
VariableType::JS_ANY(),
|
||||
VariableType::INT64(),
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(true);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(NumberIsFinite)
|
||||
{
|
||||
// 1 : 1 input parameters
|
||||
|
@ -506,6 +506,7 @@ private:
|
||||
V(CallDateNow) \
|
||||
V(NumberIsFinite) \
|
||||
V(FindElementWithCache) \
|
||||
V(UpdateFieldType) \
|
||||
V(MarkingBarrier) \
|
||||
V(MarkingBarrierWithEden) \
|
||||
V(SharedGCMarkingBarrier) \
|
||||
|
@ -339,7 +339,7 @@ GateRef ProfilerStubBuilder::TryGetBuiltinFunctionId(GateRef target)
|
||||
Label exit(env);
|
||||
|
||||
DEFVARIABLE(functionId, VariableType::INT32(), Int32(PGO_BUILTINS_STUB_ID(NONE)));
|
||||
|
||||
|
||||
BRANCH(IsJSFunction(target), &targetIsFunction, &exit);
|
||||
Bind(&targetIsFunction);
|
||||
{
|
||||
@ -479,7 +479,7 @@ void ProfilerStubBuilder::UpdatePropAttrIC(
|
||||
BRANCH(Equal(attr, newAttr), &exit, &updateLayout);
|
||||
Bind(&updateLayout);
|
||||
{
|
||||
SetPropAttrToLayoutInfo(glue, layout, attrIndex, newAttr);
|
||||
UpdateFieldType(glue, LoadHClass(receiver), newAttr);
|
||||
callback.TryPreDump();
|
||||
Jump(&exit);
|
||||
}
|
||||
@ -488,8 +488,8 @@ void ProfilerStubBuilder::UpdatePropAttrIC(
|
||||
env->SubCfgExit();
|
||||
}
|
||||
|
||||
void ProfilerStubBuilder::UpdatePropAttrWithValue(GateRef glue, GateRef receiver, GateRef layout, GateRef attr,
|
||||
GateRef attrIndex, GateRef value, ProfileOperation callback)
|
||||
void ProfilerStubBuilder::UpdatePropAttrWithValue(GateRef glue, GateRef receiver, GateRef attr,
|
||||
GateRef value, ProfileOperation callback)
|
||||
{
|
||||
if (callback.IsEmpty()) {
|
||||
return;
|
||||
@ -506,7 +506,7 @@ void ProfilerStubBuilder::UpdatePropAttrWithValue(GateRef glue, GateRef receiver
|
||||
BRANCH(Equal(attr, newAttr), &exit, &updateLayout);
|
||||
Bind(&updateLayout);
|
||||
{
|
||||
SetPropAttrToLayoutInfo(glue, layout, attrIndex, newAttr);
|
||||
UpdateFieldType(glue, LoadHClass(receiver), newAttr);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
|
@ -113,8 +113,8 @@ public:
|
||||
|
||||
GateRef UpdateTrackTypeInPropAttr(GateRef attr, GateRef value, ProfileOperation callback);
|
||||
void UpdatePropAttrIC(GateRef glue, GateRef receiver, GateRef value, GateRef handler, ProfileOperation callback);
|
||||
void UpdatePropAttrWithValue(GateRef glue, GateRef receiver, GateRef layout, GateRef attr, GateRef attrIndex,
|
||||
GateRef value, ProfileOperation callback);
|
||||
void UpdatePropAttrWithValue(
|
||||
GateRef glue, GateRef receiver, GateRef attr, GateRef value, ProfileOperation callback);
|
||||
|
||||
GateRef IsProfileTypeInfoDumped(GateRef profileTypeInfo, ProfileOperation callback);
|
||||
|
||||
|
@ -2397,12 +2397,9 @@ inline GateRef StubBuilder::GetIhcFromAOTLiteralInfo(GateRef info)
|
||||
return Load(VariableType::JS_ANY(), info, dataOffset);
|
||||
}
|
||||
|
||||
inline void StubBuilder::SetPropAttrToLayoutInfo(GateRef glue, GateRef layout, GateRef entry, GateRef attr)
|
||||
inline void StubBuilder::UpdateFieldType(GateRef glue, GateRef hclass, GateRef attr)
|
||||
{
|
||||
GateRef index = Int32Add(Int32LSL(entry, Int32(LayoutInfo::ELEMENTS_INDEX_LOG2)),
|
||||
Int32(LayoutInfo::ATTR_INDEX_OFFSET));
|
||||
GateRef taggedAttr = Int64ToTaggedInt(attr);
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, layout, index, taggedAttr);
|
||||
CallNGCRuntime(glue, RTSTUB_ID(UpdateFieldType), { hclass, attr });
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::GetPropertyMetaDataFromAttr(GateRef attr)
|
||||
|
@ -4269,8 +4269,7 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
|
||||
CheckUpdateSharedType(false, &result, glue, receiver, attr, value, &executeSetProp, &exit);
|
||||
Bind(&executeSetProp);
|
||||
JSObjectSetProperty(glue, *holder, hclass, attr, key, value);
|
||||
ProfilerStubBuilder(env).UpdatePropAttrWithValue(
|
||||
glue, receiver, layOutInfo, attr, entry, value, callback);
|
||||
ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, attr, value, callback);
|
||||
result = Undefined();
|
||||
Jump(&exit);
|
||||
}
|
||||
@ -4373,8 +4372,7 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
|
||||
GateRef receiverLayoutInfo = GetLayoutFromHClass(receiverHClass);
|
||||
GateRef holeAttr = GetPropAttrFromLayoutInfo(receiverLayoutInfo, *receiverHoleEntry);
|
||||
JSObjectSetProperty(glue, receiver, receiverHClass, holeAttr, key, value);
|
||||
ProfilerStubBuilder(env).UpdatePropAttrWithValue(
|
||||
glue, receiver, receiverLayoutInfo, holeAttr, *receiverHoleEntry, value, callback);
|
||||
ProfilerStubBuilder(env).UpdatePropAttrWithValue(glue, receiver, holeAttr, value, callback);
|
||||
result = Undefined();
|
||||
Jump(&exit);
|
||||
}
|
||||
|
@ -576,7 +576,7 @@ ShortcutBoolOr([&]{ return first; }, [&]{ return second; })
|
||||
template<typename DictionaryT>
|
||||
GateRef GetKeyFromDictionary(GateRef elements, GateRef entry);
|
||||
GateRef GetPropAttrFromLayoutInfo(GateRef layout, GateRef entry);
|
||||
void SetPropAttrToLayoutInfo(GateRef glue, GateRef layout, GateRef entry, GateRef attr);
|
||||
void UpdateFieldType(GateRef glue, GateRef hclass, GateRef attr);
|
||||
GateRef GetPropertiesAddrFromLayoutInfo(GateRef layout);
|
||||
GateRef GetPropertyMetaDataFromAttr(GateRef attr);
|
||||
GateRef TranslateToRep(GateRef value);
|
||||
|
@ -1625,18 +1625,6 @@ void TypedHCRLowering::LowerGetSuperConstructor(GateRef gate)
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), superCtor);
|
||||
}
|
||||
|
||||
GateRef TypedHCRLowering::LoadFromVTable(GateRef receiver, size_t index)
|
||||
{
|
||||
GateRef hclass = builder_.LoadConstOffset(
|
||||
VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
||||
GateRef vtable = builder_.LoadConstOffset(VariableType::JS_ANY(),
|
||||
hclass, JSHClass::VTABLE_OFFSET);
|
||||
|
||||
GateRef itemOwner = builder_.LoadFromTaggedArray(vtable, VTable::TupleItem::OWNER + index);
|
||||
GateRef itemOffset = builder_.LoadFromTaggedArray(vtable, VTable::TupleItem::OFFSET + index);
|
||||
return builder_.Load(VariableType::JS_ANY(), itemOwner, builder_.TaggedGetInt(itemOffset));
|
||||
}
|
||||
|
||||
VariableType TypedHCRLowering::GetVarType(PropertyLookupResult plr)
|
||||
{
|
||||
if (plr.GetRepresentation() == Representation::DOUBLE) {
|
||||
@ -1648,11 +1636,6 @@ VariableType TypedHCRLowering::GetVarType(PropertyLookupResult plr)
|
||||
}
|
||||
}
|
||||
|
||||
GateRef TypedHCRLowering::LoadSupers(GateRef hclass)
|
||||
{
|
||||
return builder_.LoadConstOffset(VariableType::JS_ANY(), hclass, JSHClass::SUPERS_OFFSET);
|
||||
}
|
||||
|
||||
GateRef TypedHCRLowering::GetLengthFromSupers(GateRef supers)
|
||||
{
|
||||
return builder_.LoadConstOffset(VariableType::INT32(), supers, TaggedArray::EXTRA_LENGTH_OFFSET);
|
||||
|
@ -258,12 +258,10 @@ private:
|
||||
}
|
||||
|
||||
VariableType GetVarType(PropertyLookupResult plr);
|
||||
GateRef LoadSupers(GateRef hclass);
|
||||
GateRef GetLengthFromSupers(GateRef supers);
|
||||
GateRef GetValueFromSupers(GateRef supers, size_t index);
|
||||
GateRef LoadFromTaggedArray(GateRef array, size_t index);
|
||||
GateRef LoadFromConstPool(GateRef unsharedConstPool, size_t index, size_t valVecType);
|
||||
GateRef LoadFromVTable(GateRef receiver, size_t index);
|
||||
GateRef GetLengthFromString(GateRef gate);
|
||||
GateRef LoadPropertyFromHolder(GateRef holder, PropertyLookupResult plr);
|
||||
void StorePropertyOnHolder(GateRef holder, GateRef value, PropertyLookupResult plr, bool needBarrier);
|
||||
|
@ -755,28 +755,7 @@ static void DumpHClass(const JSHClass *jshclass, std::ostream &os, bool withDeta
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
JSTaggedValue supers = jshclass->GetSupers();
|
||||
uint32_t length = 0;
|
||||
if (supers.IsTaggedArray()) {
|
||||
length = WeakVector::Cast(supers.GetTaggedObject())->GetExtraLength();
|
||||
}
|
||||
os << " - Supers[" << std::dec << length << "]: ";
|
||||
os << std::setw(DUMP_TYPE_OFFSET);
|
||||
supers.DumpTaggedValue(os);
|
||||
if (withDetail && !supers.IsUndefined()) {
|
||||
WeakVector::Cast(supers.GetTaggedObject())->Dump(os);
|
||||
} else {
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
os << " - VTable :" << std::setw(DUMP_TYPE_OFFSET);
|
||||
JSTaggedValue vtable = jshclass->GetVTable();
|
||||
vtable.DumpTaggedValue(os);
|
||||
if (withDetail && !vtable.IsUndefined()) {
|
||||
VTable::Cast(vtable.GetTaggedObject())->Dump(os);
|
||||
} else {
|
||||
os << "\n";
|
||||
}
|
||||
os << " - ProfileType : " << std::hex << jshclass->GetProfileType() << "\n";
|
||||
|
||||
os << " - Flags : " << std::setw(DUMP_TYPE_OFFSET);
|
||||
os << "IsCtor :" << std::boolalpha << jshclass->IsConstructor();
|
||||
@ -4866,8 +4845,6 @@ void JSHClass::DumpForSnapshot([[maybe_unused]] std::vector<Reference> &vec) con
|
||||
vec.emplace_back(CString("ProtoChangeMarker"), GetProtoChangeMarker());
|
||||
vec.emplace_back(CString("ProtoChangeDetails"), GetProtoChangeDetails());
|
||||
vec.emplace_back(CString("EnumCache"), GetEnumCache());
|
||||
vec.emplace_back(CString("Supers"), GetSupers());
|
||||
vec.emplace_back(CString("VTable"), GetVTable());
|
||||
vec.emplace_back(CString("BitField"), JSTaggedValue(GetBitField()));
|
||||
vec.emplace_back(CString("BitField1"), JSTaggedValue(GetBitField1()));
|
||||
}
|
||||
|
@ -1054,6 +1054,24 @@ void JSFunction::SetProfileTypeInfo(const JSThread *thread, const JSHandle<JSFun
|
||||
handleRaw->SetValue(thread, value, mode);
|
||||
}
|
||||
|
||||
void JSFunction::UpdateProfileTypeInfoCell(JSThread *thread, JSHandle<JSFunction> literalFunc,
|
||||
JSHandle<JSFunction> targetFunc)
|
||||
{
|
||||
auto profileTypeInfoCellVal = literalFunc->GetRawProfileTypeInfo();
|
||||
ASSERT(profileTypeInfoCellVal.IsProfileTypeInfoCell());
|
||||
auto profileTypeInfoCell = ProfileTypeInfoCell::Cast(profileTypeInfoCellVal);
|
||||
if (profileTypeInfoCell->IsEmptyProfileTypeInfoCell(thread)) {
|
||||
JSHandle<JSTaggedValue> handleUndefined(thread, JSTaggedValue::Undefined());
|
||||
JSHandle<ProfileTypeInfoCell> newProfileTypeInfoCell =
|
||||
thread->GetEcmaVM()->GetFactory()->NewProfileTypeInfoCell(handleUndefined);
|
||||
literalFunc->SetRawProfileTypeInfo(thread, newProfileTypeInfoCell);
|
||||
targetFunc->SetRawProfileTypeInfo(thread, newProfileTypeInfoCell);
|
||||
} else {
|
||||
ProfileTypeInfoCell::Cast(profileTypeInfoCell)->UpdateProfileTypeInfoCellType(thread);
|
||||
targetFunc->SetRawProfileTypeInfo(thread, profileTypeInfoCellVal);
|
||||
}
|
||||
}
|
||||
|
||||
void JSFunction::SetJitMachineCodeCache(const JSThread *thread, const JSHandle<MachineCode> &machineCode)
|
||||
{
|
||||
JSHandle<ProfileTypeInfoCell> handleRaw(thread, GetRawProfileTypeInfo());
|
||||
|
@ -308,6 +308,8 @@ public:
|
||||
void *data, size_t nativeBindingsize = 0);
|
||||
static void SetProfileTypeInfo(const JSThread *thread, const JSHandle<JSFunction> &func,
|
||||
const JSHandle<JSTaggedValue> &value, BarrierMode mode = WRITE_BARRIER);
|
||||
static void UpdateProfileTypeInfoCell(JSThread *thread, JSHandle<JSFunction> literalFunc,
|
||||
JSHandle<JSFunction> targetFunc);
|
||||
void SetJitMachineCodeCache(const JSThread *thread, const JSHandle<MachineCode> &machineCode);
|
||||
|
||||
JSTaggedValue GetFunctionExtraInfo() const;
|
||||
|
@ -299,10 +299,12 @@ inline void JSHClass::Copy(const JSThread *thread, const JSHClass *jshclass)
|
||||
inline JSHClass *JSHClass::FindRootHClass(JSHClass *hclass)
|
||||
{
|
||||
auto root = hclass;
|
||||
auto parent = hclass->GetParent();
|
||||
while (parent.IsJSHClass()) {
|
||||
while (!ProfileType(root->GetProfileType()).IsRootType()) {
|
||||
auto parent = root->GetParent();
|
||||
if (!parent.IsJSHClass()) {
|
||||
break;
|
||||
}
|
||||
root = JSHClass::Cast(parent.GetTaggedObject());
|
||||
parent = root->GetParent();
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
@ -159,9 +159,7 @@ void JSHClass::InitializeWithDefaultValue(const JSThread *thread, uint32_t size,
|
||||
SetProtoChangeMarker(thread, JSTaggedValue::Null());
|
||||
SetProtoChangeDetails(thread, JSTaggedValue::Null());
|
||||
SetEnumCache(thread, JSTaggedValue::Null());
|
||||
SetSupers(thread, JSTaggedValue::Undefined());
|
||||
SetLevel(0);
|
||||
SetVTable(thread, JSTaggedValue::Undefined());
|
||||
}
|
||||
|
||||
bool JSHClass::IsJSTypeShared(JSType type)
|
||||
@ -207,7 +205,6 @@ void JSHClass::Initialize(const JSThread *thread, uint32_t size, JSType type, ui
|
||||
if (JSType::JS_OBJECT_FIRST <= type && type <= JSType::JS_OBJECT_LAST) {
|
||||
SetLayout(thread, thread->GlobalConstants()->GetEmptyLayoutInfo());
|
||||
}
|
||||
InitTSInheritInfo(thread);
|
||||
}
|
||||
|
||||
// for sharedHeap
|
||||
@ -223,22 +220,6 @@ void JSHClass::Initialize(const JSThread *thread, uint32_t size, JSType type,
|
||||
}
|
||||
}
|
||||
|
||||
void JSHClass::InitTSInheritInfo(const JSThread *thread)
|
||||
{
|
||||
// Supers and Level are used to record the relationship between TSHClass.
|
||||
if (ShouldSetDefaultSupers()) {
|
||||
ASSERT(thread->GlobalConstants()->GetDefaultSupers().IsTaggedArray());
|
||||
SetSupers(thread, thread->GlobalConstants()->GetDefaultSupers());
|
||||
} else {
|
||||
SetSupers(thread, JSTaggedValue::Undefined());
|
||||
}
|
||||
SetLevel(0);
|
||||
|
||||
// VTable records the location information of properties and methods of TSHClass,
|
||||
// which is used to perform efficient IC at runtime
|
||||
SetVTable(thread, JSTaggedValue::Undefined());
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> JSHClass::Clone(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||
bool withoutInlinedProperties, uint32_t incInlinedProperties)
|
||||
{
|
||||
@ -563,7 +544,6 @@ void JSHClass::TransitionToDictionary(const JSThread *thread, const JSHandle<JSO
|
||||
// 1. new a hclass
|
||||
JSHandle<JSHClass> jshclass(thread, obj->GetJSHClass());
|
||||
JSHandle<JSHClass> newJsHClass = CloneWithoutInlinedProperties(thread, jshclass);
|
||||
UpdateRootHClass(thread, jshclass, newJsHClass);
|
||||
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
@ -587,7 +567,6 @@ void JSHClass::OptimizeAsFastProperties(const JSThread *thread, const JSHandle<J
|
||||
// 1. new a hclass
|
||||
JSHandle<JSHClass> jshclass(thread, obj->GetJSHClass());
|
||||
JSHandle<JSHClass> newJsHClass = Clone(thread, jshclass, isDictionary);
|
||||
UpdateRootHClass(thread, jshclass, newJsHClass);
|
||||
|
||||
// 2. If it is dictionary, migrate should change layout. otherwise, copy the hclass only.
|
||||
JSHandle<NameDictionary> properties(thread, obj->GetProperties());
|
||||
@ -752,6 +731,62 @@ bool JSHClass::TransitToElementsKind(const JSThread *thread, const JSHandle<JSOb
|
||||
return false;
|
||||
}
|
||||
|
||||
void JSHClass::UpdateFieldType(JSHClass *hclass, const PropertyAttributes &attr)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
JSHClass *ownHClass = FindFieldOwnHClass(hclass, attr);
|
||||
VisitAndUpdateLayout(ownHClass, attr);
|
||||
}
|
||||
|
||||
JSHClass *JSHClass::FindFieldOwnHClass(JSHClass *hclass, const PropertyAttributes &attr)
|
||||
{
|
||||
uint32_t offset = attr.GetOffset();
|
||||
JSTaggedValue parent(hclass);
|
||||
JSHClass *curHClass = hclass;
|
||||
while (parent.IsJSHClass()) {
|
||||
auto parentHClass = JSHClass::Cast(parent.GetTaggedObject());
|
||||
if (parentHClass->NumberOfProps() <= offset) {
|
||||
break;
|
||||
}
|
||||
curHClass = parentHClass;
|
||||
parent = curHClass->GetParent();
|
||||
}
|
||||
return curHClass;
|
||||
}
|
||||
|
||||
void JSHClass::VisitAndUpdateLayout(JSHClass *ownHClass, const PropertyAttributes &attr)
|
||||
{
|
||||
uint32_t offset = attr.GetOffset();
|
||||
auto targetTrackType = attr.GetTrackType();
|
||||
std::queue<JSHClass *> backHClass;
|
||||
backHClass.push(ownHClass);
|
||||
while (!backHClass.empty()) {
|
||||
JSHClass *current = backHClass.front();
|
||||
backHClass.pop();
|
||||
|
||||
auto layout = LayoutInfo::Cast(current->GetLayout().GetTaggedObject());
|
||||
if (layout->GetAttr(offset).GetTrackType() != targetTrackType) {
|
||||
layout->UpdateTrackTypeAttr(offset, attr);
|
||||
}
|
||||
|
||||
auto transitions = current->GetTransitions();
|
||||
if (transitions.IsUndefined()) {
|
||||
continue;
|
||||
}
|
||||
if (transitions.IsWeak()) {
|
||||
auto cache = transitions.GetTaggedWeakRef();
|
||||
backHClass.push(JSHClass::Cast(cache));
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT(transitions.IsTaggedArray());
|
||||
TransitionsDictionary *dict = TransitionsDictionary::Cast(transitions.GetTaggedObject());
|
||||
dict->IterateEntryValue([&backHClass] (JSHClass *cache) {
|
||||
backHClass.push(JSHClass::Cast(cache));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TransitionResult JSHClass::ConvertOrTransitionWithRep(const JSThread *thread,
|
||||
const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
|
||||
PropertyAttributes &attr)
|
||||
@ -760,7 +795,7 @@ TransitionResult JSHClass::ConvertOrTransitionWithRep(const JSThread *thread,
|
||||
auto layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
|
||||
attr = layout->GetAttr(attr.GetOffset());
|
||||
if (thread->IsPGOProfilerEnable() && !hclass->IsJSShared() && attr.UpdateTrackType(value.GetTaggedValue())) {
|
||||
layout->SetNormalAttr(thread, attr.GetOffset(), attr);
|
||||
UpdateFieldType(hclass, attr);
|
||||
}
|
||||
|
||||
Representation oldRep = attr.GetRepresentation();
|
||||
@ -805,11 +840,7 @@ JSHandle<JSTaggedValue> JSHClass::EnableProtoChangeMarker(const JSThread *thread
|
||||
// PHC (prototype-HClass) and its IHC (instance-HClass) from the current PHC along the chain.
|
||||
// therefore, when registering, it is also necessary to register IHC into its
|
||||
// PHC's Listener to ensure that it can be notified.
|
||||
if (jshclass->IsTSIHCWithInheritInfo()) {
|
||||
RegisterOnProtoChain(thread, jshclass);
|
||||
} else {
|
||||
RegisterOnProtoChain(thread, protoClass);
|
||||
}
|
||||
RegisterOnProtoChain(thread, protoClass);
|
||||
|
||||
JSTaggedValue protoChangeMarker = protoClass->GetProtoChangeMarker();
|
||||
if (protoChangeMarker.IsProtoChangeMarker()) {
|
||||
@ -980,19 +1011,15 @@ JSHandle<ProtoChangeDetails> JSHClass::GetProtoChangeDetails(const JSThread *thr
|
||||
return GetProtoChangeDetails(thread, jshclass);
|
||||
}
|
||||
|
||||
void JSHClass::MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
||||
void JSHClass::MarkProtoChanged([[maybe_unused]] const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
ASSERT(jshclass->IsPrototype() || jshclass->HasTSSubtyping());
|
||||
ASSERT(jshclass->IsPrototype());
|
||||
JSTaggedValue markerValue = jshclass->GetProtoChangeMarker();
|
||||
if (markerValue.IsProtoChangeMarker()) {
|
||||
ProtoChangeMarker *protoChangeMarker = ProtoChangeMarker::Cast(markerValue.GetTaggedObject());
|
||||
protoChangeMarker->SetHasChanged(true);
|
||||
}
|
||||
|
||||
if (jshclass->HasTSSubtyping()) {
|
||||
jshclass->InitTSInheritInfo(thread);
|
||||
}
|
||||
}
|
||||
|
||||
void JSHClass::NoticeThroughChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||
@ -1038,21 +1065,6 @@ void JSHClass::RefreshUsers(const JSThread *thread, const JSHandle<JSHClass> &ol
|
||||
}
|
||||
}
|
||||
|
||||
bool JSHClass::HasTSSubtyping() const
|
||||
{
|
||||
// if fill TS inherit info, supers must not be empty
|
||||
if (!GetSupers().IsHeapObject()) {
|
||||
return false;
|
||||
}
|
||||
WeakVector *supers = WeakVector::Cast(GetSupers().GetTaggedObject());
|
||||
return !(supers->Empty());
|
||||
}
|
||||
|
||||
bool JSHClass::IsTSIHCWithInheritInfo() const
|
||||
{
|
||||
return IsTS() && !IsPrototype() && HasTSSubtyping();
|
||||
}
|
||||
|
||||
PropertyLookupResult JSHClass::LookupPropertyInAotHClass(const JSThread *thread, JSHClass *hclass, JSTaggedValue key)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
@ -1089,23 +1101,6 @@ PropertyLookupResult JSHClass::LookupPropertyInAotHClass(const JSThread *thread,
|
||||
return result;
|
||||
}
|
||||
|
||||
// found in vtable
|
||||
if (hclass->GetVTable().IsUndefined()) {
|
||||
result.SetIsFound(false);
|
||||
return result;
|
||||
}
|
||||
JSHandle<VTable> vtable(thread, hclass->GetVTable());
|
||||
entry = vtable->GetTupleIndexByName(key);
|
||||
if (entry != -1) {
|
||||
result.SetIsVtable();
|
||||
uint32_t offset = static_cast<uint32_t>(entry * VTable::TUPLE_SIZE);
|
||||
result.SetOffset(offset);
|
||||
if (vtable->IsAccessor(entry)) {
|
||||
result.SetIsAccessor(true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// not found
|
||||
result.SetIsFound(false);
|
||||
return result;
|
||||
@ -1191,21 +1186,6 @@ PropertyLookupResult JSHClass::LookupPropertyInBuiltinPrototypeHClass(const JSTh
|
||||
return result;
|
||||
}
|
||||
|
||||
void JSHClass::CopyTSInheritInfo(const JSThread *thread, const JSHandle<JSHClass> &oldHClass,
|
||||
JSHandle<JSHClass> &newHClass)
|
||||
{
|
||||
JSHandle<WeakVector> supers(thread, oldHClass->GetSupers());
|
||||
JSHandle<WeakVector> copySupers = WeakVector::Copy(thread, supers);
|
||||
newHClass->SetSupers(thread, copySupers);
|
||||
|
||||
uint8_t level = oldHClass->GetLevel();
|
||||
newHClass->SetLevel(level);
|
||||
|
||||
JSHandle<VTable> vtable(thread, oldHClass->GetVTable());
|
||||
JSHandle<VTable> copyVtable = VTable::Copy(thread, vtable);
|
||||
newHClass->SetVTable(thread, copyVtable);
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> JSHClass::ParseKeyFromPGOCString(ObjectFactory* factory,
|
||||
const CString& cstring,
|
||||
const PGOHandler& handler)
|
||||
@ -1385,9 +1365,7 @@ bool JSHClass::UpdateChildLayoutDescByPGO(const JSHClass* hclass, HClassLayoutDe
|
||||
return layoutInfo->UpdateFieldIndexByPGO(last, childDesc);
|
||||
}
|
||||
|
||||
bool JSHClass::UpdateRootLayoutDescByPGO(const JSHClass* hclass,
|
||||
const PGOHClassTreeDesc* treeDesc,
|
||||
HClassLayoutDesc* desc)
|
||||
bool JSHClass::UpdateRootLayoutDescByPGO(const JSHClass* hclass, HClassLayoutDesc* desc)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
if (hclass->IsDictionaryMode()) {
|
||||
@ -1396,25 +1374,10 @@ bool JSHClass::UpdateRootLayoutDescByPGO(const JSHClass* hclass,
|
||||
|
||||
auto rootDesc = reinterpret_cast<const pgo::RootHClassLayoutDesc *>(desc);
|
||||
int rootPropLen = static_cast<int>(rootDesc->NumOfProps());
|
||||
int element = static_cast<int>(hclass->NumberOfProps());
|
||||
ASSERT(element >= rootPropLen);
|
||||
LayoutInfo *layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
|
||||
for (int i = 0; i < rootPropLen; i++) {
|
||||
layout->UpdateFieldIndexByPGO(i, desc);
|
||||
}
|
||||
auto lastDesc = desc;
|
||||
for (int i = rootPropLen; i < element - 1; i++) {
|
||||
if (lastDesc == nullptr || lastDesc->GetChildSize() == 0) {
|
||||
break;
|
||||
}
|
||||
lastDesc->IterateChilds([treeDesc, layout, i, &lastDesc] (const ProfileType &childType) -> bool {
|
||||
lastDesc = treeDesc->GetHClassLayoutDesc(childType);
|
||||
if (lastDesc == nullptr) {
|
||||
return true;
|
||||
}
|
||||
return !layout->UpdateFieldIndexByPGO(i, lastDesc);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1432,10 +1395,13 @@ CString JSHClass::DumpToString(JSTaggedType hclassVal)
|
||||
for (int i = 0; i < element; i++) {
|
||||
auto key = layout->GetKey(i);
|
||||
if (key.IsString()) {
|
||||
result += EcmaStringAccessor(key).ToCString();
|
||||
uint64_t value = EcmaStringAccessor(key).GetHashcode();
|
||||
value <<= sizeof(uint32_t) * BITS_PER_BYTE;
|
||||
auto attr = layout->GetAttr(i);
|
||||
result += static_cast<int32_t>(attr.GetTrackType());
|
||||
result += attr.GetPropertyMetaData();
|
||||
auto defaultAttr = PropertyAttributes(attr.GetPropertyMetaData());
|
||||
defaultAttr.SetTrackType(attr.GetTrackType());
|
||||
value += defaultAttr.GetValue();
|
||||
result += ToCString(value);
|
||||
} else if (key.IsSymbol()) {
|
||||
result += JSSymbol::Cast(key)->GetPrivateId();
|
||||
auto attr = layout->GetAttr(i);
|
||||
|
@ -475,6 +475,10 @@ public:
|
||||
const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
|
||||
PropertyAttributes &attr);
|
||||
|
||||
static void UpdateFieldType(JSHClass *hclass, const PropertyAttributes &attr);
|
||||
static JSHClass *FindFieldOwnHClass(JSHClass *hclass, const PropertyAttributes &attr);
|
||||
static void VisitAndUpdateLayout(JSHClass *ownHClass, const PropertyAttributes &attr);
|
||||
|
||||
static JSHandle<JSTaggedValue> EnableProtoChangeMarker(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
|
||||
static JSHandle<JSTaggedValue> EnablePHCProtoChangeMarker(
|
||||
const JSThread *thread, const JSHandle<JSHClass> &protoClass);
|
||||
@ -504,21 +508,13 @@ public:
|
||||
static void RefreshUsers(const JSThread *thread, const JSHandle<JSHClass> &oldHclass,
|
||||
const JSHandle<JSHClass> &newHclass);
|
||||
|
||||
void InitTSInheritInfo(const JSThread *thread);
|
||||
|
||||
bool PUBLIC_API HasTSSubtyping() const;
|
||||
|
||||
bool IsTSIHCWithInheritInfo() const;
|
||||
|
||||
static void CopyTSInheritInfo(const JSThread *thread, const JSHandle<JSHClass> &oldHClass,
|
||||
JSHandle<JSHClass> &newHClass);
|
||||
|
||||
static JSHandle<JSTaggedValue> ParseKeyFromPGOCString(ObjectFactory* factory,
|
||||
const CString& key,
|
||||
const PGOHandler& handler);
|
||||
|
||||
inline void ClearBitField()
|
||||
{
|
||||
SetProfileType(0ULL);
|
||||
SetBitField(0UL);
|
||||
SetBitField1(0UL);
|
||||
}
|
||||
@ -1977,9 +1973,8 @@ public:
|
||||
ACCESSORS(Parent, PARENT_OFFSET, PROTO_CHANGE_MARKER_OFFSET);
|
||||
ACCESSORS(ProtoChangeMarker, PROTO_CHANGE_MARKER_OFFSET, PROTO_CHANGE_DETAILS_OFFSET);
|
||||
ACCESSORS(ProtoChangeDetails, PROTO_CHANGE_DETAILS_OFFSET, ENUM_CACHE_OFFSET);
|
||||
ACCESSORS(EnumCache, ENUM_CACHE_OFFSET, SUPERS_OFFSET);
|
||||
ACCESSORS(Supers, SUPERS_OFFSET, VTABLE_OFFSET);
|
||||
ACCESSORS(VTable, VTABLE_OFFSET, BIT_FIELD_OFFSET);
|
||||
ACCESSORS(EnumCache, ENUM_CACHE_OFFSET, PROFILE_TYPE);
|
||||
ACCESSORS_PRIMITIVE_FIELD(ProfileType, uint64_t, PROFILE_TYPE, BIT_FIELD_OFFSET);
|
||||
ACCESSORS_PRIMITIVE_FIELD(BitField, uint32_t, BIT_FIELD_OFFSET, BIT_FIELD1_OFFSET);
|
||||
ACCESSORS_PRIMITIVE_FIELD(BitField1, uint32_t, BIT_FIELD1_OFFSET, LAST_OFFSET);
|
||||
DEFINE_ALIGN_SIZE(LAST_OFFSET);
|
||||
@ -2019,13 +2014,11 @@ public:
|
||||
const HClassLayoutDesc* desc);
|
||||
static bool DumpRootHClassByPGO(const JSHClass* hclass, HClassLayoutDesc* desc);
|
||||
static bool DumpChildHClassByPGO(const JSHClass* hclass, HClassLayoutDesc* desc);
|
||||
static bool UpdateRootLayoutDescByPGO(const JSHClass* hclass,
|
||||
const PGOHClassTreeDesc* treeDesc,
|
||||
HClassLayoutDesc* rootDesc);
|
||||
static bool UpdateRootLayoutDescByPGO(const JSHClass* hclass, HClassLayoutDesc* rootDesc);
|
||||
static bool UpdateChildLayoutDescByPGO(const JSHClass* hclass, HClassLayoutDesc* childDesc);
|
||||
static CString DumpToString(JSTaggedType hclassVal);
|
||||
|
||||
DECL_VISIT_OBJECT(PROTOTYPE_OFFSET, BIT_FIELD_OFFSET);
|
||||
DECL_VISIT_OBJECT(PROTOTYPE_OFFSET, PROFILE_TYPE);
|
||||
inline JSHClass *FindProtoTransitions(const JSTaggedValue &key, const JSTaggedValue &proto);
|
||||
inline bool HasTransitions() const
|
||||
{
|
||||
|
@ -415,7 +415,9 @@ JSHandle<JSFunction> ClassHelper::DefineClassFromExtractor(JSThread *thread, con
|
||||
for (uint32_t index = 0; index < nonStaticLength; ++index) {
|
||||
propValue.Update(nonStaticProperties->Get(index));
|
||||
if (propValue->IsJSFunction()) {
|
||||
JSHandle<JSFunction> propFunc = factory->CloneJSFunction(JSHandle<JSFunction>::Cast(propValue));
|
||||
auto literalFunc = JSHandle<JSFunction>::Cast(propValue);
|
||||
JSHandle<JSFunction> propFunc = factory->CloneJSFunction(literalFunc);
|
||||
JSFunction::UpdateProfileTypeInfoCell(thread, literalFunc, propFunc);
|
||||
propFunc->SetHomeObject(thread, prototype);
|
||||
propFunc->SetLexicalEnv(thread, lexenv);
|
||||
propValue.Update(propFunc);
|
||||
@ -441,7 +443,9 @@ JSHandle<JSFunction> ClassHelper::DefineClassFromExtractor(JSThread *thread, con
|
||||
for (uint32_t index = 0; index < staticLength; ++index) {
|
||||
propValue.Update(staticProperties->Get(index));
|
||||
if (propValue->IsJSFunction()) {
|
||||
JSHandle<JSFunction> propFunc = factory->CloneJSFunction(JSHandle<JSFunction>::Cast(propValue));
|
||||
auto literalFunc = JSHandle<JSFunction>::Cast(propValue);
|
||||
JSHandle<JSFunction> propFunc = factory->CloneJSFunction(literalFunc);
|
||||
JSFunction::UpdateProfileTypeInfoCell(thread, literalFunc, propFunc);
|
||||
propFunc->SetHomeObject(thread, constructor);
|
||||
propFunc->SetLexicalEnv(thread, lexenv);
|
||||
propValue.Update(propFunc);
|
||||
@ -508,7 +512,9 @@ JSHandle<JSFunction> ClassHelper::DefineClassWithIHClass(JSThread *thread,
|
||||
for (uint32_t index = 0; index < nonStaticLength; ++index) {
|
||||
propValue.Update(nonStaticProperties->Get(index));
|
||||
if (propValue->IsJSFunction()) {
|
||||
JSHandle<JSFunction> propFunc = factory->CloneJSFunction(JSHandle<JSFunction>::Cast(propValue));
|
||||
auto literalFunc = JSHandle<JSFunction>::Cast(propValue);
|
||||
JSHandle<JSFunction> propFunc = factory->CloneJSFunction(literalFunc);
|
||||
JSFunction::UpdateProfileTypeInfoCell(thread, literalFunc, propFunc);
|
||||
propFunc->SetHomeObject(thread, prototype);
|
||||
propFunc->SetLexicalEnv(thread, lexenv);
|
||||
propValue.Update(propFunc);
|
||||
@ -535,7 +541,9 @@ JSHandle<JSFunction> ClassHelper::DefineClassWithIHClass(JSThread *thread,
|
||||
for (uint32_t index = 0; index < staticLength; ++index) {
|
||||
propValue.Update(staticProperties->Get(index));
|
||||
if (propValue->IsJSFunction()) {
|
||||
JSHandle<JSFunction> propFunc = factory->CloneJSFunction(JSHandle<JSFunction>::Cast(propValue));
|
||||
auto literalFunc = JSHandle<JSFunction>::Cast(propValue);
|
||||
JSHandle<JSFunction> propFunc = factory->CloneJSFunction(literalFunc);
|
||||
JSFunction::UpdateProfileTypeInfoCell(thread, literalFunc, propFunc);
|
||||
propFunc->SetHomeObject(thread, constructor);
|
||||
propFunc->SetLexicalEnv(thread, lexenv);
|
||||
propValue.Update(propFunc);
|
||||
|
@ -626,13 +626,8 @@ public:
|
||||
}
|
||||
}
|
||||
JSHandle<JSObject> obj = JSObject::CreateObjectFromProperties(thread, properties, ihcVal);
|
||||
if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
|
||||
pgo::ApEntityId abcId(0);
|
||||
pgo::PGOProfilerManager::GetInstance()->GetPandaFileId(jsPandaFile->GetJSPandaFileDesc(),
|
||||
abcId);
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileCreateObject(obj.GetTaggedType(), abcId,
|
||||
id.GetOffset());
|
||||
}
|
||||
auto profiler = thread->GetEcmaVM()->GetPGOProfiler();
|
||||
profiler->RecordProfileType(obj->GetClass(), jsPandaFile, id.GetOffset());
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
|
||||
size_t elementsLen = elements->GetLength();
|
||||
|
@ -187,6 +187,22 @@ inline void LayoutInfo::SetIsNotHole(const JSThread *thread, int index)
|
||||
TaggedArray::Set(thread, fixedIdx, attr.GetTaggedValue());
|
||||
}
|
||||
|
||||
inline void LayoutInfo::UpdateTrackTypeAttr(int index, const PropertyAttributes &attr)
|
||||
{
|
||||
uint32_t fixedIdx = GetAttrIndex(index);
|
||||
PropertyAttributes oldAttr(TaggedArray::Get(fixedIdx));
|
||||
oldAttr.SetNormalAttr(attr.GetNormalAttr());
|
||||
oldAttr.SetIsPGODumped(false);
|
||||
TaggedArray::Set(fixedIdx, oldAttr.GetTaggedValue());
|
||||
}
|
||||
|
||||
inline void LayoutInfo::SetIsPGODumped(int index)
|
||||
{
|
||||
uint32_t fixedIdx = GetAttrIndex(index);
|
||||
PropertyAttributes attr(TaggedArray::Get(fixedIdx));
|
||||
attr.SetIsPGODumped(true);
|
||||
TaggedArray::Set(fixedIdx, attr.GetTaggedValue());
|
||||
}
|
||||
|
||||
template<bool checkDuplicateKeys /* = false*/>
|
||||
void LayoutInfo::AddKey(const JSThread *thread, [[maybe_unused]] int index, const JSTaggedValue &key,
|
||||
|
@ -226,16 +226,14 @@ CString LayoutInfo::GetSymbolKeyString(JSTaggedValue key)
|
||||
void LayoutInfo::DumpFieldIndexByPGO(int index, pgo::HClassLayoutDesc* desc)
|
||||
{
|
||||
auto key = GetKey(index);
|
||||
auto attr = GetAttr(index);
|
||||
SetIsPGODumped(index);
|
||||
TrackType type = attr.GetTrackType();
|
||||
int propertyMeta = attr.GetPropertyMetaData();
|
||||
if (key.IsString()) {
|
||||
auto attr = GetAttr(index);
|
||||
TrackType type = attr.GetTrackType();
|
||||
int propertyMeta = attr.GetPropertyMetaData();
|
||||
auto keyString = EcmaStringAccessor(key).ToCString();
|
||||
desc->InsertKeyAndDesc(keyString, PGOHandler(type, propertyMeta, false));
|
||||
} else if (key.IsSymbol()) {
|
||||
auto attr = GetAttr(index);
|
||||
TrackType type = attr.GetTrackType();
|
||||
int propertyMeta = attr.GetPropertyMetaData();
|
||||
auto keyString = GetSymbolKeyString(key);
|
||||
if (keyString.empty()) {
|
||||
return;
|
||||
@ -247,16 +245,17 @@ void LayoutInfo::DumpFieldIndexByPGO(int index, pgo::HClassLayoutDesc* desc)
|
||||
bool LayoutInfo::UpdateFieldIndexByPGO(int index, pgo::HClassLayoutDesc* desc)
|
||||
{
|
||||
auto key = GetKey(index);
|
||||
auto attr = GetAttr(index);
|
||||
if (attr.IsPGODumped()) {
|
||||
return true;
|
||||
}
|
||||
SetIsPGODumped(index);
|
||||
TrackType type = attr.GetTrackType();
|
||||
int propertyMeta = attr.GetPropertyMetaData();
|
||||
if (key.IsString()) {
|
||||
auto attr = GetAttr(index);
|
||||
TrackType type = attr.GetTrackType();
|
||||
int propertyMeta = attr.GetPropertyMetaData();
|
||||
auto keyString = EcmaStringAccessor(key).ToCString();
|
||||
return desc->UpdateKeyAndDesc(keyString, PGOHandler(type, propertyMeta, false));
|
||||
} else if (key.IsSymbol()) {
|
||||
auto attr = GetAttr(index);
|
||||
TrackType type = attr.GetTrackType();
|
||||
int propertyMeta = attr.GetPropertyMetaData();
|
||||
auto keyString = GetSymbolKeyString(key);
|
||||
if (keyString.empty()) {
|
||||
return false;
|
||||
|
@ -67,6 +67,8 @@ public:
|
||||
template<bool checkDuplicateKeys = false>
|
||||
void AddKey(const JSThread *thread, int index, const JSTaggedValue &key, const PropertyAttributes &attr);
|
||||
void SetIsNotHole(const JSThread *thread, int index);
|
||||
void UpdateTrackTypeAttr(int index, const PropertyAttributes &attr);
|
||||
void SetIsPGODumped(int index);
|
||||
|
||||
inline uint32_t GetLength() const
|
||||
{
|
||||
|
@ -41,18 +41,16 @@
|
||||
#include "macros.h"
|
||||
|
||||
namespace panda::ecmascript::pgo {
|
||||
void PGOProfiler::ProfileCreateObject(JSTaggedType object, ApEntityId abcId, int32_t traceId)
|
||||
void PGOProfiler::RecordProfileType(JSHClass *hclass, JSPandaFile *pandaFile, int32_t traceId)
|
||||
{
|
||||
if (!isEnable_) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSTaggedValue objectValue(object);
|
||||
if (objectValue.IsJSObject()) {
|
||||
auto hclass = objectValue.GetTaggedObject()->GetClass();
|
||||
hclass->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
|
||||
ProfileType traceType(abcId, traceId, ProfileType::Kind::ObjectLiteralId, true);
|
||||
InsertProfileTypeSafe(JSTaggedType(hclass), JSTaggedType(hclass), traceType);
|
||||
ProfileType traceType = GetProfileType(hclass);
|
||||
if (traceType.IsNone()) {
|
||||
pgo::ApEntityId abcId(0);
|
||||
pgo::PGOProfilerManager::GetInstance()->GetPandaFileId(pandaFile->GetJSPandaFileDesc(), abcId);
|
||||
SetRootProfileType(hclass, abcId, traceId, ProfileType::Kind::ObjectLiteralId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,31 +75,19 @@ void PGOProfiler::ProfileDefineClass(JSTaggedType ctor)
|
||||
return;
|
||||
}
|
||||
|
||||
auto ctorMethodHClass = ctorFunc->GetClass();
|
||||
ctorMethodHClass->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
|
||||
auto ctorRootHClass = JSTaggedType(ctorMethodHClass);
|
||||
if (GetProfileType(ctorRootHClass, ctorRootHClass).IsNone()) {
|
||||
ProfileType ctorProfileType(GetMethodAbcId(ctorFunc), entityId, ProfileType::Kind::ConstructorId, true);
|
||||
InsertProfileTypeSafe(ctorRootHClass, ctorRootHClass, ctorProfileType);
|
||||
}
|
||||
auto abcId = GetMethodAbcId(ctorFunc);
|
||||
auto chc = ctorFunc->GetClass();
|
||||
SetRootProfileType(chc, abcId, entityId, ProfileType::Kind::ConstructorId);
|
||||
|
||||
auto protoOrHClass = ctorFunc->GetProtoOrHClass();
|
||||
if (protoOrHClass.IsJSHClass()) {
|
||||
auto ihc = JSHClass::Cast(protoOrHClass.GetTaggedObject());
|
||||
ihc->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
|
||||
auto localRootHClass = JSTaggedType(ihc);
|
||||
ProfileType localProfileType(GetMethodAbcId(ctorFunc), entityId, ProfileType::Kind::ClassId, true);
|
||||
InsertProfileTypeSafe(localRootHClass, localRootHClass, localProfileType);
|
||||
SetRootProfileType(ihc, abcId, entityId, ProfileType::Kind::ClassId);
|
||||
protoOrHClass = ihc->GetProto();
|
||||
}
|
||||
if (protoOrHClass.IsJSObject()) {
|
||||
auto prototypeHClass = protoOrHClass.GetTaggedObject()->GetClass();
|
||||
prototypeHClass->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
|
||||
auto protoRootHClass = JSTaggedType(prototypeHClass);
|
||||
if (GetProfileType(protoRootHClass, protoRootHClass).IsNone()) {
|
||||
ProfileType protoProfileType(GetMethodAbcId(ctorFunc), entityId, ProfileType::Kind::PrototypeId, true);
|
||||
InsertProfileTypeSafe(protoRootHClass, protoRootHClass, protoProfileType);
|
||||
}
|
||||
auto phc = protoOrHClass.GetTaggedObject()->GetClass();
|
||||
SetRootProfileType(phc, abcId, entityId, ProfileType::Kind::PrototypeId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,11 +116,8 @@ void PGOProfiler::ProfileClassRootHClass(JSTaggedType ctor, JSTaggedType rootHcV
|
||||
}
|
||||
|
||||
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);
|
||||
InsertProfileTypeSafe(rootHcValue, rootHcValue, ihcProfileType);
|
||||
}
|
||||
auto abcId = GetMethodAbcId(ctorFunc);
|
||||
SetRootProfileType(rootHc, abcId, entityId, kind);
|
||||
}
|
||||
|
||||
void PGOProfiler::ProfileProtoTransitionClass(JSHandle<JSFunction> func,
|
||||
@ -238,22 +221,11 @@ void PGOProfiler::UpdateRootProfileTypeSafe(JSHClass* oldHClass, JSHClass* newHC
|
||||
return;
|
||||
}
|
||||
auto oldRootHClass = JSHClass::FindRootHClass(oldHClass);
|
||||
auto iter = tracedProfiles_.find(JSTaggedType(oldRootHClass));
|
||||
if (iter == tracedProfiles_.end()) {
|
||||
return;
|
||||
ProfileType oldPt = GetProfileType(oldRootHClass);
|
||||
if (oldPt.IsRootType()) {
|
||||
newHClass->SetProfileType(oldPt.GetRaw());
|
||||
oldRootHClass->SetProfileType(0);
|
||||
}
|
||||
auto generator = iter->second;
|
||||
auto rootProfileType = generator->GetProfileType(JSTaggedType(oldRootHClass));
|
||||
{
|
||||
LockHolder lock(tracedProfilesMutex_);
|
||||
nativeAreaAllocator_->Delete(iter->second);
|
||||
tracedProfiles_.erase(iter);
|
||||
}
|
||||
if (rootProfileType.IsNone()) {
|
||||
return;
|
||||
}
|
||||
newHClass->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
|
||||
InsertProfileTypeSafe(JSTaggedType(newHClass), JSTaggedType(newHClass), rootProfileType);
|
||||
}
|
||||
|
||||
void PGOProfiler::UpdateTrackElementsKind(JSTaggedValue trackInfoVal, ElementsKind newKind)
|
||||
@ -1229,11 +1201,10 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco
|
||||
void PGOProfiler::TryDumpProtoTransitionType(JSHClass *hclass)
|
||||
{
|
||||
JSHClass *ihc1 = JSHClass::FindRootHClass(hclass);
|
||||
auto transitionType = GetProfileTypeSafe(JSTaggedType(ihc1), JSTaggedType(ihc1));
|
||||
if (transitionType.IsNone() || !transitionType.IsTransitionClassType()) {
|
||||
auto transitionType = GetProfileType(ihc1, true);
|
||||
if (!transitionType.IsRootType() || !transitionType.IsTransitionClassType()) {
|
||||
return;
|
||||
}
|
||||
ASSERT(transitionType.IsRootType());
|
||||
JSTaggedValue phc1Root = JSHClass::FindProtoRootHClass(ihc1);
|
||||
|
||||
auto thread = vm_->GetJSThread();
|
||||
@ -1243,21 +1214,23 @@ void PGOProfiler::TryDumpProtoTransitionType(JSHClass *hclass)
|
||||
if ((ihc0 == 0) || (baseIhc == 0)) {
|
||||
return;
|
||||
}
|
||||
UpdateLayout(JSHClass::Cast(JSTaggedValue(ihc0).GetTaggedObject()));
|
||||
auto ihc0Obj = JSHClass::Cast(JSTaggedValue(ihc0).GetTaggedObject());
|
||||
auto baseIhcObj = JSHClass::Cast(JSTaggedValue(baseIhc).GetTaggedObject());
|
||||
UpdateLayout(ihc0Obj);
|
||||
UpdateLayout(ihc1);
|
||||
UpdateLayout(JSHClass::Cast(JSTaggedValue(baseIhc).GetTaggedObject()));
|
||||
UpdateLayout(baseIhcObj);
|
||||
|
||||
auto ihc0RootType = GetProfileTypeSafe(ihc0, ihc0);
|
||||
auto ihc0RootType = GetProfileType(ihc0Obj);
|
||||
ASSERT(ihc0RootType.IsRootType());
|
||||
auto transitionProtoType = GetProfileTypeSafe(phc1Root.GetRawData(), phc1Root.GetRawData());
|
||||
auto transitionProtoType = GetProfileType(JSHClass::Cast(phc1Root.GetTaggedObject()), true);
|
||||
ASSERT(transitionProtoType.IsRootType());
|
||||
auto baseRootHClass = JSHClass::FindRootHClass(JSHClass::Cast(JSTaggedValue(baseIhc).GetTaggedObject()));
|
||||
auto baseRootType = GetProfileTypeSafe(JSTaggedType(baseRootHClass), JSTaggedType(baseRootHClass));
|
||||
auto baseRootHClass = JSHClass::FindRootHClass(baseIhcObj);
|
||||
auto baseRootType = GetProfileType(baseRootHClass, true);
|
||||
if (!baseRootType.IsRootType()) {
|
||||
LOG_ECMA(WARN) << "Unsupported prototypes which cannot be recorded!";
|
||||
return;
|
||||
}
|
||||
auto baseType = GetProfileTypeSafe(JSTaggedType(baseRootHClass), baseIhc);
|
||||
auto baseType = GetProfileType(baseIhcObj);
|
||||
ASSERT(!baseType.IsNone());
|
||||
PGOProtoTransitionType protoTransitionType(ihc0RootType);
|
||||
protoTransitionType.SetBaseType(baseRootType, baseType);
|
||||
@ -1301,55 +1274,48 @@ void PGOProfiler::DumpDefineClass(ApEntityId abcId, const CString &recordName, E
|
||||
if (object->GetClass()->IsJSFunction()) {
|
||||
JSFunction *ctorFunction = JSFunction::Cast(object);
|
||||
auto ctorMethod = ctorFunction->GetMethod();
|
||||
if (!ctorMethod.IsMethod()) {
|
||||
return;
|
||||
}
|
||||
if (!FunctionKindVerify(ctorFunction)) {
|
||||
if (!ctorMethod.IsMethod() || !FunctionKindVerify(ctorFunction)) {
|
||||
return;
|
||||
}
|
||||
ApEntityId ctorAbcId = GetMethodAbcId(ctorFunction);
|
||||
auto ctorJSMethod = Method::Cast(ctorMethod);
|
||||
auto ctorMethodId = ctorJSMethod->GetMethodId().GetOffset();
|
||||
ProfileType recordType = GetRecordProfileType(abcId, recordName);
|
||||
|
||||
auto localType = PGOSampleType::CreateProfileType(ctorAbcId, ctorMethodId, ProfileType::Kind::ClassId, true);
|
||||
PGODefineOpType objDefType(localType.GetProfileType());
|
||||
auto localType = ProfileType(ctorAbcId, ctorMethodId, ProfileType::Kind::ClassId, true);
|
||||
if (IsSkippableObjectTypeSafe(localType)) {
|
||||
return;
|
||||
}
|
||||
PGODefineOpType objDefType(localType);
|
||||
auto protoOrHClass = ctorFunction->GetProtoOrHClass();
|
||||
if (protoOrHClass.IsJSHClass()) {
|
||||
auto hclass = JSHClass::Cast(protoOrHClass.GetTaggedObject());
|
||||
auto result = InsertProfileTypeSafe(JSTaggedType(hclass), JSTaggedType(hclass), localType.GetProfileType());
|
||||
if (!result) {
|
||||
LOG_COMPILER(DEBUG)
|
||||
<< "DumpDefineClass InsertFail, May already exist , Method Name "
|
||||
<< Method::Cast(ctorFunction->GetMethod())->GetMethodName();
|
||||
}
|
||||
recordInfos_->AddRootLayout(JSTaggedType(hclass), localType.GetProfileType());
|
||||
protoOrHClass = hclass->GetProto();
|
||||
auto ihc = JSHClass::Cast(protoOrHClass.GetTaggedObject());
|
||||
SetRootProfileType(ihc, ctorAbcId, ctorMethodId, ProfileType::Kind::ClassId);
|
||||
recordInfos_->AddRootLayout(JSTaggedType(ihc), localType);
|
||||
protoOrHClass = ihc->GetProto();
|
||||
}
|
||||
|
||||
auto ctorHClass = ctorFunction->GetJSHClass();
|
||||
auto ctorRootHClass = JSTaggedType(JSHClass::FindRootHClass(ctorHClass));
|
||||
auto ctorType = GetProfileTypeSafe(ctorRootHClass, ctorRootHClass);
|
||||
if (ctorType.IsNone()) {
|
||||
auto ctorRootHClass = JSHClass::FindRootHClass(ctorFunction->GetJSHClass());
|
||||
auto ctorType = GetProfileType(ctorRootHClass);
|
||||
if (!ctorType.IsRootType()) {
|
||||
LOG_ECMA(DEBUG) << "The profileType of constructor root hclass was not found.";
|
||||
} else {
|
||||
objDefType.SetCtorPt(ctorType);
|
||||
recordInfos_->AddRootLayout(ctorRootHClass, ctorType);
|
||||
recordInfos_->AddRootLayout(JSTaggedType(ctorRootHClass), ctorType);
|
||||
}
|
||||
|
||||
if (protoOrHClass.IsJSObject()) {
|
||||
auto prototypeObj = JSObject::Cast(protoOrHClass);
|
||||
auto prototypeHClass = prototypeObj->GetClass();
|
||||
auto prototypeRootHClass = JSTaggedType(JSHClass::FindRootHClass(prototypeHClass));
|
||||
auto prototypeType = GetProfileType(prototypeRootHClass, prototypeRootHClass);
|
||||
if (prototypeType.IsNone()) {
|
||||
auto prototypeHClass = JSObject::Cast(protoOrHClass)->GetClass();
|
||||
auto prototypeRootHClass = JSHClass::FindRootHClass(prototypeHClass);
|
||||
ProfileType prototypeType = GetProfileType(prototypeRootHClass);
|
||||
if (!prototypeType.IsRootType()) {
|
||||
LOG_ECMA(DEBUG) << "The profileType of prototype root hclass was not found.";
|
||||
} else {
|
||||
objDefType.SetProtoTypePt(prototypeType);
|
||||
recordInfos_->AddRootLayout(prototypeRootHClass, prototypeType);
|
||||
recordInfos_->AddRootLayout(JSTaggedType(prototypeRootHClass), prototypeType);
|
||||
}
|
||||
}
|
||||
|
||||
ProfileType recordType = GetRecordProfileType(abcId, recordName);
|
||||
recordInfos_->AddDefine(recordType, methodId, bcOffset, objDefType);
|
||||
}
|
||||
}
|
||||
@ -1367,9 +1333,8 @@ void PGOProfiler::DumpCreateObject(ApEntityId abcId, const CString &recordName,
|
||||
if (object->GetClass()->IsHClass()) {
|
||||
auto newHClass = JSHClass::Cast(object);
|
||||
auto rootHClass = JSHClass::FindRootHClass(newHClass);
|
||||
ASSERT(rootHClass->IsJSObject());
|
||||
auto profileType = GetProfileTypeSafe(JSTaggedType(rootHClass), JSTaggedType(rootHClass));
|
||||
if (profileType.IsNone()) {
|
||||
ProfileType profileType = GetProfileType(rootHClass);
|
||||
if (!profileType.IsRootType()) {
|
||||
return;
|
||||
}
|
||||
ASSERT(profileType.GetKind() == ProfileType::Kind::ObjectLiteralId);
|
||||
@ -1502,27 +1467,26 @@ void PGOProfiler::DumpInstanceof(ApEntityId abcId, const CString &recordName, En
|
||||
void PGOProfiler::UpdateLayout(JSHClass *hclass)
|
||||
{
|
||||
auto parentHClass = hclass->GetParent();
|
||||
if (parentHClass.IsJSHClass()) {
|
||||
if (!GetProfileType(hclass).IsRootType() && parentHClass.IsJSHClass()) {
|
||||
UpdateTransitionLayout(JSHClass::Cast(parentHClass.GetTaggedObject()), hclass);
|
||||
} else {
|
||||
auto rootHClass = JSHClass::FindRootHClass(hclass);
|
||||
auto rootHClassVal = JSTaggedType(rootHClass);
|
||||
auto rootType = GetProfileTypeSafe(rootHClassVal, rootHClassVal);
|
||||
if (rootType.IsNone()) {
|
||||
ProfileType rootType = GetProfileType(rootHClass, true);
|
||||
if (!rootType.IsRootType()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto prototypeHClass = JSHClass::FindProtoRootHClass(rootHClass);
|
||||
if (prototypeHClass.IsJSHClass()) {
|
||||
auto prototypeValue = prototypeHClass.GetRawData();
|
||||
auto prototypeType = GetProfileTypeSafe(prototypeValue, prototypeValue);
|
||||
if (!prototypeType.IsNone()) {
|
||||
auto prototypeObject = JSHClass::Cast(prototypeHClass.GetTaggedObject());
|
||||
ProfileType prototypeType = GetProfileType(prototypeObject, true);
|
||||
if (prototypeType.IsRootType()) {
|
||||
recordInfos_->AddRootPtType(rootType, prototypeType);
|
||||
UpdateLayout(JSHClass::Cast(prototypeHClass.GetTaggedObject()));
|
||||
}
|
||||
}
|
||||
|
||||
auto curType = GetOrInsertProfileTypeSafe(rootHClassVal, JSTaggedType(hclass));
|
||||
auto curType = GetOrInsertProfileType(hclass, rootType);
|
||||
recordInfos_->UpdateLayout(rootType, JSTaggedType(hclass), curType);
|
||||
}
|
||||
}
|
||||
@ -1530,49 +1494,45 @@ void PGOProfiler::UpdateLayout(JSHClass *hclass)
|
||||
void PGOProfiler::UpdateTransitionLayout(JSHClass* parent, JSHClass* child)
|
||||
{
|
||||
auto rootHClass = JSHClass::FindRootHClass(parent);
|
||||
auto rootHClassVal = JSTaggedType(rootHClass);
|
||||
auto rootType = GetProfileTypeSafe(rootHClassVal, rootHClassVal);
|
||||
if (rootType.IsNone()) {
|
||||
auto rootType = GetProfileType(rootHClass, true);
|
||||
if (!rootType.IsRootType()) {
|
||||
return;
|
||||
}
|
||||
auto curHClass = JSTaggedType(child);
|
||||
auto curType = GetOrInsertProfileTypeSafe(rootHClassVal, curHClass);
|
||||
CVector<JSTaggedType> hclassVec;
|
||||
CVector<ProfileType> typeVec;
|
||||
hclassVec.push_back(curHClass);
|
||||
typeVec.push_back(curType);
|
||||
CStack<JSHClass *> hclassVec;
|
||||
hclassVec.emplace(child);
|
||||
ASSERT(!GetProfileType(child).IsRootType());
|
||||
hclassVec.emplace(parent);
|
||||
|
||||
auto parentHClass = JSTaggedValue(parent);
|
||||
auto parentHCValue = JSTaggedType(parent);
|
||||
auto parentType = GetOrInsertProfileTypeSafe(rootHClassVal, parentHCValue);
|
||||
while (parentHClass.IsJSHClass()) {
|
||||
parentHClass = JSHClass::Cast(parentHClass.GetTaggedObject())->GetParent();
|
||||
if (!parentHClass.IsJSHClass()) {
|
||||
while (!GetProfileType(parent).IsRootType()) {
|
||||
auto parentHCValue = parent->GetParent();
|
||||
if (!parentHCValue.IsJSHClass()) {
|
||||
break;
|
||||
}
|
||||
hclassVec.push_back(parentHCValue);
|
||||
typeVec.push_back(parentType);
|
||||
parentHCValue = JSTaggedType(parentHClass.GetTaggedObject());
|
||||
parentType = GetOrInsertProfileTypeSafe(rootHClassVal, parentHCValue);
|
||||
parent = JSHClass::Cast(parentHCValue.GetTaggedObject());
|
||||
hclassVec.emplace(parent);
|
||||
}
|
||||
|
||||
auto prototypeHClass = JSHClass::FindProtoRootHClass(rootHClass);
|
||||
if (prototypeHClass.IsJSHClass()) {
|
||||
auto prototypeValue = prototypeHClass.GetRawData();
|
||||
auto prototypeType = GetProfileTypeSafe(prototypeValue, prototypeValue);
|
||||
if (!prototypeType.IsNone()) {
|
||||
auto prototypeRootHClassVal = JSHClass::FindProtoRootHClass(rootHClass);
|
||||
if (prototypeRootHClassVal.IsJSHClass()) {
|
||||
auto prototypeRootHClass = JSHClass::Cast(prototypeRootHClassVal.GetTaggedObject());
|
||||
auto prototypeType = GetProfileType(prototypeRootHClass);
|
||||
if (prototypeType.IsRootType()) {
|
||||
recordInfos_->AddRootPtType(rootType, prototypeType);
|
||||
UpdateLayout(JSHClass::Cast(prototypeHClass.GetTaggedObject()));
|
||||
UpdateLayout(prototypeRootHClass);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t size = static_cast<int32_t>(hclassVec.size());
|
||||
for (int32_t i = size - 1; i >= 0; i--) {
|
||||
curHClass = hclassVec[i];
|
||||
curType = typeVec[i];
|
||||
recordInfos_->UpdateTransitionLayout(rootType, parentHCValue, parentType, curHClass, curType);
|
||||
parentHCValue = curHClass;
|
||||
parentType = curType;
|
||||
parent = hclassVec.top();
|
||||
hclassVec.pop();
|
||||
auto parentType = GetProfileType(parent);
|
||||
while (!hclassVec.empty()) {
|
||||
child = hclassVec.top();
|
||||
hclassVec.pop();
|
||||
auto childType = GetOrInsertProfileType(child, rootType);
|
||||
recordInfos_->UpdateTransitionLayout(
|
||||
rootType, JSTaggedType(parent), parentType, JSTaggedType(child), childType);
|
||||
parentType = childType;
|
||||
parent = child;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1584,26 +1544,19 @@ bool PGOProfiler::AddTransitionObjectInfo(ProfileType recordType,
|
||||
JSHClass* holdTra,
|
||||
PGOSampleType accessorMethod)
|
||||
{
|
||||
auto receiverRootHClass = JSTaggedType(JSHClass::FindRootHClass(receiver));
|
||||
auto receiverRootType = GetProfileTypeSafe(receiverRootHClass, receiverRootHClass);
|
||||
if (receiverRootType.IsNone()) {
|
||||
auto receiverRootType = FindRootProfileType(receiver);
|
||||
if (!receiverRootType.IsRootType()) {
|
||||
return false;
|
||||
}
|
||||
auto receiverType = GetOrInsertProfileTypeSafe(receiverRootHClass, JSTaggedType(receiver));
|
||||
|
||||
auto holdRootHClass = JSTaggedType(JSHClass::FindRootHClass(hold));
|
||||
auto holdRootType = GetProfileTypeSafe(holdRootHClass, holdRootHClass);
|
||||
if (holdRootType.IsNone()) {
|
||||
auto holdRootType = FindRootProfileType(hold);
|
||||
if (!holdRootType.IsRootType()) {
|
||||
return true;
|
||||
}
|
||||
auto holdType = GetOrInsertProfileTypeSafe(holdRootHClass, JSTaggedType(hold));
|
||||
|
||||
auto holdTraRootHClass = JSTaggedType(JSHClass::FindRootHClass(holdTra));
|
||||
auto holdTraRootType = GetProfileTypeSafe(holdTraRootHClass, holdTraRootHClass);
|
||||
if (holdTraRootType.IsNone()) {
|
||||
return true;
|
||||
}
|
||||
auto holdTraType = GetOrInsertProfileTypeSafe(holdTraRootHClass, JSTaggedType(holdTra));
|
||||
auto receiverType = GetOrInsertProfileType(receiver, receiverRootType);
|
||||
auto holdType = GetOrInsertProfileType(hold, holdRootType);
|
||||
auto holdTraType = GetOrInsertProfileType(holdTra, holdRootType);
|
||||
|
||||
if (receiver != hold) {
|
||||
UpdateLayout(receiver);
|
||||
@ -1615,7 +1568,7 @@ bool PGOProfiler::AddTransitionObjectInfo(ProfileType recordType,
|
||||
UpdateTransitionLayout(hold, holdTra);
|
||||
}
|
||||
|
||||
PGOObjectInfo info(receiverRootType, receiverType, holdRootType, holdType, holdTraRootType, holdTraType,
|
||||
PGOObjectInfo info(receiverRootType, receiverType, holdRootType, holdType, holdRootType, holdTraType,
|
||||
accessorMethod);
|
||||
UpdatePrototypeChainInfo(receiver, hold, info);
|
||||
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
|
||||
@ -1643,12 +1596,11 @@ void PGOProfiler::UpdatePrototypeChainInfo(JSHClass *receiver, JSHClass *holder,
|
||||
if (protoHClass == holder) {
|
||||
break;
|
||||
}
|
||||
auto protoRootHClass = JSTaggedType(JSHClass::FindRootHClass(protoHClass));
|
||||
auto protoRootType = GetProfileTypeSafe(protoRootHClass, protoRootHClass);
|
||||
if (protoRootType.IsNone()) {
|
||||
auto protoRootType = FindRootProfileType(protoHClass);
|
||||
if (!protoRootType.IsRootType()) {
|
||||
break;
|
||||
}
|
||||
auto protoType = GetOrInsertProfileTypeSafe(protoRootHClass, JSTaggedType(protoHClass));
|
||||
auto protoType = GetOrInsertProfileType(protoHClass, protoRootType);
|
||||
protoChain.emplace_back(protoRootType, protoType);
|
||||
proto = JSHClass::FindProtoHClass(protoHClass);
|
||||
}
|
||||
@ -1817,82 +1769,51 @@ bool PGOProfiler::IsRecoredTransRootType(ProfileType type)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PGOProfiler::InsertProfileTypeSafe(JSTaggedType root, JSTaggedType child, ProfileType traceType)
|
||||
void PGOProfiler::SetRootProfileType(JSHClass *root, ApEntityId abcId, uint32_t type, ProfileType::Kind kind)
|
||||
{
|
||||
if (!isEnable_) {
|
||||
return false;
|
||||
}
|
||||
if (IsRecoredTransRootType(traceType)) {
|
||||
return false;
|
||||
}
|
||||
auto iter = tracedProfiles_.find(root);
|
||||
if (iter != tracedProfiles_.end()) {
|
||||
auto generator = iter->second;
|
||||
return generator->InsertProfileType(child, traceType);
|
||||
} else {
|
||||
LockHolder lock(tracedProfilesMutex_);
|
||||
auto generator = nativeAreaAllocator_->New<PGOTypeGenerator>();
|
||||
generator->InsertProfileType(child, traceType);
|
||||
tracedProfiles_.emplace(root, generator);
|
||||
return true;
|
||||
ProfileType traceType(root->GetProfileType());
|
||||
if (traceType.IsNone()) {
|
||||
traceType = ProfileType(abcId, type, kind, true);
|
||||
if (IsRecoredTransRootType(traceType)) {
|
||||
return;
|
||||
}
|
||||
root->SetProfileType(traceType.GetRaw());
|
||||
}
|
||||
}
|
||||
|
||||
ProfileType PGOProfiler::GetProfileType(JSTaggedType root, JSTaggedType child)
|
||||
ProfileType PGOProfiler::FindRootProfileType(JSHClass *hclass)
|
||||
{
|
||||
auto iter = tracedProfiles_.find(root);
|
||||
if (iter == tracedProfiles_.end()) {
|
||||
return ProfileType::PROFILE_TYPE_NONE;
|
||||
auto rootHClass = JSHClass::FindRootHClass(hclass);
|
||||
return GetProfileType(rootHClass, true);
|
||||
}
|
||||
|
||||
ProfileType PGOProfiler::GetOrInsertProfileType(JSHClass *child, ProfileType rootType)
|
||||
{
|
||||
ProfileType childType = GetProfileType(child);
|
||||
if (childType.IsNone()) {
|
||||
ASSERT(rootType.IsRootType());
|
||||
childType = PGOTypeGenerator::GenerateProfileType(JSTaggedType(child), rootType);
|
||||
child->SetProfileType(childType.GetRaw());
|
||||
}
|
||||
auto generator = iter->second;
|
||||
auto result = generator->GetProfileType(child);
|
||||
if (IsSkippableObjectTypeSafe(result)) {
|
||||
return ProfileType::PROFILE_TYPE_NONE;
|
||||
return childType;
|
||||
}
|
||||
|
||||
ProfileType PGOProfiler::GetProfileType(JSHClass *hclass, bool check)
|
||||
{
|
||||
auto result = ProfileType(hclass->GetProfileType());
|
||||
if (check) {
|
||||
if (IsSkippableObjectTypeSafe(result)) {
|
||||
result = ProfileType::PROFILE_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ProfileType PGOProfiler::GetProfileTypeSafe(JSTaggedType root, JSTaggedType child)
|
||||
{
|
||||
LockHolder lock(tracedProfilesMutex_);
|
||||
return GetProfileType(root, child);
|
||||
}
|
||||
|
||||
ProfileType PGOProfiler::GetOrInsertProfileTypeSafe(JSTaggedType root, JSTaggedType child)
|
||||
{
|
||||
LockHolder lock(tracedProfilesMutex_);
|
||||
auto iter = tracedProfiles_.find(root);
|
||||
if (iter == tracedProfiles_.end()) {
|
||||
return ProfileType::PROFILE_TYPE_NONE;
|
||||
}
|
||||
auto generator = iter->second;
|
||||
auto rootType = generator->GetProfileType(root);
|
||||
if (rootType.IsNone()) {
|
||||
return ProfileType::PROFILE_TYPE_NONE;
|
||||
}
|
||||
return generator->GenerateProfileType(rootType, child);
|
||||
}
|
||||
|
||||
void PGOProfiler::ProcessReferences(const WeakRootVisitor &visitor)
|
||||
{
|
||||
if (!isEnable_) {
|
||||
return;
|
||||
}
|
||||
for (auto iter = tracedProfiles_.begin(); iter != tracedProfiles_.end();) {
|
||||
JSTaggedType object = iter->first;
|
||||
auto fwd = visitor(reinterpret_cast<TaggedObject *>(object));
|
||||
if (fwd == nullptr) {
|
||||
nativeAreaAllocator_->Delete(iter->second);
|
||||
iter = tracedProfiles_.erase(iter);
|
||||
continue;
|
||||
}
|
||||
if (fwd != reinterpret_cast<TaggedObject *>(object)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
auto generator = iter->second;
|
||||
generator->ProcessReferences(visitor);
|
||||
++iter;
|
||||
}
|
||||
preDumpWorkList_.Iterate([this, &visitor](WorkNode *node) {
|
||||
auto object = reinterpret_cast<TaggedObject *>(node->GetValue());
|
||||
auto fwd = visitor(object);
|
||||
@ -1933,9 +1854,6 @@ PGOProfiler::PGOProfiler(EcmaVM* vm, bool isEnable)
|
||||
PGOProfiler::~PGOProfiler()
|
||||
{
|
||||
Reset(false);
|
||||
for (auto iter : tracedProfiles_) {
|
||||
nativeAreaAllocator_->Delete(iter.second);
|
||||
}
|
||||
}
|
||||
|
||||
void PGOProfiler::Reset(bool isEnable)
|
||||
|
@ -57,8 +57,9 @@ public:
|
||||
|
||||
virtual ~PGOProfiler();
|
||||
|
||||
void PUBLIC_API RecordProfileType(JSHClass *hclass, JSPandaFile *pandaFile, int32_t traceId);
|
||||
|
||||
static ProfileType CreateRecordProfileType(ApEntityId abcId, ApEntityId classId);
|
||||
void PUBLIC_API ProfileCreateObject(JSTaggedType object, ApEntityId abcId, int32_t traceId);
|
||||
void ProfileDefineClass(JSTaggedType ctor);
|
||||
void ProfileProtoTransitionClass(JSHandle<JSFunction> func,
|
||||
JSHandle<JSHClass> hclass,
|
||||
@ -216,10 +217,12 @@ private:
|
||||
void AddBuiltinsGlobalInfo(ApEntityId abcId, const CString &recordName, EntityId methodId,
|
||||
int32_t bcOffset, GlobalIndex globalId);
|
||||
|
||||
ProfileType GetProfileType(JSTaggedType root, JSTaggedType child);
|
||||
ProfileType GetProfileTypeSafe(JSTaggedType root, JSTaggedType child);
|
||||
ProfileType GetOrInsertProfileTypeSafe(JSTaggedType root, JSTaggedType child);
|
||||
bool InsertProfileTypeSafe(JSTaggedType root, JSTaggedType child, ProfileType traceType);
|
||||
void SetRootProfileType(JSHClass *root, ApEntityId abcId, uint32_t type, ProfileType::Kind kind);
|
||||
ProfileType FindRootProfileType(JSHClass *hclass);
|
||||
|
||||
ProfileType GetOrInsertProfileType(JSHClass *child, ProfileType rootType);
|
||||
ProfileType GetProfileType(JSHClass *hclass, bool check = false);
|
||||
|
||||
bool IsRecoredTransRootType(ProfileType type);
|
||||
|
||||
class WorkNode;
|
||||
@ -525,8 +528,6 @@ private:
|
||||
ConditionVariable condition_;
|
||||
WorkList dumpWorkList_;
|
||||
WorkList preDumpWorkList_;
|
||||
Mutex tracedProfilesMutex_;
|
||||
CMap<JSTaggedType, PGOTypeGenerator *> tracedProfiles_;
|
||||
std::unique_ptr<PGORecordDetailInfos> recordInfos_;
|
||||
// AOT only supports executing Defineclass bc once currently.
|
||||
// If defineclass executed multiple times, It will gives up collection.
|
||||
|
@ -81,6 +81,7 @@ bool PGOHClassTreeDesc::DumpForRoot(JSTaggedType root, ProfileType rootType)
|
||||
auto rootHClass = JSHClass::Cast(JSTaggedValue(root).GetTaggedObject());
|
||||
if (iter != transitionLayout_.end()) {
|
||||
rootLayout = iter->second;
|
||||
return JSHClass::UpdateRootLayoutDescByPGO(rootHClass, rootLayout);
|
||||
} else {
|
||||
rootLayout = new RootHClassLayoutDesc(rootType, rootHClass->GetObjectType(),
|
||||
rootHClass->GetObjectSizeExcludeInlinedProps());
|
||||
@ -93,13 +94,7 @@ bool PGOHClassTreeDesc::DumpForRoot(JSTaggedType root, ProfileType rootType)
|
||||
bool PGOHClassTreeDesc::DumpForChild(JSTaggedType child, ProfileType childType)
|
||||
{
|
||||
ASSERT(!childType.IsRootType());
|
||||
auto rootType = GetProfileType();
|
||||
auto rootIter = transitionLayout_.find(rootType);
|
||||
auto childHClass = JSHClass::Cast(JSTaggedValue(child).GetTaggedObject());
|
||||
if (rootIter != transitionLayout_.end()) {
|
||||
auto rootLayout = rootIter->second;
|
||||
JSHClass::UpdateRootLayoutDescByPGO(childHClass, this, rootLayout);
|
||||
}
|
||||
|
||||
HClassLayoutDesc *childLayout;
|
||||
auto iter = transitionLayout_.find(childType);
|
||||
@ -134,10 +129,6 @@ bool PGOHClassTreeDesc::UpdateForTransition(
|
||||
if (!DumpForRoot(parent, parentType)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!DumpForChild(parent, parentType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool ret = DumpForChild(child, childType);
|
||||
auto parentLayoutDesc = transitionLayout_.find(parentType)->second;
|
||||
|
@ -35,12 +35,8 @@
|
||||
namespace panda::ecmascript::pgo {
|
||||
class PGOHandler {
|
||||
public:
|
||||
using PropertyMetaDataField = BitField<int, 0, 4>; // 4: property metaData field occupies 4 bits
|
||||
using WritableField = BitField<bool, 0, 1>;
|
||||
using EnumerableField = WritableField::NextFlag;
|
||||
using ConfigurableField = EnumerableField::NextFlag;
|
||||
using IsAccessorField = ConfigurableField::NextFlag;
|
||||
using TrackTypeField = IsAccessorField::NextField<TrackType, PropertyAttributes::TRACK_TYPE_NUM>;
|
||||
using TrackTypeField =
|
||||
PropertyAttributes::PropertyMetaDataField::NextField<TrackType, PropertyAttributes::TRACK_TYPE_NUM>;
|
||||
using IsSymbol = TrackTypeField::NextFlag;
|
||||
|
||||
PGOHandler()
|
||||
@ -120,32 +116,32 @@ public:
|
||||
|
||||
void SetPropertyMeta(int meta)
|
||||
{
|
||||
PropertyMetaDataField::Set(meta, &value_);
|
||||
PropertyAttributes::PropertyMetaDataField::Set(meta, &value_);
|
||||
}
|
||||
|
||||
int GetPropertyMeta() const
|
||||
{
|
||||
return PropertyMetaDataField::Get(value_);
|
||||
return PropertyAttributes::PropertyMetaDataField::Get(value_);
|
||||
}
|
||||
|
||||
bool IsAccessor() const
|
||||
{
|
||||
return IsAccessorField::Get(value_);
|
||||
return PropertyAttributes::IsAccessorField::Get(value_);
|
||||
}
|
||||
|
||||
bool IsWritable() const
|
||||
{
|
||||
return WritableField::Get(value_);
|
||||
return PropertyAttributes::WritableField::Get(value_);
|
||||
}
|
||||
|
||||
bool IsEnumerable() const
|
||||
{
|
||||
return EnumerableField::Get(value_);
|
||||
return PropertyAttributes::EnumerableField::Get(value_);
|
||||
}
|
||||
|
||||
bool IsConfigurable() const
|
||||
{
|
||||
return ConfigurableField::Get(value_);
|
||||
return PropertyAttributes::ConfigurableField::Get(value_);
|
||||
}
|
||||
|
||||
bool operator!=(const PGOHandler &right) const
|
||||
|
@ -26,76 +26,18 @@
|
||||
namespace panda::ecmascript::pgo {
|
||||
class PGOTypeGenerator {
|
||||
public:
|
||||
ProfileType GenerateProfileType(ProfileType rootType, JSTaggedType hclass)
|
||||
static ProfileType GenerateProfileType(JSTaggedType child, ProfileType rootType)
|
||||
{
|
||||
{
|
||||
LockHolder lock(mutex_);
|
||||
auto iter = exsitId_.find(hclass);
|
||||
if (iter != exsitId_.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
CString result = JSHClass::DumpToString(hclass);
|
||||
CString result = JSHClass::DumpToString(child);
|
||||
uint32_t traceId = ComputeHashCode(result);
|
||||
ProfileType type(rootType.GetAbcId(), traceId, rootType.GetKind());
|
||||
LockHolder lock(mutex_);
|
||||
exsitId_.emplace(hclass, type);
|
||||
return type;
|
||||
}
|
||||
|
||||
ProfileType GetProfileType(JSTaggedType hclass)
|
||||
{
|
||||
LockHolder lock(mutex_);
|
||||
auto iter = exsitId_.find(hclass);
|
||||
if (iter != exsitId_.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
return ProfileType::PROFILE_TYPE_NONE;
|
||||
}
|
||||
|
||||
bool InsertProfileType(JSTaggedType hclass, ProfileType type)
|
||||
{
|
||||
LockHolder lock(mutex_);
|
||||
auto iter = exsitId_.find(hclass);
|
||||
if (iter != exsitId_.end()) {
|
||||
return false;
|
||||
}
|
||||
exsitId_.emplace(hclass, type);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UpdateProfileType(JSTaggedType oldHClass, JSTaggedType newHClass)
|
||||
{
|
||||
LockHolder lock(mutex_);
|
||||
auto iter = exsitId_.find(oldHClass);
|
||||
if (iter != exsitId_.end()) {
|
||||
auto profileType = iter->second;
|
||||
exsitId_.erase(oldHClass);
|
||||
exsitId_.emplace(newHClass, profileType);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessReferences(const WeakRootVisitor &visitor)
|
||||
{
|
||||
for (auto iter = exsitId_.begin(); iter != exsitId_.end();) {
|
||||
JSTaggedType object = iter->first;
|
||||
auto fwd = visitor(reinterpret_cast<TaggedObject *>(object));
|
||||
if (fwd == nullptr) {
|
||||
iter = exsitId_.erase(iter);
|
||||
continue;
|
||||
}
|
||||
if (fwd != reinterpret_cast<TaggedObject *>(object)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr uint32_t INVALID_ID = 0;
|
||||
|
||||
uint32_t ComputeHashCode(const CString &string)
|
||||
static uint32_t ComputeHashCode(const CString &string)
|
||||
{
|
||||
uint32_t hash = INVALID_ID;
|
||||
Span<const char> sp(string.c_str(), string.size());
|
||||
@ -105,9 +47,6 @@ private:
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
Mutex mutex_;
|
||||
CMap<JSTaggedType, ProfileType> exsitId_;
|
||||
};
|
||||
} // namespace panda::ecmascript::pgo
|
||||
#endif // ECMASCRIPT_PGO_PROFILER_TYPES_PGO_TYPE_GENERATOR_H
|
||||
|
@ -124,6 +124,7 @@ public:
|
||||
static_assert(FastModeStartField::SIZE == CommonLastBitField::SIZE);
|
||||
using OffsetField = FastModeStartField::NextField<uint32_t, OFFSET_BITFIELD_NUM>; // 17
|
||||
using TrackTypeField = OffsetField::NextField<TrackType, TRACK_TYPE_NUM>; // 20: 3 bits
|
||||
static_assert(TrackTypeField::END_BIT <= sizeof(uint32_t) * BITS_PER_BYTE, "Invalid");
|
||||
|
||||
// normal attr should include SharedFieldTypeField when set to layout
|
||||
static constexpr uint32_t NORMAL_ATTR_BITS = 28;
|
||||
@ -132,7 +133,8 @@ public:
|
||||
using SortedIndexField = SharedFieldTypeField::NextField<uint32_t, OFFSET_BITFIELD_NUM>; // 38: 10 bits
|
||||
using IsConstPropsField = SortedIndexField::NextFlag; // 39
|
||||
using IsNotHoleField = IsConstPropsField::NextFlag; // 40
|
||||
using FastModeLastField = IsNotHoleField;
|
||||
using IsPGODumpedField = IsNotHoleField::NextFlag; // 41
|
||||
using FastModeLastField = IsPGODumpedField;
|
||||
static_assert(
|
||||
FastModeLastField::START_BIT + FastModeLastField::SIZE <= MAX_BIT_SIZE, "Invalid");
|
||||
|
||||
@ -321,6 +323,16 @@ public:
|
||||
TrackTypeField::Set<uint64_t>(type, &value_);
|
||||
}
|
||||
|
||||
inline bool IsPGODumped()
|
||||
{
|
||||
return IsPGODumpedField::Get(value_);
|
||||
}
|
||||
|
||||
inline void SetIsPGODumped(bool isDumped)
|
||||
{
|
||||
IsPGODumpedField::Set<uint64_t>(isDumped, &value_);
|
||||
}
|
||||
|
||||
inline SharedFieldType GetSharedFieldType() const
|
||||
{
|
||||
return SharedFieldTypeField::Get(value_);
|
||||
|
@ -152,8 +152,7 @@ void BaseSerializer::SerializeHClassFieldIndividually(TaggedObject *root, Object
|
||||
break;
|
||||
}
|
||||
case JSHClass::TRANSTIONS_OFFSET:
|
||||
case JSHClass::PARENT_OFFSET:
|
||||
case JSHClass::VTABLE_OFFSET: {
|
||||
case JSHClass::PARENT_OFFSET: {
|
||||
data_->WriteEncodeFlag(EncodeFlag::PRIMITIVE);
|
||||
data_->WriteJSTaggedValue(JSTaggedValue::Undefined());
|
||||
slot++;
|
||||
@ -167,13 +166,6 @@ void BaseSerializer::SerializeHClassFieldIndividually(TaggedObject *root, Object
|
||||
slot++;
|
||||
break;
|
||||
}
|
||||
case JSHClass::SUPERS_OFFSET: {
|
||||
auto globalConst = const_cast<GlobalEnvConstants *>(thread_->GlobalConstants());
|
||||
data_->WriteEncodeFlag(EncodeFlag::ROOT_OBJECT);
|
||||
data_->WriteUint32(globalConst->GetEmptyArrayIndex());
|
||||
slot++;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
SerializeJSTaggedValue(JSTaggedValue(slot.GetTaggedType()));
|
||||
slot++;
|
||||
|
@ -3089,6 +3089,13 @@ int32_t RuntimeStubs::FindElementWithCache(uintptr_t argGlue, JSTaggedType hclas
|
||||
return index;
|
||||
}
|
||||
|
||||
void RuntimeStubs::UpdateFieldType(JSTaggedType hclass, uint64_t value)
|
||||
{
|
||||
auto cls = reinterpret_cast<JSHClass *>(hclass);
|
||||
PropertyAttributes attrValue(value);
|
||||
JSHClass::UpdateFieldType(cls, attrValue);
|
||||
}
|
||||
|
||||
JSTaggedType RuntimeStubs::GetActualArgvNoGC(uintptr_t argGlue)
|
||||
{
|
||||
auto thread = JSThread::GlueToJSThread(argGlue);
|
||||
|
@ -194,6 +194,7 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
|
||||
V(CallDateNow) \
|
||||
V(NumberIsFinite) \
|
||||
V(FindElementWithCache) \
|
||||
V(UpdateFieldType) \
|
||||
V(CreateArrayFromList) \
|
||||
V(StringsAreEquals) \
|
||||
V(BigIntEquals) \
|
||||
@ -595,6 +596,7 @@ public:
|
||||
static double CallDateNow();
|
||||
static int32_t FindElementWithCache(uintptr_t argGlue, JSTaggedType hclass,
|
||||
JSTaggedType key, int32_t num);
|
||||
static void UpdateFieldType(JSTaggedType hclass, uint64_t value);
|
||||
static bool StringsAreEquals(EcmaString *str1, EcmaString *str2);
|
||||
static bool BigIntEquals(JSTaggedType left, JSTaggedType right);
|
||||
static bool BigIntSameValueZero(JSTaggedType key, JSTaggedType other);
|
||||
|
@ -98,6 +98,15 @@ inline void TaggedArray::Set(const JSThread *thread, uint32_t idx, const JSTagge
|
||||
}
|
||||
}
|
||||
|
||||
inline void TaggedArray::Set(uint32_t idx, const JSTaggedValue &value)
|
||||
{
|
||||
ASSERT(idx < GetLength());
|
||||
ASSERT(!value.IsHeapObject());
|
||||
size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
|
||||
|
||||
Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, value.GetRawData());
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> TaggedArray::Append(const JSThread *thread, const JSHandle<TaggedArray> &first,
|
||||
const JSHandle<TaggedArray> &second)
|
||||
{
|
||||
|
@ -43,6 +43,8 @@ public:
|
||||
|
||||
template <bool needBarrier = true>
|
||||
void Set(const JSThread *thread, uint32_t idx, const JSTaggedValue &value);
|
||||
|
||||
void Set(uint32_t idx, const JSTaggedValue &value);
|
||||
void SetBit(const JSThread* thread, uint32_t idx, uint32_t bitOffset, const JSTaggedValue& value);
|
||||
|
||||
static inline JSHandle<TaggedArray> Append(const JSThread *thread, const JSHandle<TaggedArray> &first,
|
||||
|
@ -900,7 +900,7 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
|
||||
break;
|
||||
}
|
||||
case JSType::HCLASS: {
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), JSHClass::SIZE, 10U);
|
||||
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), JSHClass::SIZE, 9U);
|
||||
JSHandle<JSHClass> hclass = factory->NewEcmaHClass(JSHClass::SIZE, JSType::HCLASS, proto);
|
||||
DUMP_FOR_HANDLE(hclass);
|
||||
break;
|
||||
|
@ -128,11 +128,24 @@ public:
|
||||
}
|
||||
|
||||
int FindEntry(const JSTaggedValue &key, const JSTaggedValue &metaData);
|
||||
template <typename Callback>
|
||||
void IterateEntryValue(Callback callback)
|
||||
{
|
||||
auto number = EntriesCount();
|
||||
for (int entry = 0; entry < number; entry++) {
|
||||
JSTaggedValue ret = GetValue(entry);
|
||||
if (ret.IsWeak()) {
|
||||
auto next = ret.GetTaggedWeakRef();
|
||||
callback(JSHClass::Cast(next));
|
||||
}
|
||||
}
|
||||
}
|
||||
static JSHandle<TransitionsDictionary> PutIfAbsent(const JSThread *thread,
|
||||
const JSHandle<TransitionsDictionary> &dictionary,
|
||||
const JSHandle<JSTaggedValue> &key,
|
||||
const JSHandle<JSTaggedValue> &value,
|
||||
const JSHandle<JSTaggedValue> &metaData);
|
||||
// For test
|
||||
static JSHandle<TransitionsDictionary> Remove(const JSThread *thread, const JSHandle<TransitionsDictionary> &table,
|
||||
const JSHandle<JSTaggedValue> &key, const JSTaggedValue &metaData);
|
||||
void Rehash(const JSThread *thread, TransitionsDictionary *newTable);
|
||||
|
@ -338,6 +338,7 @@
|
||||
panda::ecmascript::pgo::ApNameUtils::GetRuntimeApName*;
|
||||
panda::ecmascript::pgo::PGOMethodInfo::CalcChecksum*;
|
||||
panda::ecmascript::pgo::PGOProfiler::ProfileCreateObject*;
|
||||
panda::ecmascript::pgo::PGOProfiler::RecordProfileType*;
|
||||
panda::ecmascript::pgo::PGOProfiler::GetMethodAbcId*;
|
||||
panda::ecmascript::pgo::PGOProfilerManager::GetInstance*;
|
||||
panda::ecmascript::pgo::PGOProfilerManager::MergeApFiles*;
|
||||
|
@ -14,3 +14,5 @@
|
||||
0.5
|
||||
0.5
|
||||
0.5
|
||||
1
|
||||
-20
|
||||
|
@ -14,3 +14,5 @@
|
||||
0.5
|
||||
0.5
|
||||
0.5
|
||||
1
|
||||
-10
|
||||
|
@ -58,3 +58,41 @@ Vec3.set(a.a0, 0.5, 0.5, 0.5);
|
||||
print(a.a0.x)
|
||||
print(a.a0.y)
|
||||
print(a.a0.z)
|
||||
|
||||
class QType {
|
||||
arr: number[];
|
||||
Lastx:number = 0;
|
||||
Lasty:number = 0;
|
||||
Normal: Float64Array[] = new Array();
|
||||
Line: boolean[] = new Array();
|
||||
Edge: number[][] = new Array();
|
||||
}
|
||||
|
||||
let obj = {x: 1, y: 2, z: 3, u: 3, v: 4}
|
||||
|
||||
let next = {x: 1, z: 2, y: 3, v: 3, u: 3}
|
||||
|
||||
let count = 0;
|
||||
let Init = Change;
|
||||
|
||||
function Change(CubeSize: number) {
|
||||
let Q: QType = new QType();
|
||||
Q.arr = []
|
||||
|
||||
Q.arr[0] = base + 0 * -20;
|
||||
if (count == 0) {
|
||||
Q.arr[0] = 1;
|
||||
}
|
||||
|
||||
obj.x = Q.arr[0];
|
||||
print(obj.x);
|
||||
}
|
||||
|
||||
let base = -10
|
||||
if (ArkTools.isAOTCompiled(Init)) {
|
||||
base = -20
|
||||
}
|
||||
|
||||
Init(20)
|
||||
count++;
|
||||
Init(20)
|
||||
|
@ -16,7 +16,6 @@
|
||||
declare function print(a0:any, a1?:any):string;
|
||||
declare class ArkTools {
|
||||
static isTSHClass(o:object):boolean;
|
||||
static hasTSSubtyping(o:object):boolean;
|
||||
}
|
||||
|
||||
class A {
|
||||
@ -38,7 +37,6 @@ function testVTable(o:A) {
|
||||
|
||||
let b = new B();
|
||||
print("Before breaking, B's ihclass is TS:", ArkTools.isTSHClass(b));
|
||||
print("Before breaking, B's ihclass has TS inherit info:", ArkTools.hasTSSubtyping(b));
|
||||
testVTable(b);
|
||||
|
||||
// break TS Chain on object
|
||||
@ -47,5 +45,4 @@ b.foo = function () {
|
||||
}
|
||||
|
||||
print("After breaking, b's hclass is TS:", ArkTools.isTSHClass(b));
|
||||
print("After breaking, b's hclass has TS inherit info:", ArkTools.hasTSSubtyping(b));
|
||||
testVTable(b); // occur deopt
|
||||
|
@ -12,8 +12,6 @@
|
||||
# limitations under the License.
|
||||
|
||||
Before breaking, B's ihclass is TS: false
|
||||
Before breaking, B's ihclass has TS inherit info: false
|
||||
A foo
|
||||
After breaking, b's hclass is TS: false
|
||||
After breaking, b's hclass has TS inherit info: false
|
||||
b foo
|
||||
|
@ -14,9 +14,6 @@
|
||||
*/
|
||||
|
||||
declare function print(a0:any, a1?:any):string;
|
||||
declare class ArkTools {
|
||||
static hasTSSubtyping(o:object):boolean;
|
||||
}
|
||||
|
||||
class A {
|
||||
x:number;
|
||||
@ -36,7 +33,6 @@ function testVTable(o:A) {
|
||||
}
|
||||
|
||||
let b = new B();
|
||||
print("Before breaking, B's ihclass has TS inherit info:", ArkTools.hasTSSubtyping(b));
|
||||
testVTable(b);
|
||||
|
||||
// break TS Chain on prototype and notify through chain
|
||||
@ -45,5 +41,4 @@ Object.defineProperty(B.prototype, "foo", { value: function() {
|
||||
}
|
||||
})
|
||||
|
||||
print("After breaking, B's ihclass has TS inherit info:", ArkTools.hasTSSubtyping(b));
|
||||
testVTable(b); // occur deopt
|
||||
|
@ -11,7 +11,5 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
Before breaking, B's ihclass has TS inherit info: false
|
||||
A foo
|
||||
After breaking, B's ihclass has TS inherit info: false
|
||||
B foo
|
||||
|
@ -15,9 +15,6 @@
|
||||
|
||||
// @ts-nocheck
|
||||
declare function print(a0:any, a1?:any):string;
|
||||
declare class ArkTools {
|
||||
static hasTSSubtyping(o:object):boolean;
|
||||
}
|
||||
|
||||
class A {
|
||||
x:number;
|
||||
@ -39,7 +36,6 @@ class B extends A {
|
||||
let b = new B();
|
||||
b.z1 = 123;
|
||||
b.z2 = 456;
|
||||
print(ArkTools.hasTSSubtyping(b));
|
||||
print(b.x);
|
||||
print(b.y);
|
||||
print(b.z);
|
||||
@ -50,7 +46,6 @@ print(b.z2);
|
||||
A.prototype.t = 789; // break inherit info
|
||||
let b1 = new B();
|
||||
b1.z1 = 321; // transion success, has cleared inherit info
|
||||
print(ArkTools.hasTSSubtyping(b1));
|
||||
print(b1.x); // occur depot
|
||||
print(b1.y);
|
||||
print(b1.z);
|
||||
|
@ -11,13 +11,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
false
|
||||
1
|
||||
2
|
||||
z
|
||||
123
|
||||
456
|
||||
false
|
||||
1
|
||||
2
|
||||
z
|
||||
|
@ -14,9 +14,6 @@
|
||||
*/
|
||||
|
||||
declare function print(a0:any, a1?:any):string;
|
||||
declare class ArkTools {
|
||||
static hasTSSubtyping(o:object):boolean;
|
||||
}
|
||||
|
||||
class A {
|
||||
x:number;
|
||||
@ -38,7 +35,6 @@ class B extends A {
|
||||
let b = new B();
|
||||
delete b.y;
|
||||
Reflect.deleteProperty(b, "z");
|
||||
print(ArkTools.hasTSSubtyping(b));
|
||||
print(b.x);
|
||||
print(b.y);
|
||||
print(b.z);
|
||||
|
@ -11,7 +11,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
false
|
||||
1
|
||||
undefined
|
||||
undefined
|
||||
|
@ -11,5 +11,4 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
false
|
||||
1
|
||||
|
@ -35,5 +35,4 @@ class B {
|
||||
}
|
||||
|
||||
let b = new B();
|
||||
print(ArkTools.hasTSSubtyping(b));
|
||||
print(b.x);
|
||||
|
@ -11,7 +11,5 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
false
|
||||
1
|
||||
false
|
||||
123
|
||||
|
@ -43,9 +43,7 @@ class B extends A {
|
||||
}
|
||||
|
||||
let a = new A();
|
||||
print(ArkTools.hasTSSubtyping(a));
|
||||
print(a.x);
|
||||
|
||||
let b = new B();
|
||||
print(ArkTools.hasTSSubtyping(b));
|
||||
print(b.x);
|
||||
|
@ -11,19 +11,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
false
|
||||
1
|
||||
false
|
||||
1
|
||||
false
|
||||
1
|
||||
false
|
||||
2
|
||||
false
|
||||
3
|
||||
false
|
||||
4
|
||||
false
|
||||
5
|
||||
false
|
||||
6
|
||||
|
@ -48,12 +48,10 @@ class B extends A {
|
||||
}
|
||||
|
||||
let a = new A();
|
||||
print(ArkTools.hasTSSubtyping(a)); // true
|
||||
print(a.foo()); // typedpath ---> 1
|
||||
|
||||
|
||||
let b = new B();
|
||||
print(ArkTools.hasTSSubtyping(b)); // false
|
||||
print(b.foo); // slowpath ---> 1
|
||||
|
||||
// Base class and Object check
|
||||
@ -64,7 +62,6 @@ class C {
|
||||
}
|
||||
|
||||
let c = new C();
|
||||
print(ArkTools.hasTSSubtyping(c)); // false
|
||||
print(c.hasOwnProperty);
|
||||
|
||||
class C2 {
|
||||
@ -74,7 +71,6 @@ class C2 {
|
||||
}
|
||||
|
||||
let c2 = new C2();
|
||||
print(ArkTools.hasTSSubtyping(c2)); // false
|
||||
print(c2.isPrototypeOf);
|
||||
|
||||
class C3 {
|
||||
@ -84,7 +80,6 @@ class C3 {
|
||||
}
|
||||
|
||||
let c3 = new C3();
|
||||
print(ArkTools.hasTSSubtyping(c3)); // false
|
||||
print(c3.propertyIsEnumerable);
|
||||
|
||||
class C4 {
|
||||
@ -94,7 +89,6 @@ class C4 {
|
||||
}
|
||||
|
||||
let c4 = new C4();
|
||||
print(ArkTools.hasTSSubtyping(c4)); // false
|
||||
print(c4.toLocaleString);
|
||||
|
||||
class C5 {
|
||||
@ -104,7 +98,6 @@ class C5 {
|
||||
}
|
||||
|
||||
let c5 = new C5();
|
||||
print(ArkTools.hasTSSubtyping(c5)); // false
|
||||
print(c5.toString);
|
||||
|
||||
class C6 {
|
||||
@ -114,5 +107,4 @@ class C6 {
|
||||
}
|
||||
|
||||
let c6 = new C6();
|
||||
print(ArkTools.hasTSSubtyping(c6)); // false
|
||||
print(c6.valueOf);
|
||||
|
@ -11,7 +11,5 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
false
|
||||
undefined
|
||||
false
|
||||
x
|
||||
|
@ -38,10 +38,8 @@ class B extends A {
|
||||
}
|
||||
|
||||
let a = new A();
|
||||
print(ArkTools.hasTSSubtyping(a));
|
||||
print(a.x);
|
||||
|
||||
|
||||
let b = new B();
|
||||
print(ArkTools.hasTSSubtyping(b));
|
||||
print(b.x());
|
||||
|
@ -11,19 +11,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
false
|
||||
x
|
||||
false
|
||||
1
|
||||
false
|
||||
1
|
||||
false
|
||||
2
|
||||
false
|
||||
3
|
||||
false
|
||||
4
|
||||
false
|
||||
5
|
||||
false
|
||||
6
|
||||
|
@ -38,12 +38,10 @@ class B extends A {
|
||||
}
|
||||
|
||||
let a = new A();
|
||||
print(ArkTools.hasTSSubtyping(a));
|
||||
print(a.x());
|
||||
|
||||
|
||||
let b = new B();
|
||||
print(ArkTools.hasTSSubtyping(b));
|
||||
print(b.x);
|
||||
|
||||
// Base class and Object check
|
||||
@ -55,7 +53,6 @@ class C {
|
||||
}
|
||||
|
||||
let c = new C();
|
||||
print(ArkTools.hasTSSubtyping(c)); // false
|
||||
print(c.hasOwnProperty);
|
||||
|
||||
class C2 {
|
||||
@ -66,7 +63,6 @@ class C2 {
|
||||
}
|
||||
|
||||
let c2 = new C2();
|
||||
print(ArkTools.hasTSSubtyping(c2)); // false
|
||||
print(c2.isPrototypeOf);
|
||||
|
||||
class C3 {
|
||||
@ -77,7 +73,6 @@ class C3 {
|
||||
}
|
||||
|
||||
let c3 = new C3();
|
||||
print(ArkTools.hasTSSubtyping(c3)); // false
|
||||
print(c3.propertyIsEnumerable);
|
||||
|
||||
class C4 {
|
||||
@ -88,7 +83,6 @@ class C4 {
|
||||
}
|
||||
|
||||
let c4 = new C4();
|
||||
print(ArkTools.hasTSSubtyping(c4)); // false
|
||||
print(c4.toLocaleString);
|
||||
|
||||
class C5 {
|
||||
@ -99,7 +93,6 @@ class C5 {
|
||||
}
|
||||
|
||||
let c5 = new C5();
|
||||
print(ArkTools.hasTSSubtyping(c5)); // false
|
||||
print(c5.toString);
|
||||
|
||||
class C6 {
|
||||
@ -110,5 +103,4 @@ class C6 {
|
||||
}
|
||||
|
||||
let c6 = new C6();
|
||||
print(ArkTools.hasTSSubtyping(c6)); // false
|
||||
print(c6.valueOf);
|
||||
|
Loading…
Reference in New Issue
Block a user