BlockAllocator.cpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Platform.h>
  7. #include <AK/Random.h>
  8. #include <AK/Vector.h>
  9. #include <LibJS/Heap/BlockAllocator.h>
  10. #include <LibJS/Heap/HeapBlock.h>
  11. #include <sys/mman.h>
  12. #ifdef HAS_ADDRESS_SANITIZER
  13. # include <sanitizer/asan_interface.h>
  14. #endif
  15. namespace JS {
  16. BlockAllocator::~BlockAllocator()
  17. {
  18. for (auto* block : m_blocks) {
  19. ASAN_UNPOISON_MEMORY_REGION(block, HeapBlock::block_size);
  20. #ifdef AK_OS_SERENITY
  21. if (munmap(block, HeapBlock::block_size) < 0) {
  22. perror("munmap");
  23. VERIFY_NOT_REACHED();
  24. }
  25. #else
  26. free(block);
  27. #endif
  28. }
  29. }
  30. void* BlockAllocator::allocate_block([[maybe_unused]] char const* name)
  31. {
  32. if (!m_blocks.is_empty()) {
  33. // To reduce predictability, take a random block from the cache.
  34. size_t random_index = get_random_uniform(m_blocks.size());
  35. auto* block = m_blocks.unstable_take(random_index);
  36. ASAN_UNPOISON_MEMORY_REGION(block, HeapBlock::block_size);
  37. #ifdef AK_OS_SERENITY
  38. if (set_mmap_name(block, HeapBlock::block_size, name) < 0) {
  39. perror("set_mmap_name");
  40. VERIFY_NOT_REACHED();
  41. }
  42. #endif
  43. return block;
  44. }
  45. #ifdef AK_OS_SERENITY
  46. auto* block = (HeapBlock*)serenity_mmap(nullptr, HeapBlock::block_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_RANDOMIZED | MAP_PRIVATE, 0, 0, HeapBlock::block_size, name);
  47. VERIFY(block != MAP_FAILED);
  48. #else
  49. auto* block = (HeapBlock*)aligned_alloc(HeapBlock::block_size, HeapBlock::block_size);
  50. VERIFY(block);
  51. #endif
  52. return block;
  53. }
  54. void BlockAllocator::deallocate_block(void* block)
  55. {
  56. VERIFY(block);
  57. if (m_blocks.size() >= max_cached_blocks) {
  58. #ifdef AK_OS_SERENITY
  59. if (munmap(block, HeapBlock::block_size) < 0) {
  60. perror("munmap");
  61. VERIFY_NOT_REACHED();
  62. }
  63. #else
  64. free(block);
  65. #endif
  66. return;
  67. }
  68. ASAN_POISON_MEMORY_REGION(block, HeapBlock::block_size);
  69. m_blocks.append(block);
  70. }
  71. }