HaskellWiki

Haskell | Wiki community | Recent changes
Random page | Special pages

 

Not logged in
Log in | Help

Yhc/RTS/Machine

< Yhc | RTS

Part of Yhc

(Download)

The Yhc runtime is a stack machine based on the spineless G-Machine.

The stack machine has several major components:

Contents

1 Registers

The stack machine uses 'registers' (i.e. C variables) to store important information about the running state of the machine (see src/runtime/BCKernel/mutator.c).

The stack machine works by evaluating application nodes. Application nodes are calls to a given function with a given set of arguments. At any one time some application node (and thus some function) is 'currently under evaluation'. When a function is called it executes the bytecode instructions in that function which might cause the further evaluation of more application nodes. Eventually an application will produce a result and evaluation of an earlier application will continue.

The registers used in this process are:

2 Heap

The layout of heap nodes is described in Yhc/RTS/Heap and garbage collection in Yhc/RTS/GC.

The heap used to be stored in memory with the heap growing one way and the stack growing the other. However with the introduction of concurrency to yhc each process needs its own stack.

Process stacks are thus allocated as ProcStackNodes (see Yhc/RTS/Heap) in the heap and are garbage collected like normal nodes.

3 Mark Table

Another part of the heap is the mark table, which is an area of memory 1 bit for each word in the heap. This is used in garbage collecting. The more traditional method of including mark bits, having a bit as a field of a node header wasn't appropriate for Yhc, mainly due to it not having enough room to fit it in!

Having a seperate table does allow some useful optimisations in the garbage collector, however, see Yhc/RTS/GC for details.

4 Stack

The program stack is used to store previous values of the machine registers in stack frames. This is used to allow nested function calls. The program stack is also used to during evaluation to perform calculation and as temporary store. The layout of the stack might thus be something like

===================   <- G_spBase
 |   frame 0     |
 +---------------+
 :  stack data   :
 +---------------+
 |   frame 1     |
 +---------------+ 
 |   frame 2     |     <- fp
 +---------------+     
 :  stack data   :
 :...............:
 :  stack data   :     <- sp
 :---------------:

The structure of a single stack frame is:

 struct Frame {
   Frame*     fp;     /* saved value of the fp register */
   CodePtr    ip;     /* saved value of the ip register */
   Node*      vapptr; /* saved value of the vapptr register */
 };

When a new node is evaluated a new frame is pushed on top of the stack. The current values of the registers are saved in the frame and the registers get new values:

When the function returns:

  1. the value on the top of the stack is saved temporarily
  2. ip and vapptr are set to the value saved in the current frame
  3. fp is set the value saved in the current frame
  4. constptr is set to the constant table of vapptr
  5. sp is set to the new value of fp
  6. the value saved earlier is pushed back onto the top of the stack

Each process has its own stack and stacks are stored as normal heap nodes. When a process outgrows its stack it's simply given a larger one and the old one is left to be garbage collected.

5 Global registers

There are some additional registers that are used (see src/runtime/BCKernel/heap.h):

There are also global registers that act as 'caches'. Which is to say they are globally visible copies of mutator registers (it's necessary to copy them back and from when moving in/out of the mutator).

Retrieved from "http://www.haskell.org/haskellwiki/Yhc/RTS/Machine"

This page has been accessed 2,903 times. This page was last modified 15:13, 12 May 2006. Recent content is available under a simple permissive license.