The MMTk Test Harness

Overview

The MMTk harness is a debugging tool. It allows you to run MMTk with a simple client - a simple Java-like scripting language - which can explicitly allocate objects, create and delete references, etc. This allows MMTk to be run and debugged stand-alone, without the entire VM, greatly simplifying initial debugging and reducing the edit-debug turnaround time. This is all accessible through the command line or an IDE such as eclipse.

Running the test harness

The harness can be run standalone or via Eclipse (or other IDE).

Standalone

ant mmtk-harness
java -jar target/mmtk/mmtk-harness.jar <script-file> [options...]

There is a collection of sample scripts in the MMTk/harness/test-scripts directory.

In Eclipse

ant mmtk-harness-eclipse-project

Define a new run configuration with main class org.mmtk.harness.Main.

You can configure eclipse to display vmmagic values (Address/ObjectReference/etc) using their toString method through the Eclipse -> Preferences... -> Java -> Debug -> Detail Formatters menu. The simplest option is to check the boxto use toString 'As the label for all variables'.

Test harness options

Options are passed to the test harness as 'keyword=value' pairs.  The standard MMTk options that are available through JikesRVM are accepted (leave off the "-X:gc:"), as well as the following harness-specific options:

Option

Meaning
plan The MMTk plan class.  Defaults to org.mmtk.plan.marksweep.MS

collectors The number of concurrent collector threads (default: 1)

initHeap Initial heap size

maxHeap Maximum heap size (default: 64 pages)

trace Debugging messages from the MMTk Harness.  Trace options include
  • CALL - trace procedure calls
  • ALLOC - trace object allocation
  • OBJECT - trace object mutation events
gcEvery Force frequent GCs.  Options are
  • ALLOC - GC after every object allocation 
  • SAFEPOINT - GC at every GC safepoint



Scripting language

Basics

The language has two types: integer and object.  Objects are allocated

with the 'alloc' statement, and have a specified number of pointers and

nonpointers (integers).  Variables are declared 'c' style, and are optionally

initialized at declaration.

Object fields are referenced using syntax like "tmp.int[5]" or "tmp.object[i*3]",

ie like a struct of arrays of the appropriate types.

Syntax

script ::= method...

method ::= ident "(" { type ident { "," type ident}...  ")" "{" statement... "}"

statement ::=
	  "if" "(" expr ")" block { "elif" "(" expr ")" block } [ "else" block ]
	| "while "(" expr ")" block
	| [ [ type ] ident "=" ] "alloc" "(" expr "," expr [ "," expr ] ")" ";"
	| [ ident "=" ] "hash" "(" expr ")" ";"
        | "gc" "(" ")"
        | "spawn" "(" ident [ "," expr ]... ")" ";"
	| type ident [ "=" expr ] ";"
	| lvalue "=" expr ";"

lvalue ::= ident "=" expr ";"
	| ident "." type "[" expr "]"

type ::= "int" | "object"

expr ::= expr binop expr
		| unop expr
		| "(" expr ")"
		| ident
		| ident "." type "[" expr "]"
		| int-const
		| intrinsic

intrinsic ::= "alloc" "(" expr "," expr ["," expr] ")
            | "(" expr ")"
            | "gc " "(" ")"

binop ::= "+" | "-" | "*" | "/" | "%" | "&&" | "||" | "==" | "!="

unop ::= "!" | "-"