1 /*
2  * Copyright (c) 2021 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_MEM_CHUNK_H
17 #define ECMASCRIPT_MEM_CHUNK_H
18 
19 #include "ecmascript/common.h"
20 #include "ecmascript/log_wrapper.h"
21 #include "ecmascript/mem/ecma_list.h"
22 #include "ecmascript/mem/area.h"
23 
24 namespace panda::ecmascript {
25 class NativeAreaAllocator;
26 
27 class PUBLIC_API Chunk {
28 public:
29     static constexpr size_t MEM_ALIGN = 8U;
30 
31     explicit Chunk(NativeAreaAllocator *allocator);
32     Chunk() = default;
~Chunk()33     ~Chunk()
34     {
35         ReleaseMemory();
36     }
37 
38     NO_COPY_SEMANTIC(Chunk);
39     NO_MOVE_SEMANTIC(Chunk);
40 
Allocate(size_t size)41     [[nodiscard]] void *Allocate(size_t size)
42     {
43         if (size == 0) {
44             LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0";
45             UNREACHABLE();
46         }
47         uintptr_t result = ptr_;
48         size = AlignUp(size, MEM_ALIGN);
49         if (UNLIKELY(size > end_ - ptr_)) {
50             result = Expand(size);
51         } else {
52             ptr_ += size;
53         }
54 
55         return reinterpret_cast<void *>(result);
56     }
57 
58     template<class T>
NewArray(size_t size)59     [[nodiscard]] T *NewArray(size_t size)
60     {
61         return static_cast<T *>(Allocate(size * sizeof(T)));
62     }
63 
64     template<typename T, typename... Args>
New(Args &&.... args)65     [[nodiscard]] T *New(Args &&... args)
66     {
67         auto p = reinterpret_cast<void *>(Allocate(sizeof(T)));
68         new (p) T(std::forward<Args>(args)...);
69         return reinterpret_cast<T *>(p);
70     }
71 
72     template<class T>
Delete(T *ptr)73     void Delete(T *ptr)
74     {
75         ASSERT(ptr != nullptr);
76         // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon)
77         if constexpr (std::is_class_v<T>) {
78             ptr->~T();
79         }
80         Free(ptr);
81     }
82 
Free([[maybe_unused]] void *mem)83     void Free([[maybe_unused]] void *mem)
84     {
85         // do nothing
86     }
87 
88 protected:
89     uintptr_t ptr_ {0};
90     uintptr_t end_ {0};
91 
92     Area *currentArea_ {nullptr};
93     NativeAreaAllocator *allocator_ {nullptr};
94 
95 private:
96     uintptr_t Expand(size_t size);
97     Area *NewArea(size_t size);
98     void ReleaseMemory();
99 
100     EcmaList<Area> areaList_ {};
101 };
102 
103 class PUBLIC_API ChunkObject {
104 public:
operator new(size_t size, Chunk* chunk)105     void *operator new(size_t size, Chunk* chunk)
106     {
107         return chunk->Allocate(size);
108     }
109 
operator delete([[maybe_unused]] void* ptr)110     void operator delete([[maybe_unused]] void* ptr)
111     {
112         UNREACHABLE();
113     }
114 };
115 }  // namespace panda::ecmascript
116 
117 #endif  // ECMASCRIPT_MEM_CHUNK_H
118