Merge "Implement ThreadReference.CurrentContendedMonitor and ThreadReference.Interrupt." into dalvik-dev
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 420ad33..9d41e01 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -423,21 +423,14 @@
 	XandY
 
 # subdirectories of test/ which are used with test-art-target-oat
-# Declare the simplest tests (Main, HelloWorld, and Fibonacci) first, the rest are alphabetical
+# Declare the simplest tests (Main, HelloWorld) first, the rest are alphabetical
 TEST_OAT_DIRECTORIES := \
 	Main \
 	HelloWorld \
-	Fibonacci \
 	\
-	ExceptionTest \
-	GrowthLimit \
-	ConcurrentGC \
 	IntMath \
-	Invoke \
-	MemUsage \
 	ParallelGC \
 	ReferenceMap \
-	ReflectionTest \
 	StackWalk \
 	ThreadStress
 
diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
index a555c3d..81cbdd5 100644
--- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
+++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
@@ -244,7 +244,6 @@
 }
 
 uintptr_t GetDeoptimizationEntryPoint() {
-  UNIMPLEMENTED(FATAL);
   return reinterpret_cast<uintptr_t>(art_deoptimize);
 }
 
diff --git a/src/oat/runtime/x86/runtime_support_x86.S b/src/oat/runtime/x86/runtime_support_x86.S
index 1d24606..379fcce 100644
--- a/src/oat/runtime/x86/runtime_support_x86.S
+++ b/src/oat/runtime/x86/runtime_support_x86.S
@@ -374,15 +374,20 @@
 TWO_ARG_DOWNCALL art_initialize_type_from_code, artInitializeTypeFromCode, RETURN_IF_EAX_NOT_ZERO
 TWO_ARG_DOWNCALL art_initialize_type_and_verify_access_from_code, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_EAX_NOT_ZERO
 
+    /*
+     * On entry, eax and ecx must be preserved, edx is dex PC
+     */
 DEFINE_FUNCTION art_update_debugger
-    mov  %eax, %ebx               // stash away eax so that it's saved as if it were an argument
+    mov %eax, %ebx                // stash away eax so that it's saved as if it were an argument
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+    subl LITERAL(4), %esp         // alignment padding
     pushl %esp                    // pass arg2 (sp)
     pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
     pushl %edx                    // pass arg0 (dex pc)
     call SYMBOL(artUpdateDebuggerFromCode) // artUpdateDebuggerFromCode(int32_t, Thread*, Method**)
+    addl LITERAL(16), %esp        // pop arguments
     RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
-    mov  %ebx, %eax               // restore original eax
+    mov %ebx, %eax                // restore original eax
     ret
 
 DEFINE_FUNCTION art_get_and_clear_exception
@@ -745,13 +750,68 @@
     addl LITERAL(44), %esp        // pop arguments
     RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
 
+    /*
+     * Routine that intercepts method calls and returns.
+     */
 DEFINE_FUNCTION art_instrumentation_entry_from_code
-    ret
+    xchgl %eax, (%esp)            // place LR in eax, save eax
+    pushl %ecx                    // save ecx
+    pushl %edx                    // save edx
+    pushl %ebx                    // save ebx
+    lea   16(%esp), %edx          // remember bottom of caller's frame
+    pushl %eax                    // pass LR
+    pushl %edx                    // pass SP
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    pushl 24(%esp)                // pass Method*
+    call  SYMBOL(artInstrumentationMethodEntryFromCode) // (Method*, Thread*, SP, LR)
+    addl  LITERAL(16), %esp       // pop arguments
+    popl  %ebx                    // restore ebx
+    popl  %edx                    // restore edx
+    movl  (%esp), %ecx            // restore ecx (without popping)
+    movl  %eax, (%esp)            // place method's code pointer on stack
+    movl  4(%esp), %eax           // restore eax (without popping)
+    movl  LITERAL(SYMBOL(art_instrumentation_exit_from_code)), 4(%esp)
+                                  // place instrumentation exit as return pc
+    ret                           // call method (and pop)
 DEFINE_FUNCTION art_instrumentation_exit_from_code
-    ret
+    mov   %esp, %ecx              // remember bottom of caller's frame
+    pushl %edx                    // save return value
+    pushl %eax                    // save other half of return value
+    pushl %ecx                    // pass SP
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current
+    call  SYMBOL(artInstrumentationMethodExitFromCode)  // (Thread*, SP)
+    mov   %eax, %ecx              // move returned link register
+    // TODO: Set link register for deopt
+    addl  LITERAL(8), %esp        // pop arguments
+    popl  %eax                    // restore return value
+    popl  %edx                    // restore other half of return value
+    jmp   *%ecx                   // return
 
+    /*
+     * The thread's enter interpreter flag is set and so we should transition to the interpreter
+     * rather than allow execution to continue in the frame below. There may be live results in
+     * registers depending on how complete the operation is when we safepoint - for example, a
+     * set operation may have completed while a get operation needs writing back into the vregs.
+     */
 DEFINE_FUNCTION art_deoptimize
