Remove JSNativePointer in InternalAccessor

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAJ4G8
Signed-off-by: Gymee <yumeijie@huawei.com>
Change-Id: I85d4677b4aa7041c63ec0bb1592a6e6c2abb3785
This commit is contained in:
Gymee 2024-06-12 18:02:48 +08:00
parent 93b2ba8990
commit 25d4d5d9ef
7 changed files with 72 additions and 65 deletions

View File

@ -26,11 +26,27 @@
#include "ecmascript/record.h"
namespace panda::ecmascript {
class AccessorData final : public Record {
class InternalAccessor final : public Record {
public:
using InternalGetFunc = JSTaggedValue (*)(JSThread *, const JSHandle<JSObject> &);
using InternalSetFunc = bool (*)(JSThread *, const JSHandle<JSObject> &, const JSHandle<JSTaggedValue> &, bool);
CAST_CHECK(InternalAccessor, IsInternalAccessor);
inline bool HasSetter() const
{
return GetSetter() != nullptr;
}
static constexpr size_t GETTER_OFFSET = Record::SIZE;
ACCESSORS_FIXED_SIZE_FIELD(Getter, InternalGetFunc, JSTaggedType, GETTER_OFFSET, SETTER_OFFSET)
ACCESSORS_FIXED_SIZE_FIELD(Setter, InternalSetFunc, JSTaggedType, SETTER_OFFSET, SIZE)
DECL_VISIT_NATIVE_FIELD(GETTER_OFFSET, SIZE)
};
class AccessorData final : public Record {
public:
static AccessorData *Cast(TaggedObject *object)
{
ASSERT(JSTaggedValue(object).IsAccessorData() || JSTaggedValue(object).IsInternalAccessor());
@ -44,23 +60,23 @@ public:
inline bool HasSetter() const
{
return !GetSetter().IsUndefined();
auto setter = GetSetter();
// When the raw data is 0, means the InternalAccessor's setter is nullptr.
return !(setter.IsUndefined() || setter.GetRawData() == 0U);
}
JSTaggedValue CallInternalGet(JSThread *thread, const JSHandle<JSObject> &obj) const
{
ASSERT(GetGetter().IsJSNativePointer());
JSNativePointer *getter = JSNativePointer::Cast(GetGetter().GetTaggedObject());
auto getFunc = reinterpret_cast<InternalGetFunc>(getter->GetExternalPointer());
ASSERT(IsInternal());
auto getFunc = InternalAccessor::ConstCast(this)->GetGetter();
return getFunc(thread, obj);
}
bool CallInternalSet(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &value,
bool mayThrow = false) const
{
ASSERT(GetSetter().IsJSNativePointer());
JSNativePointer *setter = JSNativePointer::Cast(GetSetter().GetTaggedObject());
auto setFunc = reinterpret_cast<InternalSetFunc>(setter->GetExternalPointer());
ASSERT(IsInternal());
auto setFunc = InternalAccessor::ConstCast(this)->GetSetter();
return setFunc(thread, obj, value, mayThrow);
}
@ -72,6 +88,10 @@ public:
DECL_VISIT_OBJECT(GETTER_OFFSET, SIZE)
};
static_assert(AccessorData::SIZE == InternalAccessor::SIZE &&
AccessorData::GETTER_OFFSET == InternalAccessor::GETTER_OFFSET &&
AccessorData::SETTER_OFFSET == InternalAccessor::SETTER_OFFSET);
enum class CompletionRecordType : uint8_t {
NORMAL = 0U,
BREAK,

View File

@ -1603,8 +1603,8 @@ void AccessorData::Dump(std::ostream &os) const
{
auto *hclass = GetClass();
if (hclass->GetObjectType() == JSType::INTERNAL_ACCESSOR) {
os << " - Getter: " << reinterpret_cast<void *>(GetGetter().GetTaggedObject()) << "\n";
os << " - Setter: " << reinterpret_cast<void *>(GetSetter().GetTaggedObject()) << "\n";
os << " - Getter: " << InternalAccessor::ConstCast(this)->GetGetter() << "\n";
os << " - Setter: " << InternalAccessor::ConstCast(this)->GetSetter() << "\n";
return;
}
@ -5297,6 +5297,12 @@ void JSSymbol::DumpForSnapshot(std::vector<Reference> &vec) const
void AccessorData::DumpForSnapshot(std::vector<Reference> &vec) const
{
if (GetClass()->GetObjectType() == JSType::INTERNAL_ACCESSOR) {
vec.emplace_back(CString("getter"), JSTaggedValue(InternalAccessor::ConstCast(this)->GetGetter()));
vec.emplace_back(CString("setter"), JSTaggedValue(InternalAccessor::ConstCast(this)->GetSetter()));
return;
}
vec.emplace_back(CString("getter"), GetGetter());
vec.emplace_back(CString("setter"), GetSetter());
}

View File

@ -472,9 +472,13 @@ public:
GlobalEnv::Cast(object)->VisitRangeSlot<visitType>(visitor);
break;
case JSType::ACCESSOR_DATA:
case JSType::INTERNAL_ACCESSOR:
AccessorData::Cast(object)->VisitRangeSlot<visitType>(visitor);
break;
case JSType::INTERNAL_ACCESSOR:
if constexpr (visitType == VisitType::ALL_VISIT) {
InternalAccessor::Cast(object)->VisitRangeSlot<visitType>(visitor);
}
break;
case JSType::SYMBOL:
JSSymbol::Cast(object)->VisitRangeSlot<visitType>(visitor);
break;

View File

@ -2389,20 +2389,11 @@ JSHandle<AccessorData> ObjectFactory::NewInternalAccessor(void *setter, void *ge
NewObjectHook();
TaggedObject *header = heap_->AllocateNonMovableOrHugeObject(
JSHClass::Cast(thread_->GlobalConstants()->GetInternalAccessorClass().GetTaggedObject()));
JSHandle<AccessorData> obj(thread_, AccessorData::Cast(header));
obj->SetGetter(thread_, JSTaggedValue::Undefined());
obj->SetSetter(thread_, JSTaggedValue::Undefined());
if (setter != nullptr) {
JSHandle<JSNativePointer> setFunc = NewJSNativePointer(setter, nullptr, nullptr, true);
obj->SetSetter(thread_, setFunc.GetTaggedValue());
} else {
JSTaggedValue setFunc = JSTaggedValue::Undefined();
obj->SetSetter(thread_, setFunc);
ASSERT(!obj->HasSetter());
}
JSHandle<JSNativePointer> getFunc = NewJSNativePointer(getter, nullptr, nullptr, true);
obj->SetGetter(thread_, getFunc);
return obj;
JSHandle<InternalAccessor> obj(thread_, InternalAccessor::Cast(header));
obj->SetSetter(reinterpret_cast<InternalAccessor::InternalSetFunc>(setter));
obj->SetGetter(reinterpret_cast<InternalAccessor::InternalGetFunc>(getter));
return JSHandle<AccessorData>::Cast(obj);
}
JSHandle<PromiseCapability> ObjectFactory::NewPromiseCapability()

View File

@ -521,18 +521,11 @@ JSHandle<AccessorData> ObjectFactory::NewSInternalAccessor(void *setter, void *g
NewSObjectHook();
TaggedObject *header = sHeap_->AllocateReadOnlyOrHugeObject(thread_,
JSHClass::Cast(thread_->GlobalConstants()->GetInternalAccessorClass().GetTaggedObject()));
JSHandle<AccessorData> obj(thread_, AccessorData::Cast(header));
obj->SetGetter(thread_, JSTaggedValue::Undefined());
obj->SetSetter(thread_, JSTaggedValue::Undefined());
if (setter != nullptr) {
JSHandle<JSNativePointer> setFunc = NewSReadOnlyJSNativePointer(setter);
obj->SetSetter(thread_, setFunc.GetTaggedValue());
}
if (getter != nullptr) {
JSHandle<JSNativePointer> getFunc = NewSReadOnlyJSNativePointer(getter);
obj->SetGetter(thread_, getFunc);
}
return obj;
JSHandle<InternalAccessor> obj(thread_, InternalAccessor::Cast(header));
obj->SetSetter(reinterpret_cast<InternalAccessor::InternalSetFunc>(setter));
obj->SetGetter(reinterpret_cast<InternalAccessor::InternalGetFunc>(getter));
return JSHandle<AccessorData>::Cast(obj);
}
JSHandle<ConstantPool> ObjectFactory::NewSConstantPool(uint32_t capacity)

View File

@ -48,8 +48,8 @@ HWTEST_F_L0(AccessorDataTest, AccessorData_Cast)
JSHandle<JSHClass> internalAccClassHandle =
factory->NewEcmaHClass(JSObject::SIZE, JSType::INTERNAL_ACCESSOR, nullHandle);
TaggedObject *internalAccObject = factory->NewObject(internalAccClassHandle);
AccessorData::Cast(internalAccObject)->SetGetter(thread, JSTaggedValue::Undefined());
AccessorData::Cast(internalAccObject)->SetSetter(thread, JSTaggedValue::Undefined());
InternalAccessor::Cast(internalAccObject)->SetGetter(nullptr);
InternalAccessor::Cast(internalAccObject)->SetSetter(nullptr);
EXPECT_TRUE(JSTaggedValue(internalAccObject).IsInternalAccessor());
AccessorData *internalAcc = AccessorData::Cast(internalAccObject);
EXPECT_TRUE(JSTaggedValue(internalAcc).IsInternalAccessor());
@ -83,8 +83,8 @@ HWTEST_F_L0(AccessorDataTest, IsInternal)
JSHandle<JSHClass> internalAccClass =
factory->NewEcmaHClass(JSObject::SIZE, JSType::INTERNAL_ACCESSOR, nullHandle);
TaggedObject *internalAccObject = factory->NewObject(internalAccClass);
AccessorData::Cast(internalAccObject)->SetGetter(thread, JSTaggedValue::Undefined());
AccessorData::Cast(internalAccObject)->SetSetter(thread, JSTaggedValue::Undefined());
InternalAccessor::Cast(internalAccObject)->SetGetter(nullptr);
InternalAccessor::Cast(internalAccObject)->SetSetter(nullptr);
AccessorData *internalAcc = AccessorData::Cast(internalAccObject);
EXPECT_EQ(internalAcc->IsInternal(), true);
}
@ -112,11 +112,12 @@ HWTEST_F_L0(AccessorDataTest, HasSetter)
// 2.Create internal AccessorData object by NewInternalAccessor function.
void *setter = nullptr;
void *getter = nullptr;
JSHandle<AccessorData> internalAccHandle = factory->NewInternalAccessor(setter, getter);
JSHandle<InternalAccessor> internalAccHandle = JSHandle<InternalAccessor>::Cast(
factory->NewInternalAccessor(setter, getter));
EXPECT_EQ(internalAccHandle->HasSetter(), false);
internalAccHandle->SetSetter(thread, JSTaggedValue::Undefined());
internalAccHandle->SetSetter(nullptr);
EXPECT_EQ(internalAccHandle->HasSetter(), false);
internalAccHandle->SetSetter(thread, normalFunction);
internalAccHandle->SetSetter(JSFunction::PrototypeSetter);
EXPECT_EQ(internalAccHandle->HasSetter(), true);
// 3.Create normal AccessorData object from dynamic class.
@ -125,7 +126,6 @@ HWTEST_F_L0(AccessorDataTest, HasSetter)
TaggedObject *accObject = factory->NewObject(accClass);
AccessorData *acc = AccessorData::Cast(accObject);
acc->SetGetter(thread, JSTaggedValue::Undefined());
EXPECT_EQ(acc->HasSetter(), true);
acc->SetSetter(thread, JSTaggedValue::Undefined());
EXPECT_EQ(acc->HasSetter(), false);
acc->SetSetter(thread, normalFunction);
@ -135,12 +135,11 @@ HWTEST_F_L0(AccessorDataTest, HasSetter)
JSHandle<JSHClass> internalAccClass =
factory->NewEcmaHClass(JSObject::SIZE, JSType::INTERNAL_ACCESSOR, nullHandle);
TaggedObject *internalAccObject = factory->NewObject(internalAccClass);
AccessorData *internalAcc = AccessorData::Cast(internalAccObject);
internalAcc->SetGetter(thread, JSTaggedValue::Undefined());
EXPECT_EQ(internalAcc->HasSetter(), true);
internalAcc->SetSetter(thread, JSTaggedValue::Undefined());
InternalAccessor *internalAcc = InternalAccessor::Cast(internalAccObject);
internalAcc->SetGetter(nullptr);
internalAcc->SetSetter(nullptr);
EXPECT_EQ(internalAcc->HasSetter(), false);
internalAcc->SetSetter(thread, normalFunction);
internalAcc->SetSetter(JSFunction::PrototypeSetter);
EXPECT_EQ(internalAcc->HasSetter(), true);
}
@ -165,21 +164,16 @@ HWTEST_F_L0(AccessorDataTest, CallInternalSet)
JSHandle<JSTaggedValue> nullPrototypeHandle(thread, JSTaggedValue::Null());
JSHandle<JSHClass> accClass1 =
factory->NewEcmaHClass(JSObject::SIZE, JSType::INTERNAL_ACCESSOR, nullPrototypeHandle);
JSHandle<AccessorData> accObject1(thread, factory->NewObject(accClass1));
accObject1->SetGetter(thread, JSTaggedValue::Undefined());
accObject1->SetSetter(thread, JSTaggedValue::Undefined());
JSHandle<JSNativePointer> prototypeGetterFuncNativePtrHandle =
factory->NewJSNativePointer(reinterpret_cast<void *>(JSFunction::PrototypeGetter), nullptr, nullptr, true);
accObject1->SetGetter(thread, prototypeGetterFuncNativePtrHandle);
JSHandle<InternalAccessor> internal(thread, factory->NewObject(accClass1));
JSHandle<AccessorData> accObject1 = JSHandle<AccessorData>::Cast(internal);
internal->SetGetter(JSFunction::PrototypeGetter);
JSTaggedValue valNullPrototype = accObject1->CallInternalGet(thread, JSHandle<JSObject>::Cast(funcTagVal1));
EXPECT_NE(valNullPrototype.GetRawData(), JSTaggedValue::Undefined().GetRawData());
// Call the CallInternalSet method to set new prototype.
JSHandle<JSTaggedValue> undefPrototypeHandle(thread, JSTaggedValue::Undefined());
JSHandle<JSNativePointer> prototypeSetterFuncNativePtrHandle =
factory->NewJSNativePointer(reinterpret_cast<void *>(JSFunction::PrototypeSetter), nullptr, nullptr, true);
accObject1->SetSetter(thread, prototypeSetterFuncNativePtrHandle);
internal->SetSetter(JSFunction::PrototypeSetter);
bool res1 = accObject1->CallInternalSet(thread, JSHandle<JSObject>::Cast(funcTagVal1), undefPrototypeHandle);
EXPECT_TRUE(res1);

View File

@ -43,8 +43,8 @@ static JSFunction *JSObjectTestCreate(JSThread *thread)
}
bool TestBoolSetter([[maybe_unused]] JSThread *thread,
[[maybe_unused]] JSHandle<JSObject> &jsObject,
[[maybe_unused]] JSHandle<JSTaggedValue> &value,
[[maybe_unused]] const JSHandle<JSObject> &jsObject,
[[maybe_unused]] const JSHandle<JSTaggedValue> &value,
[[maybe_unused]] bool success)
{
return true;
@ -183,10 +183,9 @@ HWTEST_F_L0(ObjectOperatorTest, UpdateDateValue_001)
auto *resultDict = NumberDictionary::Cast(handleObject->GetElements().GetTaggedObject());
EXPECT_EQ(resultDict->GetValue(objectOperator1.GetIndex()).GetInt(), 5);
// objcet value is InternalAccessor
JSHandle<AccessorData> handleAccessorData = factory->NewAccessorData();
JSHandle<JSNativePointer> handleSetter = factory->NewJSNativePointer(reinterpret_cast<void *>(TestBoolSetter));
handleAccessorData->SetSetter(thread, handleSetter.GetTaggedValue());
// object value is InternalAccessor
JSHandle<AccessorData> handleAccessorData = factory->NewInternalAccessor(
reinterpret_cast<void*>(TestBoolSetter), nullptr);
JSHandle<JSTaggedValue> handleValue2(handleAccessorData);
ObjectOperator objectOperator2(thread, handleKey);
objectOperator2.SetValue(handleAccessorData.GetTaggedValue());