@@ -19,9 +19,9 @@ package runtime
1919// "head" and is followed by "tail" blocks. The reason for this distinction is
2020// that this way, the start and end of every object can be found easily.
2121//
22- // Metadata is stored in a special area at the beginning of the heap, in the
23- // area heapStart..poolStart . The actual blocks are stored in
24- // poolStart..heapEnd .
22+ // Metadata is stored in a special area at the end of the heap, in the area
23+ // metadataStart..heapEnd . The actual blocks are stored in
24+ // heapStart..metadataStart .
2525//
2626// More information:
2727// https://github.com/micropython/micropython/wiki/Memory-Manager
@@ -51,9 +51,9 @@ const (
5151)
5252
5353var (
54- poolStart uintptr // the first heap pointer
55- nextAlloc gcBlock // the next block that should be tried by the allocator
56- endBlock gcBlock // the block just past the end of the available space
54+ metadataStart unsafe. Pointer // pointer to the start of the heap
55+ nextAlloc gcBlock // the next block that should be tried by the allocator
56+ endBlock gcBlock // the block just past the end of the available space
5757)
5858
5959// zeroSizedAlloc is just a sentinel that gets returned when allocating 0 bytes.
@@ -96,10 +96,10 @@ type gcBlock uintptr
9696// blockFromAddr returns a block given an address somewhere in the heap (which
9797// might not be heap-aligned).
9898func blockFromAddr (addr uintptr ) gcBlock {
99- if gcAsserts && (addr < poolStart || addr >= heapEnd ) {
99+ if gcAsserts && (addr < heapStart || addr >= uintptr ( metadataStart ) ) {
100100 runtimePanic ("gc: trying to get block from invalid address" )
101101 }
102- return gcBlock ((addr - poolStart ) / bytesPerBlock )
102+ return gcBlock ((addr - heapStart ) / bytesPerBlock )
103103}
104104
105105// Return a pointer to the start of the allocated object.
@@ -109,7 +109,7 @@ func (b gcBlock) pointer() unsafe.Pointer {
109109
110110// Return the address of the start of the allocated object.
111111func (b gcBlock ) address () uintptr {
112- return poolStart + uintptr (b )* bytesPerBlock
112+ return heapStart + uintptr (b )* bytesPerBlock
113113}
114114
115115// findHead returns the head (first block) of an object, assuming the block
@@ -141,15 +141,15 @@ func (b gcBlock) findNext() gcBlock {
141141
142142// State returns the current block state.
143143func (b gcBlock ) state () blockState {
144- stateBytePtr := (* uint8 )(unsafe .Pointer (heapStart + uintptr (b / blocksPerStateByte )))
144+ stateBytePtr := (* uint8 )(unsafe .Pointer (uintptr ( metadataStart ) + uintptr (b / blocksPerStateByte )))
145145 return blockState (* stateBytePtr >> ((b % blocksPerStateByte )* 2 )) % 4
146146}
147147
148148// setState sets the current block to the given state, which must contain more
149149// bits than the current state. Allowed transitions: from free to any state and
150150// from head to mark.
151151func (b gcBlock ) setState (newState blockState ) {
152- stateBytePtr := (* uint8 )(unsafe .Pointer (heapStart + uintptr (b / blocksPerStateByte )))
152+ stateBytePtr := (* uint8 )(unsafe .Pointer (uintptr ( metadataStart ) + uintptr (b / blocksPerStateByte )))
153153 * stateBytePtr |= uint8 (newState << ((b % blocksPerStateByte ) * 2 ))
154154 if gcAsserts && b .state () != newState {
155155 runtimePanic ("gc: setState() was not successful" )
@@ -158,7 +158,7 @@ func (b gcBlock) setState(newState blockState) {
158158
159159// markFree sets the block state to free, no matter what state it was in before.
160160func (b gcBlock ) markFree () {
161- stateBytePtr := (* uint8 )(unsafe .Pointer (heapStart + uintptr (b / blocksPerStateByte )))
161+ stateBytePtr := (* uint8 )(unsafe .Pointer (uintptr ( metadataStart ) + uintptr (b / blocksPerStateByte )))
162162 * stateBytePtr &^= uint8 (blockStateMask << ((b % blocksPerStateByte ) * 2 ))
163163 if gcAsserts && b .state () != blockStateFree {
164164 runtimePanic ("gc: markFree() was not successful" )
@@ -172,7 +172,7 @@ func (b gcBlock) unmark() {
172172 runtimePanic ("gc: unmark() on a block that is not marked" )
173173 }
174174 clearMask := blockStateMask ^ blockStateHead // the bits to clear from the state
175- stateBytePtr := (* uint8 )(unsafe .Pointer (heapStart + uintptr (b / blocksPerStateByte )))
175+ stateBytePtr := (* uint8 )(unsafe .Pointer (uintptr ( metadataStart ) + uintptr (b / blocksPerStateByte )))
176176 * stateBytePtr &^= uint8 (clearMask << ((b % blocksPerStateByte ) * 2 ))
177177 if gcAsserts && b .state () != blockStateHead {
178178 runtimePanic ("gc: unmark() was not successful" )
@@ -188,18 +188,17 @@ func initHeap() {
188188
189189 // Allocate some memory to keep 2 bits of information about every block.
190190 metadataSize := totalSize / (blocksPerStateByte * bytesPerBlock )
191+ metadataStart = unsafe .Pointer (heapEnd - metadataSize )
191192
192- // Align the pool.
193- poolStart = (heapStart + metadataSize + (bytesPerBlock - 1 )) &^ (bytesPerBlock - 1 )
194- poolEnd := heapEnd &^ (bytesPerBlock - 1 )
195- numBlocks := (poolEnd - poolStart ) / bytesPerBlock
193+ // Use the rest of the available memory as heap.
194+ numBlocks := (uintptr (metadataStart ) - heapStart ) / bytesPerBlock
196195 endBlock = gcBlock (numBlocks )
197196 if gcDebug {
198197 println ("heapStart: " , heapStart )
199198 println ("heapEnd: " , heapEnd )
200199 println ("total size: " , totalSize )
201200 println ("metadata size: " , metadataSize )
202- println ("poolStart : " , poolStart )
201+ println ("metadataStart : " , metadataStart )
203202 println ("# of blocks: " , numBlocks )
204203 println ("# of block states:" , metadataSize * blocksPerStateByte )
205204 }
@@ -209,7 +208,7 @@ func initHeap() {
209208 }
210209
211210 // Set all block states to 'free'.
212- memzero (unsafe . Pointer ( heapStart ) , metadataSize )
211+ memzero (metadataStart , metadataSize )
213212}
214213
215214// alloc tries to find some free space on the heap, possibly doing a garbage
@@ -496,7 +495,7 @@ func sweep() {
496495// simply returns whether it lies anywhere in the heap. Go allows interior
497496// pointers so we can't check alignment or anything like that.
498497func looksLikePointer (ptr uintptr ) bool {
499- return ptr >= poolStart && ptr < heapEnd
498+ return ptr >= heapStart && ptr < uintptr ( metadataStart )
500499}
501500
502501// dumpHeap can be used for debugging purposes. It dumps the state of each heap
0 commit comments