Signed-off-by: linxiang8 <linxiang8@huawei.com>

Change-Id: I474a84db7d80ec0f5370a4f58df115963e21d90f

Change-Id: I471252903083c4d2d15f389b23afbc6c5427f664
This commit is contained in:
linxiang8 2023-03-01 19:26:53 +08:00
parent fa6dd8ea2f
commit 1fe4846e88
11 changed files with 144 additions and 15 deletions

View File

@ -71,7 +71,7 @@ int TransitionsDictionary::FindEntry(const JSTaggedValue &key, const JSTaggedVal
return -1;
}
if (TransitionsDictionary::IsMatch(key, metaData, element, GetAttributes(entry))) {
if (TransitionsDictionary::IsMatch(key, metaData, element, GetAttributes(entry).GetWeakRawValue())) {
return static_cast<int>(entry);
}
}
@ -95,27 +95,29 @@ JSHandle<TransitionsDictionary> TransitionsDictionary::Remove(const JSThread *th
void TransitionsDictionary::Rehash(const JSThread *thread, TransitionsDictionary *newTable)
{
DISALLOW_GARBAGE_COLLECTION;
if ((newTable == nullptr) || (newTable->Size() < EntriesCount())) {
if (newTable == nullptr) {
return;
}
int size = this->Size();
// Rehash elements to new table
int entryCount = 0;
for (int i = 0; i < size; i++) {
int fromIndex = GetEntryIndex(i);
JSTaggedValue k = this->GetKey(i);
if (!IsKey(k)) {
continue;
}
int hash = TransitionsDictionary::Hash(k, this->GetAttributes(i));
int insertionIndex = GetEntryIndex(newTable->FindInsertIndex(hash));
JSTaggedValue tv = Get(fromIndex);
newTable->Set(thread, insertionIndex, tv);
for (int j = 1; j < TransitionsDictionary::ENTRY_SIZE; j++) {
tv = Get(fromIndex + j);
newTable->Set(thread, insertionIndex + j, tv);
JSTaggedValue v = this->GetValue(i);
if (IsKey(k) && TransitionsDictionary::CheckWeakExist(v)) {
int hash = TransitionsDictionary::Hash(k, this->GetAttributes(i));
int insertionIndex = GetEntryIndex(newTable->FindInsertIndex(hash));
JSTaggedValue tv = Get(fromIndex);
newTable->Set(thread, insertionIndex, tv);
for (int j = 1; j < TransitionsDictionary::ENTRY_SIZE; j++) {
tv = Get(fromIndex + j);
newTable->Set(thread, insertionIndex + j, tv);
}
entryCount++;
}
}
newTable->SetEntriesCount(thread, EntriesCount());
newTable->SetEntriesCount(thread, entryCount);
newTable->SetHoleEntriesCount(thread, 0);
}

View File

@ -200,6 +200,14 @@ public:
return JSTaggedValue(value_ | TAG_WEAK);
}
inline JSTaggedValue GetWeakRawValue() const
{
if (IsHeapObject()) {
return JSTaggedValue(value_ & (~TAG_WEAK));
}
return JSTaggedValue(value_);
}
ARK_INLINE bool IsWeak() const
{
return ((value_ & TAG_WEAK_MASK) == TAG_WEAK);

View File

@ -132,6 +132,11 @@ public:
const JSHandle<CjsModuleCache> &dictionary,
const JSHandle<JSTaggedValue> &key,
const JSHandle<JSTaggedValue> &value);
static int ComputeCompactSize([[maybe_unused]] const JSHandle<CjsModuleCache> &table, int computeHashTableSize,
[[maybe_unused]] int tableSize, [[maybe_unused]] int addedElements)
{
return computeHashTableSize;
}
static constexpr int ENTRY_KEY_INDEX = 0;
static constexpr int ENTRY_VALUE_INDEX = 1;
static constexpr int ENTRY_SIZE = 2;

View File

@ -100,6 +100,11 @@ public:
}
return JSTaggedValue::Undefined();
}
static int ComputeCompactSize([[maybe_unused]] const JSHandle<SymbolTable> &table, int computeHashTableSize,
[[maybe_unused]] int tableSize, [[maybe_unused]] int addedElements)
{
return computeHashTableSize;
}
static constexpr int ENTRY_KEY_INDEX = 0;
static constexpr int ENTRY_VALUE_INDEX = 1;
static constexpr int ENTRY_SIZE = 2;

View File

