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