LARA

// Simple malloc and free, fragmentation possible
class Heap(size : Int) {
  private var mem = new Array[Int](size)   // OS would provide this memory
  private var nextAvailable : Int = 1 // where to allocate next
 
  val nextOffset = 0 // offset of 'next' field in free list
  val sizeOffset = 1 // offset of 'size' field in free list
  val minFreeListBlockSize = 2 // each free list block must have size at least 2 words
 
  // initially, free list contains one block whose size is memory size
  def initFreeList = {
    nextAvailable = 1
    mem(nextAvailable + nextOffset) = 0
    mem(nextAvailable + sizeOffset) = size - 1
  }
 
  def malloc(blockSize : Int) : Int = {
    var prev = 0
    var current = nextAvailable
    while ((current != 0) &&
	   (current < size) &&
	   load(current, sizeOffset) < blockSize) {
      prev = current
      current = load(current, nextOffset)
    }
 
    def setPrev(v : Int) = {
      if (prev==0) 
	nextAvailable = v
      else
	mem(prev + nextOffset) = v
    }
 
    // current is the block we would like to return
    if (current==0) {
      error("Out of useful memory")
    } else {
      // found block of the right size
      val restSize = mem(current + sizeOffset) - blockSize
      if (restSize >= minFreeListBlockSize) {
	// replace original block with remaining block
	val restAddr = current + blockSize
	mem(restAddr + sizeOffset) = restSize
	mem(restAddr + nextOffset) = mem(current + nextOffset)
	setPrev(restAddr)
      } else {// remove entire block from free list
	setPrev(mem(current + nextOffset))
      }
      initMem(current, current + blockSize)
    }
    current
  }
 
  def initMem(from : Int, to : Int) = {
    var i = from
    while (i < to) { 
      mem(i) = 0;
      i = i + 1;
    }
  }
 
  // Find where to put the block
  def free(ptr : Int, blockSize : Int) = {
    var prev = 0
    var current = nextAvailable
 
    def setPrev(v : Int) = {
      if (prev==0) 
	nextAvailable = v
      else
	mem(prev + nextOffset) = v
    }
 
    while ((current != 0) && (current < ptr)) {
      prev = current
      current = mem(current + nextOffset)
    }
    // insert the freed block
    mem(ptr + nextOffset) = current
    mem(ptr + sizeOffset) = blockSize
    setPrev(ptr)
    // to reduce fragmentation we should merge here
  }
 
  val nullPtr = 0
 
  // x.f
  def load(x : Int, f : Int) = {
    if (x==0) error("Null dereference!")
    else mem(x + f)
  }
 
  // x.f = y
  def store(x : Int, f : Int, y : Int) = {
    if (x==0) error("Null dereference!")
    else { mem(x + f) = y }
  }
 
  override def toString() : String = {
    var res = "nextAvailable:" + nextAvailable + "\n"
    var i : Int = 0
    while (i < size) {
      res += (i + "->" + mem(i) + "  ")
      i = i + 1
    }
    res
  }
 
  initFreeList
}
 
// source code example
object TestSourceCode {
  class Node {
    var next : Node = null
    var data : Int = 0
  }
  def main(args : Array[String]) = {
    var x : Node = new Node()
    var y : Node = new Node()
    x.next = y
    x.data = 42
    var z : Node = x.next
    z.data = 9
  }
}
 
// object code for the above example
object TestObjectCode {
  val typeTagOffset  = 0 // implicit, first, field
  val nextOffset     = 1 // second field
  val dataOffset     = 2 // third field
  val nodeSize = 3 // three 1-word fields total
 
  val nodeTypeTag = 555 // inded of type 'Node'
 
  def main(args : Array[String]) = {
    var h : Heap = new Heap(64)
    println(h)
    var x : Int = h.malloc(nodeSize)
    h.store(x, typeTagOffset, nodeTypeTag)
    println(h)
 
    var y : Int = h.malloc(nodeSize)
    h.store(y, typeTagOffset, nodeTypeTag)
    println(h)
 
    h.store(x, nextOffset, y)
    h.store(x, dataOffset, 42)
    var z : Int = h.load(x, nextOffset)
    h.store(z, dataOffset, 9)
    println(h)
    println("About to free")
    h.free(z, nodeSize)
    println(h)
  }
}