14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 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#include "ecmascript/mem/native_area_allocator.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/platform/os.h"
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_ZAP_MEM
214514f5e3Sopenharmony_ci#include "securec.h"
224514f5e3Sopenharmony_ci#endif
234514f5e3Sopenharmony_cinamespace panda::ecmascript {
244514f5e3Sopenharmony_ciArea *NativeAreaAllocator::AllocateArea(size_t capacity)
254514f5e3Sopenharmony_ci{
264514f5e3Sopenharmony_ci    size_t headerSize = sizeof(Area);
274514f5e3Sopenharmony_ci    if (capacity < headerSize) { // LOCV_EXCL_BR_LINE
284514f5e3Sopenharmony_ci        LOG_ECMA_MEM(FATAL) << "capacity must have a size not less than sizeof Area.";
294514f5e3Sopenharmony_ci        UNREACHABLE();
304514f5e3Sopenharmony_ci    }
314514f5e3Sopenharmony_ci    if (cachedArea_ != nullptr && capacity <= cachedArea_->GetSize()) {
324514f5e3Sopenharmony_ci        auto result = cachedArea_;
334514f5e3Sopenharmony_ci        cachedArea_ = nullptr;
344514f5e3Sopenharmony_ci        return result;
354514f5e3Sopenharmony_ci    }
364514f5e3Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
374514f5e3Sopenharmony_ci    void *mem = malloc(capacity);
384514f5e3Sopenharmony_ci    if (mem == nullptr) { // LOCV_EXCL_BR_LINE
394514f5e3Sopenharmony_ci        LOG_ECMA_MEM(FATAL) << "malloc failed, current alloc size = " << capacity
404514f5e3Sopenharmony_ci                            << ", total allocated size = " << nativeMemoryUsage_.load(std::memory_order_relaxed);
414514f5e3Sopenharmony_ci        UNREACHABLE();
424514f5e3Sopenharmony_ci    }
434514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_ZAP_MEM
444514f5e3Sopenharmony_ci    if (memset_s(mem, capacity, 0, capacity) != EOK) { // LOCV_EXCL_BR_LINE
454514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "memset_s failed";
464514f5e3Sopenharmony_ci        UNREACHABLE();
474514f5e3Sopenharmony_ci    }
484514f5e3Sopenharmony_ci#endif
494514f5e3Sopenharmony_ci    IncreaseNativeMemoryUsage(capacity);
504514f5e3Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
514514f5e3Sopenharmony_ci    uintptr_t begin = reinterpret_cast<uintptr_t>(mem) + headerSize;
524514f5e3Sopenharmony_ci    capacity -= headerSize;
534514f5e3Sopenharmony_ci    return new (mem) Area(begin, capacity);
544514f5e3Sopenharmony_ci}
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_civoid NativeAreaAllocator::FreeArea(Area *area)
574514f5e3Sopenharmony_ci{
584514f5e3Sopenharmony_ci    if (area == nullptr) {
594514f5e3Sopenharmony_ci        return;
604514f5e3Sopenharmony_ci    }
614514f5e3Sopenharmony_ci    if (cachedArea_ == nullptr && area->GetSize() <= MAX_CACHED_CHUNK_AREA_SIZE) {
624514f5e3Sopenharmony_ci        cachedArea_ = area;
634514f5e3Sopenharmony_ci        return;
644514f5e3Sopenharmony_ci    }
654514f5e3Sopenharmony_ci    auto size = area->GetSize() + sizeof(Area);
664514f5e3Sopenharmony_ci    DecreaseNativeMemoryUsage(size);
674514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_ZAP_MEM
684514f5e3Sopenharmony_ci    if (memset_s(area, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
694514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "memset_s failed";
704514f5e3Sopenharmony_ci        UNREACHABLE();
714514f5e3Sopenharmony_ci    }
724514f5e3Sopenharmony_ci#endif
734514f5e3Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
744514f5e3Sopenharmony_ci    free(reinterpret_cast<std::byte *>(area));
754514f5e3Sopenharmony_ci}
764514f5e3Sopenharmony_ci
774514f5e3Sopenharmony_civoid NativeAreaAllocator::Free(void *mem, size_t size)
784514f5e3Sopenharmony_ci{
794514f5e3Sopenharmony_ci    if (mem == nullptr) {
804514f5e3Sopenharmony_ci        return;
814514f5e3Sopenharmony_ci    }
824514f5e3Sopenharmony_ci    DecreaseNativeMemoryUsage(size);
834514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_ZAP_MEM
844514f5e3Sopenharmony_ci    if (memset_s(mem, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
854514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "memset_s failed";
864514f5e3Sopenharmony_ci        UNREACHABLE();
874514f5e3Sopenharmony_ci    }
884514f5e3Sopenharmony_ci#endif
894514f5e3Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
904514f5e3Sopenharmony_ci    free(mem);
914514f5e3Sopenharmony_ci}
924514f5e3Sopenharmony_ci
934514f5e3Sopenharmony_civoid *NativeAreaAllocator::AllocateBuffer(size_t size)
944514f5e3Sopenharmony_ci{
954514f5e3Sopenharmony_ci    if (size == 0) { // LOCV_EXCL_BR_LINE
964514f5e3Sopenharmony_ci        LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0";
974514f5e3Sopenharmony_ci        UNREACHABLE();
984514f5e3Sopenharmony_ci    }
994514f5e3Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
1004514f5e3Sopenharmony_ci    void *ptr = malloc(size);
1014514f5e3Sopenharmony_ci    if (ptr == nullptr) { // LOCV_EXCL_BR_LINE
1024514f5e3Sopenharmony_ci        LOG_ECMA_MEM(FATAL) << "malloc failed, current alloc size = " << size
1034514f5e3Sopenharmony_ci                            << ", total allocated size = " << nativeMemoryUsage_.load(std::memory_order_relaxed);
1044514f5e3Sopenharmony_ci        UNREACHABLE();
1054514f5e3Sopenharmony_ci    }
1064514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_ZAP_MEM
1074514f5e3Sopenharmony_ci    if (memset_s(ptr, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
1084514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "memset_s failed";
1094514f5e3Sopenharmony_ci        UNREACHABLE();
1104514f5e3Sopenharmony_ci    }
1114514f5e3Sopenharmony_ci#endif
1124514f5e3Sopenharmony_ci    IncreaseNativeMemoryUsage(MallocUsableSize(ptr));
1134514f5e3Sopenharmony_ci    return ptr;
1144514f5e3Sopenharmony_ci}
1154514f5e3Sopenharmony_ci
1164514f5e3Sopenharmony_civoid NativeAreaAllocator::FreeBuffer(void *mem)
1174514f5e3Sopenharmony_ci{
1184514f5e3Sopenharmony_ci    if (mem == nullptr) {
1194514f5e3Sopenharmony_ci        return;
1204514f5e3Sopenharmony_ci    }
1214514f5e3Sopenharmony_ci    size_t size = MallocUsableSize(mem);
1224514f5e3Sopenharmony_ci    DecreaseNativeMemoryUsage(size);
1234514f5e3Sopenharmony_ci
1244514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_ZAP_MEM
1254514f5e3Sopenharmony_ci    if (memset_s(mem, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
1264514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "memset_s failed";
1274514f5e3Sopenharmony_ci        UNREACHABLE();
1284514f5e3Sopenharmony_ci    }
1294514f5e3Sopenharmony_ci#endif
1304514f5e3Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
1314514f5e3Sopenharmony_ci    free(mem);
1324514f5e3Sopenharmony_ci}
1334514f5e3Sopenharmony_ci
1344514f5e3Sopenharmony_civoid NativeAreaAllocator::FreeBufferFunc([[maybe_unused]] void *env, void *buffer, void *data)
1354514f5e3Sopenharmony_ci{
1364514f5e3Sopenharmony_ci    if (buffer == nullptr || data == nullptr) {
1374514f5e3Sopenharmony_ci        return;
1384514f5e3Sopenharmony_ci    }
1394514f5e3Sopenharmony_ci    NativeAreaAllocator* allocator = reinterpret_cast<NativeAreaAllocator*>(data);
1404514f5e3Sopenharmony_ci    allocator->FreeBuffer(buffer);
1414514f5e3Sopenharmony_ci}
1424514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
143