@ -74,7 +74,9 @@ public:
}
return table;
}
int newSize = ComputeHashTableSize(table->Size() + numOfAddedElements);
int newSize = Derived::ComputeCompactSize(table, ComputeHashTableSize(table->Size() + numOfAddedElements),
table->Size(), numOfAddedElements);
newSize = std::max(newSize, MIN_SHRINK_SIZE);
int length = Derived::GetEntryIndex(newSize);
JSHandle<Derived> newTable(thread->GetEcmaVM()->GetFactory()->NewDictionaryArray(length));
newTable->SetHashTableSize(thread, newSize);
@ -488,6 +490,12 @@ public:
return result;
}
static int ComputeCompactSize([[maybe_unused]] const JSHandle<Derived> &table, int computeHashTableSize,
[[maybe_unused]] int tableSize, [[maybe_unused]] int addedElements)
{
return computeHashTableSize;
}
static const int NEXT_ENUMERATION_INDEX = HashTableT::SIZE_INDEX + 1;
static const int DEFAULT_ELEMENTS_NUMBER = 128;
static constexpr int TABLE_HEADER_SIZE = 4;

View File

@ -59,6 +59,11 @@ public:
{
return HashTable::Create(thread, numberOfElements);
}
static int ComputeCompactSize([[maybe_unused]] const JSHandle<TemplateMap> &table, int computeHashTableSize,
[[maybe_unused]] int tableSize, [[maybe_unused]] int addedElements)
{
return computeHashTableSize;
}
static const int ENTRY_SIZE = 2;
static const int ENTRY_KEY_INDEX = 0;
static const int ENTRY_VALUE_INDEX = 1;

View File

@ -111,7 +111,12 @@ public:
SetKey(thread, entry, key);
JSTaggedValue weakValue = JSTaggedValue(value.CreateAndGetWeakRef());
SetValue(thread, entry, weakValue);
SetAttributes(thread, entry, metaData);
if (!metaData.IsHeapObject()) {
SetAttributes(thread, entry, metaData);
return;
}
JSTaggedValue weakMetaData = JSTaggedValue(metaData.CreateAndGetWeakRef());
SetAttributes(thread, entry, weakMetaData);
}
inline void RemoveElement(const JSThread *thread, int entry)
@ -132,10 +137,33 @@ public:
const JSHandle<JSTaggedValue> &key, const JSTaggedValue &metaData);
void Rehash(const JSThread *thread, TransitionsDictionary *newTable);
static bool CheckWeakExist(const JSTaggedValue &value)
{
if (value == JSTaggedValue::Undefined()) {
return false;
}
return true;
}
static int ComputeCompactSize(const JSHandle<TransitionsDictionary> &table, int computeHashTableSize,
int tableSize, int addedElements)
{
int realEntryCount = 0;
for (int i = 0; i < tableSize; i++) {
// value is weak reference, if not use will be set undefined.
if (TransitionsDictionary::CheckWeakExist(table->GetValue(i))) {
realEntryCount++;
}
}
return std::min(computeHashTableSize,
static_cast<int>(helpers::math::GetPowerOfTwoValue32(realEntryCount + addedElements) * HASH_TABLE_BUFFER));
}
static constexpr int ENTRY_SIZE = 3;
static constexpr int ENTRY_KEY_INDEX = 0;
static constexpr int ENTRY_VALUE_INDEX = 1;
static constexpr int ENTRY_DETAILS_INDEX = 2;
static constexpr int HASH_TABLE_BUFFER = 2;
DECL_DUMP()
};
} // namespace panda::ecmascript

View File

@ -51,6 +51,7 @@ group("ark_js_moduletest") {
"linkedhashtable:linkedhashtableAction",
"loadicbyvalue:loadicbyvalueAction",
"localelowercase:localelowercaseAction",
"memleak/objectcreate:objectcreateAction",
"merge:mergeAction",
"module:moduleAction",
"moduleImportJson:moduleImportJsonAction",

View File

@ -0,0 +1,18 @@
# Copyright (c) 2023 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_moduletest_action("objectcreate") {
deps = []
}

View File

@ -0,0 +1,14 @@
# 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.
log test

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2023 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.
*/
function foo() {
for (let i = 0; i < 100; i++) {
var base = {
extend() {
return Object.create(this);
},
test() {
print("log test");
}
}
if (i == 0) {
var instance = base.extend();
base.test()
}
}
}
ArkTools.forceFullGC();
foo()
ArkTools.forceFullGC();