BlockAllocator.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. }
  19. BlockAllocator::~BlockAllocator()
  20. {
  21. for (auto* block : m_blocks) {
  22. ASAN_UNPOISON_MEMORY_REGION(block, HeapBlock::block_size);
  23. #ifdef __serenity__
  24. if (munmap(block, HeapBlock::block_size) < 0) {
  25. perror("munmap");
  26. VERIFY_NOT_REACHED();
  27. }
  28. #else
  29. free(block);
  30. #endif
  31. }
  32. }
  33. void* BlockAllocator::allocate_block([[maybe_unused]] char const* name)
  34. {
  35. if (!m_blocks.is_empty()) {
  36. // To reduce predictability, take a random block from the cache.
  37. size_t random_index = get_random_uniform(m_blocks.size());
  38. auto* block = m_blocks.unstable_take(random_index);
  39. ASAN_UNPOISON_MEMORY_REGION(block, HeapBlock::block_size);
  40. #ifdef __serenity__
  41. if (set_mmap_name(block, HeapBlock::block_size, name) < 0) {
  42. perror("set_mmap_name");
  43. VERIFY_NOT_REACHED();
  44. }
  45. #endif
  46. return block;
  47. }
  48. #ifdef __serenity__
  49. 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);
  50. VERIFY(block != MAP_FAILED);
  51. #else
  52. auto* block = (HeapBlock*)aligned_alloc(HeapBlock::block_size, HeapBlock::block_size);
  53. VERIFY(block);
  54. #endif
  55. return block;
  56. }
  57. void BlockAllocator::deallocate_block(void* block)
  58. {
  59. VERIFY(block);
  60. if (m_blocks.size() >= max_cached_blocks) {
  61. #ifdef __serenity__
  62. if (munmap(block, HeapBlock::block_size) < 0) {
  63. perror("munmap");
  64. VERIFY_NOT_REACHED();
  65. }
  66. #else
  67. free(block);
  68. #endif
  69. return;
  70. }
  71. ASAN_POISON_MEMORY_REGION(block, HeapBlock::block_size);
  72. m_blocks.append(block);
  73. }
  74. }