1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_SERIALIZER_SERIALIZATION_CHUNK_H 17 #define ECMASCRIPT_SERIALIZER_SERIALIZATION_CHUNK_H 18 19 #include "ecmascript/js_tagged_value-inl.h" 20 #include "ecmascript/mem/mem.h" 21 22 namespace panda::ecmascript { 23 24 class SerializationChunk { 25 public: SerializationChunk()26 explicit SerializationChunk() {} ~SerializationChunk()27 ~SerializationChunk() 28 { 29 if (begin_ != 0U) { 30 free(ToVoidPtr(begin_)); 31 } 32 } 33 NO_COPY_SEMANTIC(SerializationChunk); 34 NO_MOVE_SEMANTIC(SerializationChunk); 35 Emplace(JSTaggedType value)36 void Emplace(JSTaggedType value) 37 { 38 if (top_ == end_) { 39 Expand(); 40 } 41 ASSERT(top_ < end_); 42 *reinterpret_cast<JSTaggedType *>(top_) = value; 43 top_ += JSTaggedValue::TaggedTypeSize(); 44 } 45 Set(size_t index,JSTaggedType value)46 void Set(size_t index, JSTaggedType value) 47 { 48 ASSERT(begin_ + index * JSTaggedValue::TaggedTypeSize() < top_); 49 *reinterpret_cast<JSTaggedType *>(begin_ + index * JSTaggedValue::TaggedTypeSize()) = value; 50 } 51 Get(size_t index)52 JSTaggedType Get(size_t index) const 53 { 54 ASSERT(begin_ + index * JSTaggedValue::TaggedTypeSize() < top_); 55 return *reinterpret_cast<JSTaggedType *>(begin_ + index * JSTaggedValue::TaggedTypeSize()); 56 } 57 Expand()58 void Expand() 59 { 60 ASSERT(top_ == end_); 61 size_t oldCapacity = end_ - begin_; 62 size_t newCapacity = 0; 63 if (oldCapacity == 0U) { 64 newCapacity = INITIAL_CHUNK_CAPACITY; 65 } else { 66 newCapacity = (end_ - begin_) * CHUNK_CAPACITY_INCREASE_RATE; 67 } 68 void *newChunk = malloc(newCapacity); 69 if (newChunk == nullptr) { 70 LOG_ECMA_MEM(FATAL) << "malloc failed, current alloc size = " << newCapacity; 71 UNREACHABLE(); 72 } 73 74 if (begin_ != 0U) { 75 if (memcpy_s(newChunk, newCapacity, ToVoidPtr(begin_), end_ - begin_) != EOK) { 76 LOG_FULL(FATAL) << "memcpy_s fail"; 77 } 78 free(ToVoidPtr(begin_)); 79 } 80 begin_ = ToUintPtr(newChunk); 81 top_ = begin_ + oldCapacity; 82 end_ = begin_ + newCapacity; 83 } 84 Empty()85 bool Empty() const 86 { 87 return top_ == begin_; 88 } 89 Size()90 size_t Size() const 91 { 92 return (top_ - begin_) / JSTaggedValue::TaggedTypeSize(); 93 } 94 Iterate(RootVisitor & v)95 void Iterate(RootVisitor &v) 96 { 97 for (uintptr_t slot = begin_; slot < top_; slot += JSTaggedValue::TaggedTypeSize()) { 98 v.VisitRoot(Root::ROOT_VM, ObjectSlot(slot)); 99 } 100 } 101 102 private: 103 static constexpr size_t INITIAL_CHUNK_CAPACITY = 1_KB; 104 static constexpr int CHUNK_CAPACITY_INCREASE_RATE = 2; 105 uintptr_t begin_ {0U}; 106 uintptr_t end_ {0U}; 107 uintptr_t top_ {0U}; 108 }; 109 } 110 111 #endif // ECMASCRIPT_SERIALIZER_SERIALIZE_DATA_H 112