/* * Copyright (c) 2024 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_SERIALIZER_SERIALIZATION_CHUNK_H #define ECMASCRIPT_SERIALIZER_SERIALIZATION_CHUNK_H #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/mem/mem.h" namespace panda::ecmascript { class SerializationChunk { public: explicit SerializationChunk() {} ~SerializationChunk() { if (begin_ != 0U) { free(ToVoidPtr(begin_)); } } NO_COPY_SEMANTIC(SerializationChunk); NO_MOVE_SEMANTIC(SerializationChunk); void Emplace(JSTaggedType value) { if (top_ == end_) { Expand(); } ASSERT(top_ < end_); *reinterpret_cast(top_) = value; top_ += JSTaggedValue::TaggedTypeSize(); } void Set(size_t index, JSTaggedType value) { ASSERT(begin_ + index * JSTaggedValue::TaggedTypeSize() < top_); *reinterpret_cast(begin_ + index * JSTaggedValue::TaggedTypeSize()) = value; } JSTaggedType Get(size_t index) const { ASSERT(begin_ + index * JSTaggedValue::TaggedTypeSize() < top_); return *reinterpret_cast(begin_ + index * JSTaggedValue::TaggedTypeSize()); } void Expand() { ASSERT(top_ == end_); size_t oldCapacity = end_ - begin_; size_t newCapacity = 0; if (oldCapacity == 0U) { newCapacity = INITIAL_CHUNK_CAPACITY; } else { newCapacity = (end_ - begin_) * CHUNK_CAPACITY_INCREASE_RATE; } void *newChunk = malloc(newCapacity); if (newChunk == nullptr) { LOG_ECMA_MEM(FATAL) << "malloc failed, current alloc size = " << newCapacity; UNREACHABLE(); } if (begin_ != 0U) { if (memcpy_s(newChunk, newCapacity, ToVoidPtr(begin_), end_ - begin_) != EOK) { LOG_FULL(FATAL) << "memcpy_s fail"; } free(ToVoidPtr(begin_)); } begin_ = ToUintPtr(newChunk); top_ = begin_ + oldCapacity; end_ = begin_ + newCapacity; } bool Empty() const { return top_ == begin_; } size_t Size() const { return (top_ - begin_) / JSTaggedValue::TaggedTypeSize(); } void Iterate(RootVisitor &v) { for (uintptr_t slot = begin_; slot < top_; slot += JSTaggedValue::TaggedTypeSize()) { v.VisitRoot(Root::ROOT_VM, ObjectSlot(slot)); } } private: static constexpr size_t INITIAL_CHUNK_CAPACITY = 1_KB; static constexpr int CHUNK_CAPACITY_INCREASE_RATE = 2; uintptr_t begin_ {0U}; uintptr_t end_ {0U}; uintptr_t top_ {0U}; }; } #endif // ECMASCRIPT_SERIALIZER_SERIALIZE_DATA_H