Allocate heap memory. Args: size: requested allocation size in bytes Returns: The address of the newly allocated memory chunk, or 0 if allocation has failed
(self, size: int)
| 719 | self.mem_alloc = saved_state['mem_alloc'] |
| 720 | |
| 721 | def alloc(self, size: int) -> int: |
| 722 | """Allocate heap memory. |
| 723 | |
| 724 | Args: |
| 725 | size: requested allocation size in bytes |
| 726 | |
| 727 | Returns: |
| 728 | The address of the newly allocated memory chunk, or 0 if allocation has failed |
| 729 | """ |
| 730 | |
| 731 | # attempt to recycle an existing unused chunk first. |
| 732 | # locate the smallest available chunk that has enough room |
| 733 | chunk = min((chunk for chunk in self.chunks if (not chunk.inuse) and (chunk.size >= size)), default=None, key=lambda ch: ch.size) |
| 734 | |
| 735 | # if could not find any, create a new one |
| 736 | if chunk is None: |
| 737 | # is new chunk going to exceed currently allocated heap space? |
| 738 | # in case it does, allocate additional heap space |
| 739 | if self.current_use + size > self.current_alloc: |
| 740 | real_size = self.ql.mem.align_up(size) |
| 741 | |
| 742 | # if that additional allocation is going to exceed heap upper bound, fail |
| 743 | if self.start_address + self.current_use + real_size > self.end_address: |
| 744 | return 0 |
| 745 | |
| 746 | self.ql.mem.map(self.start_address + self.current_alloc, real_size, info="[heap]") |
| 747 | self.mem_alloc.append((self.start_address + self.current_alloc, real_size)) |
| 748 | self.current_alloc += real_size |
| 749 | |
| 750 | chunk = Chunk(self.start_address + self.current_use, size) |
| 751 | self.current_use += size |
| 752 | self.chunks.append(chunk) |
| 753 | |
| 754 | chunk.inuse = True |
| 755 | return chunk.address |
| 756 | |
| 757 | def size(self, addr: int) -> int: |
| 758 | """Get the size of allocated memory chunk starting at a specific address. |