optimize get interface of list container

Signed-off-by: shilei <shilei91@huawei.com>
Change-Id: I2a8ff19917847baf36c3b1c7db61362838b0c7fa
This commit is contained in:
shilei 2024-01-29 03:30:41 +00:00
parent 50a0b1195d
commit 78eb353337
8 changed files with 93 additions and 4 deletions

View File

@ -44,6 +44,7 @@ JSTaggedValue ContainersList::ListConstructor(EcmaRuntimeCallInfo *argv)
JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSHandle<JSAPIList> list = JSHandle<JSAPIList>::Cast(obj);
list->SetIsOrderedList(true);
JSTaggedValue singleList = TaggedSingleList::Create(thread);
list->SetSingleList(thread, singleList);
@ -213,7 +214,8 @@ JSTaggedValue ContainersList::Get(EcmaRuntimeCallInfo *argv)
JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
return jsAPIList->Get(index->GetInt());
return JSAPIList::FastGet(thread, index->GetInt(), jsAPIList);
}
JSTaggedValue ContainersList::GetIndexOf(EcmaRuntimeCallInfo *argv)

View File

@ -2275,6 +2275,7 @@ void JSAPIList::Dump(std::ostream &os) const
os << " - length: " << std::dec << list->GetCapacityFromTaggedArray() << "\n";
os << " - node num: " << std::dec << list->NumberOfNodes() << "\n";
os << " - delete node num: " << std::dec << list->NumberOfDeletedNodes() << "\n";
os << " - is odered list: " << std::dec << this->IsOrderedList() << "\n";
JSObject::Dump(os);
list->Dump(os);
}

View File

@ -67,6 +67,9 @@ JSTaggedValue JSAPIList::Insert(JSThread *thread, const JSHandle<JSAPIList> &lis
}
JSTaggedValue newList = TaggedSingleList::Insert(thread, singleList, value, index);
list->SetSingleList(thread, newList);
if (index != nodeLength) {
list->SetIsOrderedList(false);
}
return JSTaggedValue::True();
}
@ -108,6 +111,26 @@ JSTaggedValue JSAPIList::Get(const int index)
return singleList->Get(index);
}
JSTaggedValue JSAPIList::FastGet(JSThread *thread, const int index, const JSHandle<JSAPIList> &list)
{
JSHandle<TaggedSingleList> singleList(thread, list->GetSingleList());
if (index < 0 || index >= singleList->Length()) {
return JSTaggedValue::Undefined();
}
int dataIndex = TaggedSingleList::ELEMENTS_START_INDEX + (index + 1) * TaggedSingleList::ENTRY_SIZE;
if (!list->IsOrderedList()) {
auto newSingleList = TaggedSingleList::SortByNodeOrder(thread, singleList);
TaggedSingleList *newList = TaggedSingleList::Cast(newSingleList.GetTaggedObject());
if (newList == nullptr) {
return JSTaggedValue::Undefined();
}
list->SetSingleList(thread, newSingleList);
list->SetIsOrderedList(true);
return newList->GetElement(dataIndex);
}
return singleList->GetElement(dataIndex);
}
JSTaggedValue JSAPIList::GetIndexOf(const JSTaggedValue &element)
{
TaggedSingleList *singleList = TaggedSingleList::Cast(GetSingleList().GetTaggedObject());
@ -126,6 +149,7 @@ void JSAPIList::Clear(JSThread *thread)
if (singleList->NumberOfNodes() > 0) {
singleList->Clear(thread);
}
SetIsOrderedList(true);
}
JSTaggedValue JSAPIList::RemoveByIndex(JSThread *thread, const JSHandle<JSAPIList> &list, const int &index)
@ -140,12 +164,16 @@ JSTaggedValue JSAPIList::RemoveByIndex(JSThread *thread, const JSHandle<JSAPILis
JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
if (index != (nodeLength - 1)) {
list->SetIsOrderedList(false);
}
return singleList->RemoveByIndex(thread, index);
}
JSTaggedValue JSAPIList::Remove(JSThread *thread, const JSTaggedValue &element)
{
TaggedSingleList *singleList = TaggedSingleList::Cast(GetSingleList().GetTaggedObject());
SetIsOrderedList(false);
return singleList->Remove(thread, element);
}
@ -163,6 +191,7 @@ JSTaggedValue JSAPIList::Sort(JSThread *thread, const JSHandle<JSTaggedValue> &t
{
JSHandle<JSAPIList> list = JSHandle<JSAPIList>::Cast(thisHandle);
JSHandle<TaggedSingleList> singleList(thread, list->GetSingleList());
list->SetIsOrderedList(false);
return TaggedSingleList::Sort(thread, callbackFn, singleList);
}
@ -204,6 +233,7 @@ JSTaggedValue JSAPIList::GetSubList(JSThread *thread, const JSHandle<JSAPIList>
JSHandle<JSAPIList> sublist = thread->GetEcmaVM()->GetFactory()->NewJSAPIList();
TaggedSingleList::GetSubList(thread, singleList, fromIndex, toIndex, subSingleList);
sublist->SetSingleList(thread, subSingleList);
sublist->SetIsOrderedList(true);
return sublist.GetTaggedValue();
}

View File

@ -24,12 +24,36 @@ namespace panda::ecmascript {
class JSAPIList : public JSObject {
public:
static constexpr uint32_t DEFAULT_CAPACITY_LENGTH = 10;
static constexpr uint32_t UNUSED_BIT_FILEDS_NUM = 31;
using IsOrderedListBit = BitField<uint32_t, 0, UNUSED_BIT_FILEDS_NUM>::NextFlag;
static JSAPIList *Cast(TaggedObject *object)
{
ASSERT(JSTaggedValue(object).IsJSAPIList());
return static_cast<JSAPIList *>(object);
}
inline void SetIsOrderedList(bool flag) const
{
IsOrderedListBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline bool IsOrderedList() const
{
uint32_t bits = GetBitField();
return IsOrderedListBit::Decode(bits);
}
uint32_t *GetBitFieldAddr() const
{
return reinterpret_cast<uint32_t *>(ToUintPtr(this) + BIT_FIELD_OFFSET);
}
inline void ClearBitField()
{
SetBitField(0UL);
}
static void Add(JSThread *thread, const JSHandle<JSAPIList> &list, const JSHandle<JSTaggedValue> &value);
static JSTaggedValue Insert(JSThread *thread, const JSHandle<JSAPIList> &list,
const JSHandle<JSTaggedValue> &value, const int index);
@ -52,6 +76,7 @@ public:
static bool SetProperty(JSThread *thread, const JSHandle<JSAPIList> &obj,
const JSHandle<JSTaggedValue> &key,
const JSHandle<JSTaggedValue> &value);
static JSTaggedValue FastGet(JSThread *thread, const int index, const JSHandle<JSAPIList> &list);
JSTaggedValue GetFirst();
JSTaggedValue GetLast();
@ -69,8 +94,10 @@ public:
}
static constexpr size_t SINGLY_LIST_OFFSET = JSObject::SIZE;
ACCESSORS(SingleList, SINGLY_LIST_OFFSET, SIZE);
DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, SINGLY_LIST_OFFSET, SIZE)
ACCESSORS(SingleList, SINGLY_LIST_OFFSET, BIT_FIELD_OFFSET)
ACCESSORS_PRIMITIVE_FIELD(BitField, uint32_t, BIT_FIELD_OFFSET, LAST_OFFSET)
DEFINE_ALIGN_SIZE(LAST_OFFSET);
DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, SINGLY_LIST_OFFSET, BIT_FIELD_OFFSET)
DECL_DUMP()
};
} // namespace panda::ecmascript

View File

@ -1335,6 +1335,7 @@ void ObjectFactory::InitializeJSObject(const JSHandle<JSObject> &obj, const JSHa
}
case JSType::JS_API_LIST: {
JSAPIList::Cast(*obj)->SetSingleList(thread_, JSTaggedValue::Undefined());
JSAPIList::Cast(*obj)->SetBitField(0UL);
break;
}
case JSType::JS_API_LINKED_LIST: {

View File

@ -570,6 +570,32 @@ JSHandle<TaggedArray> TaggedSingleList::OwnKeys(JSThread *thread, const JSHandle
return TaggedList<TaggedSingleList>::OwnKeys(thread, taggedList);
}
JSTaggedValue TaggedSingleList::SortByNodeOrder(const JSThread *thread, const JSHandle<TaggedSingleList> &taggedList)
{
int actualNodeNum = taggedList->NumberOfNodes();
int nextDataIndex = taggedList->GetElement(ELEMENTS_START_INDEX + NEXT_PTR_OFFSET).GetInt();
uint32_t length = static_cast<uint32_t>(actualNodeNum);
JSHandle<TaggedSingleList> list = TaggedList<TaggedSingleList>::Create(
thread, length < DEFAULT_ARRAY_LENGHT ? DEFAULT_ARRAY_LENGHT : length);
int tailTableIndex = ELEMENTS_START_INDEX + actualNodeNum * TaggedSingleList::ENTRY_SIZE;
int nextTailIndex = ELEMENTS_START_INDEX + TaggedSingleList::ENTRY_SIZE;
list->SetNumberOfNodes(thread, actualNodeNum);
list->SetElement(thread, TAIL_TABLE_INDEX, JSTaggedValue(tailTableIndex));
list->SetElement(thread, ELEMENTS_START_INDEX, JSTaggedValue::Hole());
list->SetElement(thread, ELEMENTS_START_INDEX + NEXT_PTR_OFFSET, JSTaggedValue(nextTailIndex));
for (int i = 0; i < actualNodeNum; ++i) {
int curDataIndex = ELEMENTS_START_INDEX + (i + 1) * TaggedSingleList::ENTRY_SIZE;
list->SetElement(thread, curDataIndex, taggedList->GetElement(nextDataIndex));
list->SetElement(thread, curDataIndex + NEXT_PTR_OFFSET,
JSTaggedValue(curDataIndex + TaggedSingleList::ENTRY_SIZE));
nextDataIndex = taggedList->GetElement(nextDataIndex + NEXT_PTR_OFFSET).GetInt();
}
list->SetElement(thread, tailTableIndex + NEXT_PTR_OFFSET, JSTaggedValue(ELEMENTS_START_INDEX));
return list.GetTaggedValue();
}
// TaggedDoubleList
JSTaggedValue TaggedDoubleList::Create(const JSThread *thread, int numberOfElements)
{

View File

@ -146,6 +146,8 @@ public:
static void GetSubList(JSThread *thread, const JSHandle<TaggedSingleList> &taggedList,
const int fromIndex, const int toIndex, const JSHandle<TaggedSingleList> &subList);
static JSHandle<TaggedArray> OwnKeys(JSThread *thread, const JSHandle<TaggedSingleList> &taggedList);
static JSTaggedValue SortByNodeOrder(const JSThread *thread, const JSHandle<TaggedSingleList> &taggedList);
void Clear(const JSThread *thread);
bool IsEmpty() const;
bool Has(const JSTaggedValue &value);

View File

@ -1301,7 +1301,7 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
}
case JSType::JS_API_LIST: {
// 1 : 1 dump fileds number
CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPIList::SIZE, 1U);
CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPIList::SIZE, 2U);
JSHandle<JSAPIList> jsAPIList = NewJSAPIList(thread, factory);
DUMP_FOR_HANDLE(jsAPIList);
break;