!9055 修复ihc设置proto时的错误不克隆行为

Merge pull request !9055 from zhouyong/fix-hclassbug
This commit is contained in:
openharmony_ci 2024-09-04 16:06:17 +00:00 committed by Gitee
commit 4267f4db80
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
10 changed files with 57 additions and 23 deletions

View File

@ -1042,7 +1042,7 @@ JSTaggedValue BuiltinsObject::ProtoSetter(EcmaRuntimeCallInfo *argv)
}
// 5. Let status be O.[[SetPrototypeOf]](proto).
bool status = JSTaggedValue::SetPrototype(thread, obj, proto);
bool status = JSTaggedValue::SetPrototype(thread, obj, proto, true);
// 6. ReturnIfAbrupt(status).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);

View File

@ -348,7 +348,7 @@ JSHandle<JSHClass> JSHClass::TransitionExtension(const JSThread *thread, const J
}
JSHandle<JSHClass> JSHClass::TransitionProto(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
const JSHandle<JSTaggedValue> &proto)
const JSHandle<JSTaggedValue> &proto, bool isChangeProto)
{
JSHandle<JSTaggedValue> key(thread->GlobalConstants()->GetHandledPrototypeString());
@ -366,7 +366,7 @@ JSHandle<JSHClass> JSHClass::TransitionProto(const JSThread *thread, const JSHan
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
// 2. new a hclass
JSHandle<JSHClass> newJsHClass = JSHClass::Clone(thread, jshclass);
newJsHClass->SetPrototype(thread, proto.GetTaggedValue());
newJsHClass->SetPrototype(thread, proto.GetTaggedValue(), isChangeProto);
JSTaggedValue layout = newJsHClass->GetLayout();
{
@ -461,21 +461,22 @@ JSHandle<JSHClass> JSHClass::TransProtoWithoutLayout(const JSThread *thread, con
return CloneWithAddProto(thread, jshclass, key, proto);
}
void JSHClass::SetPrototype(const JSThread *thread, JSTaggedValue proto)
void JSHClass::SetPrototype(const JSThread *thread, JSTaggedValue proto, bool isChangeProto)
{
// Because the heap-space of hclass is non-movable, this function can be non-static.
JSHandle<JSTaggedValue> protoHandle(thread, proto);
SetPrototype(thread, protoHandle);
SetPrototype(thread, protoHandle, isChangeProto);
}
JSHandle<JSHClass> JSHClass::SetPrototypeWithNotification(const JSThread *thread,
const JSHandle<JSHClass> &hclass,
const JSHandle<JSTaggedValue> &proto)
const JSHandle<JSTaggedValue> &proto,
bool isChangeProto)
{
// `hclass` can become prototype inside `TransitionProto` if `hclass` is HClass of `proto`.
// In this case we don't need to notify
auto wasPrototype = hclass->IsPrototype();
JSHandle<JSHClass> newClass = JSHClass::TransitionProto(thread, hclass, proto);
JSHandle<JSHClass> newClass = JSHClass::TransitionProto(thread, hclass, proto, isChangeProto);
if (wasPrototype) {
ASSERT(hclass->IsPrototype());
JSHClass::NotifyHclassChanged(thread, hclass, newClass);
@ -484,21 +485,21 @@ JSHandle<JSHClass> JSHClass::SetPrototypeWithNotification(const JSThread *thread
}
void JSHClass::SetPrototypeTransition(JSThread *thread, const JSHandle<JSObject> &object,
const JSHandle<JSTaggedValue> &proto)
const JSHandle<JSTaggedValue> &proto, bool isChangeProto)
{
JSHandle<JSHClass> hclass(thread, object->GetJSHClass());
auto newClass = SetPrototypeWithNotification(thread, hclass, proto);
auto newClass = SetPrototypeWithNotification(thread, hclass, proto, isChangeProto);
RestoreElementsKindToGeneric(*newClass);
object->SynchronizedSetClass(thread, *newClass);
thread->NotifyStableArrayElementsGuardians(object, StableArrayChangeKind::PROTO);
ObjectOperator::UpdateDetectorOnSetPrototype(thread, object.GetTaggedValue());
}
void JSHClass::SetPrototype(const JSThread *thread, const JSHandle<JSTaggedValue> &proto)
void JSHClass::SetPrototype(const JSThread *thread, const JSHandle<JSTaggedValue> &proto, bool isChangeProto)
{
// Because the heap-space of hclass is non-movable, this function can be non-static.
if (proto->IsJSObject()) {
OptimizePrototypeForIC(thread, proto);
OptimizePrototypeForIC(thread, proto, isChangeProto);
}
SetProto(thread, proto);
}

View File

@ -458,7 +458,7 @@ public:
const JSHandle<JSTaggedValue> &transIhc,
const JSHandle<JSTaggedValue> &transPhc);
static JSHandle<JSHClass> TransitionProto(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
const JSHandle<JSTaggedValue> &proto);
const JSHandle<JSTaggedValue> &proto, bool isChangeProto = false);
static JSHClass *FindTransitionProtoForAOT(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
const JSHandle<JSTaggedValue> &proto);
static JSHandle<JSHClass> TransProtoWithoutLayout(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
@ -2004,12 +2004,17 @@ public:
static JSHandle<JSHClass> SetPrototypeWithNotification(const JSThread *thread,
const JSHandle<JSHClass> &hclass,
const JSHandle<JSTaggedValue> &proto);
const JSHandle<JSTaggedValue> &proto,
bool isChangeProto = false);
static void SetPrototypeTransition(JSThread *thread, const JSHandle<JSObject> &object,
const JSHandle<JSTaggedValue> &proto);
void SetPrototype(const JSThread *thread, JSTaggedValue proto);
void PUBLIC_API SetPrototype(const JSThread *thread, const JSHandle<JSTaggedValue> &proto);
static void OptimizePrototypeForIC(const JSThread *thread, const JSHandle<JSTaggedValue> &proto,
const JSHandle<JSTaggedValue> &proto,
bool isChangeProto = false);
void SetPrototype(const JSThread *thread, JSTaggedValue proto, bool isChangeProto = false);
void PUBLIC_API SetPrototype(const JSThread *thread,
const JSHandle<JSTaggedValue> &proto,
bool isChangeProto = false);
static void OptimizePrototypeForIC(const JSThread *thread,
const JSHandle<JSTaggedValue> &proto,
bool isChangeProto = false);
inline JSTaggedValue GetPrototype() const
{

View File

@ -1490,7 +1490,9 @@ JSTaggedValue JSObject::GetPrototype(const JSHandle<JSObject> &obj)
return hclass->GetPrototype();
}
bool JSObject::SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &proto)
bool JSObject::SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj,
const JSHandle<JSTaggedValue> &proto,
bool isChangeProto)
{
ASSERT_PRINT(proto->IsECMAObject() || proto->IsNull(), "proto must be object or null");
JSTaggedValue current = JSObject::GetPrototype(obj);
@ -1517,7 +1519,7 @@ bool JSObject::SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj, con
}
ElementsKind oldKind = obj->GetJSHClass()->GetElementsKind();
// map transition
JSHClass::SetPrototypeTransition(thread, obj, proto);
JSHClass::SetPrototypeTransition(thread, obj, proto, isChangeProto);
TryMigrateToGenericKindForJSObject(thread, obj, oldKind);
return true;
}

