| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:52:18 -06:00
										 |  |  | #include <AK/Platform.h>
 | 
					
						
							| 
									
										
										
										
											2021-10-07 23:25:12 +02:00
										 |  |  | #include <AK/Random.h>
 | 
					
						
							| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  | #include <AK/Vector.h>
 | 
					
						
							|  |  |  | #include <LibJS/Heap/BlockAllocator.h>
 | 
					
						
							|  |  |  | #include <LibJS/Heap/HeapBlock.h>
 | 
					
						
							|  |  |  | #include <sys/mman.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:52:18 -06:00
										 |  |  | #ifdef HAS_ADDRESS_SANITIZER
 | 
					
						
							|  |  |  | #    include <sanitizer/asan_interface.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  | namespace JS { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BlockAllocator::BlockAllocator() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BlockAllocator::~BlockAllocator() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (auto* block : m_blocks) { | 
					
						
							| 
									
										
										
										
											2021-05-27 17:52:18 -06:00
										 |  |  |         ASAN_UNPOISON_MEMORY_REGION(block, HeapBlock::block_size); | 
					
						
							| 
									
										
										
										
											2021-05-27 20:06:47 +02:00
										 |  |  | #ifdef __serenity__
 | 
					
						
							| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  |         if (munmap(block, HeapBlock::block_size) < 0) { | 
					
						
							|  |  |  |             perror("munmap"); | 
					
						
							|  |  |  |             VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-27 20:06:47 +02:00
										 |  |  | #else
 | 
					
						
							|  |  |  |         free(block); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void* BlockAllocator::allocate_block([[maybe_unused]] char const* name) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-05-27 21:23:56 +02:00
										 |  |  |     if (!m_blocks.is_empty()) { | 
					
						
							| 
									
										
										
										
											2021-10-07 23:25:12 +02:00
										 |  |  |         // To reduce predictability, take a random block from the cache.
 | 
					
						
							|  |  |  |         size_t random_index = get_random_uniform(m_blocks.size()); | 
					
						
							|  |  |  |         auto* block = m_blocks.unstable_take(random_index); | 
					
						
							| 
									
										
										
										
											2021-05-27 17:52:18 -06:00
										 |  |  |         ASAN_UNPOISON_MEMORY_REGION(block, HeapBlock::block_size); | 
					
						
							| 
									
										
										
										
											2021-05-27 21:23:56 +02:00
										 |  |  | #ifdef __serenity__
 | 
					
						
							|  |  |  |         if (set_mmap_name(block, HeapBlock::block_size, name) < 0) { | 
					
						
							|  |  |  |             perror("set_mmap_name"); | 
					
						
							|  |  |  |             VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         return block; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef __serenity__
 | 
					
						
							|  |  |  |     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); | 
					
						
							| 
									
										
										
										
											2021-05-27 21:07:56 +02:00
										 |  |  |     VERIFY(block != MAP_FAILED); | 
					
						
							| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     auto* block = (HeapBlock*)aligned_alloc(HeapBlock::block_size, HeapBlock::block_size); | 
					
						
							| 
									
										
										
										
											2021-05-27 21:07:56 +02:00
										 |  |  |     VERIFY(block); | 
					
						
							| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     return block; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BlockAllocator::deallocate_block(void* block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     VERIFY(block); | 
					
						
							|  |  |  |     if (m_blocks.size() >= max_cached_blocks) { | 
					
						
							| 
									
										
										
										
											2021-05-27 20:06:47 +02:00
										 |  |  | #ifdef __serenity__
 | 
					
						
							| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  |         if (munmap(block, HeapBlock::block_size) < 0) { | 
					
						
							|  |  |  |             perror("munmap"); | 
					
						
							|  |  |  |             VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-27 20:06:47 +02:00
										 |  |  | #else
 | 
					
						
							|  |  |  |         free(block); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-27 17:52:18 -06:00
										 |  |  |     ASAN_POISON_MEMORY_REGION(block, HeapBlock::block_size); | 
					
						
							| 
									
										
										
										
											2021-05-27 19:01:26 +02:00
										 |  |  |     m_blocks.append(block); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |