14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2022 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_COMPILER_BITSET_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_COMPILER_BITSET_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include <cstddef>
204514f5e3Sopenharmony_ci#include <cstdint>
214514f5e3Sopenharmony_ci#include "ecmascript/mem/chunk.h"
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
244514f5e3Sopenharmony_ciclass BitSet {
254514f5e3Sopenharmony_cipublic:
264514f5e3Sopenharmony_ci    static constexpr uint32_t BYTE_PER_WORD = sizeof(uint64_t);
274514f5e3Sopenharmony_ci    static constexpr uint32_t BYTE_PER_WORD_LOG2 = 3;
284514f5e3Sopenharmony_ci    static constexpr uint32_t BIT_PER_BYTE = 8;
294514f5e3Sopenharmony_ci    static constexpr uint32_t BIT_PER_WORD = BYTE_PER_WORD * BIT_PER_BYTE;
304514f5e3Sopenharmony_ci    static constexpr uint32_t BIT_PER_WORD_LOG2 = 6;
314514f5e3Sopenharmony_ci    static constexpr uint32_t BIT_PER_WORD_MASK = BIT_PER_WORD - 1;
324514f5e3Sopenharmony_ci
334514f5e3Sopenharmony_ci    explicit BitSet(Chunk* chunk, size_t bitSize)
344514f5e3Sopenharmony_ci    {
354514f5e3Sopenharmony_ci        wordCount_ = SizeOf(bitSize);
364514f5e3Sopenharmony_ci        if (UseWords()) {
374514f5e3Sopenharmony_ci            data_.words_ = chunk->NewArray<uint64_t>(wordCount_);
384514f5e3Sopenharmony_ci            Reset();
394514f5e3Sopenharmony_ci        }
404514f5e3Sopenharmony_ci    }
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_ci    ~BitSet()
434514f5e3Sopenharmony_ci    {
444514f5e3Sopenharmony_ci        if (UseWords()) {
454514f5e3Sopenharmony_ci            // no need delete chunk memory
464514f5e3Sopenharmony_ci            data_.words_ = nullptr;
474514f5e3Sopenharmony_ci        }
484514f5e3Sopenharmony_ci    }
494514f5e3Sopenharmony_ci
504514f5e3Sopenharmony_ci    void Reset()
514514f5e3Sopenharmony_ci    {
524514f5e3Sopenharmony_ci        if (!UseWords()) {
534514f5e3Sopenharmony_ci            data_.inlineWord_ = 0;
544514f5e3Sopenharmony_ci        } else {
554514f5e3Sopenharmony_ci            for (size_t i = 0; i < wordCount_; i++) {
564514f5e3Sopenharmony_ci                data_.words_[i] = 0;
574514f5e3Sopenharmony_ci            }
584514f5e3Sopenharmony_ci        }
594514f5e3Sopenharmony_ci    }
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_ci    bool TestBit(size_t offset) const
624514f5e3Sopenharmony_ci    {
634514f5e3Sopenharmony_ci        if (!UseWords()) {
644514f5e3Sopenharmony_ci            return data_.inlineWord_ & Mask(offset);
654514f5e3Sopenharmony_ci        }  else {
664514f5e3Sopenharmony_ci            ASSERT(wordCount_ > Index(offset));
674514f5e3Sopenharmony_ci            return data_.words_[Index(offset)] & Mask(IndexInWord(offset));
684514f5e3Sopenharmony_ci        }
694514f5e3Sopenharmony_ci    }
704514f5e3Sopenharmony_ci
714514f5e3Sopenharmony_ci    void SetBit(size_t offset)
724514f5e3Sopenharmony_ci    {
734514f5e3Sopenharmony_ci        if (!UseWords()) {
744514f5e3Sopenharmony_ci            data_.inlineWord_ |= Mask(offset);
754514f5e3Sopenharmony_ci        } else {
764514f5e3Sopenharmony_ci            ASSERT(wordCount_ > Index(offset));
774514f5e3Sopenharmony_ci            data_.words_[Index(offset)] |= Mask(IndexInWord(offset));
784514f5e3Sopenharmony_ci        }
794514f5e3Sopenharmony_ci    }
804514f5e3Sopenharmony_ci
814514f5e3Sopenharmony_ci    void ClearBit(size_t offset)
824514f5e3Sopenharmony_ci    {
834514f5e3Sopenharmony_ci        if (!UseWords()) {
844514f5e3Sopenharmony_ci            data_.inlineWord_ &= ~Mask(offset);
854514f5e3Sopenharmony_ci        } else {
864514f5e3Sopenharmony_ci            ASSERT(wordCount_ > Index(offset));
874514f5e3Sopenharmony_ci            data_.words_[Index(offset)] &= ~Mask(IndexInWord(offset));
884514f5e3Sopenharmony_ci        }
894514f5e3Sopenharmony_ci    }
904514f5e3Sopenharmony_ci
914514f5e3Sopenharmony_ci    void Union(const BitSet &bitset)
924514f5e3Sopenharmony_ci    {
934514f5e3Sopenharmony_ci        if (!UseWords()) {
944514f5e3Sopenharmony_ci            data_.inlineWord_ |= bitset.data_.inlineWord_;
954514f5e3Sopenharmony_ci        } else {
964514f5e3Sopenharmony_ci            for (size_t i = 0; i < wordCount_; i++) {
974514f5e3Sopenharmony_ci                data_.words_[i] |= bitset.data_.words_[i];
984514f5e3Sopenharmony_ci            }
994514f5e3Sopenharmony_ci        }
1004514f5e3Sopenharmony_ci    }
1014514f5e3Sopenharmony_ci
1024514f5e3Sopenharmony_ci    bool UnionWithChanged(const BitSet &bitset)
1034514f5e3Sopenharmony_ci    {
1044514f5e3Sopenharmony_ci        if (!UseWords()) {
1054514f5e3Sopenharmony_ci            auto oldValue = data_.inlineWord_;
1064514f5e3Sopenharmony_ci            data_.inlineWord_ |= bitset.data_.inlineWord_;
1074514f5e3Sopenharmony_ci            return data_.inlineWord_ != oldValue;
1084514f5e3Sopenharmony_ci        } else {
1094514f5e3Sopenharmony_ci            bool changed = false;
1104514f5e3Sopenharmony_ci            for (size_t i = 0; i < wordCount_; i++) {
1114514f5e3Sopenharmony_ci                auto oldValue = data_.words_[i];
1124514f5e3Sopenharmony_ci                data_.words_[i] |= bitset.data_.words_[i];
1134514f5e3Sopenharmony_ci                if (!changed && data_.words_[i] != oldValue) {
1144514f5e3Sopenharmony_ci                    changed = true;
1154514f5e3Sopenharmony_ci                }
1164514f5e3Sopenharmony_ci            }
1174514f5e3Sopenharmony_ci            return changed;
1184514f5e3Sopenharmony_ci        }
1194514f5e3Sopenharmony_ci    }
1204514f5e3Sopenharmony_ci
1214514f5e3Sopenharmony_ci    void Intersect(const BitSet &bitset)
1224514f5e3Sopenharmony_ci    {
1234514f5e3Sopenharmony_ci        if (!UseWords()) {
1244514f5e3Sopenharmony_ci            data_.inlineWord_ &= bitset.data_.inlineWord_;
1254514f5e3Sopenharmony_ci        } else {
1264514f5e3Sopenharmony_ci            for (size_t i = 0; i < wordCount_; i++) {
1274514f5e3Sopenharmony_ci                data_.words_[i] &= bitset.data_.words_[i];
1284514f5e3Sopenharmony_ci            }
1294514f5e3Sopenharmony_ci        }
1304514f5e3Sopenharmony_ci    }
1314514f5e3Sopenharmony_ci
1324514f5e3Sopenharmony_ci    void CopyFrom(const BitSet &other)
1334514f5e3Sopenharmony_ci    {
1344514f5e3Sopenharmony_ci        ASSERT(wordCount_ == other.wordCount_);
1354514f5e3Sopenharmony_ci        wordCount_ = other.wordCount_;
1364514f5e3Sopenharmony_ci        if (!UseWords()) {
1374514f5e3Sopenharmony_ci            data_.inlineWord_ = other.data_.inlineWord_;
1384514f5e3Sopenharmony_ci            return;
1394514f5e3Sopenharmony_ci        }
1404514f5e3Sopenharmony_ci        for (size_t i = 0; i < wordCount_; i++) {
1414514f5e3Sopenharmony_ci            data_.words_[i] = other.data_.words_[i];
1424514f5e3Sopenharmony_ci        }
1434514f5e3Sopenharmony_ci    }
1444514f5e3Sopenharmony_ci
1454514f5e3Sopenharmony_ci    void CopyDataFrom(const BitSet &other)
1464514f5e3Sopenharmony_ci    {
1474514f5e3Sopenharmony_ci        ASSERT(wordCount_ >= other.wordCount_);
1484514f5e3Sopenharmony_ci        if (!other.UseWords()) {
1494514f5e3Sopenharmony_ci            if (UseWords()) {
1504514f5e3Sopenharmony_ci                data_.words_[0] = other.data_.inlineWord_;
1514514f5e3Sopenharmony_ci            } else {
1524514f5e3Sopenharmony_ci                data_.inlineWord_ = other.data_.inlineWord_;
1534514f5e3Sopenharmony_ci            }
1544514f5e3Sopenharmony_ci            return;
1554514f5e3Sopenharmony_ci        }
1564514f5e3Sopenharmony_ci        for (size_t i = 0; i < other.wordCount_; i++) {
1574514f5e3Sopenharmony_ci            data_.words_[i] = other.data_.words_[i];
1584514f5e3Sopenharmony_ci        }
1594514f5e3Sopenharmony_ci    }
1604514f5e3Sopenharmony_ci
1614514f5e3Sopenharmony_ci    bool ShouldExpand(size_t size)
1624514f5e3Sopenharmony_ci    {
1634514f5e3Sopenharmony_ci        if (SizeOf(size) == this->wordCount_) {
1644514f5e3Sopenharmony_ci            return false;
1654514f5e3Sopenharmony_ci        }
1664514f5e3Sopenharmony_ci        return true;
1674514f5e3Sopenharmony_ci    }
1684514f5e3Sopenharmony_ciprivate:
1694514f5e3Sopenharmony_ci    union Data {
1704514f5e3Sopenharmony_ci        uint64_t inlineWord_;
1714514f5e3Sopenharmony_ci        uint64_t *words_ {nullptr};
1724514f5e3Sopenharmony_ci    };
1734514f5e3Sopenharmony_ci    static size_t SizeOf(size_t bitSize)
1744514f5e3Sopenharmony_ci    {
1754514f5e3Sopenharmony_ci        ASSERT(bitSize > 0);
1764514f5e3Sopenharmony_ci        // +1: for word 1
1774514f5e3Sopenharmony_ci        return ((bitSize - 1) >> BIT_PER_WORD_LOG2) + 1;
1784514f5e3Sopenharmony_ci    }
1794514f5e3Sopenharmony_ci
1804514f5e3Sopenharmony_ci    uint64_t Mask(size_t index) const
1814514f5e3Sopenharmony_ci    {
1824514f5e3Sopenharmony_ci        return uint64_t{1} << index;
1834514f5e3Sopenharmony_ci    }
1844514f5e3Sopenharmony_ci
1854514f5e3Sopenharmony_ci    size_t IndexInWord(size_t offset) const
1864514f5e3Sopenharmony_ci    {
1874514f5e3Sopenharmony_ci        return offset & BIT_PER_WORD_MASK;
1884514f5e3Sopenharmony_ci    }
1894514f5e3Sopenharmony_ci
1904514f5e3Sopenharmony_ci    size_t Index(size_t offset) const
1914514f5e3Sopenharmony_ci    {
1924514f5e3Sopenharmony_ci        return offset >> BIT_PER_WORD_LOG2;
1934514f5e3Sopenharmony_ci    }
1944514f5e3Sopenharmony_ci
1954514f5e3Sopenharmony_ci    size_t WordCount(size_t size) const
1964514f5e3Sopenharmony_ci    {
1974514f5e3Sopenharmony_ci        return size >> BYTE_PER_WORD_LOG2;
1984514f5e3Sopenharmony_ci    }
1994514f5e3Sopenharmony_ci
2004514f5e3Sopenharmony_ci    bool UseWords() const
2014514f5e3Sopenharmony_ci    {
2024514f5e3Sopenharmony_ci        return wordCount_ > 1;
2034514f5e3Sopenharmony_ci    }
2044514f5e3Sopenharmony_ci
2054514f5e3Sopenharmony_ci    uint32_t wordCount_ {0};
2064514f5e3Sopenharmony_ci    Data data_;
2074514f5e3Sopenharmony_ci};
2084514f5e3Sopenharmony_ci}  // panda::ecmascript::kungfu
2094514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_COMPILER_BITSET_H
210