MCPcopy Create free account
hub / github.com/emscripten-core/emscripten / allocate_memory

Function allocate_memory

system/lib/emmalloc.c:664–812  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

662EM_JS_DEPS(_em_malloc_deps, "$ptrToString");
663
664static void *allocate_memory(size_t alignment, size_t size) {
665 ASSERT_MALLOC_IS_ACQUIRED();
666
667#ifdef EMMALLOC_VERBOSE
668 MAIN_THREAD_ASYNC_EM_ASM(out('allocate_memory(align=' + $0 + ', size=' + Number($1) + ' bytes)'), alignment, size);
669#endif
670
671#ifdef EMMALLOC_MEMVALIDATE
672 validate_memory_regions();
673#endif
674
675 if (!IS_POWER_OF_2(alignment)) {
676#ifdef EMMALLOC_VERBOSE
677 MAIN_THREAD_ASYNC_EM_ASM(out('Allocation failed: alignment not power of 2!'));
678#endif
679 return 0;
680 }
681
682 if (size > MAX_ALLOC_SIZE) {
683#ifdef EMMALLOC_VERBOSE
684 MAIN_THREAD_ASYNC_EM_ASM(out('Allocation failed: attempted allocation size is too large: ' + Number($0) + 'bytes! (negative integer wraparound?)'), size);
685#endif
686 return 0;
687 }
688
689 alignment = validate_alloc_alignment(alignment);
690 size = validate_alloc_size(size);
691
692 // Attempt to allocate memory starting from smallest bucket that can contain the required amount of memory.
693 // Under normal alignment conditions this should always be the first or second bucket we look at, but if
694 // performing an allocation with complex alignment, we may need to look at multiple buckets.
695 int bucketIndex = compute_free_list_bucket(size);
696 BUCKET_BITMASK_T bucketMask = freeRegionBucketsUsed >> bucketIndex;
697
698 // Loop through each bucket that has free regions in it, based on bits set in freeRegionBucketsUsed bitmap.
699 while (bucketMask) {
700 BUCKET_BITMASK_T indexAdd = __builtin_ctzll(bucketMask);
701 bucketIndex += indexAdd;
702 bucketMask >>= indexAdd;
703 assert(bucketIndex >= 0);
704 assert(bucketIndex <= NUM_FREE_BUCKETS-1);
705 assert(freeRegionBucketsUsed & (((BUCKET_BITMASK_T)1) << bucketIndex));
706
707 Region *freeRegion = freeRegionBuckets[bucketIndex].next;
708 assert(freeRegion);
709 if (freeRegion != &freeRegionBuckets[bucketIndex]) {
710 void *ptr = attempt_allocate(freeRegion, alignment, size);
711 if (ptr) {
712 return ptr;
713 }
714
715 // We were not able to allocate from the first region found in this bucket, so penalize
716 // the region by cycling it to the end of the doubly circular linked list. (constant time)
717 // This provides a randomized guarantee that when performing allocations of size k to a
718 // bucket of [k-something, k+something] range, we will not always attempt to satisfy the
719 // allocation from the same available region at the front of the list, but we try each
720 // region in turn.
721 unlink_from_free_list(freeRegion);

Callers 1

emmalloc_memalignFunction · 0.85

Calls 11

validate_memory_regionsFunction · 0.85
validate_alloc_alignmentFunction · 0.85
validate_alloc_sizeFunction · 0.85
compute_free_list_bucketFunction · 0.85
attempt_allocateFunction · 0.85
unlink_from_free_listFunction · 0.85
prepend_to_free_listFunction · 0.85
__builtin_clzllFunction · 0.85
claim_more_memoryFunction · 0.85
outFunction · 0.50
assertFunction · 0.50

Tested by

no test coverage detected