!1091 move the definition to the declare head file, and delete inl.h file

Merge pull request !1091 from hjzhangcm/master
This commit is contained in:
openharmony_ci 2022-04-22 13:41:27 +00:00 committed by Gitee
commit 455f18dcc6
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
32 changed files with 632 additions and 906 deletions

View File

@ -19,7 +19,7 @@
#include "ecmascript/interpreter/interpreter.h"
#include "ecmascript/js_map.h"
#include "ecmascript/js_map_iterator.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/object_factory.h"
namespace panda::ecmascript::builtins {

View File

@ -19,7 +19,7 @@
#include "ecmascript/interpreter/interpreter.h"
#include "ecmascript/js_set.h"
#include "ecmascript/js_set_iterator.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_array-inl.h"

View File

@ -19,7 +19,7 @@
#include "ecmascript/interpreter/interpreter.h"
#include "ecmascript/js_set_iterator.h"
#include "ecmascript/js_weak_container.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/object_factory.h"
namespace panda::ecmascript::builtins {

View File

@ -20,7 +20,7 @@
#include "ecmascript/js_api_tree_map_iterator.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_array-inl.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
namespace panda::ecmascript::containers {
JSTaggedValue ContainersTreeMap::TreeMapConstructor(EcmaRuntimeCallInfo *argv)

View File

@ -20,7 +20,7 @@
#include "ecmascript/js_api_tree_set_iterator.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_array-inl.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
namespace panda::ecmascript::containers {
JSTaggedValue ContainersTreeSet::TreeSetConstructor(EcmaRuntimeCallInfo *argv)

View File

@ -67,7 +67,7 @@
#include "ecmascript/js_weak_container.h"
#include "ecmascript/layout_info-inl.h"
#include "ecmascript/lexical_env.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/mem/assert_scope.h"
#include "ecmascript/mem/c_containers.h"
#include "ecmascript/mem/machine_code.h"

View File

@ -80,7 +80,7 @@
#include "ecmascript/js_weak_container.h"
#include "ecmascript/layout_info-inl.h"
#include "ecmascript/lexical_env.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/mem/assert_scope.h"
#include "ecmascript/mem/c_containers.h"
#include "ecmascript/mem/machine_code.h"
@ -88,7 +88,7 @@
#include "ecmascript/module/js_module_source_text.h"
#include "ecmascript/tagged_array.h"
#include "ecmascript/tagged_dictionary.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
#include "ecmascript/template_map.h"
#include "ecmascript/transitions_dictionary.h"
#include "ecmascript/ts_types/ts_type.h"

View File

@ -16,7 +16,7 @@
#include "ecmascript/js_api_tree_map.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
namespace panda::ecmascript {
void JSAPITreeMap::Set(JSThread *thread, const JSHandle<JSAPITreeMap> &map, const JSHandle<JSTaggedValue> &key,

View File

@ -18,7 +18,7 @@
#include "base/builtins_base.h"
#include "js_api_tree_map.h"
#include "js_array.h"
#include "tagged_tree-inl.h"
#include "tagged_tree.h"
#include "object_factory.h"
namespace panda::ecmascript {

View File

@ -16,7 +16,7 @@
#include "ecmascript/js_api_tree_set.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
namespace panda::ecmascript {
void JSAPITreeSet::Add(JSThread *thread, const JSHandle<JSAPITreeSet> &set, const JSHandle<JSTaggedValue> &value)

View File

@ -18,7 +18,7 @@
#include "base/builtins_base.h"
#include "js_api_tree_set.h"
#include "js_array.h"
#include "tagged_tree-inl.h"
#include "tagged_tree.h"
#include "object_factory.h"
namespace panda::ecmascript {

View File

@ -15,7 +15,7 @@
#include "ecmascript/js_tagged_value.h"
#include "js_map.h"
#include "linked_hash_table-inl.h"
#include "linked_hash_table.h"
#include "object_factory.h"
#include "utils/bit_utils.h"

View File

@ -17,7 +17,7 @@
#include "builtins/builtins_errors.h"
#include "js_array.h"
#include "js_map.h"
#include "linked_hash_table-inl.h"
#include "linked_hash_table.h"
#include "object_factory.h"
namespace panda::ecmascript {

View File

@ -26,7 +26,7 @@
#include "ecmascript/js_regexp.h"
#include "ecmascript/js_set.h"
#include "ecmascript/js_typed_array.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/shared_mm/shared_mm.h"
#include "libpandabase/mem/mem.h"
#include "securec.h"

View File

@ -16,7 +16,7 @@
#include "js_set.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/object_factory.h"
#include "linked_hash_table-inl.h"
#include "linked_hash_table.h"
#include "utils/bit_utils.h"
namespace panda::ecmascript {

View File

@ -18,7 +18,7 @@
#include "ecmascript/ecma_macros.h"
#include "ecmascript/js_array.h"
#include "ecmascript/js_set.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/object_factory.h"
namespace panda::ecmascript {

View File

@ -16,7 +16,7 @@
#include "ecmascript/js_weak_container.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/object_factory.h"
#include "libpandabase/utils/bit_utils.h"

View File

@ -1,271 +0,0 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_LINKED_HASH_TABLE_INL_H
#define ECMASCRIPT_LINKED_HASH_TABLE_INL_H
#include "linked_hash_table.h"
#include "tagged_array-inl.h"
#include "utils/bit_utils.h"
namespace panda::ecmascript {
template<typename Derived, typename HashObject>
JSTaggedValue LinkedHashTable<Derived, HashObject>::GetElement(int index) const
{
ASSERT(index >= 0 && index < static_cast<int>(GetLength()));
return Get(index);
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::SetElement(const JSThread *thread, int index, JSTaggedValue element)
{
ASSERT(index >= 0 && index < static_cast<int>(GetLength()));
Set(thread, index, element);
}
template<typename Derived, typename HashObject>
int LinkedHashTable<Derived, HashObject>::NumberOfElements() const
{
return Get(NUMBER_OF_ELEMENTS_INDEX).GetInt();
}
template<typename Derived, typename HashObject>
int LinkedHashTable<Derived, HashObject>::NumberOfDeletedElements() const
{
return Get(NUMBER_OF_DELETED_ELEMENTS_INDEX).GetInt();
}
template<typename Derived, typename HashObject>
int LinkedHashTable<Derived, HashObject>::Capacity() const
{
return JSTaggedValue(Get(CAPACITY_INDEX)).GetInt();
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::SetNumberOfElements(const JSThread *thread, int nof)
{
Set(thread, NUMBER_OF_ELEMENTS_INDEX, JSTaggedValue(nof));
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::SetNumberOfDeletedElements(const JSThread *thread, int nod)
{
Set(thread, NUMBER_OF_DELETED_ELEMENTS_INDEX, JSTaggedValue(nod));
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::SetCapacity(const JSThread *thread, int capacity)
{
Set(thread, CAPACITY_INDEX, JSTaggedValue(capacity));
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::SetNextTable(const JSThread *thread, JSTaggedValue nextTable)
{
Set(thread, NEXT_TABLE_INDEX, nextTable);
}
template<typename Derived, typename HashObject>
JSTaggedValue LinkedHashTable<Derived, HashObject>::GetNextTable() const
{
return JSTaggedValue(Get(NEXT_TABLE_INDEX));
}
template<typename Derived, typename HashObject>
int LinkedHashTable<Derived, HashObject>::GetDeletedNum(int entry) const
{
ASSERT_PRINT(!GetNextTable().IsUndefined(), "function only execute after rehash");
return GetNextEntry(entry).GetInt();
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::SetDeletedNum(const JSThread *thread, int entry, JSTaggedValue num)
{
ASSERT_PRINT(!GetNextTable().IsUndefined(), "function only execute after rehash");
SetNextEntry(thread, entry, num);
}
template<typename Derived, typename HashObject>
int LinkedHashTable<Derived, HashObject>::GetDeletedElementsAt(int entry) const
{
ASSERT_PRINT(!GetNextTable().IsUndefined(), "function only execute after rehash");
int currentEntry = entry - 1;
while (currentEntry >= 0) {
if (GetKey(currentEntry).IsHole()) {
return GetDeletedNum(currentEntry);
}
currentEntry--;
}
return 0;
}
template<typename Derived, typename HashObject>
uint32_t LinkedHashTable<Derived, HashObject>::HashToBucket(uint32_t hash) const
{
return hash & static_cast<uint32_t>(Capacity() - 1);
}
template<typename Derived, typename HashObject>
uint32_t LinkedHashTable<Derived, HashObject>::BucketToIndex(uint32_t bucket)
{
return bucket + ELEMENTS_START_INDEX;
}
template<typename Derived, typename HashObject>
uint32_t LinkedHashTable<Derived, HashObject>::EntryToIndex(uint32_t entry) const
{
return ELEMENTS_START_INDEX + Capacity() + static_cast<int>(entry) * (HashObject::ENTRY_SIZE + 1);
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::SetKey(const JSThread *thread, int entry, JSTaggedValue key)
{
int index = static_cast<int>(EntryToIndex(entry));
SetElement(thread, index, key);
}
template<typename Derived, typename HashObject>
JSTaggedValue LinkedHashTable<Derived, HashObject>::GetKey(int entry) const
{
int index = static_cast<int>(EntryToIndex(entry));
return GetElement(index);
}
template<typename Derived, typename HashObject>
JSTaggedValue LinkedHashTable<Derived, HashObject>::GetValue(int entry) const
{
int index = static_cast<int>(EntryToIndex(entry)) + HashObject::ENTRY_VALUE_INDEX;
return GetElement(index);
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::SetValue(const JSThread *thread, int entry, JSTaggedValue value)
{
int index = static_cast<int>(EntryToIndex(entry)) + HashObject::ENTRY_VALUE_INDEX;
SetElement(thread, index, value);
}
template<typename Derived, typename HashObject>
JSTaggedValue LinkedHashTable<Derived, HashObject>::GetNextEntry(int entry) const
{
int index = static_cast<int>(EntryToIndex(entry)) + HashObject::ENTRY_SIZE;
return GetElement(index);
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::SetNextEntry(const JSThread *thread, int entry, JSTaggedValue nextEntry)
{
int index = static_cast<int>(EntryToIndex(entry)) + HashObject::ENTRY_SIZE;
SetElement(thread, index, nextEntry);
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::InsertNewEntry(const JSThread *thread, int bucket, int entry)
{
int bucketIndex = static_cast<int>(BucketToIndex(bucket));
JSTaggedValue previousEntry = GetElement(bucketIndex);
SetNextEntry(thread, entry, previousEntry);
SetElement(thread, bucketIndex, JSTaggedValue(entry));
}
template<typename Derived, typename HashObject>
int LinkedHashTable<Derived, HashObject>::FindElement(JSTaggedValue key) const
{
if (!IsKey(key)) {
return -1;
}
int hash = static_cast<int>(LinkedHash::Hash(key));
uint32_t bucket = HashToBucket(hash);
for (JSTaggedValue entry = GetElement(BucketToIndex(bucket)); !entry.IsHole();
entry = GetNextEntry(entry.GetInt())) {
JSTaggedValue element = GetKey(entry.GetInt());
if (element.IsHole()) {
continue;
}
if (element.IsWeak()) {
element.RemoveWeakTag();
}
if (HashObject::IsMatch(key, element)) {
return entry.GetInt();
}
}
return -1;
} // namespace panda::ecmascript
template<typename Derived, typename HashObject>
bool LinkedHashTable<Derived, HashObject>::HasSufficientCapacity(int numOfAddElements) const
{
int numberOfElements = NumberOfElements();
int numOfDelElements = NumberOfDeletedElements();
int capacity = Capacity();
int nof = numberOfElements + numOfAddElements;
// Return true if:
// 50% is still free after adding numOfAddElements elements and
// at most 50% of the free elements are deleted elements.
if ((nof < capacity) && ((numOfDelElements <= (capacity - nof) / 2))) { // 2: half
int neededFree = nof / 2; // 2: half
if (nof + neededFree <= capacity) {
return true;
}
}
return false;
}
template<typename Derived, typename HashObject>
int LinkedHashTable<Derived, HashObject>::ComputeCapacity(uint32_t atLeastSpaceFor)
{
// Add 50% slack to make slot collisions sufficiently unlikely.
// See matching computation in HashTable::HasSufficientCapacity().
uint32_t rawCap = atLeastSpaceFor + (atLeastSpaceFor >> 1UL);
int capacity = static_cast<int>(helpers::math::GetPowerOfTwoValue32(rawCap));
return (capacity > MIN_CAPACITY) ? capacity : MIN_CAPACITY;
}
template<typename Derived, typename HashObject>
void LinkedHashTable<Derived, HashObject>::RemoveEntry(const JSThread *thread, int entry)
{
ASSERT_PRINT(entry >= 0 && entry < Capacity(), "entry must be a non-negative integer less than capacity");
int index = static_cast<int>(EntryToIndex(entry));
for (int i = 0; i < HashObject::ENTRY_SIZE; i++) {
SetElement(thread, index + i, JSTaggedValue::Hole());
}
SetNumberOfElements(thread, NumberOfElements() - 1);
SetNumberOfDeletedElements(thread, NumberOfDeletedElements() + 1);
}
template<typename Derived, typename HashObject>
int LinkedHashTable<Derived, HashObject>::ComputeCapacityWithShrink(int currentCapacity, int atLeastSpaceFor)
{
// Shrink to fit the number of elements if only a quarter of the
// capacity is filled with elements.
if (atLeastSpaceFor > (currentCapacity / 4)) { // 4: quarter
return currentCapacity;
}
// Recalculate the smaller capacity actually needed.
int newCapacity = ComputeCapacity(atLeastSpaceFor);
ASSERT_PRINT(newCapacity > atLeastSpaceFor, "new capacity must greater than atLeastSpaceFor");
// Don't go lower than room for MIN_SHRINK_CAPACITY elements.
if (newCapacity < Derived::MIN_SHRINK_CAPACITY) {
return currentCapacity;
}
return newCapacity;
}
bool LinkedHashMapObject::IsMatch(JSTaggedValue key, JSTaggedValue other)
{
return JSTaggedValue::SameValueZero(key, other);
}
} // namespace panda::ecmascript
#endif // ECMASCRIPT_LINKED_HASH_TABLE_INL_H

View File

@ -13,10 +13,9 @@
* limitations under the License.
*/
#include "linked_hash_table.h"
#include "ecmascript/js_object-inl.h"
#include "libpandabase/utils/bit_utils.h"
#include "linked_hash_table-inl.h"
#include "object_factory.h"
namespace panda::ecmascript {

View File

@ -20,9 +20,15 @@
#include "js_handle.h"
#include "js_symbol.h"
#include "js_tagged_number.h"
#include "tagged_array.h"
#include "tagged_array-inl.h"
#include "utils/bit_utils.h"
namespace panda::ecmascript {
class LinkedHash {
public:
static int Hash(JSTaggedValue key);
};
/**
* memory in LinkedHashTable is divided into 3 parts
* 1.array[0-2] is used to store common information of hashtale such as numberOfElements and capacity
@ -60,79 +66,235 @@ public:
void Rehash(const JSThread *thread, Derived *newTable);
inline bool HasSufficientCapacity(int numOfAddElements) const;
inline bool HasSufficientCapacity(int numOfAddElements) const
{
int numberOfElements = NumberOfElements();
int numOfDelElements = NumberOfDeletedElements();
int capacity = Capacity();
int nof = numberOfElements + numOfAddElements;
// Return true if:
// 50% is still free after adding numOfAddElements elements and
// at most 50% of the free elements are deleted elements.
if ((nof < capacity) && ((numOfDelElements <= (capacity - nof) / 2))) { // 2: half
int neededFree = nof / 2; // 2: half
if (nof + neededFree <= capacity) {
return true;
}
}
return false;
}
inline int FindElement(JSTaggedValue key) const;
inline int FindElement(JSTaggedValue key) const
{
if (!IsKey(key)) {
return -1;
}
int hash = static_cast<int>(LinkedHash::Hash(key));
uint32_t bucket = HashToBucket(hash);
for (JSTaggedValue entry = GetElement(BucketToIndex(bucket)); !entry.IsHole();
entry = GetNextEntry(entry.GetInt())) {
JSTaggedValue element = GetKey(entry.GetInt());
if (element.IsHole()) {
continue;
}
if (element.IsWeak()) {
element.RemoveWeakTag();
}
if (HashObject::IsMatch(key, element)) {
return entry.GetInt();
}
}
return -1;
}
inline void RemoveEntry(const JSThread *thread, int entry);
inline void RemoveEntry(const JSThread *thread, int entry)
{
ASSERT_PRINT(entry >= 0 && entry < Capacity(), "entry must be a non-negative integer less than capacity");
int index = static_cast<int>(EntryToIndex(entry));
for (int i = 0; i < HashObject::ENTRY_SIZE; i++) {
SetElement(thread, index + i, JSTaggedValue::Hole());
}
SetNumberOfElements(thread, NumberOfElements() - 1);
SetNumberOfDeletedElements(thread, NumberOfDeletedElements() + 1);
}
inline static int ComputeCapacity(uint32_t atLeastSpaceFor);
inline static int ComputeCapacity(uint32_t atLeastSpaceFor)
{
// Add 50% slack to make slot collisions sufficiently unlikely.
// See matching computation in HashTable::HasSufficientCapacity().
uint32_t rawCap = atLeastSpaceFor + (atLeastSpaceFor >> 1UL);
int capacity = static_cast<int>(helpers::math::GetPowerOfTwoValue32(rawCap));
return (capacity > MIN_CAPACITY) ? capacity : MIN_CAPACITY;
}
inline static int ComputeCapacityWithShrink(int currentCapacity, int atLeastSpaceFor);
inline static int ComputeCapacityWithShrink(int currentCapacity, int atLeastSpaceFor)
{
// Shrink to fit the number of elements if only a quarter of the
// capacity is filled with elements.
if (atLeastSpaceFor > (currentCapacity / 4)) { // 4: quarter
return currentCapacity;
}
// Recalculate the smaller capacity actually needed.
int newCapacity = ComputeCapacity(atLeastSpaceFor);
ASSERT_PRINT(newCapacity > atLeastSpaceFor, "new capacity must greater than atLeastSpaceFor");
// Don't go lower than room for MIN_SHRINK_CAPACITY elements.
if (newCapacity < Derived::MIN_SHRINK_CAPACITY) {
return currentCapacity;
}
return newCapacity;
}
inline int NumberOfElements() const;
inline int NumberOfElements() const
{
return Get(NUMBER_OF_ELEMENTS_INDEX).GetInt();
}
inline int NumberOfDeletedElements() const;
inline int NumberOfDeletedElements() const
{
return Get(NUMBER_OF_DELETED_ELEMENTS_INDEX).GetInt();
}
inline int Capacity() const;
inline int Capacity() const
{
return JSTaggedValue(Get(CAPACITY_INDEX)).GetInt();
}
inline JSTaggedValue GetKey(int entry) const;
inline JSTaggedValue GetKey(int entry) const
{
int index = static_cast<int>(EntryToIndex(entry));
return GetElement(index);
}
inline JSTaggedValue GetValue(int entry) const;
inline JSTaggedValue GetValue(int entry) const
{
int index = static_cast<int>(EntryToIndex(entry)) + HashObject::ENTRY_VALUE_INDEX;
return GetElement(index);
}
inline static bool IsKey(JSTaggedValue key)
{
return !key.IsHole();
}
inline void SetNumberOfElements(const JSThread *thread, int nof);
inline void SetNumberOfElements(const JSThread *thread, int nof)
{
Set(thread, NUMBER_OF_ELEMENTS_INDEX, JSTaggedValue(nof));
}
inline void SetNumberOfDeletedElements(const JSThread *thread, int nod);
inline void SetNumberOfDeletedElements(const JSThread *thread, int nod)
{
Set(thread, NUMBER_OF_DELETED_ELEMENTS_INDEX, JSTaggedValue(nod));
}
inline void SetCapacity(const JSThread *thread, int capacity);
inline void SetCapacity(const JSThread *thread, int capacity)
{
Set(thread, CAPACITY_INDEX, JSTaggedValue(capacity));
}
inline JSTaggedValue GetNextTable() const;
inline JSTaggedValue GetNextTable() const
{
return JSTaggedValue(Get(NEXT_TABLE_INDEX));
}
inline void SetNextTable(const JSThread *thread, JSTaggedValue nextTable);
inline void SetNextTable(const JSThread *thread, JSTaggedValue nextTable)
{
Set(thread, NEXT_TABLE_INDEX, nextTable);
}
inline int GetDeletedElementsAt(int entry) const;
inline int GetDeletedElementsAt(int entry) const
{
ASSERT_PRINT(!GetNextTable().IsUndefined(), "function only execute after rehash");
int currentEntry = entry - 1;
while (currentEntry >= 0) {
if (GetKey(currentEntry).IsHole()) {
return GetDeletedNum(currentEntry);
}
currentEntry--;
}
return 0;
}
protected:
inline JSTaggedValue GetElement(int index) const;
inline JSTaggedValue GetElement(int index) const
{
ASSERT(index >= 0 && index < static_cast<int>(GetLength()));
return Get(index);
}
inline void SetElement(const JSThread *thread, int index, JSTaggedValue element);
inline void SetElement(const JSThread *thread, int index, JSTaggedValue element)
{
ASSERT(index >= 0 && index < static_cast<int>(GetLength()));
Set(thread, index, element);
}
inline void SetKey(const JSThread *thread, int entry, JSTaggedValue key);
inline void SetKey(const JSThread *thread, int entry, JSTaggedValue key)
{
int index = static_cast<int>(EntryToIndex(entry));
SetElement(thread, index, key);
}
inline void SetValue(const JSThread *thread, int entry, JSTaggedValue value);
inline void SetValue(const JSThread *thread, int entry, JSTaggedValue value)
{
int index = static_cast<int>(EntryToIndex(entry)) + HashObject::ENTRY_VALUE_INDEX;
SetElement(thread, index, value);
}
inline JSTaggedValue GetNextEntry(int entry) const;
inline JSTaggedValue GetNextEntry(int entry) const
{
int index = static_cast<int>(EntryToIndex(entry)) + HashObject::ENTRY_SIZE;
return GetElement(index);
}
inline void SetNextEntry(const JSThread *thread, int entry, JSTaggedValue nextEntry);
inline void SetNextEntry(const JSThread *thread, int entry, JSTaggedValue nextEntry)
{
int index = static_cast<int>(EntryToIndex(entry)) + HashObject::ENTRY_SIZE;
SetElement(thread, index, nextEntry);
}
inline uint32_t HashToBucket(uint32_t hash) const;
inline uint32_t HashToBucket(uint32_t hash) const
{
return hash & static_cast<uint32_t>(Capacity() - 1);
}
inline static uint32_t BucketToIndex(uint32_t bucket);
inline static uint32_t BucketToIndex(uint32_t bucket)
{
return bucket + ELEMENTS_START_INDEX;
}
// min entry = 0
inline uint32_t EntryToIndex(uint32_t entry) const;
inline uint32_t EntryToIndex(uint32_t entry) const
{
return ELEMENTS_START_INDEX + Capacity() + static_cast<int>(entry) * (HashObject::ENTRY_SIZE + 1);
}
inline void InsertNewEntry(const JSThread *thread, int bucket, int entry);
inline void InsertNewEntry(const JSThread *thread, int bucket, int entry)
{
int bucketIndex = static_cast<int>(BucketToIndex(bucket));
JSTaggedValue previousEntry = GetElement(bucketIndex);
SetNextEntry(thread, entry, previousEntry);
SetElement(thread, bucketIndex, JSTaggedValue(entry));
}
inline int GetDeletedNum(int entry) const;
inline int GetDeletedNum(int entry) const
{
ASSERT_PRINT(!GetNextTable().IsUndefined(), "function only execute after rehash");
return GetNextEntry(entry).GetInt();
}
inline void SetDeletedNum(const JSThread *thread, int entry, JSTaggedValue num);
};
class LinkedHash {
public:
static int Hash(JSTaggedValue key);
inline void SetDeletedNum(const JSThread *thread, int entry, JSTaggedValue num)
{
ASSERT_PRINT(!GetNextTable().IsUndefined(), "function only execute after rehash");
SetNextEntry(thread, entry, num);
}
};
class LinkedHashMapObject {
public:
// key must be string now for other object has no 'equals' method
static inline bool IsMatch(JSTaggedValue key, JSTaggedValue other);
static inline bool IsMatch(JSTaggedValue key, JSTaggedValue other)
{
return JSTaggedValue::SameValueZero(key, other);
}
static const int ENTRY_SIZE = 2;
static const int ENTRY_VALUE_INDEX = 1;

View File

@ -79,7 +79,7 @@
#include "ecmascript/js_typed_array.h"
#include "ecmascript/js_weak_container.h"
#include "ecmascript/layout_info-inl.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/mem/heap-inl.h"
#include "ecmascript/mem/space.h"
#include "ecmascript/module/js_module_namespace.h"
@ -87,7 +87,7 @@
#include "ecmascript/record.h"
#include "ecmascript/shared_mm/shared_mm.h"
#include "ecmascript/symbol_table.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
#include "ecmascript/template_map.h"
#include "ecmascript/ts_types/ts_obj_layout_info.h"
#include "ecmascript/ts_types/ts_type.h"

View File

@ -1,511 +0,0 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_TAGGED_TREE_INL_H
#define ECMASCRIPT_TAGGED_TREE_INL_H
#include "ecmascript/tagged_tree.h"
#include "ecmascript/global_env.h"
#include "ecmascript/interpreter/interpreter.h"
#include "tagged_array-inl.h"
#include "utils/bit_utils.h"
namespace panda::ecmascript {
// TaggedTree
template<typename Derived>
JSTaggedValue TaggedTree<Derived>::GetRootKey() const
{
return GetKey(GetRootEntries());
}
template<typename Derived>
void TaggedTree<Derived>::SetRoot(JSThread *thread, int index, JSTaggedValue key, JSTaggedValue value)
{
SetKey(thread, 0, key);
SetValue(thread, 0, value);
SetParent(thread, 0, JSTaggedValue(-1));
SetColor(thread, 0, TreeColor::BLACK);
SetRootEntries(thread, index);
}
template<typename Derived>
void TaggedTree<Derived>::SetKey(const JSThread *thread, uint32_t entry, JSTaggedValue key)
{
int index = EntryToIndex(entry);
SetElement(thread, index, key);
}
template<typename Derived>
void TaggedTree<Derived>::SetValue(const JSThread *thread, uint32_t entry, JSTaggedValue value)
{
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_VALUE_INDEX);
SetElement(thread, index, value);
}
template<typename Derived>
void TaggedTree<Derived>::SetColor(const JSThread *thread, int entry, TreeColor color)
{
if (entry >= 0) {
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_COLOR_INDEX);
SetElement(thread, index, JSTaggedValue(static_cast<int>(color)));
}
}
template<typename Derived>
void TaggedTree<Derived>::SetParent(const JSThread *thread, int entry, JSTaggedValue value)
{
if (entry < 0) {
return;
}
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_PARENT_INDEX);
SetElement(thread, index, value);
}
template<typename Derived>
void TaggedTree<Derived>::SetLeftChild(const JSThread *thread, uint32_t entry, JSTaggedValue value)
{
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_LEFT_CHILD_INDEX);
SetElement(thread, index, value);
}
template<typename Derived>
void TaggedTree<Derived>::SetRightChild(const JSThread *thread, uint32_t entry, JSTaggedValue value)
{
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_RIGHT_CHILD_INDEX);
SetElement(thread, index, value);
}
template<typename Derived>
void TaggedTree<Derived>::SetCompare(const JSThread *thread, JSTaggedValue fn)
{
Set(thread, COMPARE_FUNCTION_INDEX, fn);
}
template<typename Derived>
JSTaggedValue TaggedTree<Derived>::GetCompare() const
{
return Get(COMPARE_FUNCTION_INDEX);
}
template<typename Derived>
JSTaggedValue TaggedTree<Derived>::GetKey(int entry) const
{
if (entry < 0) {
return JSTaggedValue::Hole();
}
int index = EntryToIndex(entry);
return GetElement(index);
}
template<typename Derived>
JSTaggedValue TaggedTree<Derived>::GetValue(int entry) const
{
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_VALUE_INDEX);
return GetElement(index);
}
template<typename Derived>
TreeColor TaggedTree<Derived>::GetColor(int entry) const
{
if (entry < 0) {
return TreeColor::BLACK;
}
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_COLOR_INDEX);
JSTaggedValue color = GetElement(index);
return color.GetInt() == TreeColor::RED ? TreeColor::RED : TreeColor::BLACK;
}
template<typename Derived>
int TaggedTree<Derived>::EntryToIndex(uint32_t entry) const
{
return ELEMENTS_START_INDEX + entry * (Derived::ENTRY_SIZE);
}
template<typename Derived>
void TaggedTree<Derived>::SetElement(const JSThread *thread, uint32_t index, JSTaggedValue element)
{
ASSERT(index >= 0 && index < GetLength());
Set(thread, index, element);
}
template<typename Derived>
JSTaggedValue TaggedTree<Derived>::GetElement(int index) const
{
ASSERT(index >= 0 && index < static_cast<int>(GetLength()));
return Get(index);
}
template<typename Derived>
int TaggedTree<Derived>::NumberOfElements() const
{
return Get(NUMBER_OF_ELEMENTS_INDEX).GetInt();
}
template<typename Derived>
int TaggedTree<Derived>::NumberOfDeletedElements() const
{
return Get(NUMBER_OF_HOLE_ENTRIES_INDEX).GetInt();
}
template<typename Derived>
void TaggedTree<Derived>::SetNumberOfElements(const JSThread *thread, int num)
{
Set(thread, NUMBER_OF_ELEMENTS_INDEX, JSTaggedValue(num));
}
template<typename Derived>
void TaggedTree<Derived>::SetNumberOfDeletedElements(const JSThread *thread, int num)
{
Set(thread, NUMBER_OF_HOLE_ENTRIES_INDEX, JSTaggedValue(num));
}
template<typename Derived>
void TaggedTree<Derived>::SetRootEntries(const JSThread *thread, int num)
{
Set(thread, ROOT_INDEX, JSTaggedValue(num));
}
template<typename Derived>
int TaggedTree<Derived>::GetRootEntries() const
{
return Get(ROOT_INDEX).GetInt();
}
template<typename Derived>
JSTaggedValue TaggedTree<Derived>::GetLeftChild(int parent) const
{
if (parent < 0) {
return JSTaggedValue::Hole();
}
int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_LEFT_CHILD_INDEX);
return Get(index);
}
template<typename Derived>
JSTaggedValue TaggedTree<Derived>::GetRightChild(int parent) const
{
if (parent < 0) {
return JSTaggedValue::Hole();
}
int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_RIGHT_CHILD_INDEX);
return Get(index);
}
template<typename Derived>
int TaggedTree<Derived>::GetLeftChildIndex(int parent) const
{
if (parent < 0) {
return -1;
}
int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_LEFT_CHILD_INDEX);
JSTaggedValue child = Get(index);
return child.IsHole() ? -1 : child.GetInt();
}
template<typename Derived>
int TaggedTree<Derived>::GetRightChildIndex(int parent) const
{
if (parent < 0) {
return -1;
}
int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_RIGHT_CHILD_INDEX);
JSTaggedValue child = Get(index);
return child.IsHole() ? -1: child.GetInt();
}
template<typename Derived>
int TaggedTree<Derived>::GetParent(int entry) const
{
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_PARENT_INDEX);
JSTaggedValue parent = GetElement(index);
return parent.GetInt();
}
template<typename Derived>
int TaggedTree<Derived>::GetMinimum(int entry) const
{
JSTaggedValue child = GetLeftChild(entry);
while (!child.IsHole()) {
entry = child.GetInt();
child = GetLeftChild(entry);
}
return entry;
}
template<typename Derived>
int TaggedTree<Derived>::GetMaximum(int entry) const
{
JSTaggedValue child = GetRightChild(entry);
while (!child.IsHole()) {
entry = child.GetInt();
child = GetRightChild(entry);
}
return entry;
}
template<typename Derived>
bool TaggedTree<Derived>::IsLeft(int entry) const
{
JSTaggedValue child = GetLeftChild(GetParent(entry));
return child.IsHole() ? false : (child.GetInt() == entry);
}
template<typename Derived>
bool TaggedTree<Derived>::IsRight(int entry) const
{
JSTaggedValue child = GetRightChild(GetParent(entry));
return child.IsHole() ? false : (child.GetInt() == entry);
}
template<typename Derived>
bool TaggedTree<Derived>::IsValidIndex(int entry) const
{
return entry != GetRootEntries() && !GetKey(entry).IsHole();
}
template<typename Derived>
int TaggedTree<Derived>::GetLeftBrother(int entry) const
{
JSTaggedValue child = GetRightChild(GetParent(entry));
return child.IsHole() ? -1 : child.GetInt();
}
template<typename Derived>
int TaggedTree<Derived>::GetRightBrother(int entry) const
{
JSTaggedValue child = GetLeftChild(GetParent(entry));
return child.IsHole() ? -1 : child.GetInt();
}
template<typename Derived>
void TaggedTree<Derived>::SetCapacity(const JSThread *thread, int capacity)
{
Set(thread, CAPACITY_INDEX, JSTaggedValue(capacity));
}
template<typename Derived>
int TaggedTree<Derived>::Capacity() const
{
return Get(CAPACITY_INDEX).GetInt();
}
template<typename Derived>
int TaggedTree<Derived>::ComputeCapacity(int oldCapacity)
{
int capacity = (static_cast<uint32_t>(oldCapacity) << 1) + 1;
return (capacity > MIN_CAPACITY) ? capacity : MIN_CAPACITY;
}
template<typename Derived>
void TaggedTree<Derived>::InsertLeftEntry(const JSThread *thread, uint32_t parentIndex, uint32_t entry,
JSTaggedValue key, JSTaggedValue value)
{
SetKey(thread, entry, key);
SetValue(thread, entry, value);
SetColor(thread, entry, TreeColor::RED);
SetParent(thread, entry, JSTaggedValue(parentIndex));
SetLeftChild(thread, parentIndex, JSTaggedValue(entry));
}
template<typename Derived>
void TaggedTree<Derived>::InsertRightEntry(const JSThread *thread, uint32_t parentIndex, uint32_t entry,
JSTaggedValue key, JSTaggedValue value)
{
SetKey(thread, entry, key);
SetValue(thread, entry, value);
SetColor(thread, entry, TreeColor::RED);
SetParent(thread, entry, JSTaggedValue(parentIndex));
SetRightChild(thread, parentIndex, JSTaggedValue(entry));
}
template<typename Derived>
void TaggedTree<Derived>::CopyEntry(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index)
{
newTree->SetKey(thread, index, GetKey(parent));
newTree->SetColor(thread, index, GetColor(parent));
}
template<typename Derived>
void TaggedTree<Derived>::CopyData(const JSThread *thread, int dst, int src)
{
SetKey(thread, dst, GetKey(src));
}
template<typename Derived>
void TaggedTree<Derived>::CopyAllData(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index)
{
newTree->SetKey(thread, index, GetKey(parent));
newTree->SetValue(thread, index, GetValue(parent));
newTree->SetColor(thread, index, GetColor(parent));
newTree->SetParent(thread, index, JSTaggedValue(GetParent(parent)));
newTree->SetRightChild(thread, index, GetRightChild(parent));
newTree->SetLeftChild(thread, index, GetLeftChild(parent));
}
template<typename Derived>
void TaggedTree<Derived>::RemoveEntry(const JSThread *thread, int index)
{
SetKey(thread, index, JSTaggedValue::Hole());
SetParent(thread, index, JSTaggedValue::Hole());
SetLeftChild(thread, index, JSTaggedValue::Hole());
SetRightChild(thread, index, JSTaggedValue::Hole());
}
template<typename Derived>
ComparisonResult TaggedTree<Derived>::EntryCompare(JSThread *thread, const JSHandle<JSTaggedValue> valueX,
const JSHandle<JSTaggedValue> valueY, JSHandle<Derived> tree)
{
JSTaggedValue fn = tree->GetCompare();
if (fn.IsHole()) {
return OrdinayEntryCompare(thread, valueX, valueY);
}
JSHandle<JSTaggedValue> compareFn(thread, fn);
JSHandle<JSTaggedValue> thisArgHandle = thread->GlobalConstants()->GetHandledUndefined();
const size_t argsLength = 2;
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo info =
EcmaInterpreter::NewRuntimeCallInfo(thread, compareFn, thisArgHandle, undefined, argsLength);
info.SetCallArg(valueX.GetTaggedValue(), valueY.GetTaggedValue());
JSTaggedValue callResult = JSFunction::Call(&info);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
int compareResult = 0;
if (callResult.IsInt()) {
compareResult = callResult.GetInt();
} else {
JSHandle<JSTaggedValue> resultHandle(thread, callResult);
JSTaggedNumber v = JSTaggedValue::ToNumber(thread, resultHandle);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
double value = v.GetNumber();
if (std::isnan(value)) {
THROW_TYPE_ERROR_AND_RETURN(thread, "CompareFn has illegal return value", ComparisonResult::UNDEFINED);
}
compareResult = static_cast<int>(value);
}
return compareResult > 0 ? ComparisonResult::GREAT :
(compareResult < 0 ? ComparisonResult::LESS : ComparisonResult::EQUAL);
}
template<typename Derived>
ComparisonResult TaggedTree<Derived>::OrdinayEntryCompare(JSThread *thread, const JSHandle<JSTaggedValue> valueX,
const JSHandle<JSTaggedValue> valueY)
{
if (valueX->IsString() && valueY->IsString()) {
auto xString = static_cast<EcmaString *>(valueX->GetTaggedObject());
auto yString = static_cast<EcmaString *>(valueY->GetTaggedObject());
int result = xString->Compare(yString);
if (result < 0) {
return ComparisonResult::LESS;
}
if (result == 0) {
return ComparisonResult::EQUAL;
}
return ComparisonResult::GREAT;
}
if (valueX->IsNumber() && valueY->IsNumber()) {
return JSTaggedValue::StrictNumberCompare(valueX->GetNumber(), valueY->GetNumber());
}
if (valueX->IsNumber() && valueY->IsString()) {
return ComparisonResult::LESS;
}
if (valueX->IsString() && valueY->IsNumber()) {
return ComparisonResult::GREAT;
}
JSHandle<JSTaggedValue> xValueHandle(JSTaggedValue::ToString(thread, valueX));
JSHandle<JSTaggedValue> yValueHandle(JSTaggedValue::ToString(thread, valueY));
ASSERT_NO_ABRUPT_COMPLETION(thread);
return JSTaggedValue::Compare(thread, xValueHandle, yValueHandle);
}
template<typename Derived>
JSTaggedValue TaggedTree<Derived>::Transform(JSTaggedValue v) const
{
return v.IsHole() ? JSTaggedValue::Undefined() : v;
}
// TaggedTreeMap
void TaggedTreeMap::CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeMap> &newMap, int index)
{
RBTree::CopyEntry(thread, parent, newMap, index);
newMap->SetValue(thread, index, GetValue(parent));
}
void TaggedTreeMap::CopyData(const JSThread *thread, int dst, int src)
{
RBTree::CopyData(thread, dst, src);
SetValue(thread, dst, GetValue(src));
}
void TaggedTreeMap::RemoveEntry(const JSThread *thread, int index)
{
RBTree::RemoveEntry(thread, index);
SetValue(thread, index, JSTaggedValue::Hole());
}
JSTaggedValue TaggedTreeMap::Get(JSThread *thread, const JSHandle<TaggedTreeMap> &map,
const JSHandle<JSTaggedValue> &key)
{
int index = RBTree::FindEntry(thread, map, key);
return index == -1 ? JSTaggedValue::Undefined() : map->GetValue(index);
}
JSTaggedValue TaggedTreeMap::GetFirstKey() const
{
JSTaggedValue key = GetKey(GetMinimum(GetRootEntries()));
return Transform(key);
}
JSTaggedValue TaggedTreeMap::GetLastKey() const
{
JSTaggedValue key = GetKey(GetMaximum(GetRootEntries()));
return Transform(key);
}
// TaggedTreeSet
void TaggedTreeSet::CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeSet> &newMap, int index)
{
RBTree::CopyEntry(thread, parent, newMap, index);
newMap->SetValue(thread, index, GetValue(parent));
}
void TaggedTreeSet::CopyData(const JSThread *thread, int dst, int src)
{
RBTree::CopyData(thread, dst, src);
SetValue(thread, dst, GetValue(src));
}
void TaggedTreeSet::RemoveEntry(const JSThread *thread, int index)
{
RBTree::RemoveEntry(thread, index);
SetValue(thread, index, JSTaggedValue::Hole());
}
JSTaggedValue TaggedTreeSet::GetFirstKey() const
{
JSTaggedValue key = GetKey(GetMinimum(GetRootEntries()));
return Transform(key);
}
JSTaggedValue TaggedTreeSet::GetLastKey() const
{
JSTaggedValue key = GetKey(GetMaximum(GetRootEntries()));
return Transform(key);
}
} // namespace panda::ecmascript
#endif // ECMASCRIPT_TAGGED_TREE_INL_H

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
#include "ecmascript/js_object-inl.h"
#include "ecmascript/object_factory.h"
#include "libpandabase/utils/bit_utils.h"

View File

@ -16,9 +16,12 @@
#ifndef ECMASCRIPT_TAGGED_TREE_H
#define ECMASCRIPT_TAGGED_TREE_H
#include "ecmascript/global_env.h"
#include "ecmascript/interpreter/interpreter.h"
#include "ecmascript/js_tagged_value.h"
#include "js_handle.h"
#include "tagged_array.h"
#include "utils/bit_utils.h"
namespace panda::ecmascript {
enum TreeColor : uint8_t { BLACK = 0, RED };
@ -49,100 +52,393 @@ public:
static JSHandle<Derived> GrowCapacity(const JSThread *thread, JSHandle<Derived> &tree);
inline static int ComputeCapacity(int oldCapacity);
inline static int ComputeCapacity(int oldCapacity)
{
int capacity = (static_cast<uint32_t>(oldCapacity) << 1) + 1;
return (capacity > MIN_CAPACITY) ? capacity : MIN_CAPACITY;
}
static void Remove(const JSThread *thread, const JSHandle<Derived> &tree, int entry);
inline int NumberOfElements() const;
inline int NumberOfDeletedElements() const;
inline int NumberOfElements() const
{
return Get(NUMBER_OF_ELEMENTS_INDEX).GetInt();
}
inline int Capacity() const;
inline int NumberOfDeletedElements() const
{
return Get(NUMBER_OF_HOLE_ENTRIES_INDEX).GetInt();
}
inline JSTaggedValue GetKey(int entry) const;
inline JSTaggedValue GetValue(int entry) const;
inline int Capacity() const
{
return Get(CAPACITY_INDEX).GetInt();
}
inline TreeColor GetColor(int entry) const;
inline JSTaggedValue GetKey(int entry) const
{
if (entry < 0) {
return JSTaggedValue::Hole();
}
int index = EntryToIndex(entry);
return GetElement(index);
}
inline void SetCapacity(const JSThread *thread, int capacity);
inline JSTaggedValue GetValue(int entry) const
{
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_VALUE_INDEX);
return GetElement(index);
}
inline TreeColor GetColor(int entry) const
{
if (entry < 0) {
return TreeColor::BLACK;
}
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_COLOR_INDEX);
JSTaggedValue color = GetElement(index);
return color.GetInt() == TreeColor::RED ? TreeColor::RED : TreeColor::BLACK;
}
inline void SetCapacity(const JSThread *thread, int capacity)
{
Set(thread, CAPACITY_INDEX, JSTaggedValue(capacity));
}
inline static bool IsKey(JSTaggedValue key)
{
return !key.IsHole();
}
inline void SetNumberOfElements(const JSThread *thread, int num);
inline void SetNumberOfDeletedElements(const JSThread *thread, int num);
inline void SetNumberOfElements(const JSThread *thread, int num)
{
Set(thread, NUMBER_OF_ELEMENTS_INDEX, JSTaggedValue(num));
}
inline void SetNumberOfDeletedElements(const JSThread *thread, int num)
{
Set(thread, NUMBER_OF_HOLE_ENTRIES_INDEX, JSTaggedValue(num));
}
inline void SetRootEntries(const JSThread *thread, int num);
inline int GetRootEntries() const;
inline void SetRootEntries(const JSThread *thread, int num)
{
Set(thread, ROOT_INDEX, JSTaggedValue(num));
}
inline int GetRootEntries() const
{
return Get(ROOT_INDEX).GetInt();
}
static int FindEntry(JSThread *thread, const JSHandle<Derived> &tree, const JSHandle<JSTaggedValue> &key);
inline static ComparisonResult EntryCompare(JSThread *thread, const JSHandle<JSTaggedValue> valueX,
const JSHandle<JSTaggedValue> valueY, JSHandle<Derived> tree);
const JSHandle<JSTaggedValue> valueY, JSHandle<Derived> tree)
{
JSTaggedValue fn = tree->GetCompare();
if (fn.IsHole()) {
return OrdinayEntryCompare(thread, valueX, valueY);
}
inline void SetKey(const JSThread *thread, uint32_t entry, JSTaggedValue key);
inline void SetValue(const JSThread *thread, uint32_t entry, JSTaggedValue value);
inline void SetCompare(const JSThread *thread, JSTaggedValue fn);
inline JSTaggedValue GetCompare() const;
JSHandle<JSTaggedValue> compareFn(thread, fn);
JSHandle<JSTaggedValue> thisArgHandle = thread->GlobalConstants()->GetHandledUndefined();
const size_t argsLength = 2;
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo info =
EcmaInterpreter::NewRuntimeCallInfo(thread, compareFn, thisArgHandle, undefined, argsLength);
info.SetCallArg(valueX.GetTaggedValue(), valueY.GetTaggedValue());
JSTaggedValue callResult = JSFunction::Call(&info);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
int compareResult = 0;
if (callResult.IsInt()) {
compareResult = callResult.GetInt();
} else {
JSHandle<JSTaggedValue> resultHandle(thread, callResult);
JSTaggedNumber v = JSTaggedValue::ToNumber(thread, resultHandle);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
double value = v.GetNumber();
if (std::isnan(value)) {
THROW_TYPE_ERROR_AND_RETURN(thread, "CompareFn has illegal return value", ComparisonResult::UNDEFINED);
}
compareResult = static_cast<int>(value);
}
return compareResult > 0 ? ComparisonResult::GREAT :
(compareResult < 0 ? ComparisonResult::LESS : ComparisonResult::EQUAL);
}
inline int GetMinimum(int entry) const;
inline int GetMaximum(int entry) const;
inline void SetKey(const JSThread *thread, uint32_t entry, JSTaggedValue key)
{
int index = EntryToIndex(entry);
SetElement(thread, index, key);
}
inline int GetParent(int entry) const;
inline JSTaggedValue GetLeftChild(int parent) const;
inline JSTaggedValue GetRightChild(int parent) const;
inline int GetLeftChildIndex(int parent) const;
inline int GetRightChildIndex(int parent) const;
inline void SetValue(const JSThread *thread, uint32_t entry, JSTaggedValue value)
{
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_VALUE_INDEX);
SetElement(thread, index, value);
}
inline void SetCompare(const JSThread *thread, JSTaggedValue fn)
{
Set(thread, COMPARE_FUNCTION_INDEX, fn);
}
inline JSTaggedValue GetCompare() const
{
return Get(COMPARE_FUNCTION_INDEX);
}
inline int GetMinimum(int entry) const
{
JSTaggedValue child = GetLeftChild(entry);
while (!child.IsHole()) {
entry = child.GetInt();
child = GetLeftChild(entry);
}
return entry;
}
inline int GetMaximum(int entry) const
{
JSTaggedValue child = GetRightChild(entry);
while (!child.IsHole()) {
entry = child.GetInt();
child = GetRightChild(entry);
}
return entry;
}
inline int GetParent(int entry) const
{
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_PARENT_INDEX);
JSTaggedValue parent = GetElement(index);
return parent.GetInt();
}
inline JSTaggedValue GetLeftChild(int parent) const
{
if (parent < 0) {
return JSTaggedValue::Hole();
}
int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_LEFT_CHILD_INDEX);
return Get(index);
}
inline JSTaggedValue GetRightChild(int parent) const
{
if (parent < 0) {
return JSTaggedValue::Hole();
}
int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_RIGHT_CHILD_INDEX);
return Get(index);
}
inline int GetLeftChildIndex(int parent) const
{
if (parent < 0) {
return -1;
}
int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_LEFT_CHILD_INDEX);
JSTaggedValue child = Get(index);
return child.IsHole() ? -1 : child.GetInt();
}
inline int GetRightChildIndex(int parent) const
{
if (parent < 0) {
return -1;
}
int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_RIGHT_CHILD_INDEX);
JSTaggedValue child = Get(index);
return child.IsHole() ? -1: child.GetInt();
}
protected:
inline JSTaggedValue GetElement(int index) const;
inline JSTaggedValue GetElement(int index) const
{
ASSERT(index >= 0 && index < static_cast<int>(GetLength()));
return Get(index);
}
// get root
inline JSTaggedValue GetRootKey() const;
inline JSTaggedValue GetRootKey() const
{
return GetKey(GetRootEntries());
}
inline void SetRoot(JSThread *thread, int index, JSTaggedValue key, JSTaggedValue value);
inline int EntryToIndex(uint32_t entry) const
{
return ELEMENTS_START_INDEX + entry * (Derived::ENTRY_SIZE);
}
inline void SetElement(const JSThread *thread, uint32_t index, JSTaggedValue element);
inline void SetColor(const JSThread *thread, int entry, TreeColor color);
inline void SetParent(const JSThread *thread, int entry, JSTaggedValue value);
inline void SetElement(const JSThread *thread, uint32_t index, JSTaggedValue element)
{
ASSERT(index >= 0 && index < GetLength());
Set(thread, index, element);
}
inline void SetParent(const JSThread *thread, int entry, JSTaggedValue value)
{
if (entry < 0) {
return;
}
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_PARENT_INDEX);
SetElement(thread, index, value);
}
inline void SetRoot(JSThread *thread, int index, JSTaggedValue key, JSTaggedValue value)
{
SetKey(thread, 0, key);
SetValue(thread, 0, value);
SetParent(thread, 0, JSTaggedValue(-1));
SetColor(thread, 0, TreeColor::BLACK);
SetRootEntries(thread, index);
}
inline void SetColor(const JSThread *thread, int entry, TreeColor color)
{
if (entry >= 0) {
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_COLOR_INDEX);
SetElement(thread, index, JSTaggedValue(static_cast<int>(color)));
}
}
inline int EntryToIndex(uint32_t entry) const;
inline void InsertLeftEntry(const JSThread *thread, uint32_t parentIndex, uint32_t entry, JSTaggedValue key,
JSTaggedValue value);
JSTaggedValue value)
{
SetKey(thread, entry, key);
SetValue(thread, entry, value);
SetColor(thread, entry, TreeColor::RED);
SetParent(thread, entry, JSTaggedValue(parentIndex));
SetLeftChild(thread, parentIndex, JSTaggedValue(entry));
}
inline void InsertRightEntry(const JSThread *thread, uint32_t parentIndex, uint32_t entry, JSTaggedValue key,
JSTaggedValue value);
JSTaggedValue value)
{
SetKey(thread, entry, key);
SetValue(thread, entry, value);
SetColor(thread, entry, TreeColor::RED);
SetParent(thread, entry, JSTaggedValue(parentIndex));
SetRightChild(thread, parentIndex, JSTaggedValue(entry));
}
void InsertRebalance(const JSThread *thread, int index);
void DeleteRebalance(const JSThread *thread, int index);
inline bool IsValidIndex(int entry) const;
inline int GetLeftBrother(int entry) const;
inline int GetRightBrother(int entry) const;
inline bool IsValidIndex(int entry) const
{
return entry != GetRootEntries() && !GetKey(entry).IsHole();
}
inline bool IsLeft(int entry) const;
inline bool IsRight(int entry) const;
inline int GetLeftBrother(int entry) const
{
JSTaggedValue child = GetRightChild(GetParent(entry));
return child.IsHole() ? -1 : child.GetInt();
}
inline int GetRightBrother(int entry) const
{
JSTaggedValue child = GetLeftChild(GetParent(entry));
return child.IsHole() ? -1 : child.GetInt();
}
inline bool IsLeft(int entry) const
{
JSTaggedValue child = GetLeftChild(GetParent(entry));
return child.IsHole() ? false : (child.GetInt() == entry);
}
inline bool IsRight(int entry) const
{
JSTaggedValue child = GetRightChild(GetParent(entry));
return child.IsHole() ? false : (child.GetInt() == entry);
}
int GetPreDecessor(int entry) const;
int GetSuccessor(int entry) const;
inline void SetLeftChild(const JSThread *thread, uint32_t entry, JSTaggedValue value);
inline void SetRightChild(const JSThread *thread, uint32_t entry, JSTaggedValue value);
inline void SetLeftChild(const JSThread *thread, uint32_t entry, JSTaggedValue value)
{
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_LEFT_CHILD_INDEX);
SetElement(thread, index, value);
}
inline void SetRightChild(const JSThread *thread, uint32_t entry, JSTaggedValue value)
{
int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_RIGHT_CHILD_INDEX);
SetElement(thread, index, value);
}
void LeftRotate(const JSThread *thread, int index);
void RightRotate(const JSThread *thread, int index);
static JSHandle<Derived> AdjustTaggedTree(const JSThread *thread, const JSHandle<Derived> &tree, int len);
inline static ComparisonResult OrdinayEntryCompare(JSThread *thread, const JSHandle<JSTaggedValue> valueX,
const JSHandle<JSTaggedValue> valueY);
const JSHandle<JSTaggedValue> valueY)
{
if (valueX->IsString() && valueY->IsString()) {
auto xString = static_cast<EcmaString *>(valueX->GetTaggedObject());
auto yString = static_cast<EcmaString *>(valueY->GetTaggedObject());
int result = xString->Compare(yString);
if (result < 0) {
return ComparisonResult::LESS;
}
if (result == 0) {
return ComparisonResult::EQUAL;
}
return ComparisonResult::GREAT;
}
inline void CopyEntry(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index);
inline void CopyData(const JSThread *thread, int dst, int src);
inline void CopyAllData(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index);
if (valueX->IsNumber() && valueY->IsNumber()) {
return JSTaggedValue::StrictNumberCompare(valueX->GetNumber(), valueY->GetNumber());
}
inline void RemoveEntry(const JSThread *thread, int index);
if (valueX->IsNumber() && valueY->IsString()) {
return ComparisonResult::LESS;
}
if (valueX->IsString() && valueY->IsNumber()) {
return ComparisonResult::GREAT;
}
JSHandle<JSTaggedValue> xValueHandle(JSTaggedValue::ToString(thread, valueX));
JSHandle<JSTaggedValue> yValueHandle(JSTaggedValue::ToString(thread, valueY));
ASSERT_NO_ABRUPT_COMPLETION(thread);
return JSTaggedValue::Compare(thread, xValueHandle, yValueHandle);
}
inline void CopyEntry(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index)
{
newTree->SetKey(thread, index, GetKey(parent));
newTree->SetColor(thread, index, GetColor(parent));
}
inline void CopyData(const JSThread *thread, int dst, int src)
{
SetKey(thread, dst, GetKey(src));
}
inline void CopyAllData(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index)
{
newTree->SetKey(thread, index, GetKey(parent));
newTree->SetValue(thread, index, GetValue(parent));
newTree->SetColor(thread, index, GetColor(parent));
newTree->SetParent(thread, index, JSTaggedValue(GetParent(parent)));
newTree->SetRightChild(thread, index, GetRightChild(parent));
newTree->SetLeftChild(thread, index, GetLeftChild(parent));
}
inline void RemoveEntry(const JSThread *thread, int index)
{
SetKey(thread, index, JSTaggedValue::Hole());
SetParent(thread, index, JSTaggedValue::Hole());
SetLeftChild(thread, index, JSTaggedValue::Hole());
SetRightChild(thread, index, JSTaggedValue::Hole());
}
inline JSTaggedValue Transform(JSTaggedValue v) const
{
return v.IsHole() ? JSTaggedValue::Undefined() : v;
}
inline JSTaggedValue Transform(JSTaggedValue v) const;
void Transplant(const JSThread *thread, int dst, int src);
static JSTaggedValue GetLowerKey(JSThread *thread, const JSHandle<Derived> &tree,
@ -166,7 +462,12 @@ public:
static JSTaggedValue Set(JSThread *thread, JSHandle<TaggedTreeMap> &obj,
const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value);
inline static JSTaggedValue Get(JSThread *thread, const JSHandle<TaggedTreeMap> &map,
const JSHandle<JSTaggedValue> &key);
const JSHandle<JSTaggedValue> &key)
{
int index = RBTree::FindEntry(thread, map, key);
return index == -1 ? JSTaggedValue::Undefined() : map->GetValue(index);
}
static JSTaggedValue Delete(JSThread *thread, const JSHandle<TaggedTreeMap> &map, int entry);
bool HasValue(const JSThread *thread, JSTaggedValue value) const;
@ -175,8 +476,17 @@ public:
static JSTaggedValue GetHigherKey(JSThread *thread, const JSHandle<TaggedTreeMap> &map,
const JSHandle<JSTaggedValue> &key);
inline JSTaggedValue GetFirstKey() const;
inline JSTaggedValue GetLastKey() const;
inline JSTaggedValue GetFirstKey() const
{
JSTaggedValue key = GetKey(GetMinimum(GetRootEntries()));
return Transform(key);
}
inline JSTaggedValue GetLastKey() const
{
JSTaggedValue key = GetKey(GetMaximum(GetRootEntries()));
return Transform(key);
}
static JSTaggedValue SetAll(JSThread *thread, JSHandle<TaggedTreeMap> &dst, const JSHandle<TaggedTreeMap> &src);
static JSHandle<TaggedArray> GetArrayFromMap(const JSThread *thread, const JSHandle<TaggedTreeMap> &map);
@ -190,9 +500,22 @@ public:
static const int ENTRY_RIGHT_CHILD_INDEX = 5;
DECL_DUMP()
inline void CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeMap> &newTree, int index);
inline void CopyData(const JSThread *thread, int dst, int src);
inline void RemoveEntry(const JSThread *thread, int index);
inline void CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeMap> &newMap, int index)
{
RBTree::CopyEntry(thread, parent, newMap, index);
newMap->SetValue(thread, index, GetValue(parent));
}
inline void CopyData(const JSThread *thread, int dst, int src)
{
RBTree::CopyData(thread, dst, src);
SetValue(thread, dst, GetValue(src));
}
inline void RemoveEntry(const JSThread *thread, int index)
{
RBTree::RemoveEntry(thread, index);
SetValue(thread, index, JSTaggedValue::Hole());
}
};
class TaggedTreeSet : public TaggedTree<TaggedTreeSet> {
@ -212,8 +535,18 @@ public:
static JSTaggedValue GetHigherKey(JSThread *thread, const JSHandle<TaggedTreeSet> &set,
const JSHandle<JSTaggedValue> &key);
inline JSTaggedValue GetFirstKey() const;
inline JSTaggedValue GetLastKey() const;
inline JSTaggedValue GetFirstKey() const
{
JSTaggedValue key = GetKey(GetMinimum(GetRootEntries()));
return Transform(key);
}
inline JSTaggedValue GetLastKey() const
{
JSTaggedValue key = GetKey(GetMaximum(GetRootEntries()));
return Transform(key);
}
static JSHandle<TaggedArray> GetArrayFromSet(const JSThread *thread, const JSHandle<TaggedTreeSet> &set);
static int FindEntry(JSThread *thread, const JSHandle<TaggedTreeSet> &set, const JSHandle<JSTaggedValue> &key);
@ -226,9 +559,23 @@ public:
DECL_DUMP()
inline void CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeSet> &newTree, int index);
inline void CopyData(const JSThread *thread, int dst, int src);
inline void RemoveEntry(const JSThread *thread, int index);
inline void CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeSet> &newMap, int index)
{
RBTree::CopyEntry(thread, parent, newMap, index);
newMap->SetValue(thread, index, GetValue(parent));
}
inline void CopyData(const JSThread *thread, int dst, int src)
{
RBTree::CopyData(thread, dst, src);
SetValue(thread, dst, GetValue(src));
}
inline void RemoveEntry(const JSThread *thread, int index)
{
RBTree::RemoveEntry(thread, index);
SetValue(thread, index, JSTaggedValue::Hole());
}
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_TAGGED_TREE_H

View File

@ -81,7 +81,7 @@
#include "ecmascript/js_weak_container.h"
#include "ecmascript/layout_info-inl.h"
#include "ecmascript/lexical_env.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/mem/assert_scope.h"
#include "ecmascript/mem/c_containers.h"
#include "ecmascript/mem/machine_code.h"
@ -89,7 +89,7 @@
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_array.h"
#include "ecmascript/tagged_dictionary.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
#include "ecmascript/template_map.h"
#include "ecmascript/tests/test_helper.h"
#include "ecmascript/transitions_dictionary.h"

View File

@ -25,7 +25,7 @@
#include "ecmascript/js_object-inl.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
#include "ecmascript/tests/test_helper.h"
using namespace panda;

View File

@ -25,7 +25,7 @@
#include "ecmascript/js_object-inl.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
#include "ecmascript/tests/test_helper.h"
using namespace panda;

View File

@ -23,7 +23,7 @@
#include "ecmascript/js_map_iterator.h"
#include "ecmascript/js_object-inl.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_hash_table-inl.h"
#include "ecmascript/tests/test_helper.h"

View File

@ -26,7 +26,7 @@
#include "ecmascript/js_set.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/js_typed_array.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tests/test_helper.h"

View File

@ -23,7 +23,7 @@
#include "ecmascript/js_set.h"
#include "ecmascript/js_set_iterator.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_hash_table-inl.h"
#include "ecmascript/tests/test_helper.h"

View File

@ -18,7 +18,7 @@
#include "ecmascript/js_handle.h"
#include "ecmascript/js_object-inl.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/linked_hash_table-inl.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_hash_table-inl.h"

View File

@ -21,7 +21,7 @@
#include "ecmascript/js_object-inl.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_tree-inl.h"
#include "ecmascript/tagged_tree.h"
#include "ecmascript/tests/test_helper.h"
using namespace panda;