-    ret
+    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
+    pushl %esp                    // pass SP
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    pushl %edx                    // push half of return value
+    pushl %eax                    // push other half of return value
+    call SYMBOL(artDeoptimize)    // artDeoptimize(return value, Thread*, SP)
+                                  // Returns caller method's frame size.
+    addl LITERAL(16), %esp        // pop arguments
+    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+    testl %eax, %eax              // Was the caller an upcall?
+    jz    1f                      // Return if caller was upcall.
+    lea   (%esp, %eax), %edx      // edx == bottom of caller's frame.
+    mov   %edx, %esp              // Remove frame.
+    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
+    call SYMBOL(artEnterInterpreterFromDeoptimize) // Enter interpreter, callee-save ends stack fragment.
+    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+1:
+    ret                           // Return to caller.
 
     /*
      * String's indexOf.
diff --git a/test/100-reflect2/expected.txt b/test/100-reflect2/expected.txt
new file mode 100644
index 0000000..9417174
--- /dev/null
+++ b/test/100-reflect2/expected.txt
@@ -0,0 +1,77 @@
+true
+8
+x
+3.141592653589793
+3.14
+32
+81985529216486895
+16
+false
+7
+y
+2.7
+2.7
+31
+63
+15
+true
+6
+z
+1.3
+1.3
+30
+62
+14
+java.lang.IllegalArgumentException: invalid primitive conversion from int to short
+	at java.lang.reflect.Field.set(Native Method)
+	at Main.testFieldReflection(Main.java:121)
+	at Main.main(Main.java:269)
+true (class java.lang.Boolean)
+6 (class java.lang.Byte)
+z (class java.lang.Character)
+1.3 (class java.lang.Double)
+1.3 (class java.lang.Float)
+30 (class java.lang.Integer)
+62 (class java.lang.Long)
+14 (class java.lang.Short)
+[public java.lang.String(), java.lang.String(int,int,char[]), public java.lang.String(java.lang.String), private java.lang.String(java.lang.String,char), private java.lang.String(java.lang.String,int), private java.lang.String(java.lang.String,java.lang.String), private java.lang.String(java.lang.String,java.lang.String,java.lang.String), public java.lang.String(java.lang.StringBuffer), public java.lang.String(java.lang.StringBuilder), public java.lang.String(byte[]), public java.lang.String(byte[],int), public java.lang.String(byte[],int,int), public java.lang.String(byte[],int,int,int), public java.lang.String(byte[],int,int,java.lang.String) throws java.io.UnsupportedEncodingException, public java.lang.String(byte[],int,int,java.nio.charset.Charset), public java.lang.String(byte[],java.lang.String) throws java.io.UnsupportedEncodingException, public java.lang.String(byte[],java.nio.charset.Charset), public java.lang.String(char[]), public java.lang.String(char[],int,int), public java.lang.String(int[],int,int)]
+[private final char[] java.lang.String.value, private final int java.lang.String.count, private int java.lang.String.hashCode, private final int java.lang.String.offset, private static final char[] java.lang.String.ASCII, public static final java.util.Comparator java.lang.String.CASE_INSENSITIVE_ORDER, private static final char java.lang.String.REPLACEMENT_CHAR, private static final long java.lang.String.serialVersionUID]
+[void java.lang.String._getChars(int,int,char[],int), public char java.lang.String.charAt(int), public int java.lang.String.codePointAt(int), public int java.lang.String.codePointBefore(int), public int java.lang.String.codePointCount(int,int), public volatile int java.lang.String.compareTo(java.lang.Object), public native int java.lang.String.compareTo(java.lang.String), public int java.lang.String.compareToIgnoreCase(java.lang.String), public java.lang.String java.lang.String.concat(java.lang.String), public boolean java.lang.String.contains(java.lang.CharSequence), public boolean java.lang.String.contentEquals(java.lang.CharSequence), public boolean java.lang.String.contentEquals(java.lang.StringBuffer), public boolean java.lang.String.endsWith(java.lang.String), public boolean java.lang.String.equals(java.lang.Object), public boolean java.lang.String.equalsIgnoreCase(java.lang.String), public void java.lang.String.getBytes(int,int,byte[],int), public [B java.lang.String.getBytes(), public [B java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException, public [B java.lang.String.getBytes(java.nio.charset.Charset), public void java.lang.String.getChars(int,int,char[],int), public int java.lang.String.hashCode(), public int java.lang.String.indexOf(int), public int java.lang.String.indexOf(int,int), public int java.lang.String.indexOf(java.lang.String), public int java.lang.String.indexOf(java.lang.String,int), public native java.lang.String java.lang.String.intern(), public boolean java.lang.String.isEmpty(), public int java.lang.String.lastIndexOf(int), public int java.lang.String.lastIndexOf(int,int), public int java.lang.String.lastIndexOf(java.lang.String), public int java.lang.String.lastIndexOf(java.lang.String,int), public int java.lang.String.length(), public boolean java.lang.String.matches(java.lang.String), public int java.lang.String.offsetByCodePoints(int,int), public boolean java.lang.String.regionMatches(int,java.lang.String,int,int), public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int), public java.lang.String java.lang.String.replace(char,char), public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence), public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String), public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String), public [Ljava.lang.String; java.lang.String.split(java.lang.String), public [Ljava.lang.String; java.lang.String.split(java.lang.String,int), public boolean java.lang.String.startsWith(java.lang.String), public boolean java.lang.String.startsWith(java.lang.String,int), public java.lang.CharSequence java.lang.String.subSequence(int,int), public java.lang.String java.lang.String.substring(int), public java.lang.String java.lang.String.substring(int,int), public [C java.lang.String.toCharArray(), public java.lang.String java.lang.String.toLowerCase(), public java.lang.String java.lang.String.toLowerCase(java.util.Locale), public java.lang.String java.lang.String.toString(), public java.lang.String java.lang.String.toUpperCase(), public java.lang.String java.lang.String.toUpperCase(java.util.Locale), public java.lang.String java.lang.String.trim(), static void java.lang.String.<clinit>(), public static java.lang.String java.lang.String.copyValueOf(char[]), public static java.lang.String java.lang.String.copyValueOf(char[],int,int), private java.lang.StringIndexOutOfBoundsException java.lang.String.failedBoundsCheck(int,int,int), private native int java.lang.String.fastIndexOf(int,int), private char java.lang.String.foldCase(char), public static transient java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[]), public static transient java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[]), private java.lang.StringIndexOutOfBoundsException java.lang.String.indexAndLength(int), private static int java.lang.String.indexOf(java.lang.String,java.lang.String,int,int,char), private int java.lang.String.indexOfSupplementary(int,int), private int java.lang.String.lastIndexOfSupplementary(int,int), private java.lang.StringIndexOutOfBoundsException java.lang.String.startEndAndLength(int,int), public static java.lang.String java.lang.String.valueOf(char), public static java.lang.String java.lang.String.valueOf(double), public static java.lang.String java.lang.String.valueOf(float), public static java.lang.String java.lang.String.valueOf(int), public static java.lang.String java.lang.String.valueOf(long), public static java.lang.String java.lang.String.valueOf(java.lang.Object), public static java.lang.String java.lang.String.valueOf(boolean), public static java.lang.String java.lang.String.valueOf(char[]), public static java.lang.String java.lang.String.valueOf(char[],int,int)]
+[]
+[interface java.io.Serializable, interface java.lang.Comparable, interface java.lang.CharSequence]
+0
+17
+false
+true
+true
+false
+[int]
+4444
+null (null)
+[int]
+[int, int]
+1111 2222
+null (null)
+[int, int]
+1111 2222
+3333 (class java.lang.Integer)
+[class [I]
+10 (class java.lang.Integer)
+[class [Ljava.lang.String;]
+hello (class java.lang.String)
+[boolean, byte, char, double, float, int, long, short]
+true 0 1 2.0 3.0 4 5 6
+null (null)
+[boolean, byte, char, double, class java.lang.String, float, int, long, short]
+true 0 1 2.0  hello world 3.0 4 5 6
+null (null)
+[]
+java.lang.reflect.InvocationTargetException
+	at java.lang.reflect.Method.invoke(Native Method)
+	at Main.testMethodReflection(Main.java:210)
+	at Main.main(Main.java:270)
+Caused by: java.lang.ArithmeticException: surprise!
+	at Main.thrower(Main.java:218)
+	... 3 more
+ (class java.lang.String)
+yz (class java.lang.String)
diff --git a/test/100-reflect2/info.txt b/test/100-reflect2/info.txt
new file mode 100644
index 0000000..1910b6e
--- /dev/null
+++ b/test/100-reflect2/info.txt
@@ -0,0 +1 @@
+Another set of reflection tests.
\ No newline at end of file
diff --git a/test/ReflectionTest/ReflectionTest.java b/test/100-reflect2/src/Main.java
similarity index 65%
rename from test/ReflectionTest/ReflectionTest.java
rename to test/100-reflect2/src/Main.java
index a9dc6e7..0404591 100644
--- a/test/ReflectionTest/ReflectionTest.java
+++ b/test/100-reflect2/src/Main.java
@@ -17,7 +17,7 @@
 import java.lang.reflect.*;
 import java.util.*;
 
-class ReflectionTest {
+class Main {
   private static boolean z = true;
   private static byte b = 8;
   private static char c = 'x';
@@ -30,114 +30,114 @@
   public static void testFieldReflection() throws Exception {
     Field f;
 
-    f = ReflectionTest.class.getDeclaredField("z");
+    f = Main.class.getDeclaredField("z");
     System.out.println(f.getBoolean(null));
-    f = ReflectionTest.class.getDeclaredField("b");
+    f = Main.class.getDeclaredField("b");
     System.out.println(f.getByte(null));
-    f = ReflectionTest.class.getDeclaredField("c");
+    f = Main.class.getDeclaredField("c");
     System.out.println(f.getChar(null));
-    f = ReflectionTest.class.getDeclaredField("d");
+    f = Main.class.getDeclaredField("d");
     System.out.println(f.getDouble(null));
-    f = ReflectionTest.class.getDeclaredField("f");
+    f = Main.class.getDeclaredField("f");
     System.out.println(f.getFloat(null));
-    f = ReflectionTest.class.getDeclaredField("i");
+    f = Main.class.getDeclaredField("i");
     System.out.println(f.getInt(null));
-    f = ReflectionTest.class.getDeclaredField("j");
+    f = Main.class.getDeclaredField("j");
     System.out.println(f.getLong(null));
-    f = ReflectionTest.class.getDeclaredField("s");
+    f = Main.class.getDeclaredField("s");
     System.out.println(f.getShort(null));
 
-    f = ReflectionTest.class.getDeclaredField("z");
+    f = Main.class.getDeclaredField("z");
     f.setBoolean(null, false);
-    f = ReflectionTest.class.getDeclaredField("b");
+    f = Main.class.getDeclaredField("b");
     f.setByte(null, (byte) 7);
-    f = ReflectionTest.class.getDeclaredField("c");
+    f = Main.class.getDeclaredField("c");
     f.setChar(null, 'y');
-    f = ReflectionTest.class.getDeclaredField("d");
+    f = Main.class.getDeclaredField("d");
     f.setDouble(null, 2.7);
-    f = ReflectionTest.class.getDeclaredField("f");
+    f = Main.class.getDeclaredField("f");
     f.setFloat(null, 2.7f);
-    f = ReflectionTest.class.getDeclaredField("i");
+    f = Main.class.getDeclaredField("i");
     f.setInt(null, 31);
-    f = ReflectionTest.class.getDeclaredField("j");
+    f = Main.class.getDeclaredField("j");
     f.setLong(null, 63);
-    f = ReflectionTest.class.getDeclaredField("s");
+    f = Main.class.getDeclaredField("s");
     f.setShort(null, (short) 15);
 
-    f = ReflectionTest.class.getDeclaredField("z");
+    f = Main.class.getDeclaredField("z");
     System.out.println(f.getBoolean(null));
-    f = ReflectionTest.class.getDeclaredField("b");
+    f = Main.class.getDeclaredField("b");
     System.out.println(f.getByte(null));
-    f = ReflectionTest.class.getDeclaredField("c");
+    f = Main.class.getDeclaredField("c");
     System.out.println(f.getChar(null));
-    f = ReflectionTest.class.getDeclaredField("d");
+    f = Main.class.getDeclaredField("d");
     System.out.println(f.getDouble(null));
-    f = ReflectionTest.class.getDeclaredField("f");
+    f = Main.class.getDeclaredField("f");
     System.out.println(f.getFloat(null));
-    f = ReflectionTest.class.getDeclaredField("i");
+    f = Main.class.getDeclaredField("i");
     System.out.println(f.getInt(null));
-    f = ReflectionTest.class.getDeclaredField("j");
+    f = Main.class.getDeclaredField("j");
     System.out.println(f.getLong(null));
-    f = ReflectionTest.class.getDeclaredField("s");
+    f = Main.class.getDeclaredField("s");
     System.out.println(f.getShort(null));
 
-    f = ReflectionTest.class.getDeclaredField("z");
+    f = Main.class.getDeclaredField("z");
     f.set(null, Boolean.valueOf(true));
-    f = ReflectionTest.class.getDeclaredField("b");
+    f = Main.class.getDeclaredField("b");
     f.set(null, Byte.valueOf((byte) 6));
-    f = ReflectionTest.class.getDeclaredField("c");
+    f = Main.class.getDeclaredField("c");
     f.set(null, Character.valueOf('z'));
-    f = ReflectionTest.class.getDeclaredField("d");
+    f = Main.class.getDeclaredField("d");
     f.set(null, Double.valueOf(1.3));
-    f = ReflectionTest.class.getDeclaredField("f");
+    f = Main.class.getDeclaredField("f");
     f.set(null, Float.valueOf(1.3f));
-    f = ReflectionTest.class.getDeclaredField("i");
+    f = Main.class.getDeclaredField("i");
     f.set(null, Integer.valueOf(30));
-    f = ReflectionTest.class.getDeclaredField("j");
+    f = Main.class.getDeclaredField("j");
     f.set(null, Long.valueOf(62));
     f.set(null, Integer.valueOf(62));
-    f = ReflectionTest.class.getDeclaredField("s");
+    f = Main.class.getDeclaredField("s");
     f.set(null, Short.valueOf((short) 14));
 
-    f = ReflectionTest.class.getDeclaredField("z");
+    f = Main.class.getDeclaredField("z");
     System.out.println(f.getBoolean(null));
-    f = ReflectionTest.class.getDeclaredField("b");
+    f = Main.class.getDeclaredField("b");
     System.out.println(f.getByte(null));
-    f = ReflectionTest.class.getDeclaredField("c");
+    f = Main.class.getDeclaredField("c");
     System.out.println(f.getChar(null));
-    f = ReflectionTest.class.getDeclaredField("d");
+    f = Main.class.getDeclaredField("d");
     System.out.println(f.getDouble(null));
-    f = ReflectionTest.class.getDeclaredField("f");
+    f = Main.class.getDeclaredField("f");
     System.out.println(f.getFloat(null));
-    f = ReflectionTest.class.getDeclaredField("i");
+    f = Main.class.getDeclaredField("i");
     System.out.println(f.getInt(null));
-    f = ReflectionTest.class.getDeclaredField("j");
+    f = Main.class.getDeclaredField("j");
     System.out.println(f.getLong(null));
-    f = ReflectionTest.class.getDeclaredField("s");
+    f = Main.class.getDeclaredField("s");
     System.out.println(f.getShort(null));
 
     try {
-      f = ReflectionTest.class.getDeclaredField("s");
+      f = Main.class.getDeclaredField("s");
       f.set(null, Integer.valueOf(14));
     } catch (IllegalArgumentException expected) {
       expected.printStackTrace();
     }
 
-    f = ReflectionTest.class.getDeclaredField("z");
+    f = Main.class.getDeclaredField("z");
     show(f.get(null));
-    f = ReflectionTest.class.getDeclaredField("b");
+    f = Main.class.getDeclaredField("b");
     show(f.get(null));
-    f = ReflectionTest.class.getDeclaredField("c");
+    f = Main.class.getDeclaredField("c");
     show(f.get(null));
-    f = ReflectionTest.class.getDeclaredField("d");
+    f = Main.class.getDeclaredField("d");
     show(f.get(null));
-    f = ReflectionTest.class.getDeclaredField("f");
+    f = Main.class.getDeclaredField("f");
     show(f.get(null));
-    f = ReflectionTest.class.getDeclaredField("i");
+    f = Main.class.getDeclaredField("i");
     show(f.get(null));
-    f = ReflectionTest.class.getDeclaredField("j");
+    f = Main.class.getDeclaredField("j");
     show(f.get(null));
-    f = ReflectionTest.class.getDeclaredField("s");
+    f = Main.class.getDeclaredField("s");
     show(f.get(null));
 
     /*
@@ -161,10 +161,10 @@
     System.out.println(Arrays.toString(String.class.getDeclaredFields()));
     System.out.println(Arrays.toString(String.class.getDeclaredMethods()));
 
-    System.out.println(Arrays.toString(ReflectionTest.class.getInterfaces()));
+    System.out.println(Arrays.toString(Main.class.getInterfaces()));
     System.out.println(Arrays.toString(String.class.getInterfaces()));
 
-    System.out.println(ReflectionTest.class.getModifiers());
+    System.out.println(Main.class.getModifiers());
     System.out.println(String.class.getModifiers());
 
     System.out.println(String.class.isAssignableFrom(Object.class));
@@ -175,37 +175,37 @@
 
     Method m;
 
-    m = ReflectionTest.class.getDeclaredMethod("IV", int.class);
+    m = Main.class.getDeclaredMethod("IV", int.class);
     System.out.println(Arrays.toString(m.getParameterTypes()));
     show(m.invoke(null, 4444));
     System.out.println(Arrays.toString(m.getParameterTypes()));
 
-    m = ReflectionTest.class.getDeclaredMethod("IIV", int.class, int.class);
+    m = Main.class.getDeclaredMethod("IIV", int.class, int.class);
     System.out.println(Arrays.toString(m.getParameterTypes()));
     show(m.invoke(null, 1111, 2222));
 
-    m = ReflectionTest.class.getDeclaredMethod("III", int.class, int.class);
+    m = Main.class.getDeclaredMethod("III", int.class, int.class);
     System.out.println(Arrays.toString(m.getParameterTypes()));
     show(m.invoke(null, 1111, 2222));
 
-    m = ReflectionTest.class.getDeclaredMethod("sumArray", int[].class);
+    m = Main.class.getDeclaredMethod("sumArray", int[].class);
     System.out.println(Arrays.toString(m.getParameterTypes()));
     show(m.invoke(null, new int[] { 1, 2, 3, 4 }));
 
-    m = ReflectionTest.class.getDeclaredMethod("concat", String[].class);
+    m = Main.class.getDeclaredMethod("concat", String[].class);
     System.out.println(Arrays.toString(m.getParameterTypes()));
     show(m.invoke(null, (Object) new String[] { "h", "e", "l", "l", "o" }));
 
-    m = ReflectionTest.class.getDeclaredMethod("ZBCDFIJSV", boolean.class, byte.class, char.class, double.class, float.class, int.class, long.class, short.class);
+    m = Main.class.getDeclaredMethod("ZBCDFIJSV", boolean.class, byte.class, char.class, double.class, float.class, int.class, long.class, short.class);
     System.out.println(Arrays.toString(m.getParameterTypes()));
     show(m.invoke(null, true, (byte) 0, '1', 2, 3, 4, 5, (short) 6));
 
-    m = ReflectionTest.class.getDeclaredMethod("ZBCDLFIJSV", boolean.class, byte.class, char.class, double.class, String.class, float.class, int.class, long.class, short.class);
+    m = Main.class.getDeclaredMethod("ZBCDLFIJSV", boolean.class, byte.class, char.class, double.class, String.class, float.class, int.class, long.class, short.class);
     System.out.println(Arrays.toString(m.getParameterTypes()));
     show(m.invoke(null, true, (byte) 0, '1', 2, "hello world", 3, 4, 5, (short) 6));
 
     try {
-      m = ReflectionTest.class.getDeclaredMethod("thrower");
+      m = Main.class.getDeclaredMethod("thrower");
       System.out.println(Arrays.toString(m.getParameterTypes()));
       show(m.invoke(null));
       System.out.println("************* should have thrown!");
diff --git a/test/101-fibonacci/expected.txt b/test/101-fibonacci/expected.txt
new file mode 100644
index 0000000..dcc3617
--- /dev/null
+++ b/test/101-fibonacci/expected.txt
@@ -0,0 +1,2 @@
+fibonacci(10)=55
+fibonacci(11)=89
diff --git a/test/101-fibonacci/info.txt b/test/101-fibonacci/info.txt
new file mode 100644
index 0000000..991511c
--- /dev/null
+++ b/test/101-fibonacci/info.txt
@@ -0,0 +1 @@
+Computes fibonacci.
diff --git a/test/Fibonacci/Fibonacci.java b/test/101-fibonacci/src/Main.java
similarity index 98%
rename from test/Fibonacci/Fibonacci.java
rename to test/101-fibonacci/src/Main.java
index a5c4e4b..3773e1b 100644
--- a/test/Fibonacci/Fibonacci.java
+++ b/test/101-fibonacci/src/Main.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-class Fibonacci {
+class Main {
 
 /*
     // Iterative version
diff --git a/test/102-concurrent-gc/expected.txt b/test/102-concurrent-gc/expected.txt
new file mode 100644
index 0000000..f75da10
--- /dev/null
+++ b/test/102-concurrent-gc/expected.txt
@@ -0,0 +1 @@
+Test complete
diff --git a/test/102-concurrent-gc/info.txt b/test/102-concurrent-gc/info.txt
new file mode 100644
index 0000000..b423127
--- /dev/null
+++ b/test/102-concurrent-gc/info.txt
@@ -0,0 +1,2 @@
+Test that attempts to hide objects from a concurrently running GC. The
+concurrent GC should locate the "hidden" objects through a write-barrier.
diff --git a/test/102-concurrent-gc/src/Main.java b/test/102-concurrent-gc/src/Main.java
new file mode 100644
index 0000000..f4f697d
--- /dev/null
+++ b/test/102-concurrent-gc/src/Main.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Random;
+
+public class Main {
+    private static final int buckets = 16 * 1024;
+    private static final int bufferSize = 1024;
+
+    static class ByteContainer {
+        public byte[] bytes;
+    }
+
+    public static void main(String[] args) throws Exception {
+        ByteContainer[] l = new ByteContainer[buckets];
+
+        for (int i = 0; i < buckets; ++i) {
+            l[i] = new ByteContainer();
+        }
+
+        Random rnd = new Random(123456);
+        for (int i = 0; i < buckets / 256; ++i) {
+            int index = rnd.nextInt(buckets);
+            l[index].bytes = new byte[bufferSize];
+
+            // Try to get GC to run if we can
+            Runtime.getRuntime().gc();
+
+            // Shuffle the array to try cause the lost object problem:
+            // This problem occurs when an object is white, it may be
+            // only referenced from a white or grey object. If the white
+            // object is moved during a CMS to be a black object's field, it
+            // causes the moved object to not get marked. This can result in
+            // heap corruption. A typical way to address this issue is by
+            // having a card table.
+            // This aspect of the test is meant to ensure that card
+            // dirtying works and that we check the marked cards after
+            // marking.
+            // If these operations are not done, a segfault / failed assert
+            // should occur.
+            for (int j = 0; j < l.length; ++j) {
+                int a = l.length - i - 1;
+                int b = rnd.nextInt(a);
+                byte[] temp = l[a].bytes;
+                l[a].bytes = l[b].bytes;
+                l[b].bytes = temp;
+            }
+        }
+        System.out.println("Test complete");
+    }
+}
diff --git a/test/103-string-append/expected.txt b/test/103-string-append/expected.txt
new file mode 100644
index 0000000..f75da10
--- /dev/null
+++ b/test/103-string-append/expected.txt
@@ -0,0 +1 @@
+Test complete
diff --git a/test/103-string-append/info.txt b/test/103-string-append/info.txt
new file mode 100644
index 0000000..f8be9b4
--- /dev/null
+++ b/test/103-string-append/info.txt
@@ -0,0 +1 @@
+Simple test that triggers GC by appending to a String.
diff --git a/test/103-string-append/src/Main.java b/test/103-string-append/src/Main.java
new file mode 100644
index 0000000..12b1d8e
--- /dev/null
+++ b/test/103-string-append/src/Main.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+  public static final int ROUNDS = 16;
+  public static final int SIZE = 8 * 1024;
+
+  public static void main(String [] args) {
+    String s;
+    for (int j = 0; j < ROUNDS; j++) {
+      s = "";
+      for (int i = 0; i < SIZE; i++) {
+        s += "x";
+      }
+    }
+    System.out.println("Test complete");
+  }
+}
diff --git a/test/104-growth-limit/expected.txt b/test/104-growth-limit/expected.txt
new file mode 100644
index 0000000..f75da10
--- /dev/null
+++ b/test/104-growth-limit/expected.txt
@@ -0,0 +1 @@
+Test complete
diff --git a/test/104-growth-limit/info.txt b/test/104-growth-limit/info.txt
new file mode 100644
index 0000000..adef4ed
--- /dev/null
+++ b/test/104-growth-limit/info.txt
@@ -0,0 +1,3 @@
+Tests that the growth limit, used to impose the small and large Android
+conventions, can be cleared and the resulting heap is at least as large
+as the growth limited heap.
diff --git a/test/GrowthLimit/GrowthLimit.java b/test/104-growth-limit/src/Main.java
similarity index 73%
rename from test/GrowthLimit/GrowthLimit.java
rename to test/104-growth-limit/src/Main.java
index 32537d6..55469db 100644
--- a/test/GrowthLimit/GrowthLimit.java
+++ b/test/104-growth-limit/src/Main.java
@@ -14,14 +14,11 @@
  * limitations under the License.
  */
 
