Fix(Aot): Class AOT deopt bugfix

Issue: #I8F16D
Change-Id: I9226d15c8ac4da5452d98b3a5b23bb925bf3ac8f
Signed-off-by: yingguofeng@huawei.com <yingguofeng@huawei.com>
This commit is contained in:
yingguofeng@huawei.com 2023-11-09 10:58:18 +08:00
parent cb2ce85337
commit 8fef64c0a6
11 changed files with 128 additions and 32 deletions

View File

@ -407,26 +407,31 @@ void JSHClass::ShouldUpdateProtoClass(const JSThread *thread, const JSHandle<JST
JSHandle<JSHClass> hclass(thread, proto->GetTaggedObject()->GetClass());
ASSERT(!Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(*hclass))->InReadOnlySpace());
if (!hclass->IsPrototype()) {
// If the objcet should be changed to the proto of an object,
// the original hclass cannot be shared.
JSHandle<JSHClass> newProtoClass = JSHClass::Clone(thread, hclass);
JSTaggedValue layout = newProtoClass->GetLayout();
// If the type of object is JSObject, the layout info value is initialized to the default value,
// if the value is not JSObject, the layout info value is initialized to null.
if (!layout.IsNull()) {
JSMutableHandle<LayoutInfo> layoutInfoHandle(thread, layout);
layoutInfoHandle.Update(
thread->GetEcmaVM()->GetFactory()->CopyLayoutInfo(layoutInfoHandle).GetTaggedValue());
newProtoClass->SetLayout(thread, layoutInfoHandle);
}
// There is no sharing in AOT hclass. Therefore, it is not necessary or possible to clone here.
if (!hclass->IsTS()) {
// If the objcet should be changed to the proto of an object,
// the original hclass cannot be shared.
JSHandle<JSHClass> newProtoClass = JSHClass::Clone(thread, hclass);
JSTaggedValue layout = newProtoClass->GetLayout();
// If the type of object is JSObject, the layout info value is initialized to the default value,
// if the value is not JSObject, the layout info value is initialized to null.
if (!layout.IsNull()) {
JSMutableHandle<LayoutInfo> layoutInfoHandle(thread, layout);
layoutInfoHandle.Update(
thread->GetEcmaVM()->GetFactory()->CopyLayoutInfo(layoutInfoHandle).GetTaggedValue());
newProtoClass->SetLayout(thread, layoutInfoHandle);
}
#if ECMASCRIPT_ENABLE_IC
// After the hclass is updated, check whether the proto chain status of ic is updated.
NotifyHclassChanged(thread, hclass, newProtoClass);
// After the hclass is updated, check whether the proto chain status of ic is updated.
NotifyHclassChanged(thread, hclass, newProtoClass);
#endif
JSObject::Cast(proto->GetTaggedObject())->SynchronizedSetClass(*newProtoClass);
newProtoClass->SetIsPrototype(true);
thread->GetEcmaVM()->GetPGOProfiler()->UpdateProfileType(*hclass, *newProtoClass);
JSObject::Cast(proto->GetTaggedObject())->SynchronizedSetClass(*newProtoClass);
newProtoClass->SetIsPrototype(true);
thread->GetEcmaVM()->GetPGOProfiler()->UpdateProfileType(*hclass, *newProtoClass);
} else {
hclass->SetIsPrototype(true);
}
}
}

View File