View File

@ -483,7 +483,9 @@ public:
static JSTaggedValue GetPrototype(JSTaggedValue obj);
// [[SetPrototypeOf]]
static bool SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &proto);
static bool SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj,
const JSHandle<JSTaggedValue> &proto,
bool isChangeProto = false);
// [[IsExtensible]]
bool IsExtensible() const;

View File

@ -1230,7 +1230,7 @@ bool JSTaggedValue::GetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValu
}
bool JSTaggedValue::SetPrototype(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &proto)
const JSHandle<JSTaggedValue> &proto, bool isChangeProto)
{
if (obj->IsJSShared() || proto->IsJSShared()) {
THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(SetProtoWithSendable), false);
@ -1254,7 +1254,7 @@ bool JSTaggedValue::SetPrototype(JSThread *thread, const JSHandle<JSTaggedValue>
}
}
return JSObject::SetPrototype(thread, JSHandle<JSObject>(obj), proto);
return JSObject::SetPrototype(thread, JSHandle<JSObject>(obj), proto, isChangeProto);
}
JSTaggedValue JSTaggedValue::GetPrototype(JSThread *thread, const JSHandle<JSTaggedValue> &obj)

View File

@ -450,7 +450,7 @@ public:
static bool GetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
PropertyDescriptor &desc);
static bool SetPrototype(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &proto);
const JSHandle<JSTaggedValue> &proto, bool isChangeProto = false);
static JSTaggedValue GetPrototype(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
static bool PreventExtensions(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
static JSHandle<TaggedArray> GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);

View File

@ -13,3 +13,4 @@
-1
50
success

View File

@ -13,3 +13,4 @@
-1
50
success

View File

@ -29,3 +29,25 @@ Object.setPrototypeOf(object, proto);
// Check usage of proto's HClass after AOT compile
print(proto.method(50));
print(object.method(50));
function F0() {
this.f0 = 0;
}
let v3 = new F0();
let v4 = new F0();
class C27 {
c270 = 0;
}
class C28 {
c270 = 0;
}
class C42 extends C27 {
}
C27.__proto__ = v4;
v3.__proto__ = C27;
Object.defineProperty(C27, "d", { configurable: true, value: 1 });
print("success")