mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-30 13:40:51 +00:00
Maintain Subtyping when Adding Property on Prototype
Reduce some deoptimization in cocos. Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I77SBD Signed-off-by: dingding <dingding5@huawei.com> Change-Id: I1818d18fdf629d5f9d5e11d527e8280a0a414e5f
This commit is contained in:
parent
1c2e04399e
commit
a47c0c72fb
@ -241,7 +241,7 @@ void JSHClass::AddProperty(const JSThread *thread, const JSHandle<JSObject> &obj
|
||||
if (newClass != nullptr) {
|
||||
obj->SetClass(newClass);
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
JSHClass::NotifyHclassChanged(thread, jshclass, JSHandle<JSHClass>(thread, newClass));
|
||||
JSHClass::NotifyHclassChanged(thread, jshclass, JSHandle<JSHClass>(thread, newClass), key.GetTaggedValue());
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@ -271,7 +271,7 @@ void JSHClass::AddProperty(const JSThread *thread, const JSHandle<JSObject> &obj
|
||||
|
||||
// 5. update hclass in object.
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
JSHClass::NotifyHclassChanged(thread, jshclass, newJsHClass);
|
||||
JSHClass::NotifyHclassChanged(thread, jshclass, newJsHClass, key.GetTaggedValue());
|
||||
#endif
|
||||
obj->SetClass(*newJsHClass);
|
||||
|
||||
@ -459,7 +459,8 @@ JSHandle<JSTaggedValue> JSHClass::EnableProtoChangeMarker(const JSThread *thread
|
||||
return JSHandle<JSTaggedValue>(markerHandle);
|
||||
}
|
||||
|
||||
void JSHClass::NotifyHclassChanged(const JSThread *thread, JSHandle<JSHClass> oldHclass, JSHandle<JSHClass> newHclass)
|
||||
void JSHClass::NotifyHclassChanged(const JSThread *thread, JSHandle<JSHClass> oldHclass, JSHandle<JSHClass> newHclass,
|
||||
JSTaggedValue addedKey)
|
||||
{
|
||||
if (!oldHclass->IsPrototype()) {
|
||||
return;
|
||||
@ -469,7 +470,7 @@ void JSHClass::NotifyHclassChanged(const JSThread *thread, JSHandle<JSHClass> ol
|
||||
return;
|
||||
}
|
||||
newHclass->SetIsPrototype(true);
|
||||
JSHClass::NoticeThroughChain(thread, oldHclass);
|
||||
JSHClass::NoticeThroughChain(thread, oldHclass, addedKey);
|
||||
JSHClass::RefreshUsers(thread, oldHclass, newHclass);
|
||||
}
|
||||
|
||||
@ -556,8 +557,10 @@ JSHandle<ProtoChangeDetails> JSHClass::GetProtoChangeDetails(const JSThread *thr
|
||||
return GetProtoChangeDetails(thread, jshclass);
|
||||
}
|
||||
|
||||
void JSHClass::MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
||||
void JSHClass::MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||
JSTaggedValue addedKey)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
ASSERT(jshclass->IsPrototype() || jshclass->HasTSSubtyping());
|
||||
JSTaggedValue markerValue = jshclass->GetProtoChangeMarker();
|
||||
if (markerValue.IsProtoChangeMarker()) {
|
||||
@ -565,14 +568,19 @@ void JSHClass::MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass>
|
||||
protoChangeMarker->SetHasChanged(true);
|
||||
}
|
||||
|
||||
if (jshclass->HasTSSubtyping()) {
|
||||
jshclass->InitTSInheritInfo(thread);
|
||||
if (jshclass->HasTSSubtyping() && addedKey.IsString()) {
|
||||
JSHandle<JSTaggedValue> key(thread, addedKey);
|
||||
if (!SubtypingOperator::TryMaintainTSSubtypingOnPrototype(thread, jshclass, key)) {
|
||||
jshclass->InitTSInheritInfo(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JSHClass::NoticeThroughChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
||||
void JSHClass::NoticeThroughChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||
JSTaggedValue addedKey)
|
||||
{
|
||||
MarkProtoChanged(thread, jshclass);
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
MarkProtoChanged(thread, jshclass, addedKey);
|
||||
JSTaggedValue protoDetailsValue = jshclass->GetProtoChangeDetails();
|
||||
if (!protoDetailsValue.IsProtoChangeDetails()) {
|
||||
return;
|
||||
@ -585,7 +593,7 @@ void JSHClass::NoticeThroughChain(const JSThread *thread, const JSHandle<JSHClas
|
||||
for (uint32_t i = 0; i < listeners->GetEnd(); i++) {
|
||||
JSTaggedValue temp = listeners->Get(i);
|
||||
if (temp.IsJSHClass()) {
|
||||
NoticeThroughChain(thread, JSHandle<JSHClass>(thread, listeners->Get(i).GetTaggedObject()));
|
||||
NoticeThroughChain(thread, JSHandle<JSHClass>(thread, listeners->Get(i).GetTaggedObject()), addedKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -348,7 +348,8 @@ public:
|
||||
|
||||
static JSHandle<JSTaggedValue> EnableProtoChangeMarker(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
|
||||
|
||||
static void NotifyHclassChanged(const JSThread *thread, JSHandle<JSHClass> oldHclass, JSHandle<JSHClass> newHclass);
|
||||
static void NotifyHclassChanged(const JSThread *thread, JSHandle<JSHClass> oldHclass, JSHandle<JSHClass> newHclass,
|
||||
JSTaggedValue addedKey = JSTaggedValue::Undefined());
|
||||
|
||||
static void RegisterOnProtoChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
|
||||
|
||||
@ -362,9 +363,11 @@ public:
|
||||
inline void UpdatePropertyMetaData(const JSThread *thread, const JSTaggedValue &key,
|
||||
const PropertyAttributes &metaData);
|
||||
|
||||
static void MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
|
||||
static void MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||
JSTaggedValue addedKey = JSTaggedValue::Undefined());
|
||||
|
||||
static void NoticeThroughChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
|
||||
static void NoticeThroughChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||
JSTaggedValue addedKey = JSTaggedValue::Undefined());
|
||||
|
||||
static void RefreshUsers(const JSThread *thread, const JSHandle<JSHClass> &oldHclass,
|
||||
const JSHandle<JSHClass> &newHclass);
|
||||
|
@ -236,4 +236,28 @@ void SubtypingOperator::TryMaintainTSSubtyping(const JSThread *thread, const JSH
|
||||
|
||||
JSHClass::CopyTSInheritInfo(thread, oldHClass, newHClass);
|
||||
}
|
||||
|
||||
// when add property on prototype, try maintain.
|
||||
bool SubtypingOperator::TryMaintainTSSubtypingOnPrototype(const JSThread *thread, const JSHandle<JSHClass> &hclass,
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
ASSERT(key->IsString());
|
||||
JSHandle<VTable> vtable(thread, hclass->GetVTable());
|
||||
ASSERT(vtable->GetNumberOfTuples() > 0); // there have default key 'constructor' at least
|
||||
|
||||
if (vtable->Find(key.GetTaggedValue())) { // new key shadows vtable property
|
||||
LOG_ECMA(DEBUG) << "TryMaintainTSSubtypingOnPrototype failed, key: "
|
||||
<< ConvertToString(EcmaString::Cast(key->GetTaggedObject()));
|
||||
return false;
|
||||
}
|
||||
|
||||
int entry = JSHClass::FindPropertyEntry(thread, *hclass, key.GetTaggedValue());
|
||||
if (entry != -1) { // new key shadows loacl property
|
||||
LOG_ECMA(DEBUG) << "TryMaintainTSSubtypingOnPrototype failed, key: "
|
||||
<< ConvertToString(EcmaString::Cast(key->GetTaggedObject()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -37,6 +37,10 @@ public:
|
||||
|
||||
static void TryMaintainTSSubtyping(const JSThread *thread, const JSHandle<JSHClass> &oldHClass,
|
||||
JSHandle<JSHClass> &newHClass, const JSHandle<JSTaggedValue> &key);
|
||||
|
||||
static bool TryMaintainTSSubtypingOnPrototype(const JSThread *thread, const JSHandle<JSHClass> &hclass,
|
||||
const JSHandle<JSTaggedValue> &key);
|
||||
|
||||
private:
|
||||
static constexpr uint8_t MAX_LEVEL = 1 << JSHClass::LEVEL_BTTFIELD_NUM;
|
||||
|
||||
|
@ -17,7 +17,7 @@ true
|
||||
z
|
||||
123
|
||||
456
|
||||
false
|
||||
true
|
||||
1
|
||||
2
|
||||
z
|
||||
|
Loading…
Reference in New Issue
Block a user