@ -223,17 +223,20 @@ JSHandle<JSHClass> ClassInfoExtractor::CreateConstructorHClass(JSThread *thread,
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
uint32_t length = keys->GetLength();
if (length == ClassInfoExtractor::STATIC_RESERVED_LENGTH && base->IsHole() &&
properties->Get(NAME_INDEX).IsString()) {
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
if (method->IsAotWithCallField()) {
if (method->IsFastCall()) {
return JSHandle<JSHClass>(globalConst->GetHandledClassConstructorOptimizedWithFastCallClass());
if (!thread->GetEcmaVM()->IsEnablePGOProfiler()) {
// The class constructor of AOT is not shared, and PGO collect cannot be shared.
if (length == ClassInfoExtractor::STATIC_RESERVED_LENGTH && base->IsHole() &&
properties->Get(NAME_INDEX).IsString()) {
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
if (method->IsAotWithCallField()) {
if (method->IsFastCall()) {
return JSHandle<JSHClass>(globalConst->GetHandledClassConstructorOptimizedWithFastCallClass());
} else {
return JSHandle<JSHClass>(globalConst->GetHandledClassConstructorOptimizedClass());
}
} else {
return JSHandle<JSHClass>(globalConst->GetHandledClassConstructorOptimizedClass());
return JSHandle<JSHClass>(globalConst->GetHandledClassConstructorClass());
}
} else {
return JSHandle<JSHClass>(globalConst->GetHandledClassConstructorClass());
}
}
JSHandle<JSHClass> hclass;

View File

@ -221,7 +221,7 @@ bool LayoutInfo::IsUninitializedProperty(const JSObject *object, uint32_t index)
return false;
}
JSTaggedValue val = object->GetPropertyInlinedProps(attr.GetOffset());
JSTaggedValue val = object->GetPropertyInlinedPropsWithRep(attr.GetOffset(), attr);
return val.IsHole();
}

View File

@ -640,6 +640,10 @@ void PGOProfiler::DumpICByName(ApEntityId abcId, const CString &recordName, Enti
{
JSTaggedValue firstValue = profileTypeInfo->Get(slotId);
if (!firstValue.IsHeapObject()) {
if (firstValue.IsHole()) {
// Mega state
AddObjectInfoWithMega(abcId, recordName, methodId, bcOffset);
}
return;
}
if (firstValue.IsWeak()) {
@ -659,6 +663,10 @@ void PGOProfiler::DumpICByValue(ApEntityId abcId, const CString &recordName, Ent
{
JSTaggedValue firstValue = profileTypeInfo->Get(slotId);
if (!firstValue.IsHeapObject()) {
if (firstValue.IsHole()) {
// Mega state
AddObjectInfoWithMega(abcId, recordName, methodId, bcOffset);
}
return;
}
if (firstValue.IsWeak()) {
@ -1099,6 +1107,15 @@ void PGOProfiler::AddObjectInfo(ApEntityId abcId, const CString &recordName, Ent
AddTranstionObjectInfo(recordType, methodId, bcOffset, receiver, hold, holdTra);
}
void PGOProfiler::AddObjectInfoWithMega(
ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset)
{
auto megaType = ProfileType::CreateMegeType();
PGOObjectInfo info(megaType, megaType, megaType, megaType, megaType, megaType);
ProfileType recordType = GetRecordProfileType(abcId, recordName);
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
}
void PGOProfiler::AddElementInfo(
ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, JSHClass *receiver)
{

View File

@ -140,6 +140,7 @@ private:
void AddObjectInfo(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
JSHClass *receiver, JSHClass *hold, JSHClass *holdTra);
void AddObjectInfoWithMega(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset);
void AddElementInfo(
ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, JSHClass *receiver);

View File

@ -47,6 +47,7 @@ public:
ModuleRecordId,
PrototypeId,
ConstructorId,
MegaStateKinds,
TotalKinds,
UnknowId
};
@ -78,6 +79,13 @@ public:
}
}
static ProfileType CreateMegeType()
{
ProfileType type;
type.UpdateKind(Kind::MegaStateKinds);
return type;
}
ProfileType &Remap(const PGOContext &context);
bool IsNone() const
@ -135,6 +143,11 @@ public:
return GetKind() == Kind::PrototypeId;
}
bool IsMegaStateType() const
{
return GetKind() == Kind::MegaStateKinds;
}
uint32_t GetId() const
{
return IdBits::Decode(type_);
@ -231,6 +244,11 @@ public:
return false;
}
bool IsMegaStateType() const
{
return false;
}
ApEntityId GetId() const
{
return typeId_;

View File

@ -446,6 +446,11 @@ public:
return receiverType_.IsNone();
}
bool IsMegaStateType() const
{
return receiverType_.IsMegaStateType();
}
bool InConstructor() const
{
return receiverType_.IsConstructor();
@ -507,6 +512,10 @@ public:
if (info.IsNone()) {
return;
}
if (info.IsMegaStateType()) {
count_ = 0;
return;
}
uint32_t count = 0;
for (; count < count_; count++) {
if (infos_[count] == info) {

View File

@ -17,4 +17,6 @@ host_aot_test_action("pgo_class_operation") {
deps = []
is_only_typed_path = true
is_enable_pgo = true
is_enable_trace_deopt = true
log_option = " --log-info=trace"
}

View File

@ -13,5 +13,3 @@
5
5
5
5

View File

@ -18,6 +18,7 @@ declare function print(arg:any):string;
class A {
x: number;
constructor() {
// Mega state
this.x = 5;
}
}
@ -33,8 +34,34 @@ class C extends A {
}
}
class D extends A {
constructor() {
super();
}
}
class E extends A {
constructor() {
super();
}
}
class F extends A {
constructor() {
super();
}
}
class G {
x: number;
constructor() {
this.x = 5;
}
}
function foo(a) {
print(a.x);
// Mega state
a.x;
}
function bar(t) {
@ -44,8 +71,26 @@ function bar(t) {
let a = new A();
let b = new B();
let c = new C();
let d = new D();
let e = new E();
let f = new F();
foo(a);
foo(b);
for (let i = 0; i < 1000; i++) {
foo(c);
}
foo(d);
foo(e);
foo(f);
bar(b);
bar(c);
function getPrototypeOf(a)
{
return a.prototype
}
getPrototypeOf(A);
getPrototypeOf(B);

View File

@ -13,5 +13,3 @@
5
5
5
5