Codelet recycling

Discuss development specific to the Pi version of ADFFS
Post Reply
JonAbbott
Posts: 2954
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Codelet recycling

Post by JonAbbott »

Changes required to implement codelet recycling:
  • GOARM3JIT needs to initialize the codelet "firstfree" pointer (coded)
  • GOARM3JIT needs to initialize the first codelet heap entries (coded)
  • CODELET macros need to scan for a free codelet block big enough for the requested codelet size (coded)
  • Abort handlers need to free any codelets that are replaced by self-modifying code (coded)
  • hv_reset_memory_block needs to free any codelets in the region being reset (coded)
  • To check for a codelet, look for B <address> where jit_appspace_end < address < jit_code_start (coded)
  • Remove code from embedded codelets (partially coded)

Pseudo code for codelet recycling:

Two codelets need to be initialised up front:
lastfree_codelet {lastfree_codelet, lastfree_codelet, <free space size>, 0}
first_codelet {first_codelet, first_codelet, codelet_struct_size, -1}

STRUCT codelet_struct {
.next DCD 0
.previous DCD 0
.size DCD 0
.source DCD 0
.var4 DCD 0
.var3 DCD 0
.var2 DCD 0
.var1 DCD 0
}

#set codelet_struct_size = 8 * 4
#set min_codelet_size = codelet_struct_size + (4 * 4)

Allocate

pointer allocate(required + heap_struct_size) {
codelet = lastfree_codelet.next

while codelet.size < required
codelet = codelet.next
endwhile

freesize = codelet.size - required

if freesize >= (codelet_struct_size + min_codelet_size) then
codelet.size = freesize
codelet = codelet + freesize
codelet.size = required
else
;update previous/next free

(codelet.previous).next = codelet.next
(codelet.next).previous = codelet.previous
endif

;update previous/next allocated
codelet.previous = codelet + codelet.size
codelet.next = (codelet.previous).next
(codelet.previous).next = codelet
(codelet.next).previous = codelet
codelet.source = <original instruction address>

return codelet + codelet_struct_size
}


Free
if codelet.code = hypervised_SWI then return

codelet.source = 0

;update previous/next allocated
(codelet.previous).next = codelet.next
(codelet.next).previous = codelet.previous

;find next free
next = lastfree_codelet
repeat
next = next.next
until next < codelet

size = codelet.size
previous = next

;defrag down
if next + next.size = codelet then
size += next.size
codelet = next
next = next.next
endif

;defrag up
previous = previous.previous
if codelet + codelet.size = previous then
size += previous.size
previous = previous.previous
endif

codelet.size = size

;update previous/next free
codelet.next = next
codelet.previous = previous
next.previous = codelet
previous.next = codelet
}
tlsa1
Posts: 17
Joined: Wed Oct 02, 2013 2:15 pm

Re: Codelet recycling

Post by tlsa1 »

Is the codelet recycling to solve the codelet reentrancy problem needed for Cannon Fodder, etc? Or is it something else?
JonAbbott
Posts: 2954
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: Codelet recycling

Post by JonAbbott »

At the moment, memory allocated to codelets is leaked (until the JIT is reset) when the original instruction they implement is overwritten by either self-modifying code or by loading data/code over them.

Its not an issue for most games, ones that continually self-modify however run out of codelet space. Battle Chess falls into this category, filling 4mb of RAM within a second.

Codelet reentrancy Is a separate issue, I'm still pondering on the best solution to solve it.
JonAbbott
Posts: 2954
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: Codelet recycling

Post by JonAbbott »

Whilst coding this, I've realised some SWI codelets need to remain allocated once the original instruction has been overwritten.

In hindsight, SWI codelets that contain veneers should probably have been using private memory outside of codelet space for the veneer, but that would have made things messy and complicated. It's easier to mark them as immortal or simply treat all SWI codelets as immortal. The later just requires a check of the first instruction in the codelet when it's freed, if it's SWI, treat it as immortal.

Not many SWI's have codelets, so even if the whole of memory is wiped clean there won't be much "leaked". Each JIT session is private to the boot script that's being run, so this won't affect WIMP tasks when they're implemented. Each WIMP task will have its own JIT session, so codelet memory shouldn't be an issue.
JonAbbott
Posts: 2954
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: Codelet recycling

Post by JonAbbott »

This is now coded and v2.43 modules are on the dev site for testing. I've performed brief testing on RO3.71 StrongARM (emulated) and RO5.21 on the Pi, leaving Battle Chess playing itself and 2067BC running the demo for several hours. I've not however tested any existing known working games yet.

Battle Chess is ready for release, so I'll get that released at the same time. Possibly this weekend if I get time to do any testing, otherwise it will be next weekend.

EDIT: It would appear something is broken on physical RO3.71 StrongARM as all games are immediately hanging. At a guess its cache related, as I'm not seeing the problem under emulation, odd it works on the Pi though. I'll have to track this issue down before release.
JonAbbott
Posts: 2954
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: Codelet recycling

Post by JonAbbott »

Three SWI's remain which can't currently be recycled:
  • SharedCLibraryAPCS_R
  • Sound_Configure
  • Vector Claims (OS_AddCallBack, OS_Claim, OS_CallAfter, OS_CallEvery, OS_AddToVector, OS_ClaimDeviceVector)
These need moving to static entry points so the original SWI instruction can be released
Post Reply