14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_SYMBOL_TABLE_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_SYMBOL_TABLE_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/ecma_string.h"
204514f5e3Sopenharmony_ci#include "ecmascript/ecma_vm.h"
214514f5e3Sopenharmony_ci#include "ecmascript/js_symbol.h"
224514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h"
234514f5e3Sopenharmony_ci#include "ecmascript/object_factory.h"
244514f5e3Sopenharmony_ci#include "ecmascript/tagged_hash_table.h"
254514f5e3Sopenharmony_ci
264514f5e3Sopenharmony_cinamespace panda::ecmascript {
274514f5e3Sopenharmony_ciclass SymbolTable : public TaggedHashTable<SymbolTable> {
284514f5e3Sopenharmony_cipublic:
294514f5e3Sopenharmony_ci    using HashTable = TaggedHashTable<SymbolTable>;
304514f5e3Sopenharmony_ci    static SymbolTable *Cast(TaggedObject *object)
314514f5e3Sopenharmony_ci    {
324514f5e3Sopenharmony_ci        return reinterpret_cast<SymbolTable *>(object);
334514f5e3Sopenharmony_ci    }
344514f5e3Sopenharmony_ci    inline static int GetKeyIndex(int entry)
354514f5e3Sopenharmony_ci    {
364514f5e3Sopenharmony_ci        return HashTable::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_KEY_INDEX;
374514f5e3Sopenharmony_ci    }
384514f5e3Sopenharmony_ci    inline static int GetValueIndex(int entry)
394514f5e3Sopenharmony_ci    {
404514f5e3Sopenharmony_ci        return HashTable::TABLE_HEADER_SIZE + entry * GetEntrySize() + ENTRY_VALUE_INDEX;
414514f5e3Sopenharmony_ci    }
424514f5e3Sopenharmony_ci    inline static int GetEntryIndex(int entry)
434514f5e3Sopenharmony_ci    {
444514f5e3Sopenharmony_ci        return HashTable::TABLE_HEADER_SIZE + entry * GetEntrySize();
454514f5e3Sopenharmony_ci    }
464514f5e3Sopenharmony_ci    inline static int GetEntrySize()
474514f5e3Sopenharmony_ci    {
484514f5e3Sopenharmony_ci        return ENTRY_SIZE;
494514f5e3Sopenharmony_ci    }
504514f5e3Sopenharmony_ci    static inline bool IsMatch(const JSTaggedValue &name, const JSTaggedValue &other)
514514f5e3Sopenharmony_ci    {
524514f5e3Sopenharmony_ci        if (name.IsHole() || name.IsUndefined()) {
534514f5e3Sopenharmony_ci            return false;
544514f5e3Sopenharmony_ci        }
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_ci        auto *nameString = static_cast<EcmaString *>(name.GetTaggedObject());
574514f5e3Sopenharmony_ci        auto *otherString = static_cast<EcmaString *>(other.GetTaggedObject());
584514f5e3Sopenharmony_ci        return EcmaStringAccessor::StringsAreEqual(nameString, otherString);
594514f5e3Sopenharmony_ci    }
604514f5e3Sopenharmony_ci    static inline uint32_t Hash(const JSTaggedValue &obj)
614514f5e3Sopenharmony_ci    {
624514f5e3Sopenharmony_ci        if (obj.IsHeapObject()) {
634514f5e3Sopenharmony_ci            if (obj.IsString()) {
644514f5e3Sopenharmony_ci                auto *nameString = static_cast<EcmaString *>(obj.GetTaggedObject());
654514f5e3Sopenharmony_ci                return EcmaStringAccessor(nameString).GetHashcode();
664514f5e3Sopenharmony_ci            }
674514f5e3Sopenharmony_ci            return JSSymbol::ComputeHash();
684514f5e3Sopenharmony_ci        }
694514f5e3Sopenharmony_ci        LOG_ECMA(FATAL) << "this branch is unreachable";
704514f5e3Sopenharmony_ci        UNREACHABLE();
714514f5e3Sopenharmony_ci    }
724514f5e3Sopenharmony_ci
734514f5e3Sopenharmony_ci    static const int DEFAULT_ELEMENTS_NUMBER = 64;
744514f5e3Sopenharmony_ci    static JSHandle<SymbolTable> Create(JSThread *thread, int numberOfElements = DEFAULT_ELEMENTS_NUMBER)
754514f5e3Sopenharmony_ci    {
764514f5e3Sopenharmony_ci        return HashTable::Create(thread, numberOfElements);
774514f5e3Sopenharmony_ci    }
784514f5e3Sopenharmony_ci
794514f5e3Sopenharmony_ci    inline bool ContainsKey(const JSTaggedValue &key)
804514f5e3Sopenharmony_ci    {
814514f5e3Sopenharmony_ci        int entry = FindEntry(key);
824514f5e3Sopenharmony_ci        return entry != -1;
834514f5e3Sopenharmony_ci    }
844514f5e3Sopenharmony_ci
854514f5e3Sopenharmony_ci    inline JSTaggedValue GetSymbol(const JSTaggedValue &key)
864514f5e3Sopenharmony_ci    {
874514f5e3Sopenharmony_ci        int entry = FindEntry(key);
884514f5e3Sopenharmony_ci        ASSERT(entry != -1);
894514f5e3Sopenharmony_ci        return GetValue(entry);
904514f5e3Sopenharmony_ci    }
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_ci    inline JSTaggedValue FindSymbol(const JSTaggedValue &value)
934514f5e3Sopenharmony_ci    {
944514f5e3Sopenharmony_ci        JSSymbol *symbol = JSSymbol::Cast(value.GetTaggedObject());
954514f5e3Sopenharmony_ci        JSTaggedValue des = symbol->GetDescription();
964514f5e3Sopenharmony_ci        if (!des.IsUndefined()) {
974514f5e3Sopenharmony_ci            if (ContainsKey(des)) {
984514f5e3Sopenharmony_ci                return des;
994514f5e3Sopenharmony_ci            }
1004514f5e3Sopenharmony_ci        }
1014514f5e3Sopenharmony_ci        return JSTaggedValue::Undefined();
1024514f5e3Sopenharmony_ci    }
1034514f5e3Sopenharmony_ci    static int ComputeCompactSize([[maybe_unused]] const JSHandle<SymbolTable> &table, int computeHashTableSize,
1044514f5e3Sopenharmony_ci        [[maybe_unused]] int tableSize, [[maybe_unused]] int addedElements)
1054514f5e3Sopenharmony_ci    {
1064514f5e3Sopenharmony_ci        return computeHashTableSize;
1074514f5e3Sopenharmony_ci    }
1084514f5e3Sopenharmony_ci    static constexpr int ENTRY_KEY_INDEX = 0;
1094514f5e3Sopenharmony_ci    static constexpr int ENTRY_VALUE_INDEX = 1;
1104514f5e3Sopenharmony_ci    static constexpr int ENTRY_SIZE = 2;
1114514f5e3Sopenharmony_ci};
1124514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
1134514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_SYMBOL_TABLE_H