+import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
-public class GrowthLimit {
+public class Main {
 
     public static void main(String[] args) throws Exception {
 
@@ -35,8 +32,13 @@
             }
         } catch (OutOfMemoryError e) {
         }
-        // Expand the heap to the maximum size
-        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
+        // Expand the heap to the maximum size.
+        // Reflective equivalent of: dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
+        Class<?> vm_runtime = Class.forName("dalvik.system.VMRuntime");
+        Method get_runtime = vm_runtime.getDeclaredMethod("getRuntime");
+        Object runtime = get_runtime.invoke(null);
+        Method clear_growth_limit = vm_runtime.getDeclaredMethod("clearGrowthLimit");
+        clear_growth_limit.invoke(runtime);
 
         int alloc2 = 1;
         try {
@@ -53,5 +55,6 @@
                 System.exit(1);
             }
         }
+        System.out.println("Test complete");
     }
 }
diff --git a/test/105-invoke/expected.txt b/test/105-invoke/expected.txt
new file mode 100644
index 0000000..e0ffebd
--- /dev/null
+++ b/test/105-invoke/expected.txt
@@ -0,0 +1 @@
+invoke PASSED
diff --git a/test/105-invoke/info.txt b/test/105-invoke/info.txt
new file mode 100644
index 0000000..fa794de
--- /dev/null
+++ b/test/105-invoke/info.txt
@@ -0,0 +1 @@
+Tests simple method dispatch.
diff --git a/test/Invoke/Invoke.java b/test/105-invoke/src/Main.java
similarity index 96%
rename from test/Invoke/Invoke.java
rename to test/105-invoke/src/Main.java
index e8c30ef..d5f3b62 100644
--- a/test/Invoke/Invoke.java
+++ b/test/105-invoke/src/Main.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-class Invoke implements InvokeInterface {
+class Main implements InvokeInterface {
 
     int virI_I(int a) {
         return a + 123;
@@ -69,7 +69,7 @@
     }
 
     static int invoke(int a) {
-        Invoke foo = new Invoke();
+        Main foo = new Main();
 
         return foo.virI_I(a) +
                foo.virI_II(a, 1) +
diff --git a/test/106-exceptions2/expected.txt b/test/106-exceptions2/expected.txt
new file mode 100644
index 0000000..50472f7
--- /dev/null
+++ b/test/106-exceptions2/expected.txt
@@ -0,0 +1,4 @@
+nullCheckTestNoThrow PASSED
+nullCheckTestThrow PASSED
+checkAIOBE PASSED
+checkDivZero PASSED
diff --git a/test/106-exceptions2/info.txt b/test/106-exceptions2/info.txt
new file mode 100644
index 0000000..88b603f
--- /dev/null
+++ b/test/106-exceptions2/info.txt
@@ -0,0 +1 @@
+Test runtime exceptions for potential regressions caused by the compiler.
diff --git a/test/ExceptionTest/ExceptionTest.java b/test/106-exceptions2/src/Main.java
similarity index 85%
rename from test/ExceptionTest/ExceptionTest.java
rename to test/106-exceptions2/src/Main.java
index 3edae6d..7d5a64a 100644
--- a/test/ExceptionTest/ExceptionTest.java
+++ b/test/106-exceptions2/src/Main.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-class ExceptionTest {
+class Main {
 
     public int ifoo;
 
     /* Test requires visual inspection of object code to verify */
-    int noThrow(ExceptionTest nonNullA,
-                ExceptionTest nonNullB,
-                ExceptionTest nonNullC) {
+    int noThrow(Main nonNullA,
+                Main nonNullB,
+                Main nonNullC) {
 
         // "this" check should be eliminated on both IGET/IPUT
         ifoo++;
@@ -53,12 +53,12 @@
     }
 
     /* Test to ensure we don't remove necessary null checks */
-    int checkThrow(ExceptionTest nonNullA,
-                   ExceptionTest nonNullB,
-                   ExceptionTest nonNullC,
-                   ExceptionTest nullA,
-                   ExceptionTest nullB,
-                   ExceptionTest nullC) {
+    int checkThrow(Main nonNullA,
+                   Main nonNullB,
+                   Main nonNullC,
+                   Main nullA,
+                   Main nullB,
+                   Main nullC) {
 
         // "this" check should be eliminated on both IGET/IPUT
         ifoo++;
@@ -131,22 +131,22 @@
 
 
     static int nullCheckTestNoThrow(int x) {
-        ExceptionTest base = new ExceptionTest();
-        ExceptionTest a = new ExceptionTest();
-        ExceptionTest b = new ExceptionTest();
-        ExceptionTest c = new ExceptionTest();
+        Main base = new Main();
+        Main a = new Main();
+        Main b = new Main();
+        Main c = new Main();
         base.ifoo = x;
         return base.noThrow(a,b,c);
     }
 
     static int nullCheckTestThrow(int x) {
-        ExceptionTest base = new ExceptionTest();
-        ExceptionTest a = new ExceptionTest();
-        ExceptionTest b = new ExceptionTest();
-        ExceptionTest c = new ExceptionTest();
-        ExceptionTest d = null;
-        ExceptionTest e = null;
-        ExceptionTest f = null;
+        Main base = new Main();
+        Main a = new Main();
+        Main b = new Main();
+        Main c = new Main();
+        Main d = null;
+        Main e = null;
+        Main f = null;
         base.ifoo = x;
         return base.checkThrow(a,b,c,d,e,f);
     }
diff --git a/test/ConcurrentGC/ConcurrentGC.java b/test/ConcurrentGC/ConcurrentGC.java
deleted file mode 100644
index 1a0fec8..0000000
--- a/test/ConcurrentGC/ConcurrentGC.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Random;
-
-public class ConcurrentGC {
-    private static final int buckets = 16 * 1024;
-    private static final int bufferSize = 1024;
-
-    static class ByteContainer {
-        public byte[] bytes;
-    }
-
-    public static void main(String[] args) throws Exception {
-        try {
-            ByteContainer[] l = new ByteContainer[buckets];
-
-            for (int i = 0; i < buckets; ++i) {
-                l[i] = new ByteContainer();
-            }
-
-            Random rnd = new Random(123456);
-            for (int i = 0; i < buckets / 256; ++i) {
-                int index = rnd.nextInt(buckets);
-                l[index].bytes = new byte[bufferSize];
-
-                // Try to get GC to run if we can
-                Runtime.getRuntime().gc();
-
-                // Shuffle the array to try cause the lost object problem:
-                // This problem occurs when an object is white, it may be
-                // only referenced from a white or grey object. If the white
-                // object is moved during a CMS to be a black object's field, it
-                // causes the moved object to not get marked. This can result in
-                // heap corruption. A typical way to address this issue is by
-                // having a card table.
-                // This aspect of the test is meant to ensure that card
-                // dirtying works and that we check the marked cards after
-                // marking.
-                // If these operations are not done, a segfault / failed assert
-                // should occur.
-                for (int j = 0; j < l.length; ++j) {
-                    int a = l.length - i - 1;
-                    int b = rnd.nextInt(a);
-                    byte[] temp = l[a].bytes;
-                    l[a].bytes = l[b].bytes;
-                    l[b].bytes = temp;
-                }
-            }
-        } catch (OutOfMemoryError e) {
-        }
-    }
-}
diff --git a/test/MemUsage/MemUsage.java b/test/MemUsage/MemUsage.java
deleted file mode 100644
index 710031b..0000000
--- a/test/MemUsage/MemUsage.java
+++ /dev/null
@@ -1,15 +0,0 @@
-
-public class MemUsage {
-  public static final int ROUNDS = 8;
-  public static final int SIZE = 2000;
-
-  public static void main(String [] args) {
-    String s;
-    for (int j = 0; j < ROUNDS; j++) {
-      s = "";
-      for (int i = 0; i < SIZE; i++) {
-        s += "x";
-      }
-    }
-  }
-}