mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
!9055 修复ihc设置proto时的错误不克隆行为
Merge pull request !9055 from zhouyong/fix-hclassbug
This commit is contained in:
commit
4267f4db80
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -13,3 +13,4 @@
|
||||
|
||||
-1
|
||||
50
|
||||
success
|
@ -13,3 +13,4 @@
|
||||
|
||||
-1
|
||||
50
|
||||
success
|
@ -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")
|
Loading…
Reference in New Issue
Block a user