changeset 8506:c3657d00e343

-Merge with tip
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Thu, 21 Mar 2013 14:11:13 +0100
parents dee7c8b578c7 (current diff) 2bfb9644dcc2 (diff)
children c92949b1ec8a
files agent/make/bugspot.bat agent/src/share/classes/sun/jvm/hotspot/asm/amd64/AMD64FloatRegister.java agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java agent/src/share/classes/sun/jvm/hotspot/bugspot/JavaLineNumberInfo.java agent/src/share/classes/sun/jvm/hotspot/bugspot/Main.java agent/src/share/classes/sun/jvm/hotspot/bugspot/PCFinder.java agent/src/share/classes/sun/jvm/hotspot/bugspot/PackageScanner.java agent/src/share/classes/sun/jvm/hotspot/bugspot/RegisterPanel.java agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTraceEntry.java agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTracePanel.java agent/src/share/classes/sun/jvm/hotspot/bugspot/ThreadListPanel.java agent/src/share/classes/sun/jvm/hotspot/bugspot/VariablePanel.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/AddressTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/DoubleTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/EnumTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FieldTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FloatTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/LongTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/ObjectTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/livejvm/BreakpointEvent.java agent/src/share/classes/sun/jvm/hotspot/livejvm/CIntegerAccessor.java agent/src/share/classes/sun/jvm/hotspot/livejvm/CStringAccessor.java agent/src/share/classes/sun/jvm/hotspot/livejvm/Event.java agent/src/share/classes/sun/jvm/hotspot/livejvm/ExceptionEvent.java agent/src/share/classes/sun/jvm/hotspot/livejvm/JNIHandleAccessor.java agent/src/share/classes/sun/jvm/hotspot/livejvm/ServiceabilityAgentJVMDIModule.java agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java agent/src/share/classes/sun/jvm/hotspot/tools/PermStat.java agent/src/share/native/jvmdi/sa.cpp agent/src/share/native/jvmdi/sa.dsp agent/src/share/native/jvmdi/sa.dsw agent/src/share/native/jvmdi/sa.hpp graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeInfo.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeInfo.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/FieldWriteBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Code.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/GenerateLEANode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertUnreachedToGuardPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GuardCheck.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationThrows.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionalNode.java make/bsd/makefiles/wb.make make/linux/makefiles/wb.make make/solaris/makefiles/kernel.make make/solaris/makefiles/wb.make make/windows/makefiles/wb.make mx/commands.py mx/sanitycheck.py src/cpu/x86/vm/c1_Runtime1_x86.cpp src/cpu/x86/vm/graalRuntime_x86.cpp src/share/tools/whitebox/sun/hotspot/WhiteBox.java src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java src/share/vm/code/nmethod.cpp src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp src/share/vm/gc_implementation/g1/g1_globals.hpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalRuntime.cpp src/share/vm/graal/graalRuntime.hpp src/share/vm/graal/graalVmIds.cpp src/share/vm/graal/graalVmIds.hpp src/share/vm/memory/universe.cpp src/share/vm/prims/jni.cpp src/share/vm/prims/unsafe.cpp src/share/vm/runtime/arguments.cpp src/share/vm/utilities/debug.hpp src/share/vm/utilities/machineCodePrinter.cpp src/share/vm/utilities/machineCodePrinter.hpp test/runtime/7158988/TestFieldMonitor.sh
diffstat 993 files changed, 33157 insertions(+), 20017 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Thu Mar 21 11:30:38 2013 +0100
+++ b/.hgignore	Thu Mar 21 14:11:13 2013 +0100
@@ -7,7 +7,7 @@
 ^dist/
 ^java/
 ^lib/
-^jdk1.7.0
+^jdk1.(7|8).0
 ^java64/
 ^work/
 \.checkstyle$
@@ -61,10 +61,11 @@
 .DS_Store
 javadoc/
 .idea/
+^cscope.out
+^tags
 syntax: glob
 *.bgv
 core.*
 *.jar
 eclipse-build.xml
 rebuild-launch.out
-
--- a/.hgtags	Thu Mar 21 11:30:38 2013 +0100
+++ b/.hgtags	Thu Mar 21 14:11:13 2013 +0100
@@ -311,3 +311,12 @@
 70c89bd6b895a10d25ca70e08093c09ff2005fda hs25-b16
 1a3e54283c54aaa8b3437813e8507fbdc966e5b6 jdk8-b74
 b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17
+6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75
+20b605466ccb1b3725eb25314d9e8782199630c5 jdk8-b76
+412d722168bc23f8e6d98995202728678561417f hs25-b18
+cdb46031e7184d37301288f5719121a63c7054b5 jdk8-b77
+9f19f4a7d48a4ebe7f616b6068971ea5f8b075fa hs25-b19
+d5e12e7d2f719144d84903d9151455661c47b476 jdk8-b78
+555ec35a250783110aa070dbc8a8603f6cabe41f hs25-b20
+6691814929b606fe0e7954fd6e485dd876505c83 jdk8-b79
+df5396524152118535c36da5801d828b560d19a2 hs25-b21
--- a/GRAAL_AUTHORS	Thu Mar 21 11:30:38 2013 +0100
+++ b/GRAAL_AUTHORS	Thu Mar 21 14:11:13 2013 +0100
@@ -1,9 +1,12 @@
 Gilles Duboscq (gdub)
 Peter Hofer
+Christian Haeubl (chaeubl)
+Christian Humer (chumer)
+Roland Schatz
+Doug Simon (dnsimon)
+Lukas Stadler (lstadler)
 Alexander Stipsits
 Katrin Strassl
-Christian Humer (chumer)
 Christian Wimmer (cwimmer)
-Doug Simon (dnsimon)
-Lukas Stadler (lstadler)
+Andreas Woess (aw)
 Thomas Wuerthinger (thomaswue)
--- a/agent/make/Makefile	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/make/Makefile	Thu Mar 21 14:11:13 2013 +0100
@@ -19,7 +19,7 @@
 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 # or visit www.oracle.com if you need additional information or have any
 # questions.
-#  
+#
 #
 
 # This guards against adding broken .java files to the directory
@@ -42,8 +42,6 @@
 sun.jvm.hotspot \
 sun.jvm.hotspot.asm \
 sun.jvm.hotspot.asm.sparc \
-sun.jvm.hotspot.bugspot \
-sun.jvm.hotspot.bugspot.tree \
 sun.jvm.hotspot.c1 \
 sun.jvm.hotspot.ci \
 sun.jvm.hotspot.code \
@@ -84,7 +82,6 @@
 sun.jvm.hotspot.gc_interface \
 sun.jvm.hotspot.interpreter \
 sun.jvm.hotspot.jdi \
-sun.jvm.hotspot.livejvm \
 sun.jvm.hotspot.memory \
 sun.jvm.hotspot.opto \
 sun.jvm.hotspot.oops \
@@ -130,8 +127,6 @@
 sun/jvm/hotspot/*.java \
 sun/jvm/hotspot/asm/*.java \
 sun/jvm/hotspot/asm/sparc/*.java \
-sun/jvm/hotspot/bugspot/*.java \
-sun/jvm/hotspot/bugspot/tree/*.java \
 sun/jvm/hotspot/c1/*.java \
 sun/jvm/hotspot/ci/*.java \
 sun/jvm/hotspot/code/*.java \
@@ -168,7 +163,6 @@
 sun/jvm/hotspot/gc_implementation/shared/*.java \
 sun/jvm/hotspot/interpreter/*.java \
 sun/jvm/hotspot/jdi/*.java \
-sun/jvm/hotspot/livejvm/*.java \
 sun/jvm/hotspot/memory/*.java \
 sun/jvm/hotspot/oops/*.java \
 sun/jvm/hotspot/opto/*.java \
@@ -205,7 +199,7 @@
 sun/jvm/hotspot/utilities/memo/*.java \
 sun/jvm/hotspot/utilities/soql/*.java \
 com/sun/java/swing/action/*.java \
-com/sun/java/swing/ui/*.java 
+com/sun/java/swing/ui/*.java
 #END FILELIST
 
 ifneq "x$(ALT_BOOTDIR)" "x"
@@ -231,7 +225,7 @@
 OUTPUT_DIR = $(BUILD_DIR)/classes
 DOC_DIR    = $(BUILD_DIR)/doc
 
-# gnumake 3.78.1 does not accept the *s, 
+# gnumake 3.78.1 does not accept the *s,
 # so use the shell to expand them
 ALLFILES := $(patsubst %,$(SRC_DIR)/%,$(FILELIST))
 ALLFILES := $(shell /bin/ls $(ALLFILES))
@@ -303,7 +297,7 @@
 cscope: $(ALLFILES)
 	rm -f java.files
 	echo $(ALLFILES) > java.files
-	cscope -b -i java.files -f java.out 
+	cscope -b -i java.files -f java.out
 	rm -f java.files
 
 .PHONY: sa.jar
--- a/agent/make/bugspot.bat	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-REM
-REM Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
-REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-REM
-REM This code is free software; you can redistribute it and/or modify it
-REM under the terms of the GNU General Public License version 2 only, as
-REM published by the Free Software Foundation.
-REM
-REM This code is distributed in the hope that it will be useful, but WITHOUT
-REM ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-REM FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-REM version 2 for more details (a copy is included in the LICENSE file that
-REM accompanied this code).
-REM
-REM You should have received a copy of the GNU General Public License version
-REM 2 along with this work; if not, write to the Free Software Foundation,
-REM Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-REM
-REM Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-REM or visit www.oracle.com if you need additional information or have any
-REM questions.
-REM  
-REM
-
-java -showversion -cp ..\build\classes;..\src\share\lib\js.jar;.\sa.jar;lib\js.jar sun.jvm.hotspot.bugspot.Main
--- a/agent/make/marks_notes.html	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/make/marks_notes.html	Thu Mar 21 14:11:13 2013 +0100
@@ -26,14 +26,12 @@
 
     <ul>
       <li><code>java -cp classes sun.jvm.hotspot.HSDB</code>
-      <li><code>java -cp classes sun.jvm.hotspot.bugspot.Main</code>
     </ul>
 
     <h2>Feedback</h2>
     <p>
       Refactoring of package hierarchy. All user interface components should be in
-      the ui package. Perhaps: sun.jvm.hotspot.ui.hsdb.Main for the HSDB and
-      sun.jvm.hotspot.ui.bugspot.Main for BugSpot.
+      the ui package. Perhaps: sun.jvm.hotspot.ui.hsdb.Main for the HSDB.
     <p>
       The src\share\vm\agent area seems like a workspace so it should be organized like
       one. In particular, I'd like to suggest the following directory layout:<br>
@@ -47,7 +45,7 @@
     </ul>
 
     <p>
-      Seems like there is a lot of redundant functionality. Between the HSDB and BugSpot. Perhaps
+      Seems like there is a lot of redundant functionality. Perhaps
       this can be consolidated with a <code>javax.swing.Actions</code> architecture.
 
     <h2>Tasklist</h2>
@@ -55,11 +53,7 @@
     <p>
       <b>Stack memory pane</b>: 
       It's one of the more useful JVM debugging tools in the SA. However, it
-      doesn't support any interaction with the text; the Memory Panel in BugSpot
-      was written afterward (with help from Shannon) and implements proper
-      selection, scrolling, and drag-and-drop, but no annotations. I'm not sure how
-      to integrate the annotations with the JTable that's being used for the memory
-      view; if you have suggestions here please let me know.
+      doesn't support any interaction with the text.
     <p>
       <b>Integrations with the NetBeans architecture (plug in).</b> See the
       <a href="http://openide.netbeans.org">Netbeans Open APIs homepage</a>
--- a/agent/src/os/bsd/MacosxDebuggerLocal.m	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/os/bsd/MacosxDebuggerLocal.m	Thu Mar 21 14:11:13 2013 +0100
@@ -38,6 +38,8 @@
 #import <dlfcn.h>
 #import <limits.h>
 #import <errno.h>
+#import <sys/types.h>
+#import <sys/ptrace.h>
 
 jboolean debug = JNI_FALSE;
 
@@ -97,7 +99,8 @@
  * Method:    init0
  * Signature: ()V
  */
-JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
+JNIEXPORT void JNICALL 
+Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
   symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
   taskID = (*env)->GetFieldID(env, cls, "task", "J");
   CHECK_EXCEPTION;
@@ -108,7 +111,11 @@
  * Method:    lookupByName0
  * Signature: (Ljava/lang/String;Ljava/lang/String;)J
  */
-JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
+JNIEXPORT jlong JNICALL 
+Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(
+  JNIEnv *env, jobject this_obj, 
+  jstring objectName, jstring symbolName) 
+{
   jlong address = 0;
 
 JNF_COCOA_ENTER(env);
@@ -137,7 +144,11 @@
  * Method:    readBytesFromProcess0
  * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
  */
-JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
+JNIEXPORT jbyteArray JNICALL
+Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(
+  JNIEnv *env, jobject this_obj, 
+  jlong addr, jlong numBytes) 
+{
   if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
 
   // must allocate storage instead of using former parameter buf
@@ -209,12 +220,74 @@
   return array;
 }
 
+
 /*
- * Class:     sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal
+ * Lookup the thread_t that corresponds to the given thread_id.
+ * The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO
+ * and reading the m_ident_info.thread_id returned.
+ * The returned thread_t is the mach send right to the kernel port for the corresponding thread.
+ *
+ * We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self()
+ * in the VM, but that thread port is not valid for a remote debugger to access the thread.
+ */
+thread_t
+lookupThreadFromThreadId(task_t task, jlong thread_id) {
+  if (debug) {
+    printf("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
+  }
+  
+  thread_array_t thread_list = NULL;
+  mach_msg_type_number_t thread_list_count = 0;
+  thread_t result_thread = 0;
+  int i;
+  
+  // get the list of all the send rights
+  kern_return_t result = task_threads(task, &thread_list, &thread_list_count);
+  if (result != KERN_SUCCESS) {
+    if (debug) {
+      printf("task_threads returned 0x%x\n", result);
+    }
+    return 0;
+  }
+  
+  for(i = 0 ; i < thread_list_count; i++) {
+    thread_identifier_info_data_t m_ident_info;
+    mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
+
+    // get the THREAD_IDENTIFIER_INFO for the send right
+    result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count);
+    if (result != KERN_SUCCESS) {
+      if (debug) {
+        printf("thread_info returned 0x%x\n", result);
+      }
+      break;
+    }
+    
+    // if this is the one we're looking for, return the send right
+    if (thread_id == m_ident_info.thread_id)
+    {
+      result_thread = thread_list[i];
+      break;
+    }
+  }
+  
+  vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t));
+  vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count);
+  
+  return result_thread;
+}
+
+
+/*
+ * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
  * Method:    getThreadIntegerRegisterSet0
- * Signature: (I)[J
+ * Signature: (J)[J
  */
-JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(JNIEnv *env, jobject this_obj, jint lwp_id) {
+JNIEXPORT jlongArray JNICALL 
+Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(
+  JNIEnv *env, jobject this_obj, 
+  jlong thread_id) 
+{
   if (debug)
     printf("getThreadRegisterSet0 called\n");
 
@@ -226,8 +299,9 @@
   int i;
   jlongArray registerArray;
   jlong *primitiveArray;
+  task_t gTask = getTask(env, this_obj);
 
-  tid = lwp_id;
+  tid = lookupThreadFromThreadId(gTask, thread_id);
 
   result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count);
 
@@ -328,19 +402,21 @@
 }
 
 /*
- * Class:     sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal
+ * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
  * Method:    translateTID0
  * Signature: (I)I
  */
 JNIEXPORT jint JNICALL
-Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *env, jobject this_obj, jint tid) {
+Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(
+  JNIEnv *env, jobject this_obj, jint tid) 
+{
   if (debug)
     printf("translateTID0 called on tid = 0x%x\n", (int)tid);
 
   kern_return_t result;
   thread_t foreign_tid, usable_tid;
   mach_msg_type_name_t type;
-    
+  
   foreign_tid = tid;
     
   task_t gTask = getTask(env, this_obj);
@@ -356,19 +432,90 @@
   return (jint) usable_tid;
 }
 
+
+static bool ptrace_continue(pid_t pid, int signal) {
+  // pass the signal to the process so we don't swallow it
+  int res;
+  if ((res = ptrace(PT_CONTINUE, pid, (caddr_t)1, signal)) < 0) {
+    fprintf(stderr, "attach: ptrace(PT_CONTINUE, %d) failed with %d\n", pid, res);
+    return false;
+  }
+  return true;
+}
+
+// waits until the ATTACH has stopped the process
+// by signal SIGSTOP
+static bool ptrace_waitpid(pid_t pid) {
+  int ret;
+  int status;
+  while (true) {
+    // Wait for debuggee to stop.
+    ret = waitpid(pid, &status, 0);
+    if (ret >= 0) {
+      if (WIFSTOPPED(status)) {
+        // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP
+        // will still be pending and delivered when the process is DETACHED and the process
+        // will go to sleep.
+        if (WSTOPSIG(status) == SIGSTOP) {
+          // Debuggee stopped by SIGSTOP.
+          return true;
+        }
+        if (!ptrace_continue(pid, WSTOPSIG(status))) {
+          fprintf(stderr, "attach: Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
+          return false;
+        }
+      } else {
+        fprintf(stderr, "attach: waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
+        return false;
+      }
+    } else {
+      switch (errno) {
+        case EINTR:
+          continue;
+          break;
+        case ECHILD:
+          fprintf(stderr, "attach: waitpid() failed. Child process pid (%d) does not exist \n", pid);
+          break;
+        case EINVAL:
+          fprintf(stderr, "attach: waitpid() failed. Invalid options argument.\n");
+          break;
+        default:
+          fprintf(stderr, "attach: waitpid() failed. Unexpected error %d\n",errno);
+          break;
+      }
+      return false;
+    }
+  }
+}
+
+// attach to a process/thread specified by "pid"
+static bool ptrace_attach(pid_t pid) {
+  int res;
+  if ((res = ptrace(PT_ATTACH, pid, 0, 0)) < 0) {
+    fprintf(stderr, "ptrace(PT_ATTACH, %d) failed with %d\n", pid, res);
+    return false;
+  } else {
+    return ptrace_waitpid(pid);
+  }
+}
+
 /*
  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
  * Method:    attach0
  * Signature: (I)V
  */
-JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(JNIEnv *env, jobject this_obj, jint jpid) {
+JNIEXPORT void JNICALL 
+Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
+  JNIEnv *env, jobject this_obj, jint jpid) 
+{
 JNF_COCOA_ENTER(env);
   if (getenv("JAVA_SAPROC_DEBUG") != NULL)
     debug = JNI_TRUE;
   else
     debug = JNI_FALSE;
   if (debug) printf("attach0 called for jpid=%d\n", (int)jpid);
-
+  
+  // get the task from the pid
   kern_return_t result;
   task_t gTask = 0;
   result = task_for_pid(mach_task_self(), jpid, &gTask);
@@ -378,6 +525,13 @@
   }
   putTask(env, this_obj, gTask);
 
+  // use ptrace to stop the process
+  // on os x, ptrace only needs to be called on the process, not the individual threads
+  if (ptrace_attach(jpid) != true) {
+    mach_port_deallocate(mach_task_self(), gTask);
+    THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
+  }
+
   id symbolicator = nil;
   id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator");
   if (jrsSymbolicator != nil) {
@@ -401,11 +555,29 @@
  * Method:    detach0
  * Signature: ()V
  */
-JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(JNIEnv *env, jobject this_obj) {
+JNIEXPORT void JNICALL 
+Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
+  JNIEnv *env, jobject this_obj) 
+{
 JNF_COCOA_ENTER(env);
   if (debug) printf("detach0 called\n");
 
   task_t gTask = getTask(env, this_obj);
+
+  // detach from the ptraced process causing it to resume execution
+  int pid;
+  kern_return_t k_res;
+  k_res = pid_for_task(gTask, &pid);
+  if (k_res != KERN_SUCCESS) {
+    fprintf(stderr, "detach: pid_for_task(%d) failed (%d)\n", pid, k_res);
+  }
+  else {
+    int res = ptrace(PT_DETACH, pid, 0, 0);
+    if (res < 0) {
+      fprintf(stderr, "detach: ptrace(PT_DETACH, %d) failed (%d)\n", pid, res);
+    }
+  }
+  
   mach_port_deallocate(mach_task_self(), gTask);
   id symbolicator = getSymbolicator(env, this_obj);
   if (symbolicator != nil) {
@@ -419,10 +591,13 @@
  * Method:    load_library
  * Signature: (Ljava/lang/String;)L
  */
-JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIEnv * env,
-                                                                           jclass disclass,
-                                                                           jstring jrepath_s,
-                                                                           jstring libname_s) {
+JNIEXPORT jlong JNICALL
+Java_sun_jvm_hotspot_asm_Disassembler_load_1library(
+  JNIEnv * env, 
+  jclass disclass,
+  jstring jrepath_s,
+  jstring libname_s) 
+{
   uintptr_t func = 0;
   const char* error_message = NULL;
   const char* java_home;
@@ -533,13 +708,16 @@
  * Method:    decode
  * Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V
  */
-JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env,
-                                                                    jobject dis,
-                                                                    jobject visitor,
-                                                                    jlong startPc,
-                                                                    jbyteArray code,
-                                                                    jstring options_s,
-                                                                    jlong decode_instructions_virtual) {
+JNIEXPORT void JNICALL
+Java_sun_jvm_hotspot_asm_Disassembler_decode(
+   JNIEnv * env,
+   jobject dis,
+   jobject visitor,
+   jlong startPc,
+   jbyteArray code,
+   jstring options_s,
+   jlong decode_instructions_virtual) 
+{
   jboolean isCopy;
   jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy);
   jbyte* end = start + (*env)->GetArrayLength(env, code);
--- a/agent/src/os/bsd/libproc_impl.c	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/os/bsd/libproc_impl.c	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,6 +91,14 @@
    }
 }
 
+void print_error(const char* format,...) {
+  va_list alist;
+  va_start(alist, format);
+  fputs("ERROR: ", stderr);
+  vfprintf(stderr, format, alist);
+  va_end(alist);
+}
+
 bool is_debug() {
    return _libsaproc_debug;
 }
--- a/agent/src/os/bsd/libproc_impl.h	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/os/bsd/libproc_impl.h	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -107,6 +107,7 @@
 int pathmap_open(const char* name);
 
 void print_debug(const char* format,...);
+void print_error(const char* format,...);
 bool is_debug();
 
 typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid);
--- a/agent/src/os/bsd/ps_proc.c	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/os/bsd/ps_proc.c	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -129,42 +129,66 @@
   return (errno == 0)? true: false;
 }
 
+static bool ptrace_continue(pid_t pid, int signal) {
+  // pass the signal to the process so we don't swallow it
+  if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) {
+    print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid);
+    return false;
+  }
+  return true;
+}
+
+// waits until the ATTACH has stopped the process
+// by signal SIGSTOP
+static bool ptrace_waitpid(pid_t pid) {
+  int ret;
+  int status;
+  do {
+    // Wait for debuggee to stop.
+    ret = waitpid(pid, &status, 0);
+    if (ret >= 0) {
+      if (WIFSTOPPED(status)) {
+        // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP
+        // will still be pending and delivered when the process is DETACHED and the process
+        // will go to sleep.
+        if (WSTOPSIG(status) == SIGSTOP) {
+          // Debuggee stopped by SIGSTOP.
+          return true;
+        }
+        if (!ptrace_continue(pid, WSTOPSIG(status))) {
+          print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
+          return false;
+        }
+      } else {
+        print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
+        return false;
+      }
+    } else {
+      switch (errno) {
+        case EINTR:
+          continue;
+          break;
+        case ECHILD:
+          print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
+          break;
+        case EINVAL:
+          print_debug("waitpid() failed. Invalid options argument.\n");
+          break;
+        default:
+          print_debug("waitpid() failed. Unexpected error %d\n",errno);
+      }
+      return false;
+    }
+  } while(true);
+}
+
 // attach to a process/thread specified by "pid"
 static bool ptrace_attach(pid_t pid) {
   if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) {
     print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
     return false;
   } else {
-    int ret;
-    int status;
-    do {
-      // Wait for debuggee to stop.
-      ret = waitpid(pid, &status, 0);
-      if (ret >= 0) {
-        if (WIFSTOPPED(status)) {
-          // Debuggee stopped.
-          return true;
-        } else {
-          print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
-          return false;
-        }
-      } else {
-        switch (errno) {
-          case EINTR:
-            continue;
-            break;
-          case ECHILD:
-            print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
-            break;
-          case EINVAL:
-            print_debug("waitpid() failed. Invalid options argument.\n");
-            break;
-          default:
-            print_debug("waitpid() failed. Unexpected error %d\n",errno);
-        }
-        return false;
-      }
-    } while(true);
+    return ptrace_waitpid(pid);
   }
 }
 
--- a/agent/src/os/linux/LinuxDebuggerLocal.c	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/os/linux/LinuxDebuggerLocal.c	Thu Mar 21 14:11:13 2013 +0100
@@ -280,7 +280,7 @@
   return (err == PS_OK)? array : 0;
 }
 
-#if defined(i386) || defined(ia64) || defined(amd64) || defined(sparc) || defined(sparcv9)
+#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9)
 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0
   (JNIEnv *env, jobject this_obj, jint lwp_id) {
 
@@ -299,9 +299,6 @@
 #ifdef i386
 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
 #endif
-#ifdef ia64
-#define NPRGREG IA64_REG_COUNT
-#endif
 #ifdef amd64
 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
 #endif
@@ -336,13 +333,6 @@
 
 #endif /* i386 */
 
-#if ia64
-  regs = (*env)->GetLongArrayElements(env, array, &isCopy);
-  for (i = 0; i < NPRGREG; i++ ) {
-    regs[i] = 0xDEADDEAD;
-  }
-#endif /* ia64 */
-
 #ifdef amd64
 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
 
--- a/agent/src/os/linux/libproc.h	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/os/linux/libproc.h	Thu Mar 21 14:11:13 2013 +0100
@@ -79,14 +79,6 @@
 
 *************************************************************************************/
 
-#ifdef ia64
-struct user_regs_struct {
-/* copied from user.h which doesn't define this in a struct */
-
-#define IA64_REG_COUNT (EF_SIZE/8+32)   /* integer and fp regs */
-unsigned long   regs[IA64_REG_COUNT];     /* integer and fp regs */
-};
-#endif
 
 #if defined(sparc)  || defined(sparcv9)
 #define user_regs_struct  pt_regs
--- a/agent/src/os/linux/libproc_impl.c	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/os/linux/libproc_impl.c	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -92,6 +92,14 @@
    }
 }
 
+void print_error(const char* format,...) {
+  va_list alist;
+  va_start(alist, format);
+  fputs("ERROR: ", stderr);
+  vfprintf(stderr, format, alist);
+  va_end(alist);
+}
+
 bool is_debug() {
    return _libsaproc_debug;
 }
--- a/agent/src/os/linux/libproc_impl.h	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/os/linux/libproc_impl.h	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -105,6 +105,7 @@
 int pathmap_open(const char* name);
 
 void print_debug(const char* format,...);
+void print_error(const char* format,...);
 bool is_debug();
 
 typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid);
--- a/agent/src/os/linux/ps_proc.c	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/os/linux/ps_proc.c	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <signal.h>
 #include <errno.h>
 #include <sys/ptrace.h>
 #include "libproc_impl.h"
@@ -142,46 +143,71 @@
 
 }
 
+static bool ptrace_continue(pid_t pid, int signal) {
+  // pass the signal to the process so we don't swallow it
+  if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) {
+    print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid);
+    return false;
+  }
+  return true;
+}
+
+// waits until the ATTACH has stopped the process
+// by signal SIGSTOP
+static bool ptrace_waitpid(pid_t pid) {
+  int ret;
+  int status;
+  while (true) {
+    // Wait for debuggee to stop.
+    ret = waitpid(pid, &status, 0);
+    if (ret == -1 && errno == ECHILD) {
+      // try cloned process.
+      ret = waitpid(pid, &status, __WALL);
+    }
+    if (ret >= 0) {
+      if (WIFSTOPPED(status)) {
+        // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP
+        // will still be pending and delivered when the process is DETACHED and the process
+        // will go to sleep.
+        if (WSTOPSIG(status) == SIGSTOP) {
+          // Debuggee stopped by SIGSTOP.
+          return true;
+        }
+        if (!ptrace_continue(pid, WSTOPSIG(status))) {
+          print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
+          return false;
+        }
+      } else {
+        print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
+        return false;
+      }
+    } else {
+      switch (errno) {
+        case EINTR:
+          continue;
+          break;
+        case ECHILD:
+          print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
+          break;
+        case EINVAL:
+          print_debug("waitpid() failed. Invalid options argument.\n");
+          break;
+        default:
+          print_debug("waitpid() failed. Unexpected error %d\n",errno);
+          break;
+      }
+      return false;
+    }
+  }
+}
+
 // attach to a process/thread specified by "pid"
 static bool ptrace_attach(pid_t pid) {
   if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
     print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
     return false;
   } else {
-    int ret;
-    int status;
-    do {
-      // Wait for debuggee to stop.
-      ret = waitpid(pid, &status, 0);
-      if (ret == -1 && errno == ECHILD) {
-        // try cloned process.
-        ret = waitpid(pid, &status, __WALL);
-      }
-      if (ret >= 0) {
-        if (WIFSTOPPED(status)) {
-          // Debuggee stopped.
-          return true;
-        } else {
-          print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
-          return false;
-        }
-      } else {
-        switch (errno) {
-          case EINTR:
-            continue;
-            break;
-          case ECHILD:
-            print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
-            break;
-          case EINVAL:
-            print_debug("waitpid() failed. Invalid options argument.\n");
-            break;
-          default:
-            print_debug("waitpid() failed. Unexpected error %d\n",errno);
-        }
-        return false;
-      }
-    } while(true);
+    return ptrace_waitpid(pid);
   }
 }
 
--- a/agent/src/os/win32/windbg/sawindbg.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/os/win32/windbg/sawindbg.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -27,10 +27,7 @@
 
 #include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h"
 
-#ifdef _M_IA64
-  #include "sun_jvm_hotspot_debugger_ia64_IA64ThreadContext.h"
-  #define NPRGREG sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_NPRGREG
-#elif _M_IX86
+#ifdef _M_IX86
   #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"
   #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
 #elif _M_AMD64
@@ -375,8 +372,7 @@
 
      We are attaching to a process in 'read-only' mode. i.e., we do not want to
      put breakpoints, suspend/resume threads etc. For read-only JDI and HSDB kind of
-     usage this should suffice. We are not intending to use this for full-fledged
-     ProcessControl implementation to be used with BugSpotAgent.
+     usage this should suffice.
 
      Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h.
      In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not
@@ -491,92 +487,7 @@
      memset(&context, 0, sizeof(CONTEXT));
 
 #undef REG_INDEX
-#ifdef _M_IA64
-     #define REG_INDEX(x) sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_##x
-
-     context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG;
-     ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT));
-
-     ptrRegs[REG_INDEX(GR0)]  = 0; // always 0
-     ptrRegs[REG_INDEX(GR1)]  = context.IntGp;  // r1
-     ptrRegs[REG_INDEX(GR2)]  = context.IntT0;  // r2-r3
-     ptrRegs[REG_INDEX(GR3)]  = context.IntT1;
-     ptrRegs[REG_INDEX(GR4)]  = context.IntS0;  // r4-r7
-     ptrRegs[REG_INDEX(GR5)]  = context.IntS1;
-     ptrRegs[REG_INDEX(GR6)]  = context.IntS2;
-     ptrRegs[REG_INDEX(GR7)]  = context.IntS3;
-     ptrRegs[REG_INDEX(GR8)]  = context.IntV0;  // r8
-     ptrRegs[REG_INDEX(GR9)]  = context.IntT2;  // r9-r11
-     ptrRegs[REG_INDEX(GR10)] = context.IntT3;
-     ptrRegs[REG_INDEX(GR11)] = context.IntT4;
-     ptrRegs[REG_INDEX(GR12)] = context.IntSp;  // r12 stack pointer
-     ptrRegs[REG_INDEX(GR13)] = context.IntTeb; // r13 teb
-     ptrRegs[REG_INDEX(GR14)] = context.IntT5;  // r14-r31
-     ptrRegs[REG_INDEX(GR15)] = context.IntT6;
-     ptrRegs[REG_INDEX(GR16)] = context.IntT7;
-     ptrRegs[REG_INDEX(GR17)] = context.IntT8;
-     ptrRegs[REG_INDEX(GR18)] = context.IntT9;
-     ptrRegs[REG_INDEX(GR19)] = context.IntT10;
-     ptrRegs[REG_INDEX(GR20)] = context.IntT11;
-     ptrRegs[REG_INDEX(GR21)] = context.IntT12;
-     ptrRegs[REG_INDEX(GR22)] = context.IntT13;
-     ptrRegs[REG_INDEX(GR23)] = context.IntT14;
-     ptrRegs[REG_INDEX(GR24)] = context.IntT15;
-     ptrRegs[REG_INDEX(GR25)] = context.IntT16;
-     ptrRegs[REG_INDEX(GR26)] = context.IntT17;
-     ptrRegs[REG_INDEX(GR27)] = context.IntT18;
-     ptrRegs[REG_INDEX(GR28)] = context.IntT19;
-     ptrRegs[REG_INDEX(GR29)] = context.IntT20;
-     ptrRegs[REG_INDEX(GR30)] = context.IntT21;
-     ptrRegs[REG_INDEX(GR31)] = context.IntT22;
-
-     ptrRegs[REG_INDEX(INT_NATS)] = context.IntNats;
-     ptrRegs[REG_INDEX(PREDS)]    = context.Preds;
-
-     ptrRegs[REG_INDEX(BR_RP)] = context.BrRp;
-     ptrRegs[REG_INDEX(BR1)]   = context.BrS0;  // b1-b5
-     ptrRegs[REG_INDEX(BR2)]   = context.BrS1;
-     ptrRegs[REG_INDEX(BR3)]   = context.BrS2;
-     ptrRegs[REG_INDEX(BR4)]   = context.BrS3;
-     ptrRegs[REG_INDEX(BR5)]   = context.BrS4;
-     ptrRegs[REG_INDEX(BR6)]   = context.BrT0;  // b6-b7
-     ptrRegs[REG_INDEX(BR7)]   = context.BrT1;
-
-     ptrRegs[REG_INDEX(AP_UNAT)] = context.ApUNAT;
-     ptrRegs[REG_INDEX(AP_LC)]   = context.ApLC;
-     ptrRegs[REG_INDEX(AP_EC)]   = context.ApEC;
-     ptrRegs[REG_INDEX(AP_CCV)]  = context.ApCCV;
-     ptrRegs[REG_INDEX(AP_DCR)]  = context.ApDCR;
-
-     ptrRegs[REG_INDEX(RS_PFS)]      = context.RsPFS;
-     ptrRegs[REG_INDEX(RS_BSP)]      = context.RsBSP;
-     ptrRegs[REG_INDEX(RS_BSPSTORE)] = context.RsBSPSTORE;
-     ptrRegs[REG_INDEX(RS_RSC)]      = context.RsRSC;
-     ptrRegs[REG_INDEX(RS_RNAT)]     = context.RsRNAT;
-
-     ptrRegs[REG_INDEX(ST_IPSR)] = context.StIPSR;
-     ptrRegs[REG_INDEX(ST_IIP)]  = context.StIIP;
-     ptrRegs[REG_INDEX(ST_IFS)]  = context.StIFS;
-
-     ptrRegs[REG_INDEX(DB_I0)] = context.DbI0;
-     ptrRegs[REG_INDEX(DB_I1)] = context.DbI1;
-     ptrRegs[REG_INDEX(DB_I2)] = context.DbI2;
-     ptrRegs[REG_INDEX(DB_I3)] = context.DbI3;
-     ptrRegs[REG_INDEX(DB_I4)] = context.DbI4;
-     ptrRegs[REG_INDEX(DB_I5)] = context.DbI5;
-     ptrRegs[REG_INDEX(DB_I6)] = context.DbI6;
-     ptrRegs[REG_INDEX(DB_I7)] = context.DbI7;
-
-     ptrRegs[REG_INDEX(DB_D0)] = context.DbD0;
-     ptrRegs[REG_INDEX(DB_D1)] = context.DbD1;
-     ptrRegs[REG_INDEX(DB_D2)] = context.DbD2;
-     ptrRegs[REG_INDEX(DB_D3)] = context.DbD3;
-     ptrRegs[REG_INDEX(DB_D4)] = context.DbD4;
-     ptrRegs[REG_INDEX(DB_D5)] = context.DbD5;
-     ptrRegs[REG_INDEX(DB_D6)] = context.DbD6;
-     ptrRegs[REG_INDEX(DB_D7)] = context.DbD7;
-
-#elif _M_IX86
+#ifdef _M_IX86
      #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x
 
      context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
--- a/agent/src/share/classes/sun/jvm/hotspot/asm/amd64/AMD64FloatRegister.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.asm.amd64;
-
-import sun.jvm.hotspot.asm.Register;
-import sun.jvm.hotspot.utilities.Assert;
-
-public class AMD64FloatRegister extends Register {
-
-   public AMD64FloatRegister(int number) {
-      super(number);
-   }
-
-   public int getNumber() {
-      return number;
-   }
-
-   public int getNumberOfRegisters() {
-      return AMD64FloatRegisters.getNumRegisters();
-   }
-
-   public boolean isFloat() {
-      return true;
-   }
-
-   public boolean isFramePointer() {
-      return false;
-   }
-
-   public boolean isStackPointer() {
-      return false;
-   }
-
-   public boolean isValid() {
-      return number >= 0 && number < AMD64FloatRegisters.getNumRegisters();
-   }
-
-   public String toString() {
-      return AMD64FloatRegisters.getRegisterName(number);
-   }
-
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1536 +0,0 @@
-/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import javax.swing.*;
-import javax.swing.filechooser.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.debugger.posix.*;
-import sun.jvm.hotspot.debugger.windbg.*;
-import sun.jvm.hotspot.livejvm.*;
-import sun.jvm.hotspot.memory.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.ui.*;
-import sun.jvm.hotspot.utilities.*;
-
-/** The BugSpot component. This is embeddable in an application by
-    virtue of its being a JComponent. It (currently) requires the use
-    of a menu bar which can be fetched via getMenuBar(). This is
-    intended ultimately to replace HSDB. */
-
-public class BugSpot extends JPanel {
-  public BugSpot() {
-    super();
-    Runtime.getRuntime().addShutdownHook(new java.lang.Thread() {
-        public void run() {
-          detachDebugger();
-        }
-      });
-  }
-
-  /** Turn on or off MDI (Multiple Document Interface) mode. When MDI
-      is enabled, the BugSpot component contains a JDesktopPane and all
-      windows are JInternalFrames. When disabled, only the menu bar is
-      relevant. */
-  public void setMDIMode(boolean onOrOff) {
-    mdiMode = onOrOff;
-  }
-
-  /** Indicates whether MDI mode is enabled. */
-  public boolean getMDIMode() {
-    return mdiMode;
-  }
-
-  /** Build user interface widgets. This must be called before adding
-      the BugSpot component to its parent. */
-  public void build() {
-    setLayout(new BorderLayout());
-
-    menuBar = new JMenuBar();
-
-    attachMenuItems = new java.util.ArrayList();
-    detachMenuItems = new java.util.ArrayList();
-    debugMenuItems  = new java.util.ArrayList();
-    suspendDebugMenuItems = new java.util.ArrayList();
-    resumeDebugMenuItems = new java.util.ArrayList();
-
-    //
-    // File menu
-    //
-
-    JMenu menu = createMenu("File", 'F', 0);
-    JMenuItem item;
-    item = createMenuItem("Open source file...",
-                          new ActionListener() {
-                              public void actionPerformed(ActionEvent e) {
-                                openSourceFile();
-                              }
-                            },
-                          KeyEvent.VK_O, InputEvent.CTRL_MASK,
-                          'O', 0);
-    menu.add(item);
-    detachMenuItems.add(item);
-
-    menu.addSeparator();
-
-    item = createMenuItem("Attach to process...",
-                          new ActionListener() {
-                              public void actionPerformed(ActionEvent e) {
-                                showAttachDialog();
-                              }
-                            },
-                          'A', 0);
-    menu.add(item);
-    attachMenuItems.add(item);
-
-    item = createMenuItem("Detach",
-                          new ActionListener() {
-                              public void actionPerformed(ActionEvent e) {
-                                detach();
-                              }
-                            },
-                          'D', 0);
-    menu.add(item);
-    detachMenuItems.add(item);
-
-    // Disable detach menu items at first
-    setMenuItemsEnabled(detachMenuItems, false);
-
-    menu.addSeparator();
-
-    menu.add(createMenuItem("Exit",
-                            new ActionListener() {
-                                public void actionPerformed(ActionEvent e) {
-                                  detach();
-                                  System.exit(0);
-                                }
-                              },
-                            'x', 1));
-
-    menuBar.add(menu);
-
-    //
-    // Debug menu
-    //
-
-    debugMenu = createMenu("Debug", 'D', 0);
-    item = createMenuItem("Go",
-                          new ActionListener() {
-                              public void actionPerformed(ActionEvent e) {
-                                if (!attached) return;
-                                if (!isSuspended()) return;
-                                resume();
-                              }
-                            },
-                          KeyEvent.VK_F5, 0,
-                          'G', 0);
-    debugMenu.add(item);
-    resumeDebugMenuItems.add(item);
-
-    item = createMenuItem("Break",
-                          new ActionListener() {
-                              public void actionPerformed(ActionEvent e) {
-                                if (!attached) {
-                                  System.err.println("Not attached");
-                                  return;
-                                }
-                                if (isSuspended()) {
-                                  System.err.println("Already suspended");
-                                  return;
-                                }
-                                suspend();
-                              }
-                            },
-                          'B', 0);
-    debugMenu.add(item);
-    suspendDebugMenuItems.add(item);
-
-    debugMenu.addSeparator();
-
-    item = createMenuItem("Threads...",
-                          new ActionListener() {
-                              public void actionPerformed(ActionEvent e) {
-                                showThreadsDialog();
-                              }
-                            },
-                          'T', 0);
-    debugMenu.add(item);
-    debugMenuItems.add(item);
-    // FIXME: belongs under "View -> Debug Windows"
-    item = createMenuItem("Memory",
-                          new ActionListener() {
-                              public void actionPerformed(ActionEvent e) {
-                                showMemoryDialog();
-                              }
-                            },
-                          'M', 0);
-    debugMenu.add(item);
-    debugMenuItems.add(item);
-
-    debugMenu.setEnabled(false);
-    menuBar.add(debugMenu);
-
-    if (mdiMode) {
-      desktop = new JDesktopPane();
-      add(desktop, BorderLayout.CENTER);
-    }
-
-    fixedWidthFont = GraphicsUtilities.lookupFont("Courier");
-
-    debugEventTimer = new javax.swing.Timer(100, new ActionListener() {
-        public void actionPerformed(ActionEvent e) {
-          pollForDebugEvent();
-        }
-      });
-  }
-
-  public JMenuBar getMenuBar() {
-    return menuBar;
-  }
-
-  public void showAttachDialog() {
-    setMenuItemsEnabled(attachMenuItems, false);
-    final FrameWrapper attachDialog = newFrame("Attach to process");
-    attachDialog.getContentPane().setLayout(new BorderLayout());
-    attachDialog.setClosable(true);
-    attachDialog.setResizable(true);
-
-    JPanel panel = new JPanel();
-    panel.setLayout(new BorderLayout());
-    panel.setBorder(GraphicsUtilities.newBorder(5));
-    attachDialog.setBackground(panel.getBackground());
-
-    JPanel listPanel = new JPanel();
-    listPanel.setLayout(new BorderLayout());
-    final ProcessListPanel plist = new ProcessListPanel(getLocalDebugger());
-    panel.add(plist, BorderLayout.CENTER);
-    JCheckBox check = new JCheckBox("Update list continuously");
-    check.addItemListener(new ItemListener() {
-        public void itemStateChanged(ItemEvent e) {
-          if (e.getStateChange() == ItemEvent.SELECTED) {
-            plist.start();
-          } else {
-            plist.stop();
-          }
-        }
-      });
-    listPanel.add(plist, BorderLayout.CENTER);
-    listPanel.add(check, BorderLayout.SOUTH);
-    panel.add(listPanel, BorderLayout.CENTER);
-    attachDialog.getContentPane().add(panel, BorderLayout.CENTER);
-    attachDialog.setClosingActionListener(new ActionListener() {
-        public void actionPerformed(ActionEvent e) {
-          plist.stop();
-          setMenuItemsEnabled(attachMenuItems, true);
-        }
-      });
-
-    ActionListener attacher = new ActionListener() {
-        public void actionPerformed(ActionEvent e) {
-          plist.stop();
-          attachDialog.setVisible(false);
-          removeFrame(attachDialog);
-          ProcessInfo info = plist.getSelectedProcess();
-          if (info != null) {
-            attach(info.getPid());
-          }
-        }
-      };
-
-    Box hbox = Box.createHorizontalBox();
-    hbox.add(Box.createGlue());
-    JButton button = new JButton("OK");
-    button.addActionListener(attacher);
-    hbox.add(button);
-    hbox.add(Box.createHorizontalStrut(20));
-    button = new JButton("Cancel");
-    button.addActionListener(new ActionListener() {
-        public void actionPerformed(ActionEvent e) {
-          plist.stop();
-          attachDialog.setVisible(false);
-          removeFrame(attachDialog);
-          setMenuItemsEnabled(attachMenuItems, true);
-        }
-      });
-    hbox.add(button);
-    hbox.add(Box.createGlue());
-    panel = new JPanel();
-    panel.setBorder(GraphicsUtilities.newBorder(5));
-    panel.add(hbox);
-
-    attachDialog.getContentPane().add(panel, BorderLayout.SOUTH);
-
-    addFrame(attachDialog);
-    attachDialog.pack();
-    attachDialog.setSize(400, 300);
-    GraphicsUtilities.centerInContainer(attachDialog.getComponent(),
-                                        getParentDimension(attachDialog.getComponent()));
-    attachDialog.setVisible(true);
-  }
-
-  public void showThreadsDialog() {
-    final FrameWrapper threadsDialog = newFrame("Threads");
-    threadsDialog.getContentPane().setLayout(new BorderLayout());
-    threadsDialog.setClosable(true);
-    threadsDialog.setResizable(true);
-
-    ThreadListPanel threads = new ThreadListPanel(getCDebugger(), getAgent().isJavaMode());
-    threads.addListener(new ThreadListPanel.Listener() {
-        public void setFocus(ThreadProxy thread, JavaThread jthread) {
-          setCurrentThread(thread);
-          // FIXME: print this to GUI, bring some windows to foreground
-          System.err.println("Focus changed to thread " + thread);
-        }
-      });
-    threads.setBorder(GraphicsUtilities.newBorder(5));
-    threadsDialog.getContentPane().add(threads);
-    addFrame(threadsDialog);
-    threadsDialog.pack();
-    GraphicsUtilities.reshapeToAspectRatio(threadsDialog.getComponent(),
-                                           3.0f,
-                                           0.9f,
-                                           getParentDimension(threadsDialog.getComponent()));
-    GraphicsUtilities.centerInContainer(threadsDialog.getComponent(),
-                                        getParentDimension(threadsDialog.getComponent()));
-    threadsDialog.setVisible(true);
-  }
-
-  public void showMemoryDialog() {
-    final FrameWrapper memoryDialog = newFrame("Memory");
-    memoryDialog.getContentPane().setLayout(new BorderLayout());
-    memoryDialog.setClosable(true);
-    memoryDialog.setResizable(true);
-
-    memoryDialog.getContentPane().add(new MemoryViewer(getDebugger(),
-                                                       (getDebugger().getMachineDescription().getAddressSize() == 8)),
-                                      BorderLayout.CENTER);
-    addFrame(memoryDialog);
-    memoryDialog.pack();
-    GraphicsUtilities.reshapeToAspectRatio(memoryDialog.getComponent(),
-                                           1.0f,
-                                           0.7f,
-                                           getParentDimension(memoryDialog.getComponent()));
-    GraphicsUtilities.centerInContainer(memoryDialog.getComponent(),
-                                        getParentDimension(memoryDialog.getComponent()));
-    memoryDialog.setVisible(true);
-  }
-
-  /** Changes the editor factory this debugger uses to display source
-      code. Specified factory may be null, in which case the default
-      factory is used. */
-  public void setEditorFactory(EditorFactory fact) {
-    if (fact != null) {
-      editorFact = fact;
-    } else {
-      editorFact = new DefaultEditorFactory();
-    }
-  }
-
-  //----------------------------------------------------------------------
-  // Internals only below this point
-  //
-
-  private WorkerThread    workerThread;
-  private boolean         mdiMode;
-  private JVMDebugger     localDebugger;
-  private BugSpotAgent    agent = new BugSpotAgent();
-  private JMenuBar        menuBar;
-  /** List <JMenuItem> */
-  private java.util.List  attachMenuItems;
-  private java.util.List  detachMenuItems;
-  private java.util.List  debugMenuItems;
-  private java.util.List  suspendDebugMenuItems;
-  private java.util.List  resumeDebugMenuItems;
-  private FrameWrapper    stackFrame;
-  private VariablePanel   localsPanel;
-  private StackTracePanel stackTracePanel;
-  private FrameWrapper    registerFrame;
-  private RegisterPanel   registerPanel;
-  // Used for mixed-language stack traces
-  private Map             threadToJavaThreadMap;
-
-  private JMenu debugMenu;
-
-  // MDI mode only: desktop pane
-  private JDesktopPane desktop;
-
-  // Attach/detach state
-  private boolean attached;
-
-  // Suspension (combined Java/C++) state
-  private boolean suspended;
-
-  // Fixed-width font
-  private Font fixedWidthFont;
-
-  // Breakpoint setting
-  // Maps Strings to List/*<LineNumberInfo>*/
-  private Map sourceFileToLineNumberInfoMap;
-  // Maps Strings (file names) to Sets of Integers (line numbers)
-  private Map fileToBreakpointMap;
-
-  // Debug events
-  private javax.swing.Timer debugEventTimer;
-
-  // Java debug events
-  private boolean javaEventPending;
-
-  static class BreakpointResult {
-    private boolean success;
-    private boolean set;
-    private int lineNo;
-    private String why;
-
-    /** For positive results */
-    BreakpointResult(boolean success, boolean set, int lineNo) {
-      this(success, set, lineNo, null);
-    }
-
-    /** For negative results */
-    BreakpointResult(boolean success, boolean set, int lineNo, String why) {
-      this.success = success;
-      this.set = set;
-      this.lineNo = lineNo;
-      this.why = why;
-    }
-
-    public boolean succeeded() {
-      return success;
-    }
-
-    public boolean set() {
-      return set;
-    }
-
-    /** Line at which the breakpoint was actually set; only valid if
-        succeeded() returns true */
-    public int getLine() {
-      return lineNo;
-    }
-
-    public String getWhy() {
-      return why;
-    }
-  }
-
-
-  // Editors for source code. File name-to-Editor mapping.
-  private Map editors;
-  private EditorFactory editorFact = new DefaultEditorFactory();
-  private EditorCommands editorComm = new EditorCommands() {
-      public void windowClosed(Editor editor) {
-        editors.remove(editor.getSourceFileName());
-      }
-
-      public void toggleBreakpointAtLine(Editor editor, int lineNumber) {
-        // FIXME: handle "lazy" breakpoints where the source file has
-        // been opened with some other mechanism (File -> Open) and we
-        // don't have debug information pointing to that file yet
-        // FIXME: NOT FINISHED
-
-        BreakpointResult res =
-          handleBreakpointToggle(editor, lineNumber);
-        if (res.succeeded()) {
-          if (res.set()) {
-            editor.showBreakpointAtLine(res.getLine());
-          } else {
-            editor.clearBreakpointAtLine(res.getLine());
-          }
-        } else {
-          String why = res.getWhy();
-          if (why == null) {
-            why = "";
-          } else {
-            why = ": " + why;
-          }
-          showMessageDialog("Unable to toggle breakpoint" + why,
-                            "Unable to toggle breakpoint",
-                            JOptionPane.WARNING_MESSAGE);
-        }
-      }
-    };
-
-  private void attach(final int pid) {
-    try {
-      getAgent().attach(pid);
-      setMenuItemsEnabled(detachMenuItems, true);
-      setMenuItemsEnabled(suspendDebugMenuItems, false);
-      setMenuItemsEnabled(resumeDebugMenuItems, true);
-      debugMenu.setEnabled(true);
-      attached = true;
-      suspended = true;
-
-      if (getAgent().isJavaMode()) {
-        System.err.println("Java HotSpot(TM) virtual machine detected.");
-      } else {
-        System.err.println("(No Java(TM) virtual machine detected)");
-      }
-
-      // Set up editor map
-      editors = new HashMap();
-
-      // Initialize breakpoints
-      fileToBreakpointMap = new HashMap();
-
-      // Create combined stack trace and local variable panel
-      JPanel framePanel = new JPanel();
-      framePanel.setLayout(new BorderLayout());
-      framePanel.setBorder(GraphicsUtilities.newBorder(5));
-      localsPanel = new VariablePanel();
-      JTabbedPane tab = new JTabbedPane();
-      tab.addTab("Locals", localsPanel);
-      tab.setTabPlacement(JTabbedPane.BOTTOM);
-      framePanel.add(tab, BorderLayout.CENTER);
-      JPanel stackPanel = new JPanel();
-      stackPanel.setLayout(new BoxLayout(stackPanel, BoxLayout.X_AXIS));
-      stackPanel.add(new JLabel("Context:"));
-      stackPanel.add(Box.createHorizontalStrut(5));
-      stackTracePanel = new StackTracePanel();
-      stackTracePanel.addListener(new StackTracePanel.Listener() {
-          public void frameChanged(CFrame fr, JavaVFrame jfr) {
-            setCurrentFrame(fr, jfr);
-          }
-        });
-      stackPanel.add(stackTracePanel);
-      framePanel.add(stackPanel, BorderLayout.NORTH);
-      stackFrame = newFrame("Stack");
-      stackFrame.getContentPane().setLayout(new BorderLayout());
-      stackFrame.getContentPane().add(framePanel, BorderLayout.CENTER);
-      stackFrame.setResizable(true);
-      stackFrame.setClosable(false);
-      addFrame(stackFrame);
-      stackFrame.setSize(400, 200);
-      GraphicsUtilities.moveToInContainer(stackFrame.getComponent(), 0.0f, 1.0f, 0, 20);
-      stackFrame.setVisible(true);
-
-      // Create register panel
-      registerPanel = new RegisterPanel();
-      registerPanel.setFont(fixedWidthFont);
-      registerFrame = newFrame("Registers");
-      registerFrame.getContentPane().setLayout(new BorderLayout());
-      registerFrame.getContentPane().add(registerPanel, BorderLayout.CENTER);
-      addFrame(registerFrame);
-      registerFrame.setResizable(true);
-      registerFrame.setClosable(false);
-      registerFrame.setSize(225, 200);
-      GraphicsUtilities.moveToInContainer(registerFrame.getComponent(),
-                                          1.0f, 0.0f, 0, 0);
-      registerFrame.setVisible(true);
-
-      resetCurrentThread();
-    } catch (DebuggerException e) {
-      final String errMsg = formatMessage(e.getMessage(), 80);
-      setMenuItemsEnabled(attachMenuItems, true);
-      showMessageDialog("Unable to connect to process ID " + pid + ":\n\n" + errMsg,
-                        "Unable to Connect",
-                        JOptionPane.WARNING_MESSAGE);
-      getAgent().detach();
-    }
-  }
-
-  private synchronized void detachDebugger() {
-    if (!attached) {
-      return;
-    }
-    if (isSuspended()) {
-      resume(); // Necessary for JVMDI resumption
-    }
-    getAgent().detach();
-    // FIXME: clear out breakpoints (both Java and C/C++) from target
-    // process
-    sourceFileToLineNumberInfoMap = null;
-    fileToBreakpointMap = null;
-    threadToJavaThreadMap = null;
-    editors = null;
-    attached = false;
-  }
-
-  private synchronized void detach() {
-    detachDebugger();
-    setMenuItemsEnabled(attachMenuItems, true);
-    setMenuItemsEnabled(detachMenuItems, false);
-    debugMenu.setEnabled(false);
-    if (mdiMode) {
-      // FIXME: is this sufficient, or will I have to do anything else
-      // to the components to kill them off? What about WorkerThreads?
-      desktop.removeAll();
-      desktop.invalidate();
-      desktop.validate();
-      desktop.repaint();
-    }
-    // FIXME: keep track of all windows and close them even in non-MDI
-    // mode
-    debugEventTimer.stop();
-  }
-
-  // Returns a Debugger for processes on the local machine. This is
-  // only used to fetch the process list.
-  private Debugger getLocalDebugger() {
-    if (localDebugger == null) {
-      String os  = PlatformInfo.getOS();
-      String cpu = PlatformInfo.getCPU();
-
-      if (os.equals("win32")) {
-        if (!cpu.equals("x86")) {
-          throw new DebuggerException("Unsupported CPU \"" + cpu + "\" for Windows");
-        }
-
-        localDebugger = new WindbgDebuggerLocal(new MachineDescriptionIntelX86(), true);
-      } else if (os.equals("linux")) {
-        if (!cpu.equals("x86")) {
-          throw new DebuggerException("Unsupported CPU \"" + cpu + "\" for Linux");
-        }
-
-        // FIXME: figure out how to specify path to debugger module
-        throw new RuntimeException("FIXME: figure out how to specify path to debugger module");
-        //        localDebugger = new PosixDebuggerLocal(new MachineDescriptionIntelX86(), true);
-      } else {
-        // FIXME: port to Solaris
-        throw new DebuggerException("Unsupported OS \"" + os + "\"");
-      }
-
-      // FIXME: we require that the primitive type sizes be configured
-      // in order to use basic functionality in class Address such as
-      // the fetching of floating-point values. There are a lot of
-      // assumptions in the current code that Java floats and doubles
-      // are of equivalent size to C values. The configurability of the
-      // primitive type sizes hasn't seemed necessary and in this kind
-      // of debugging scenario (namely, debugging arbitrary C++
-      // processes) it appears difficult to support that kind of
-      // flexibility.
-      localDebugger.configureJavaPrimitiveTypeSizes(1, 1, 2, 8, 4, 4, 8, 2);
-    }
-
-    return localDebugger;
-  }
-
-  private BugSpotAgent getAgent() {
-    return agent;
-  }
-
-  private Debugger getDebugger() {
-    return getAgent().getDebugger();
-  }
-
-  private CDebugger getCDebugger() {
-    return getAgent().getCDebugger();
-  }
-
-  private void resetCurrentThread() {
-    setCurrentThread((ThreadProxy) getCDebugger().getThreadList().get(0));
-  }
-
-  private void setCurrentThread(ThreadProxy t) {
-    // Create stack trace
-    // FIXME: add ability to intermix C/Java frames
-    java.util.List trace = new ArrayList();
-    CFrame fr = getCDebugger().topFrameForThread(t);
-    while (fr != null) {
-      trace.add(new StackTraceEntry(fr, getCDebugger()));
-      try {
-        fr = fr.sender(t);
-      } catch (AddressException e) {
-        e.printStackTrace();
-        showMessageDialog("Error while walking stack; stack trace will be truncated\n(see console for details)",
-                          "Error walking stack",
-                          JOptionPane.WARNING_MESSAGE);
-        fr = null;
-      }
-    }
-    JavaThread jthread = javaThreadForProxy(t);
-    if (jthread != null) {
-      // Java mode, and we have a Java thread.
-      // Find all Java frames on the stack. We currently do this in a
-      // manner which involves minimal interaction between the Java
-      // and C/C++ debugging systems: any C frame which has a PC in an
-      // unknown location (i.e., not in any DSO) is assumed to be a
-      // Java frame. We merge stack segments of unknown frames with
-      // segments of Java frames beginning with native methods.
-      java.util.List javaTrace = new ArrayList();
-      VFrame vf = jthread.getLastJavaVFrameDbg();
-      while (vf != null) {
-        if (vf.isJavaFrame()) {
-          javaTrace.add(new StackTraceEntry((JavaVFrame) vf));
-          vf = vf.sender();
-        }
-      }
-      // Merge stack traces
-      java.util.List mergedTrace = new ArrayList();
-      int c = 0;
-      int j = 0;
-      while (c < trace.size()) {
-        StackTraceEntry entry = (StackTraceEntry) trace.get(c);
-        if (entry.isUnknownCFrame()) {
-          boolean gotJavaFrame = false;
-          while (j < javaTrace.size()) {
-            StackTraceEntry javaEntry = (StackTraceEntry) javaTrace.get(j);
-            JavaVFrame jvf = javaEntry.getJavaFrame();
-            Method m = jvf.getMethod();
-            if (!m.isNative() || !gotJavaFrame) {
-              gotJavaFrame = true;
-              mergedTrace.add(javaEntry);
-              ++j;
-            } else {
-              break; // Reached native method; have intervening C frames
-            }
-          }
-          if (gotJavaFrame) {
-            // Skip this sequence of unknown frames, as we've
-            // successfully identified it as Java frames
-            while (c < trace.size() && entry.isUnknownCFrame()) {
-              ++c;
-              if (c < trace.size()) {
-                entry = (StackTraceEntry) trace.get(c);
-              }
-            }
-            continue;
-          }
-        }
-        // If we get here, we either have an unknown frame we didn't
-        // know how to categorize or we have a known C frame. Add it
-        // to the trace.
-        mergedTrace.add(entry);
-        ++c;
-      }
-      trace = mergedTrace;
-    }
-    stackTracePanel.setTrace(trace);
-
-    registerPanel.update(t);
-  }
-
-  private void setCurrentFrame(CFrame fr, JavaVFrame jfr) {
-    localsPanel.clear();
-
-    if (fr != null) {
-      localsPanel.update(fr);
-
-      // FIXME: load source file if we can find it, otherwise display disassembly
-      LoadObject lo = getCDebugger().loadObjectContainingPC(fr.pc());
-      if (lo != null) {
-        CDebugInfoDataBase db = lo.getDebugInfoDataBase();
-        if (db != null) {
-          LineNumberInfo info = db.lineNumberForPC(fr.pc());
-          if (info != null) {
-            System.err.println("PC " + fr.pc() + ": Source file \"" +
-                               info.getSourceFileName() +
-                               "\", line number " +
-                               info.getLineNumber() +
-                               ", PC range [" +
-                               info.getStartPC() +
-                               ", " +
-                               info.getEndPC() +
-                               ")");
-            // OK, here we go...
-            showLineNumber(null, info.getSourceFileName(), info.getLineNumber());
-          } else {
-            System.err.println("(No line number information for PC " + fr.pc() + ")");
-            // Dump line number information for database
-            db.iterate(new LineNumberVisitor() {
-                public void doLineNumber(LineNumberInfo info) {
-                  System.err.println("  Source file \"" +
-                                     info.getSourceFileName() +
-                                     "\", line number " +
-                                     info.getLineNumber() +
-                                     ", PC range [" +
-                                     info.getStartPC() +
-                                     ", " +
-                                     info.getEndPC() +
-                                     ")");
-                }
-              });
-          }
-        }
-      }
-    } else {
-      if (Assert.ASSERTS_ENABLED) {
-        Assert.that(jfr != null, "Must have either C or Java frame");
-      }
-      localsPanel.update(jfr);
-      // See whether we can locate source file and line number
-      // FIXME: infer pathmap entries from user's locating of this
-      // source file
-      // FIXME: figure out what to do for native methods. Possible to
-      // go to line number for the native method declaration?
-      Method m = jfr.getMethod();
-      Symbol sfn = ((InstanceKlass) m.getMethodHolder()).getSourceFileName();
-      if (sfn != null) {
-        int bci = jfr.getBCI();
-        int lineNo = m.getLineNumberFromBCI(bci);
-        if (lineNo >= 0) {
-          // FIXME: show disassembly otherwise
-          showLineNumber(packageName(m.getMethodHolder().getName().asString()),
-                         sfn.asString(), lineNo);
-        }
-      }
-    }
-  }
-
-  private String packageName(String str) {
-    int idx = str.lastIndexOf('/');
-    if (idx < 0) {
-      return "";
-    }
-    return str.substring(0, idx).replace('/', '.');
-  }
-
-  private JavaThread javaThreadForProxy(ThreadProxy t) {
-    if (!getAgent().isJavaMode()) {
-      return null;
-    }
-    if (threadToJavaThreadMap == null) {
-      threadToJavaThreadMap = new HashMap();
-      Threads threads = VM.getVM().getThreads();
-      for (JavaThread thr = threads.first(); thr != null; thr = thr.next()) {
-        threadToJavaThreadMap.put(thr.getThreadProxy(), thr);
-      }
-    }
-    return (JavaThread) threadToJavaThreadMap.get(t);
-  }
-
-  private static JMenu createMenu(String name, char mnemonic, int mnemonicPos) {
-    JMenu menu = new JMenu(name);
-    menu.setMnemonic(mnemonic);
-    menu.setDisplayedMnemonicIndex(mnemonicPos);
-    return menu;
-  }
-
-  private static JMenuItem createMenuItem(String name, ActionListener l) {
-    JMenuItem item = new JMenuItem(name);
-    item.addActionListener(l);
-    return item;
-  }
-
-  private static JMenuItem createMenuItemInternal(String name, ActionListener l, int accelerator, int modifiers) {
-    JMenuItem item = createMenuItem(name, l);
-    item.setAccelerator(KeyStroke.getKeyStroke(accelerator, modifiers));
-    return item;
-  }
-
-  private static JMenuItem createMenuItem(String name, ActionListener l, int accelerator) {
-    return createMenuItemInternal(name, l, accelerator, 0);
-  }
-
-  private static JMenuItem createMenuItem(String name, ActionListener l, char mnemonic, int mnemonicPos) {
-    JMenuItem item = createMenuItem(name, l);
-    item.setMnemonic(mnemonic);
-    item.setDisplayedMnemonicIndex(mnemonicPos);
-    return item;
-  }
-
-  private static JMenuItem createMenuItem(String name,
-                                          ActionListener l,
-                                          int accelerator,
-                                          int acceleratorMods,
-                                          char mnemonic,
-                                          int mnemonicPos) {
-    JMenuItem item = createMenuItemInternal(name, l, accelerator, acceleratorMods);
-    item.setMnemonic(mnemonic);
-    item.setDisplayedMnemonicIndex(mnemonicPos);
-    return item;
-  }
-
-  /** Punctuates the given string with \n's where necessary to not
-      exceed the given number of characters per line. Strips
-      extraneous whitespace. */
-  private static String formatMessage(String message, int charsPerLine) {
-    StringBuffer buf = new StringBuffer(message.length());
-    StringTokenizer tokenizer = new StringTokenizer(message);
-    int curLineLength = 0;
-    while (tokenizer.hasMoreTokens()) {
-      String tok = tokenizer.nextToken();
-      if (curLineLength + tok.length() > charsPerLine) {
-        buf.append('\n');
-        curLineLength = 0;
-      } else {
-        if (curLineLength != 0) {
-          buf.append(' ');
-          ++curLineLength;
-        }
-      }
-      buf.append(tok);
-      curLineLength += tok.length();
-    }
-    return buf.toString();
-  }
-
-  private void setMenuItemsEnabled(java.util.List items, boolean enabled) {
-    for (Iterator iter = items.iterator(); iter.hasNext(); ) {
-      ((JMenuItem) iter.next()).setEnabled(enabled);
-    }
-  }
-
-  private void showMessageDialog(final String message, final String title, final int jOptionPaneKind) {
-    SwingUtilities.invokeLater(new Runnable() {
-        public void run() {
-          if (mdiMode) {
-            JOptionPane.showInternalMessageDialog(desktop, message, title, jOptionPaneKind);
-          } else {
-            JOptionPane.showMessageDialog(null, message, title, jOptionPaneKind);
-          }
-        }
-      });
-  }
-
-  private FrameWrapper newFrame(String title) {
-    if (mdiMode) {
-      return new JInternalFrameWrapper(new JInternalFrame(title));
-    } else {
-      return new JFrameWrapper(new JFrame(title));
-    }
-  }
-
-  private void addFrame(FrameWrapper frame) {
-    if (mdiMode) {
-      desktop.add(frame.getComponent());
-    }
-  }
-
-  private void removeFrame(FrameWrapper frame) {
-    if (mdiMode) {
-      desktop.remove(frame.getComponent());
-      desktop.invalidate();
-      desktop.validate();
-      desktop.repaint();
-    }
-    // FIXME: do something when not in MDI mode
-  }
-
-  private Dimension getParentDimension(Component c) {
-    if (mdiMode) {
-      return desktop.getSize();
-    } else {
-      return Toolkit.getDefaultToolkit().getScreenSize();
-    }
-  }
-
-  // Default editor implementation
-  class DefaultEditor implements Editor {
-    private DefaultEditorFactory factory;
-    private FrameWrapper    editorFrame;
-    private String          filename;
-    private SourceCodePanel code;
-    private boolean         shown;
-    private Object          userData;
-
-    public DefaultEditor(DefaultEditorFactory fact, String filename, final EditorCommands comm) {
-      this.filename = filename;
-      this.factory = fact;
-      editorFrame = newFrame(filename);
-      code = new SourceCodePanel();
-      // FIXME: when font changes, change font in editors as well
-      code.setFont(fixedWidthFont);
-      editorFrame.getContentPane().add(code);
-      editorFrame.setClosable(true);
-      editorFrame.setResizable(true);
-      editorFrame.setClosingActionListener(new ActionListener() {
-          public void actionPerformed(ActionEvent e) {
-            comm.windowClosed(DefaultEditor.this);
-            removeFrame(editorFrame);
-            editorFrame.dispose();
-            factory.editorClosed(DefaultEditor.this);
-          }
-        });
-      editorFrame.setActivatedActionListener(new ActionListener() {
-          public void actionPerformed(ActionEvent e) {
-            factory.makeEditorCurrent(DefaultEditor.this);
-            code.requestFocus();
-          }
-        });
-      code.setEditorCommands(comm, this);
-    }
-
-    public boolean openFile()                        { return code.openFile(filename);     }
-    public String  getSourceFileName()               { return filename;                    }
-    public int     getCurrentLineNumber()            { return code.getCurrentLineNumber(); }
-    public void showLineNumber(int lineNo) {
-      if (!shown) {
-        addFrame(editorFrame);
-        GraphicsUtilities.reshapeToAspectRatio(editorFrame.getComponent(),
-                                               1.0f,
-                                               0.85f,
-                                               getParentDimension(editorFrame.getComponent()));
-        editorFrame.setVisible(true);
-        shown = true;
-      }
-      code.showLineNumber(lineNo);
-      editorFrame.toFront();
-    }
-    public void    highlightLineNumber(int lineNo)   { code.highlightLineNumber(lineNo);        }
-    public void    showBreakpointAtLine(int lineNo)  { code.showBreakpointAtLine(lineNo);       }
-    public boolean hasBreakpointAtLine(int lineNo)   { return code.hasBreakpointAtLine(lineNo); }
-    public void    clearBreakpointAtLine(int lineNo) { code.clearBreakpointAtLine(lineNo);      }
-    public void    clearBreakpoints()                { code.clearBreakpoints();                 }
-    public void    setUserData(Object o)             { userData = o;                            }
-    public Object  getUserData()                     { return userData;                         }
-    public void    toFront()                         { editorFrame.toFront();
-                                                       factory.makeEditorCurrent(this);         }
-  }
-
-  class DefaultEditorFactory implements EditorFactory {
-    private LinkedList/*<Editor>*/ editors = new LinkedList();
-
-    public Editor openFile(String filename, EditorCommands commands) {
-      DefaultEditor editor = new DefaultEditor(this, filename, editorComm);
-      if (!editor.openFile()) {
-        return null;
-      }
-      return editor;
-    }
-
-    public Editor getCurrentEditor() {
-      if (editors.isEmpty()) {
-        return null;
-      }
-      return (Editor) editors.getFirst();
-    }
-
-    void editorClosed(Editor editor) {
-      editors.remove(editor);
-    }
-
-    void makeEditorCurrent(Editor editor) {
-      editors.remove(editor);
-      editors.addFirst(editor);
-    }
-  }
-
-  // Helper class for loading .java files; show only those with
-  // correct file name which are also in the correct package
-  static class JavaFileFilter extends javax.swing.filechooser.FileFilter {
-    private String packageName;
-    private String fileName;
-
-    JavaFileFilter(String packageName, String fileName) {
-      this.packageName = packageName;
-      this.fileName = fileName;
-    }
-
-    public boolean accept(File f) {
-      if (f.isDirectory()) {
-        return true;
-      }
-      // This rejects most files
-      if (!f.getName().equals(fileName)) {
-        return false;
-      }
-      // Ensure selected file is in the correct package
-      PackageScanner scanner = new PackageScanner();
-      String pkg = scanner.scan(f);
-      if (!pkg.equals(packageName)) {
-        return false;
-      }
-      return true;
-    }
-
-    public String getDescription() { return "Java source files"; }
-  }
-
-  // Auxiliary information used only for Java source files
-  static class JavaUserData {
-    private String packageName; // External format
-    private String sourceFileName;
-
-    /** Source file name is equivalent to that found in the .java
-        file; i.e., not a full path */
-    JavaUserData(String packageName, String sourceFileName) {
-      this.packageName = packageName;
-      this.sourceFileName = sourceFileName;
-    }
-
-    String packageName()    { return packageName; }
-    String sourceFileName() { return sourceFileName; }
-  }
-
-  // Opens a source file. This makes it available for the setting of
-  // lazy breakpoints.
-  private void openSourceFile() {
-    JFileChooser chooser = new JFileChooser();
-    chooser.setDialogTitle("Open source code file");
-    chooser.setMultiSelectionEnabled(false);
-    if (chooser.showOpenDialog(null) != JFileChooser.APPROVE_OPTION) {
-      return;
-    }
-    File chosen = chooser.getSelectedFile();
-    if (chosen == null) {
-      return;
-    }
-
-    // See whether we have a Java source file. If so, derive a package
-    // name for it.
-    String path = chosen.getPath();
-    String name = null;
-    JavaUserData data = null;
-    if (path.endsWith(".java")) {
-      PackageScanner scanner = new PackageScanner();
-      String pkg = scanner.scan(chosen);
-      // Now knowing both the package name and file name, we can put
-      // this in the editor map and use it for setting breakpoints
-      // later
-      String fileName = chosen.getName();
-      name = pkg + "." + fileName;
-      data = new JavaUserData(pkg, fileName);
-    } else {
-      // FIXME: need pathmap mechanism
-      name = path;
-    }
-    Editor editor = (Editor) editors.get(name);
-    if (editor == null) {
-      editor = editorFact.openFile(path, editorComm);
-      if (editor == null) {
-        showMessageDialog("Unable to open file \"" + path + "\" -- unexpected error.",
-                          "Unable to open file",
-                          JOptionPane.WARNING_MESSAGE);
-        return;
-      }
-      editors.put(name, editor);
-      if (data != null) {
-        editor.setUserData(data);
-      }
-    } else {
-      editor.toFront();
-    }
-    editor.showLineNumber(1);
-    // Show breakpoints as well if we have any for this file
-    Set set = (Set) fileToBreakpointMap.get(editor.getSourceFileName());
-    if (set != null) {
-      for (Iterator iter = set.iterator(); iter.hasNext(); ) {
-        editor.showBreakpointAtLine(((Integer) iter.next()).intValue());
-      }
-    }
-  }
-
-  // Package name may be null, in which case the file is assumed to be
-  // a C source file. Otherwise it is assumed to be a Java source file
-  // and certain filtering rules will be applied.
-  private void showLineNumber(String packageName, String fileName, int lineNumber) {
-    String name;
-    if (packageName == null) {
-      name = fileName;
-    } else {
-      name = packageName + "." + fileName;
-    }
-    Editor editor = (Editor) editors.get(name);
-    if (editor == null) {
-      // See whether file exists
-      File file = new File(fileName);
-      String realFileName = fileName;
-      if (!file.exists()) {
-        // User must specify path to file
-        JFileChooser chooser = new JFileChooser();
-        chooser.setDialogTitle("Please locate " + fileName);
-        chooser.setMultiSelectionEnabled(false);
-        if (packageName != null) {
-          chooser.setFileFilter(new JavaFileFilter(packageName, fileName));
-        }
-        int res = chooser.showOpenDialog(null);
-        if (res != JFileChooser.APPROVE_OPTION) {
-          // FIXME: show disassembly instead
-          return;
-        }
-        // FIXME: would like to infer more from the selection; i.e.,
-        // a pathmap leading up to this file
-        File chosen = chooser.getSelectedFile();
-        if (chosen == null) {
-          return;
-        }
-        realFileName = chosen.getPath();
-      }
-      // Now instruct editor factory to open file
-      editor = editorFact.openFile(realFileName, editorComm);
-      if (editor == null) {
-        showMessageDialog("Unable to open file \"" + realFileName + "\" -- unexpected error.",
-                          "Unable to open file",
-                          JOptionPane.WARNING_MESSAGE);
-        return;
-      }
-      // Got an editor; put it in map
-      editors.put(name, editor);
-      // If Java source file, add additional information for later
-      if (packageName != null) {
-        editor.setUserData(new JavaUserData(packageName, fileName));
-      }
-    }
-    // Got editor; show line
-    editor.showLineNumber(lineNumber);
-    editor.highlightLineNumber(lineNumber);
-    // Show breakpoints as well if we have any for this file
-    Set set = (Set) fileToBreakpointMap.get(editor.getSourceFileName());
-    if (set != null) {
-      for (Iterator iter = set.iterator(); iter.hasNext(); ) {
-        editor.showBreakpointAtLine(((Integer) iter.next()).intValue());
-      }
-    }
-  }
-
-  //
-  // Suspend/resume
-  //
-
-  private boolean isSuspended() {
-    return suspended;
-  }
-
-  private synchronized void suspend() {
-    setMenuItemsEnabled(resumeDebugMenuItems, true);
-    setMenuItemsEnabled(suspendDebugMenuItems, false);
-    BugSpotAgent agent = getAgent();
-    if (agent.canInteractWithJava() && !agent.isJavaSuspended()) {
-      agent.suspendJava();
-    }
-    agent.suspend();
-    // FIXME: call VM.getVM().fireVMSuspended()
-    resetCurrentThread();
-    debugEventTimer.stop();
-    suspended = true;
-  }
-
-  private synchronized void resume() {
-    // Note: we don't wipe out the cached state like the
-    // sourceFileToLineNumberInfoMap since it is too expensive to
-    // recompute. Instead we recompute it if any DLLs are loaded or
-    // unloaded.
-    threadToJavaThreadMap = null;
-    setMenuItemsEnabled(resumeDebugMenuItems, false);
-    setMenuItemsEnabled(suspendDebugMenuItems, true);
-    registerPanel.clear();
-    // FIXME: call VM.getVM().fireVMResumed()
-    BugSpotAgent agent = getAgent();
-    agent.resume();
-    if (agent.canInteractWithJava()) {
-      if (agent.isJavaSuspended()) {
-        agent.resumeJava();
-      }
-      if (javaEventPending) {
-        javaEventPending = false;
-        // Clear it out before resuming polling for events
-        agent.javaEventContinue();
-      }
-    }
-    agent.enableJavaInteraction();
-    suspended = false;
-    debugEventTimer.start();
-  }
-
-  //
-  // Breakpoints
-  //
-
-  private synchronized BreakpointResult handleBreakpointToggle(Editor editor, int lineNumber) {
-    // Currently we only use user data in editors to indicate Java
-    // source files. If this changes then this code will need to
-    // change.
-    JavaUserData data = (JavaUserData) editor.getUserData();
-    String filename = editor.getSourceFileName();
-    if (data == null) {
-      // C/C++ code
-      // FIXME: as noted above in EditorCommands.toggleBreakpointAtLine,
-      // this needs more work to handle "lazy" breakpoints in files
-      // which we don't know about in the debug information yet
-      CDebugger dbg = getCDebugger();
-      ProcessControl prctl = dbg.getProcessControl();
-      if (prctl == null) {
-        return new BreakpointResult(false, false, 0, "Process control not enabled");
-      }
-      boolean mustSuspendAndResume = (!prctl.isSuspended());
-      try {
-        if (mustSuspendAndResume) {
-          prctl.suspend();
-        }
-        // Search debug info for all DSOs
-        LineNumberInfo info = getLineNumberInfo(filename, lineNumber);
-        if (info != null) {
-          Set bpset = (Set) fileToBreakpointMap.get(filename);
-          if (bpset == null) {
-            bpset = new HashSet();
-            fileToBreakpointMap.put(filename, bpset);
-          }
-          Integer key = new Integer(info.getLineNumber());
-          if (bpset.contains(key)) {
-            // Clear breakpoint at this line's PC
-            prctl.clearBreakpoint(info.getStartPC());
-            bpset.remove(key);
-            return new BreakpointResult(true, false, info.getLineNumber());
-          } else {
-            // Set breakpoint at this line's PC
-            System.err.println("Setting breakpoint at PC " + info.getStartPC());
-            prctl.setBreakpoint(info.getStartPC());
-            bpset.add(key);
-            return new BreakpointResult(true, true, info.getLineNumber());
-          }
-        } else {
-          return new BreakpointResult(false, false, 0, "No debug information for this source file and line");
-        }
-      } finally {
-        if (mustSuspendAndResume) {
-          prctl.resume();
-        }
-      }
-    } else {
-      BugSpotAgent agent = getAgent();
-      if (!agent.canInteractWithJava()) {
-        String why;
-        if (agent.isJavaInteractionDisabled()) {
-          why = "Can not toggle Java breakpoints while stopped because\nof C/C++ debug events (breakpoints, single-stepping)";
-        } else {
-          why = "Could not talk to SA's JVMDI module to enable Java\nprogramming language breakpoints (run with -Xdebug -Xrunsa)";
-        }
-        return new BreakpointResult(false, false, 0, why);
-      }
-      Set bpset = (Set) fileToBreakpointMap.get(filename);
-      if (bpset == null) {
-        bpset = new HashSet();
-        fileToBreakpointMap.put(filename, bpset);
-      }
-      boolean mustResumeAndSuspend = isSuspended();
-      try {
-        if (mustResumeAndSuspend) {
-          agent.resume();
-        }
-        ServiceabilityAgentJVMDIModule.BreakpointToggleResult res =
-          getAgent().toggleJavaBreakpoint(data.sourceFileName(),
-                                          data.packageName(),
-                                          lineNumber);
-        if (res.getSuccess()) {
-          Integer key = new Integer(res.getLineNumber());
-          boolean addRemRes = false;
-          if (res.getWasSet()) {
-            addRemRes = bpset.add(key);
-            System.err.println("Setting breakpoint at " + res.getMethodName() + res.getMethodSignature() +
-                               ", bci " + res.getBCI() + ", line " + res.getLineNumber());
-          } else {
-            addRemRes = bpset.remove(key);
-            System.err.println("Clearing breakpoint at " + res.getMethodName() + res.getMethodSignature() +
-                               ", bci " + res.getBCI() + ", line " + res.getLineNumber());
-          }
-          if (Assert.ASSERTS_ENABLED) {
-            Assert.that(addRemRes, "Inconsistent Java breakpoint state with respect to target process");
-          }
-          return new BreakpointResult(true, res.getWasSet(), res.getLineNumber());
-        } else {
-          return new BreakpointResult(false, false, 0, res.getErrMsg());
-        }
-      } finally {
-        if (mustResumeAndSuspend) {
-          agent.suspend();
-          resetCurrentThread();
-        }
-      }
-    }
-  }
-
-  // Must call only when suspended
-  private LineNumberInfo getLineNumberInfo(String filename, int lineNumber) {
-    Map map = getSourceFileToLineNumberInfoMap();
-    java.util.List infos = (java.util.List) map.get(filename);
-    if (infos == null) {
-      return null;
-    }
-    // Binary search for line number
-    return searchLineNumbers(infos, lineNumber, 0, infos.size());
-  }
-
-  // Must call only when suspended
-  private Map getSourceFileToLineNumberInfoMap() {
-    if (sourceFileToLineNumberInfoMap == null) {
-      // Build from debug info
-      java.util.List loadObjects = getCDebugger().getLoadObjectList();
-      final Map map = new HashMap();
-      for (Iterator iter = loadObjects.iterator(); iter.hasNext(); ) {
-        LoadObject lo = (LoadObject) iter.next();
-        CDebugInfoDataBase db = lo.getDebugInfoDataBase();
-        if (db != null) {
-          db.iterate(new LineNumberVisitor() {
-              public void doLineNumber(LineNumberInfo info) {
-                String name = info.getSourceFileName();
-                if (name != null) {
-                  java.util.List val = (java.util.List) map.get(name);
-                  if (val == null) {
-                    val = new ArrayList();
-                    map.put(name, val);
-                  }
-                  val.add(info);
-                }
-              }
-            });
-        }
-      }
-      // Sort all lists
-      for (Iterator iter = map.values().iterator(); iter.hasNext(); ) {
-        java.util.List list = (java.util.List) iter.next();
-        Collections.sort(list, new Comparator() {
-            public int compare(Object o1, Object o2) {
-              LineNumberInfo l1 = (LineNumberInfo) o1;
-              LineNumberInfo l2 = (LineNumberInfo) o2;
-              int n1 = l1.getLineNumber();
-              int n2 = l2.getLineNumber();
-              if (n1 < n2) return -1;
-              if (n1 == n2) return 0;
-              return 1;
-            }
-          });
-      }
-      sourceFileToLineNumberInfoMap = map;
-    }
-    return sourceFileToLineNumberInfoMap;
-  }
-
-  private LineNumberInfo searchLineNumbers(java.util.List infoList, int lineNo, int lowIdx, int highIdx) {
-    if (highIdx < lowIdx) return null;
-    if (lowIdx == highIdx) {
-      // Base case: see whether start PC is less than or equal to addr
-      if (checkLineNumber(infoList, lineNo, lowIdx)) {
-        return (LineNumberInfo) infoList.get(lowIdx);
-      } else {
-        return null;
-      }
-    } else if (lowIdx == highIdx - 1) {
-      if (checkLineNumber(infoList, lineNo, lowIdx)) {
-        return (LineNumberInfo) infoList.get(lowIdx);
-      } else if (checkLineNumber(infoList, lineNo, highIdx)) {
-        return (LineNumberInfo) infoList.get(highIdx);
-      } else {
-        return null;
-      }
-    }
-    int midIdx = (lowIdx + highIdx) >> 1;
-    LineNumberInfo info = (LineNumberInfo) infoList.get(midIdx);
-    if (lineNo < info.getLineNumber()) {
-      // Always move search down
-      return searchLineNumbers(infoList, lineNo, lowIdx, midIdx);
-    } else if (lineNo == info.getLineNumber()) {
-      return info;
-    } else {
-      // Move search up
-      return searchLineNumbers(infoList, lineNo, midIdx, highIdx);
-    }
-  }
-
-  private boolean checkLineNumber(java.util.List infoList, int lineNo, int idx) {
-    LineNumberInfo info = (LineNumberInfo) infoList.get(idx);
-    return (info.getLineNumber() >= lineNo);
-  }
-
-  //
-  // Debug events
-  //
-
-  private synchronized void pollForDebugEvent() {
-    ProcessControl prctl = getCDebugger().getProcessControl();
-    if (prctl == null) {
-      return;
-    }
-    DebugEvent ev = prctl.debugEventPoll();
-    if (ev != null) {
-      DebugEvent.Type t = ev.getType();
-      if (t == DebugEvent.Type.LOADOBJECT_LOAD ||
-          t == DebugEvent.Type.LOADOBJECT_UNLOAD) {
-        // Conservatively clear cached debug info state
-        sourceFileToLineNumberInfoMap = null;
-        // FIXME: would be very useful to have "stop on load/unload"
-        // events
-        // FIXME: must do work at these events to implement lazy
-        // breakpoints
-        prctl.debugEventContinue();
-      } else if (t == DebugEvent.Type.BREAKPOINT) {
-        // Note: Visual C++ only notifies on breakpoints it doesn't
-        // know about
-
-        // FIXME: put back test
-        //        if (!prctl.isBreakpointSet(ev.getPC())) {
-          showMessageDialog("Breakpoint reached at PC " + ev.getPC(),
-                            "Breakpoint reached",
-                            JOptionPane.INFORMATION_MESSAGE);
-          //        }
-        agent.disableJavaInteraction();
-        suspend();
-        prctl.debugEventContinue();
-      } else if (t == DebugEvent.Type.SINGLE_STEP) {
-        agent.disableJavaInteraction();
-        suspend();
-        prctl.debugEventContinue();
-      } else if (t == DebugEvent.Type.ACCESS_VIOLATION) {
-        showMessageDialog("Access violation attempting to " +
-                          (ev.getWasWrite() ? "write" : "read") +
-                          " address " + ev.getAddress() +
-                          " at PC " + ev.getPC(),
-                          "Access Violation",
-                          JOptionPane.WARNING_MESSAGE);
-        agent.disableJavaInteraction();
-        suspend();
-        prctl.debugEventContinue();
-      } else {
-        String info = "Unknown debug event encountered";
-        if (ev.getUnknownEventDetail() != null) {
-          info = info + ": " + ev.getUnknownEventDetail();
-        }
-        showMessageDialog(info, "Unknown debug event", JOptionPane.INFORMATION_MESSAGE);
-        suspend();
-        prctl.debugEventContinue();
-      }
-      return;
-    }
-
-    // No C++ debug event; poll for Java debug event
-    if (getAgent().canInteractWithJava()) {
-      if (!javaEventPending) {
-        if (getAgent().javaEventPending()) {
-          suspend();
-          // This does a lot of work and we want to have the page
-          // cache available to us as it runs
-          sun.jvm.hotspot.livejvm.Event jev = getAgent().javaEventPoll();
-          if (jev != null) {
-            javaEventPending = true;
-            if (jev.getType() == sun.jvm.hotspot.livejvm.Event.Type.BREAKPOINT) {
-              BreakpointEvent bpev = (BreakpointEvent) jev;
-              showMessageDialog("Breakpoint reached in method\n" +
-                                bpev.methodID().method().externalNameAndSignature() +
-                                ",\nbci " + bpev.location(),
-                                "Breakpoint reached",
-                                JOptionPane.INFORMATION_MESSAGE);
-            } else if (jev.getType() == sun.jvm.hotspot.livejvm.Event.Type.EXCEPTION) {
-              ExceptionEvent exev = (ExceptionEvent) jev;
-              showMessageDialog(exev.exception().getKlass().getName().asString() +
-                                "\nthrown in method\n" +
-                                exev.methodID().method().externalNameAndSignature() +
-                                "\nat BCI " + exev.location(),
-                                "Exception thrown",
-                                JOptionPane.INFORMATION_MESSAGE);
-            } else {
-              Assert.that(false, "Should not reach here");
-            }
-          }
-        }
-      }
-    }
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,799 +0,0 @@
-/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import java.io.PrintStream;
-import java.net.*;
-import java.rmi.*;
-import sun.jvm.hotspot.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.debugger.bsd.*;
-import sun.jvm.hotspot.debugger.proc.*;
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.debugger.windbg.*;
-import sun.jvm.hotspot.debugger.linux.*;
-import sun.jvm.hotspot.debugger.sparc.*;
-import sun.jvm.hotspot.debugger.remote.*;
-import sun.jvm.hotspot.livejvm.*;
-import sun.jvm.hotspot.memory.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.utilities.*;
-
-/** <P> This class wraps the basic functionality for connecting to the
- * target process or debug server. It makes it simple to start up the
- * debugging system. </P>
- *
- * <P> This agent (as compared to the HotSpotAgent) can connect to
- * and interact with arbitrary processes. If the target process
- * happens to be a HotSpot JVM, the Java debugging features of the
- * Serviceability Agent are enabled. Further, if the Serviceability
- * Agent's JVMDI module is loaded into the target VM, interaction
- * with the live Java program is possible, specifically the catching
- * of exceptions and setting of breakpoints. </P>
- *
- * <P> The BugSpot debugger requires that the underlying Debugger
- * support C/C++ debugging via the CDebugger interface. </P>
- *
- * <P> FIXME: especially with the addition of remote debugging, this
- * has turned into a mess; needs rethinking. </P> */
-
-public class BugSpotAgent {
-
-    private JVMDebugger debugger;
-    private MachineDescription machDesc;
-    private TypeDataBase db;
-
-    private String os;
-    private String cpu;
-    private String fileSep;
-
-    // The system can work in several ways:
-    //  - Attaching to local process
-    //  - Attaching to local core file
-    //  - Connecting to remote debug server
-    //  - Starting debug server for process
-    //  - Starting debug server for core file
-
-    // These are options for the "client" side of things
-    private static final int PROCESS_MODE   = 0;
-    private static final int CORE_FILE_MODE = 1;
-    private static final int REMOTE_MODE    = 2;
-    private int startupMode;
-
-    // This indicates whether we are really starting a server or not
-    private boolean isServer;
-
-    // All possible required information for connecting
-    private int pid;
-    private String executableName;
-    private String coreFileName;
-    private String debugServerID;
-
-    // All needed information for server side
-    private String serverID;
-
-    // Indicates whether we are attached to a HotSpot JVM or not
-    private boolean javaMode;
-
-    // Indicates whether we have process control over a live HotSpot JVM
-    // or not; non-null if so.
-    private ServiceabilityAgentJVMDIModule jvmdi;
-    // While handling C breakpoints interactivity with the Java program
-    // is forbidden. Too many invariants are broken while the target is
-    // stopped at a C breakpoint to risk making JVMDI calls.
-    private boolean javaInteractionDisabled;
-
-    private String[] jvmLibNames;
-    private String[] saLibNames;
-
-    // FIXME: make these configurable, i.e., via a dotfile; also
-    // consider searching within the JDK from which this Java executable
-    // comes to find them
-    private static final String defaultDbxPathPrefix                = "/net/jano.eng/export/disk05/hotspot/sa";
-    private static final String defaultDbxSvcAgentDSOPathPrefix     = "/net/jano.eng/export/disk05/hotspot/sa";
-
-    private static final boolean DEBUG;
-    static {
-        DEBUG = System.getProperty("sun.jvm.hotspot.bugspot.BugSpotAgent.DEBUG")
-        != null;
-    }
-
-    static void debugPrintln(String str) {
-        if (DEBUG) {
-            System.err.println(str);
-        }
-    }
-
-    static void showUsage() {
-        System.out.println("    You can also pass these -D options to java to specify where to find dbx and the \n" +
-        "    Serviceability Agent plugin for dbx:");
-        System.out.println("       -DdbxPathName=<path-to-dbx-executable>\n" +
-        "             Default is derived from dbxPathPrefix");
-        System.out.println("    or");
-        System.out.println("       -DdbxPathPrefix=<xxx>\n" +
-        "             where xxx is the path name of a dir structure that contains:\n" +
-        "                   <os>/<arch>/bin/dbx\n" +
-        "             The default is " + defaultDbxPathPrefix);
-        System.out.println("    and");
-        System.out.println("       -DdbxSvcAgentDSOPathName=<path-to-dbx-serviceability-agent-module>\n" +
-        "             Default is determined from dbxSvcAgentDSOPathPrefix");
-        System.out.println("    or");
-        System.out.println("       -DdbxSvcAgentDSOPathPrefix=<xxx>\n" +
-        "             where xxx is the pathname of a dir structure that contains:\n" +
-        "                   <os>/<arch>/bin/lib/libsvc_agent_dbx.so\n" +
-        "             The default is " + defaultDbxSvcAgentDSOPathPrefix);
-    }
-
-    public BugSpotAgent() {
-        // for non-server add shutdown hook to clean-up debugger in case
-        // of forced exit. For remote server, shutdown hook is added by
-        // DebugServer.
-        Runtime.getRuntime().addShutdownHook(new java.lang.Thread(
-        new Runnable() {
-            public void run() {
-                synchronized (BugSpotAgent.this) {
-                    if (!isServer) {
-                        detach();
-                    }
-                }
-            }
-        }));
-    }
-
-    //--------------------------------------------------------------------------------
-    // Accessors (once the system is set up)
-    //
-
-    public synchronized Debugger getDebugger() {
-        return debugger;
-    }
-
-    public synchronized CDebugger getCDebugger() {
-        return getDebugger().getCDebugger();
-    }
-
-    public synchronized ProcessControl getProcessControl() {
-        return getCDebugger().getProcessControl();
-    }
-
-    public synchronized TypeDataBase getTypeDataBase() {
-        return db;
-    }
-
-    /** Indicates whether the target process is suspended
-      completely. Equivalent to getProcessControl().isSuspended(). */
-    public synchronized boolean isSuspended() throws DebuggerException {
-        return getProcessControl().isSuspended();
-    }
-
-    /** Suspends the target process completely. Equivalent to
-      getProcessControl().suspend(). */
-    public synchronized void suspend() throws DebuggerException {
-        getProcessControl().suspend();
-    }
-
-    /** Resumes the target process completely. Equivalent to
-      getProcessControl().suspend(). */
-    public synchronized void resume() throws DebuggerException {
-        getProcessControl().resume();
-    }
-
-    /** Indicates whether we are attached to a Java HotSpot virtual
-      machine */
-    public synchronized boolean isJavaMode() {
-        return javaMode;
-    }
-
-    /** Temporarily disables interaction with the target process via
-      JVMDI. This is done while the target process is stopped at a C
-      breakpoint. Can be called even if the JVMDI agent has not been
-      initialized. */
-    public synchronized void disableJavaInteraction() {
-        javaInteractionDisabled = true;
-    }
-
-    /** Re-enables interaction with the target process via JVMDI. This
-      is done while the target process is continued past a C
-      braekpoint. Can be called even if the JVMDI agent has not been
-      initialized. */
-    public synchronized void enableJavaInteraction() {
-        javaInteractionDisabled = false;
-    }
-
-    /** Indicates whether Java interaction has been disabled */
-    public synchronized boolean isJavaInteractionDisabled() {
-        return javaInteractionDisabled;
-    }
-
-    /** Indicates whether we can talk to the Serviceability Agent's
-      JVMDI module to be able to set breakpoints */
-    public synchronized boolean canInteractWithJava() {
-        return (jvmdi != null) && !javaInteractionDisabled;
-    }
-
-    /** Suspends all Java threads in the target process. Can only be
-      called if we are attached to a HotSpot JVM and can connect to
-      the SA's JVMDI module. Must not be called when the target
-      process has been suspended with suspend(). */
-    public synchronized void suspendJava() throws DebuggerException {
-        if (!canInteractWithJava()) {
-            throw new DebuggerException("Could not connect to SA's JVMDI module");
-        }
-        if (jvmdi.isSuspended()) {
-            throw new DebuggerException("Target process already suspended via JVMDI");
-        }
-        jvmdi.suspend();
-    }
-
-    /** Resumes all Java threads in the target process. Can only be
-      called if we are attached to a HotSpot JVM and can connect to
-      the SA's JVMDI module. Must not be called when the target
-      process has been suspended with suspend(). */
-    public synchronized void resumeJava() throws DebuggerException {
-        if (!canInteractWithJava()) {
-            throw new DebuggerException("Could not connect to SA's JVMDI module");
-        }
-        if (!jvmdi.isSuspended()) {
-            throw new DebuggerException("Target process already resumed via JVMDI");
-        }
-        jvmdi.resume();
-    }
-
-    /** Indicates whether the target process has been suspended at the
-      Java language level via the SA's JVMDI module */
-    public synchronized boolean isJavaSuspended() throws DebuggerException {
-        return jvmdi.isSuspended();
-    }
-
-    /** Toggle a Java breakpoint at the given location. */
-    public synchronized ServiceabilityAgentJVMDIModule.BreakpointToggleResult
-    toggleJavaBreakpoint(String srcFileName,
-    String pkgName,
-    int lineNo) {
-        if (!canInteractWithJava()) {
-            throw new DebuggerException("Could not connect to SA's JVMDI module; can not toggle Java breakpoints");
-        }
-        return jvmdi.toggleBreakpoint(srcFileName, pkgName, lineNo);
-    }
-
-    /** Access to JVMDI module's eventPending */
-    public synchronized boolean javaEventPending() throws DebuggerException {
-        if (!canInteractWithJava()) {
-            throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events");
-        }
-        return jvmdi.eventPending();
-    }
-
-    /** Access to JVMDI module's eventPoll */
-    public synchronized Event javaEventPoll() throws DebuggerException {
-        if (!canInteractWithJava()) {
-            throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events");
-        }
-        return jvmdi.eventPoll();
-    }
-
-    /** Access to JVMDI module's eventContinue */
-    public synchronized void javaEventContinue() throws DebuggerException {
-        if (!canInteractWithJava()) {
-            throw new DebuggerException("Could not connect to SA's JVMDI module; can not continue past Java debug events");
-        }
-        jvmdi.eventContinue();
-    }
-
-
-    // FIXME: add other accessors. For example, suspension and
-    // resumption should be done through this interface, as well as
-    // interaction with the live Java process such as breakpoint setting.
-    // Probably should not expose the ServiceabilityAgentJVMDIModule
-    // from this interface.
-
-    //--------------------------------------------------------------------------------
-    // Client-side operations
-    //
-
-    /** This attaches to a process running on the local machine. */
-    public synchronized void attach(int processID)
-    throws DebuggerException {
-        if (debugger != null) {
-            throw new DebuggerException("Already attached");
-        }
-        pid = processID;
-        startupMode = PROCESS_MODE;
-        isServer = false;
-        go();
-    }
-
-    /** This opens a core file on the local machine */
-    public synchronized void attach(String executableName, String coreFileName)
-    throws DebuggerException {
-        if (debugger != null) {
-            throw new DebuggerException("Already attached");
-        }
-        if ((executableName == null) || (coreFileName == null)) {
-            throw new DebuggerException("Both the core file name and executable name must be specified");
-        }
-        this.executableName = executableName;
-        this.coreFileName = coreFileName;
-        startupMode = CORE_FILE_MODE;
-        isServer = false;
-        go();
-    }
-
-    /** This attaches to a "debug server" on a remote machine; this
-      remote server has already attached to a process or opened a
-      core file and is waiting for RMI calls on the Debugger object to
-      come in. */
-    public synchronized void attach(String remoteServerID)
-    throws DebuggerException {
-        if (debugger != null) {
-            throw new DebuggerException("Already attached to a process");
-        }
-        if (remoteServerID == null) {
-            throw new DebuggerException("Debug server id must be specified");
-        }
-
-        debugServerID = remoteServerID;
-        startupMode = REMOTE_MODE;
-        isServer = false;
-        go();
-    }
-
-    /** This should only be called by the user on the client machine,
-      not the server machine */
-    public synchronized boolean detach() throws DebuggerException {
-        if (isServer) {
-            throw new DebuggerException("Should not call detach() for server configuration");
-        }
-        return detachInternal();
-    }
-
-    //--------------------------------------------------------------------------------
-    // Server-side operations
-    //
-
-    /** This attaches to a process running on the local machine and
-      starts a debug server, allowing remote machines to connect and
-      examine this process. uniqueID is used to uniquely identify the
-      debuggee */
-    public synchronized void startServer(int processID, String uniqueID)
-    throws DebuggerException {
-        if (debugger != null) {
-            throw new DebuggerException("Already attached");
-        }
-        pid = processID;
-        startupMode = PROCESS_MODE;
-        isServer = true;
-        serverID = uniqueID;
-        go();
-    }
-
-    /** This attaches to a process running on the local machine and
-      starts a debug server, allowing remote machines to connect and
-      examine this process. */
-    public synchronized void startServer(int processID)
-    throws DebuggerException {
-        startServer(processID, null);
-    }
-
-    /** This opens a core file on the local machine and starts a debug
-      server, allowing remote machines to connect and examine this
-      core file. uniqueID is used to uniquely identify the
-      debuggee */
-    public synchronized void startServer(String executableName, String coreFileName,
-    String uniqueID)
-    throws DebuggerException {
-        if (debugger != null) {
-            throw new DebuggerException("Already attached");
-        }
-        if ((executableName == null) || (coreFileName == null)) {
-            throw new DebuggerException("Both the core file name and Java executable name must be specified");
-        }
-        this.executableName = executableName;
-        this.coreFileName = coreFileName;
-        startupMode = CORE_FILE_MODE;
-        isServer = true;
-        serverID = uniqueID;
-        go();
-    }
-
-    /** This opens a core file on the local machine and starts a debug
-      server, allowing remote machines to connect and examine this
-      core file.*/
-    public synchronized void startServer(String executableName, String coreFileName)
-    throws DebuggerException {
-        startServer(executableName, coreFileName, null);
-    }
-
-    /** This may only be called on the server side after startServer()
-      has been called */
-    public synchronized boolean shutdownServer() throws DebuggerException {
-        if (!isServer) {
-            throw new DebuggerException("Should not call shutdownServer() for client configuration");
-        }
-        return detachInternal();
-    }
-
-
-    //--------------------------------------------------------------------------------
-    // Internals only below this point
-    //
-
-    private boolean detachInternal() {
-        if (debugger == null) {
-            return false;
-        }
-        if (canInteractWithJava()) {
-            jvmdi.detach();
-            jvmdi = null;
-        }
-        boolean retval = true;
-        if (!isServer) {
-            VM.shutdown();
-        }
-        // We must not call detach() if we are a client and are connected
-        // to a remote debugger
-        Debugger dbg = null;
-        DebuggerException ex = null;
-        if (isServer) {
-            try {
-                RMIHelper.unbind(serverID);
-            }
-            catch (DebuggerException de) {
-                ex = de;
-            }
-            dbg = debugger;
-        } else {
-            if (startupMode != REMOTE_MODE) {
-                dbg = debugger;
-            }
-        }
-        if (dbg != null) {
-            retval = dbg.detach();
-        }
-
-        debugger = null;
-        machDesc = null;
-        db = null;
-        if (ex != null) {
-            throw(ex);
-        }
-        return retval;
-    }
-
-    private void go() {
-        setupDebugger();
-        javaMode = setupVM();
-    }
-
-    private void setupDebugger() {
-        if (startupMode != REMOTE_MODE) {
-            //
-            // Local mode (client attaching to local process or setting up
-            // server, but not client attaching to server)
-            //
-
-            try {
-                os  = PlatformInfo.getOS();
-                cpu = PlatformInfo.getCPU();
-            }
-            catch (UnsupportedPlatformException e) {
-                throw new DebuggerException(e);
-            }
-            fileSep = System.getProperty("file.separator");
-
-            if (os.equals("solaris")) {
-                setupDebuggerSolaris();
-            } else if (os.equals("win32")) {
-                setupDebuggerWin32();
-            } else if (os.equals("linux")) {
-                setupDebuggerLinux();
-            } else if (os.equals("bsd")) {
-                setupDebuggerBsd();
-            } else {
-                // Add support for more operating systems here
-                throw new DebuggerException("Operating system " + os + " not yet supported");
-            }
-            if (isServer) {
-                RemoteDebuggerServer remote = null;
-                try {
-                    remote = new RemoteDebuggerServer(debugger);
-                }
-                catch (RemoteException rem) {
-                    throw new DebuggerException(rem);
-                }
-                RMIHelper.rebind(serverID, remote);
-            }
-        } else {
-            //
-            // Remote mode (client attaching to server)
-            //
-
-            // Create and install a security manager
-
-            // FIXME: currently commented out because we were having
-            // security problems since we're "in the sun.* hierarchy" here.
-            // Perhaps a permissive policy file would work around this. In
-            // the long run, will probably have to move into com.sun.*.
-
-            //    if (System.getSecurityManager() == null) {
-            //      System.setSecurityManager(new RMISecurityManager());
-            //    }
-
-            connectRemoteDebugger();
-        }
-    }
-
-    private boolean setupVM() {
-        // We need to instantiate a HotSpotTypeDataBase on both the client
-        // and server machine. On the server it is only currently used to
-        // configure the Java primitive type sizes (which we should
-        // consider making constant). On the client it is used to
-        // configure the VM.
-
-        try {
-            if (os.equals("solaris")) {
-                db = new HotSpotTypeDataBase(machDesc, new HotSpotSolarisVtblAccess(debugger, jvmLibNames),
-                debugger, jvmLibNames);
-            } else if (os.equals("win32")) {
-                db = new HotSpotTypeDataBase(machDesc, new Win32VtblAccess(debugger, jvmLibNames),
-                debugger, jvmLibNames);
-            } else if (os.equals("linux")) {
-                db = new HotSpotTypeDataBase(machDesc, new LinuxVtblAccess(debugger, jvmLibNames),
-                debugger, jvmLibNames);
-            } else if (os.equals("bsd")) {
-                db = new HotSpotTypeDataBase(machDesc, new BsdVtblAccess(debugger, jvmLibNames),
-                debugger, jvmLibNames);
-            } else {
-                throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess implemented yet)");
-            }
-        }
-        catch (NoSuchSymbolException e) {
-            e.printStackTrace();
-            return false;
-        }
-
-        if (startupMode != REMOTE_MODE) {
-            // Configure the debugger with the primitive type sizes just obtained from the VM
-            debugger.configureJavaPrimitiveTypeSizes(db.getJBooleanType().getSize(),
-            db.getJByteType().getSize(),
-            db.getJCharType().getSize(),
-            db.getJDoubleType().getSize(),
-            db.getJFloatType().getSize(),
-            db.getJIntType().getSize(),
-            db.getJLongType().getSize(),
-            db.getJShortType().getSize());
-        }
-
-        if (!isServer) {
-            // Do not initialize the VM on the server (unnecessary, since it's
-            // instantiated on the client)
-            VM.initialize(db, debugger);
-        }
-
-        try {
-            jvmdi = new ServiceabilityAgentJVMDIModule(debugger, saLibNames);
-            if (jvmdi.canAttach()) {
-                jvmdi.attach();
-                jvmdi.setCommandTimeout(6000);
-                debugPrintln("Attached to Serviceability Agent's JVMDI module.");
-                // Jog VM to suspended point with JVMDI module
-                resume();
-                suspendJava();
-                suspend();
-                debugPrintln("Suspended all Java threads.");
-            } else {
-                debugPrintln("Could not locate SA's JVMDI module; skipping attachment");
-                jvmdi = null;
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            jvmdi = null;
-        }
-
-        return true;
-    }
-
-    //--------------------------------------------------------------------------------
-    // OS-specific debugger setup/connect routines
-    //
-
-    //
-    // Solaris
-    //
-
-    private void setupDebuggerSolaris() {
-        setupJVMLibNamesSolaris();
-        ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true);
-        debugger = dbg;
-        attachDebugger();
-
-        // Set up CPU-dependent stuff
-        if (cpu.equals("x86")) {
-            machDesc = new MachineDescriptionIntelX86();
-        } else if (cpu.equals("sparc")) {
-            int addressSize = dbg.getRemoteProcessAddressSize();
-            if (addressSize == -1) {
-                throw new DebuggerException("Error occurred while trying to determine the remote process's address size");
-            }
-
-            if (addressSize == 32) {
-                machDesc = new MachineDescriptionSPARC32Bit();
-            } else if (addressSize == 64) {
-                machDesc = new MachineDescriptionSPARC64Bit();
-            } else {
-                throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
-            }
-        } else if (cpu.equals("amd64")) {
-            machDesc = new MachineDescriptionAMD64();
-        } else {
-            throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64");
-        }
-
-        dbg.setMachineDescription(machDesc);
-    }
-
-    private void connectRemoteDebugger() throws DebuggerException {
-        RemoteDebugger remote =
-        (RemoteDebugger) RMIHelper.lookup(debugServerID);
-        debugger = new RemoteDebuggerClient(remote);
-        machDesc = ((RemoteDebuggerClient) debugger).getMachineDescription();
-        os = debugger.getOS();
-        if (os.equals("solaris")) {
-            setupJVMLibNamesSolaris();
-        } else if (os.equals("win32")) {
-            setupJVMLibNamesWin32();
-        } else if (os.equals("linux")) {
-            setupJVMLibNamesLinux();
-        } else if (os.equals("bsd")) {
-            setupJVMLibNamesBsd();
-        } else {
-            throw new RuntimeException("Unknown OS type");
-        }
-
-        cpu = debugger.getCPU();
-    }
-
-    private void setupJVMLibNamesSolaris() {
-        jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so", "gamma_g" };
-        saLibNames = new String[] { "libsa.so", "libsa_g.so" };
-    }
-
-    //
-    // Win32
-    //
-
-    private void setupDebuggerWin32() {
-        setupJVMLibNamesWin32();
-
-        if (cpu.equals("x86")) {
-            machDesc = new MachineDescriptionIntelX86();
-        } else if (cpu.equals("amd64")) {
-            machDesc = new MachineDescriptionAMD64();
-        } else if (cpu.equals("ia64")) {
-            machDesc = new MachineDescriptionIA64();
-        } else {
-            throw new DebuggerException("Win32 supported under x86, amd64 and ia64 only");
-        }
-
-        // Note we do not use a cache for the local debugger in server
-        // mode; it will be taken care of on the client side (once remote
-        // debugging is implemented).
-
-        debugger = new WindbgDebuggerLocal(machDesc, !isServer);
-
-        attachDebugger();
-    }
-
-    private void setupJVMLibNamesWin32() {
-        jvmLibNames = new String[] { "jvm.dll", "jvm_g.dll" };
-        saLibNames = new String[] { "sa.dll", "sa_g.dll" };
-    }
-
-    //
-    // Linux
-    //
-
-    private void setupDebuggerLinux() {
-        setupJVMLibNamesLinux();
-
-        if (cpu.equals("x86")) {
-            machDesc = new MachineDescriptionIntelX86();
-        } else if (cpu.equals("ia64")) {
-            machDesc = new MachineDescriptionIA64();
-        } else if (cpu.equals("amd64")) {
-            machDesc = new MachineDescriptionAMD64();
-        } else if (cpu.equals("sparc")) {
-            if (LinuxDebuggerLocal.getAddressSize()==8) {
-               machDesc = new MachineDescriptionSPARC64Bit();
-            } else {
-               machDesc = new MachineDescriptionSPARC32Bit();
-            }
-        } else {
-          try {
-            machDesc = (MachineDescription)
-              Class.forName("sun.jvm.hotspot.debugger.MachineDescription" +
-              cpu.toUpperCase()).newInstance();
-          } catch (Exception e) {
-            throw new DebuggerException("unsupported machine type");
-          }
-        }
-
-
-        // Note we do not use a cache for the local debugger in server
-        // mode; it will be taken care of on the client side (once remote
-        // debugging is implemented).
-
-        debugger = new LinuxDebuggerLocal(machDesc, !isServer);
-        attachDebugger();
-    }
-
-    private void setupJVMLibNamesLinux() {
-        // same as solaris
-        setupJVMLibNamesSolaris();
-    }
-
-    //
-    // BSD
-    //
-
-    private void setupDebuggerBsd() {
-        setupJVMLibNamesBsd();
-
-        if (cpu.equals("x86")) {
-            machDesc = new MachineDescriptionIntelX86();
-        } else if (cpu.equals("amd64") || (cpu.equals("x86_64"))) {
-            machDesc = new MachineDescriptionAMD64();
-        } else {
-            throw new DebuggerException("Bsd only supported on x86/x86_64. Current arch: " + cpu);
-        }
-
-        // Note we do not use a cache for the local debugger in server
-        // mode; it will be taken care of on the client side (once remote
-        // debugging is implemented).
-
-        debugger = new BsdDebuggerLocal(machDesc, !isServer);
-        attachDebugger();
-    }
-
-    private void setupJVMLibNamesBsd() {
-        // same as solaris
-        setupJVMLibNamesSolaris();
-    }
-
-    /** Convenience routine which should be called by per-platform
-      debugger setup. Should not be called when startupMode is
-      REMOTE_MODE. */
-    private void attachDebugger() {
-        if (startupMode == PROCESS_MODE) {
-            debugger.attach(pid);
-        } else if (startupMode == CORE_FILE_MODE) {
-            debugger.attach(executableName, coreFileName);
-        } else {
-            throw new DebuggerException("Should not call attach() for startupMode == " + startupMode);
-        }
-    }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/JavaLineNumberInfo.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import sun.jvm.hotspot.oops.*;
-
-/** Wrapper class which describes line number information for Java
-    class files. The line number table is converted into this
-    representation on demand. These objects are then sorted by line
-    number for fast lookup when setting breakpoints in a particular
-    source file. */
-
-public class JavaLineNumberInfo {
-  private InstanceKlass klass;
-  private Method method;
-  private int startBCI;
-  private int lineNumber;
-
-  public JavaLineNumberInfo(InstanceKlass klass,
-                            Method method,
-                            int startBCI,
-                            int lineNumber) {
-    this.klass = klass;
-    this.method = method;
-    this.startBCI = startBCI;
-    this.lineNumber = lineNumber;
-  }
-
-  public InstanceKlass getKlass()      { return klass; }
-  public Method        getMethod()     { return method; }
-  public int           getStartBCI()   { return startBCI; }
-  public int           getLineNumber() { return lineNumber; }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/Main.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-
-import sun.jvm.hotspot.ui.*;
-
-/** The main class for the BugSpot debugger. */
-
-public class Main {
-  public static void main(String[] args) {
-    JFrame frame = new JFrame("BugSpot");
-    frame.setSize(800, 600);
-    BugSpot db = new BugSpot();
-    db.setMDIMode(true);
-    db.build();
-    frame.setJMenuBar(db.getMenuBar());
-    frame.getContentPane().add(db);
-    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
-
-    GraphicsUtilities.reshapeToAspectRatio(frame,
-                                           4.0f/3.0f, 0.85f, Toolkit.getDefaultToolkit().getScreenSize());
-    GraphicsUtilities.centerInContainer(frame,
-                                        Toolkit.getDefaultToolkit().getScreenSize());
-    frame.setVisible(true);
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/PCFinder.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.debugger.cdbg.*;
-
-/** Helper class for locating a program counter. Indicates the
-    confidence of the find. */
-
-public class PCFinder {
-  public static final int LOW_CONFIDENCE = 1;
-  public static final int HIGH_CONFIDENCE = 2;
-
-  public static class Info {
-    private String name;
-    private long   offset;
-    private int    confidence;
-
-    public Info(String name, long offset, int confidence) {
-      this.name = name;
-      this.offset = offset;
-      this.confidence = confidence;
-    }
-
-    /** May be null */
-    public String getName()       { return name;       }
-
-    /** If this is -1, a symbol could not be found, and the offset
-        should not be shown */
-    public long   getOffset()     { return offset;     }
-
-    /** PCFinder.LOW_CONFIDENCE or PCFinder.HIGH_CONFIDENCE */
-    public int    getConfidence() { return confidence; }
-  }
-
-  /** Passed loadobject may be null in which case the returned Info
-      object has low confidence */
-  public static Info findPC(Address pc, LoadObject lo, CDebugger dbg) {
-    if (lo == null) {
-      return new Info(null, -1, LOW_CONFIDENCE);
-    }
-
-    // First try debug info
-    BlockSym sym = lo.debugInfoForPC(pc);
-    while (sym != null) {
-      if (sym.isFunction()) {
-        // Highest confidence
-        return new Info(sym.toString(), pc.minus(sym.getAddress()), HIGH_CONFIDENCE);
-      }
-    }
-
-    // Now try looking up symbol in loadobject
-
-    // FIXME: must add support for mapfiles on Win32 and try looking
-    // up there first if possible. Should we hide that behind
-    // LoadObject.closestSymbolToPC and have the ClosestSymbol return
-    // confidence? I think so. On Solaris there is no notion of a
-    // mapfile, and the confidence for closestSymbolToPC will be high
-    // instead of low.
-
-    int confidence = HIGH_CONFIDENCE;
-
-    ClosestSymbol cs = lo.closestSymbolToPC(pc);
-    if (cs != null) {
-      // FIXME: currently low confidence (only on Win32)
-      return new Info(cs.getName() + "()", cs.getOffset(), LOW_CONFIDENCE);
-    }
-
-    // Unknown location
-    return new Info(dbg.getNameOfFile(lo.getName()).toUpperCase() +
-                    "! " + pc + "()", -1, HIGH_CONFIDENCE);
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/PackageScanner.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import java.io.*;
-
-/** Scans a .java file for the package that it is in. */
-
-public class PackageScanner {
-
-  public PackageScanner() {
-  }
-
-  public String scan(String filename) {
-    return scan(new File(filename));
-  }
-
-  /** Returns the String comprising the package name of the classes in
-      this .java file. Returns the (non-null) empty string if any
-      error occurs or if the classes are in the unnamed package. */
-  public String scan(File file) {
-    BufferedReader buf = null;
-    String res = "";
-    try {
-      buf = new BufferedReader(new FileReader(file));
-      StreamTokenizer tok = new StreamTokenizer(buf);
-      tok.slashStarComments(true);
-      tok.slashSlashComments(true);
-      if (tok.nextToken() != StreamTokenizer.TT_WORD) {
-        return res;
-      }
-      if (!tok.sval.equals("package")) {
-        return res;
-      }
-      if (tok.nextToken() != StreamTokenizer.TT_WORD) {
-        return res;
-      }
-      res = tok.sval;
-      return res;
-    } catch (FileNotFoundException e) {
-      return res;
-    } catch (IOException e) {
-      return res;
-    } finally {
-      try {
-        if (buf != null) {
-          buf.close();
-        }
-      } catch (IOException e) {
-      }
-    }
-  }
-
-  public static void main(String[] args) {
-    if (args.length != 1) {
-      usage();
-    }
-
-    System.out.println(new PackageScanner().scan(args[0]));
-  }
-
-  private static void usage() {
-    System.err.println("Usage: java PackageScanner <.java file name>");
-    System.err.println("Prints package the .java file is in to stdout.");
-    System.exit(1);
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/RegisterPanel.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import java.awt.*;
-import java.util.*;
-import javax.swing.*;
-import javax.swing.table.*;
-
-import sun.jvm.hotspot.debugger.*;
-
-/** Displays registers in a window. FIXME: this will need more work to
-    understand and handle register windows. */
-
-public class RegisterPanel extends JPanel {
-  private java.util.List/*<RegisterInfo>*/ registers;
-  private AbstractTableModel dataModel;
-  private boolean valid;
-  private boolean editable;
-  private String nullAddressString;
-  private ThreadProxy curThread;
-  private JTable table;
-
-  static class RegisterInfo {
-    private String name;
-    private Address value;
-
-    RegisterInfo(String name, Address value) {
-      this.name = name;
-      this.value = value;
-    }
-
-    String  getName()  { return name;  }
-    Address getValue() { return value; }
-  }
-
-  public RegisterPanel() {
-    super();
-
-    registers = new ArrayList();
-
-    dataModel = new AbstractTableModel() {
-        public int getColumnCount() { return 2; }
-        public int getRowCount()    { return registers.size(); }
-        public String getColumnName(int col) {
-          switch (col) {
-          case 0:
-            return "Register Name";
-          case 1:
-            return "Register Value";
-          default:
-            throw new RuntimeException("Index " + col + " out of bounds");
-          }
-        }
-        public Object getValueAt(int row, int col) {
-          RegisterInfo info = (RegisterInfo) registers.get(row);
-
-          switch (col) {
-          case 0:
-            return info.getName();
-          case 1:
-            if (valid) {
-              Address val = info.getValue();
-              if (val != null) {
-                return val;
-              } else {
-                return nullAddressString;
-              }
-            } else {
-              return "-";
-            }
-          default:
-            throw new RuntimeException("Index (" + col + ", " + row + ") out of bounds");
-          }
-        }
-        public boolean isCellEditable(int row, int col) {
-          if (col == 0) return false;
-          if (!valid) return false;
-          if (curThread == null) return false;
-          if (!curThread.canSetContext()) return false;
-
-          // FIXME: add listener to watch for register changes
-          //          return true;
-          return false;
-        }
-      };
-
-    // Build user interface
-    setLayout(new BorderLayout());
-    table = new JTable(dataModel);
-    table.setCellSelectionEnabled(true);
-    table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
-    table.setDragEnabled(true);
-    JTableHeader header = table.getTableHeader();
-    header.setReorderingAllowed(false);
-    JScrollPane scrollPane = new JScrollPane(table);
-    add(scrollPane, BorderLayout.CENTER);
-  }
-
-
-  /** Updates the register panel with the register set from the
-      specified thread. Call this when the process has been suspended
-      and the current thread has been set. FIXME: this interface will
-      need to change to support register windows. */
-  public void update(ThreadProxy curThread) {
-    this.curThread = curThread;
-    ThreadContext context = curThread.getContext();
-    editable = curThread.canSetContext();
-    registers.clear();
-    for (int i = 0; i < context.getNumRegisters(); i++) {
-      String name = context.getRegisterName(i);
-      Address addr = context.getRegisterAsAddress(i);
-      if ((nullAddressString == null) && (addr != null)) {
-        String addrStr = addr.toString();
-        StringBuffer buf = new StringBuffer();
-        buf.append("0x");
-        int len = addrStr.length() - 2;
-        for (int j = 0; j < len; j++) {
-          buf.append("0");
-        }
-        nullAddressString = buf.toString();
-      }
-      registers.add(new RegisterInfo(name, addr));
-    }
-    valid = true;
-    SwingUtilities.invokeLater(new Runnable() {
-        public void run() {
-          dataModel.fireTableDataChanged();
-        }
-      });
-  }
-
-  /** Clears the registers' values. Call this when the processs has
-      been resumed. */
-  public void clear() {
-    valid = false;
-    nullAddressString = null;
-    SwingUtilities.invokeLater(new Runnable() {
-        public void run() {
-          dataModel.fireTableDataChanged();
-        }
-      });
-  }
-
-  public void setFont(Font font) {
-    super.setFont(font);
-    if (table != null) {
-      table.setFont(font);
-    }
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTraceEntry.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-
-/** This class describes a frame in a stack trace. It abstracts over
-    C/C++ and Java frames. */
-
-public class StackTraceEntry {
-  private CFrame cFrame;
-  private CDebugger dbg;
-  private JavaVFrame javaFrame;
-  private String value; // What is displayed in a stack trace
-  // For merging C and Java stack traces.
-  // For more precise stack traces, should probably have a way to
-  // convert a CFrame to a sun.jvm.hotspot.runtime.Frame. For now,
-  // doing similar algorithm to jdbx (which does not have intimate
-  // knowledge of the VM).
-  private boolean isUnknownCFrame;
-
-  public StackTraceEntry(CFrame cFrame, CDebugger dbg) {
-    this.cFrame = cFrame;
-    this.dbg = dbg;
-    computeValue();
-  }
-
-  public StackTraceEntry(JavaVFrame javaFrame) {
-    this.javaFrame = javaFrame;
-    computeValue();
-  }
-
-  public boolean    isCFrame()     { return (cFrame != null);    }
-  public boolean    isJavaFrame()  { return (javaFrame != null); }
-  public CFrame     getCFrame()    { return cFrame;              }
-  public JavaVFrame getJavaFrame() { return javaFrame;           }
-  public boolean    isUnknownCFrame() { return isUnknownCFrame;  }
-  public String toString() {
-    return value;
-  }
-
-  private void computeValue() {
-    isUnknownCFrame = true;
-    value = "<unknown>";
-    if (cFrame != null) {
-      PCFinder.Info info = PCFinder.findPC(cFrame.pc(), cFrame.loadObjectForPC(), dbg);
-      if (info.getName() != null) {
-        value = "(C) " + info.getName();
-        isUnknownCFrame = false;
-        if (info.getConfidence() == PCFinder.LOW_CONFIDENCE) {
-          value = value + " (?)";
-        }
-        if (info.getOffset() >= 0) {
-          value = value + " + 0x" + Long.toHexString(info.getOffset());
-        }
-      }
-    } else if (javaFrame != null) {
-      isUnknownCFrame = false;
-      Method m = javaFrame.getMethod();
-      value = "(J) " + m.externalNameAndSignature();
-    }
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTracePanel.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.util.*;
-import javax.swing.*;
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.ui.*;
-
-/** This panel contains a ListBox with all of the stack frames in a
-    given thread. When a given entry is selected, an event is
-    fired. */
-
-public class StackTracePanel extends JPanel {
-  public interface Listener {
-    public void frameChanged(CFrame fr, JavaVFrame jfr);
-  }
-
-  class Model extends AbstractListModel implements ComboBoxModel {
-    private Object selectedItem;
-    public Object getElementAt(int index) {
-      if (trace == null) return null;
-      return trace.get(index);
-    }
-    public int getSize() {
-      if (trace == null) return 0;
-      return trace.size();
-    }
-    public Object getSelectedItem() {
-      return selectedItem;
-    }
-    public void setSelectedItem(Object item) {
-      selectedItem = item;
-    }
-    public void dataChanged() {
-      fireContentsChanged(this, 0, trace.size());
-    }
-  }
-
-  private java.util.List trace;
-  private Model model;
-  private JComboBox list;
-  private java.util.List listeners;
-
-  public StackTracePanel() {
-    super();
-
-    model = new Model();
-
-    // Build user interface
-    setLayout(new BorderLayout());
-    setBorder(GraphicsUtilities.newBorder(5));
-    list = new JComboBox(model);
-    list.setPrototypeDisplayValue("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
-    add(list, BorderLayout.CENTER);
-
-    // Add selection listener
-    list.addItemListener(new ItemListener() {
-        public void itemStateChanged(ItemEvent e) {
-          if (e.getStateChange() == ItemEvent.SELECTED) {
-            fireFrameChanged();
-          }
-        }
-      });
-  }
-
-  /** Takes a List of StackTraceEntry objects */
-  public void setTrace(java.util.List trace) {
-    this.trace = trace;
-    model.dataChanged();
-    list.setSelectedIndex(0);
-    fireFrameChanged();
-  }
-
-  public void addListener(Listener listener) {
-    if (listeners == null) {
-      listeners = new ArrayList();
-    }
-    listeners.add(listener);
-  }
-
-  protected void fireFrameChanged() {
-    if (listeners != null) {
-      StackTraceEntry entry = (StackTraceEntry) trace.get(list.getSelectedIndex());
-      for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
-        ((Listener) iter.next()).frameChanged(entry.getCFrame(), entry.getJavaFrame());
-      }
-    }
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/ThreadListPanel.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.util.*;
-import javax.swing.*;
-import javax.swing.table.*;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.ui.*;
-
-// NOTE: this class was not placed in sun.jvm.hotspot.ui to prevent
-// mixing components designed for C and C++ debugging with the ones
-// that work with the core serviceability agent functionality (which
-// does not require that the CDebugger interface be implemented).
-
-/** The ThreadListPanel is used for C and C++ debugging and can
-    visualize all threads in the target process. The caller passes in
-    a CDebugger attached to the target process and can request that
-    JavaThreads' associations with these underlying threads be
-    displayed; this option is only valid when attached to a HotSpot
-    JVM and when the {@link sun.jvm.hotspot.runtime.VM} has been
-    initialized. */
-
-public class ThreadListPanel extends JPanel {
-  /** Listener which can be added to receive "Set Focus" events */
-  public static interface Listener {
-    /** ThreadProxy will always be provided; JavaThread will only be
-        present if displayJavaThreads was specified in the constructor
-        for the panel and the thread was a JavaThread. */
-    public void setFocus(ThreadProxy thread, JavaThread jthread);
-  }
-
-  static class ThreadInfo {
-    private ThreadProxy thread;
-    // Distinguish between PC == null and no top frame
-    private boolean     gotPC;
-    private Address     pc;
-    private String      location;
-    private JavaThread  javaThread;
-    private String      javaThreadName;
-
-    public ThreadInfo(ThreadProxy thread, CDebugger dbg, JavaThread jthread) {
-      this.thread = thread;
-      this.location = "<unknown>";
-      CFrame fr = dbg.topFrameForThread(thread);
-      if (fr != null) {
-        gotPC = true;
-        pc = fr.pc();
-        PCFinder.Info info = PCFinder.findPC(pc, fr.loadObjectForPC(), dbg);
-        if (info.getName() != null) {
-          location = info.getName();
-          if (info.getConfidence() == PCFinder.LOW_CONFIDENCE) {
-            location = location + " (?)";
-          }
-          if (info.getOffset() < 0) {
-            location = location + " + 0x" + Long.toHexString(info.getOffset());
-          }
-        }
-      }
-      if (jthread != null) {
-        javaThread = jthread;
-        javaThreadName = jthread.getThreadName();
-      }
-    }
-
-    public ThreadProxy getThread()    { return thread;       }
-    public boolean     hasPC()        { return gotPC;        }
-    public Address     getPC()        { return pc;           }
-    public String      getLocation()  { return location;     }
-    public boolean     isJavaThread() { return (javaThread != null); }
-    public JavaThread  getJavaThread() { return javaThread; }
-    public String      getJavaThreadName() { return javaThreadName; }
-  }
-
-  // List<ThreadInfo>
-  private java.util.List threadList;
-  private JTable table;
-  private AbstractTableModel dataModel;
-  // List<Listener>
-  private java.util.List listeners;
-
-  /** Takes a CDebugger from which the thread list is queried.
-      displayJavaThreads must only be set to true if the debugger is
-      attached to a HotSpot JVM and if the VM has already been
-      initialized. */
-  public ThreadListPanel(CDebugger dbg, final boolean displayJavaThreads) {
-    super();
-
-    Map threadToJavaThreadMap = null;
-    if (displayJavaThreads) {
-      // Collect Java threads from virtual machine and insert them in
-      // table for later querying
-      threadToJavaThreadMap = new HashMap();
-      Threads threads = VM.getVM().getThreads();
-      for (JavaThread thr = threads.first(); thr != null; thr = thr.next()) {
-        threadToJavaThreadMap.put(thr.getThreadProxy(), thr);
-      }
-    }
-
-    java.util.List/*<ThreadProxy>*/ threads = dbg.getThreadList();
-    threadList = new ArrayList(threads.size());
-    for (Iterator iter = threads.iterator(); iter.hasNext(); ) {
-      ThreadProxy thr = (ThreadProxy) iter.next();
-      JavaThread jthr = null;
-      if (displayJavaThreads) {
-        jthr = (JavaThread) threadToJavaThreadMap.get(thr);
-      }
-      threadList.add(new ThreadInfo(thr, dbg, jthr));
-    }
-
-    // Thread ID, current PC, current symbol, Java Thread, [Java thread name]
-    dataModel = new AbstractTableModel() {
-        public int getColumnCount() { return (displayJavaThreads ? 5 : 3); }
-        public int getRowCount()    { return threadList.size(); }
-        public String getColumnName(int col) {
-          switch (col) {
-          case 0:
-            return "Thread ID";
-          case 1:
-            return "PC";
-          case 2:
-            return "Location";
-          case 3:
-            return "Java?";
-          case 4:
-            return "Java Thread Name";
-          default:
-            throw new RuntimeException("Index " + col + " out of bounds");
-          }
-        }
-        public Object getValueAt(int row, int col) {
-          ThreadInfo info = (ThreadInfo) threadList.get(row);
-
-          switch (col) {
-          case 0:
-            return info.getThread();
-          case 1:
-            {
-              if (info.hasPC()) {
-                return info.getPC();
-              }
-              return "<no frames on stack>";
-            }
-          case 2:
-            return info.getLocation();
-          case 3:
-            if (info.isJavaThread()) {
-              return "Yes";
-            } else {
-              return "";
-            }
-          case 4:
-            if (info.isJavaThread()) {
-              return info.getJavaThreadName();
-            } else {
-              return "";
-            }
-          default:
-            throw new RuntimeException("Index (" + col + ", " + row + ") out of bounds");
-          }
-        }
-      };
-
-    // Build user interface
-    setLayout(new BorderLayout());
-    table = new JTable(dataModel);
-    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-    JTableHeader header = table.getTableHeader();
-    header.setReorderingAllowed(false);
-    table.setRowSelectionAllowed(true);
-    table.setColumnSelectionAllowed(false);
-    JScrollPane scrollPane = new JScrollPane(table);
-    add(scrollPane, BorderLayout.CENTER);
-    if (threadList.size() > 0) {
-      table.setRowSelectionInterval(0, 0);
-    }
-
-    JButton button = new JButton("Set Focus");
-    button.addActionListener(new ActionListener() {
-        public void actionPerformed(ActionEvent e) {
-          int i = table.getSelectedRow();
-          if (i < 0) {
-            return;
-          }
-          ThreadInfo info = (ThreadInfo) threadList.get(i);
-          for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
-            ((Listener) iter.next()).setFocus(info.getThread(), info.getJavaThread());
-          }
-        }
-      });
-    JPanel focusPanel = new JPanel();
-    focusPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
-    focusPanel.setLayout(new BoxLayout(focusPanel, BoxLayout.Y_AXIS));
-    focusPanel.add(Box.createGlue());
-    focusPanel.add(button);
-    focusPanel.add(Box.createGlue());
-    add(focusPanel, BorderLayout.EAST);
-
-    // FIXME: make listener model for the debugger so if the user
-    // specifies a mapfile for or path to a given DSO later we can
-    // update our state
-  }
-
-  public void addListener(Listener l) {
-    if (listeners == null) {
-      listeners = new ArrayList();
-    }
-    listeners.add(l);
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/VariablePanel.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-/*
- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot;
-
-import java.awt.*;
-import javax.swing.*;
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.bugspot.tree.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.ui.tree.*;
-import sun.jvm.hotspot.ui.treetable.*;
-
-/** Manages display of a set of local variables in a frame, or the
-    contents of the "this" pointer */
-
-public class VariablePanel extends JPanel {
-  private JTreeTable treeTable;
-  private SimpleTreeTableModel model;
-  private SimpleTreeGroupNode root;
-
-  public VariablePanel() {
-    super();
-
-    model = new SimpleTreeTableModel();
-    model.setValuesEditable(false);
-    root = new SimpleTreeGroupNode();
-    model.setRoot(root);
-    treeTable = new JTreeTable(model);
-    treeTable.setRootVisible(false);
-    treeTable.setShowsRootHandles(true);
-    treeTable.setShowsIcons(false);
-    treeTable.setTreeEditable(false);
-    treeTable.getTableHeader().setReorderingAllowed(false);
-    treeTable.setCellSelectionEnabled(true);
-    treeTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
-    treeTable.setDragEnabled(true);
-    JScrollPane sp = new JScrollPane(treeTable);
-    sp.getViewport().setBackground(Color.white);
-
-    setLayout(new BorderLayout());
-    add(sp, BorderLayout.CENTER);
-  }
-
-  /** Clear the contents of this VariablePanel */
-  public void clear() {
-    root.removeAllChildren();
-    model.fireTreeStructureChanged();
-  }
-
-  /** Update the contents of this VariablePanel from the given CFrame */
-  public void update(CFrame fr) {
-    // Collect locals
-    CCollector coll = new CCollector();
-    fr.iterateLocals(coll);
-    update(coll);
-  }
-
-  /** Update the contents of this VariablePanel from the given JavaVFrame */
-  public void update(JavaVFrame jfr) {
-    Method m = jfr.getMethod();
-    if (!m.hasLocalVariableTable()) {
-      return;
-    }
-    int bci = jfr.getBCI();
-    // Get local variable table
-    LocalVariableTableElement[] locals = m.getLocalVariableTable();
-    // Get locals as StackValueCollection
-    StackValueCollection coll = jfr.getLocals();
-    root.removeAllChildren();
-    // See which locals are live
-    for (int i = 0; i < locals.length; i++) {
-      LocalVariableTableElement local = locals[i];
-      if (local.getStartBCI() <= bci && bci < local.getStartBCI() + local.getLength()) {
-        // Valid; add it
-        SimpleTreeNode node = null;
-        Symbol name = null;
-        try {
-          name = m.getConstants().getSymbolAt(local.getNameCPIndex());
-          if (name == null) {
-            System.err.println("Null name at slot " +
-                               local.getNameCPIndex() +
-                               " for local variable at slot " +
-                               local.getSlot());
-            continue;
-          }
-        } catch (Exception e) {
-          System.err.println("Unable to fetch name at slot " +
-                             local.getNameCPIndex() +
-                             " for local variable at slot " +
-                             local.getSlot());
-          e.printStackTrace();
-          continue;
-        }
-        sun.jvm.hotspot.oops.NamedFieldIdentifier f =
-          new sun.jvm.hotspot.oops.NamedFieldIdentifier(name.asString());
-        Symbol descriptor = null;
-        try {
-          descriptor = m.getConstants().getSymbolAt(local.getDescriptorCPIndex());
-        } catch (Exception e) {
-          System.err.println("Unable to fetch descriptor at slot " +
-                             local.getDescriptorCPIndex() +
-                             " for local variable " + f.getName() +
-                             " at slot " + local.getSlot());
-          e.printStackTrace();
-          continue;
-        }
-
-        if (descriptor != null) {
-          switch (descriptor.getByteAt(0)) {
-          case 'F': {
-            node = new sun.jvm.hotspot.ui.tree.FloatTreeNodeAdapter(coll.floatAt(local.getSlot()), f, true);
-            break;
-          }
-          case 'D': {
-            node = new sun.jvm.hotspot.ui.tree.DoubleTreeNodeAdapter(coll.doubleAt(local.getSlot()), f, true);
-            break;
-          }
-          case 'C': {
-            node = new sun.jvm.hotspot.ui.tree.CharTreeNodeAdapter((char) coll.intAt(local.getSlot()), f, true);
-            break;
-          }
-          case 'B':
-          case 'S':
-          case 'I': {
-            node = new sun.jvm.hotspot.ui.tree.LongTreeNodeAdapter(coll.intAt(local.getSlot()), f, true);
-            break;
-          }
-          case 'Z': {
-            node = new sun.jvm.hotspot.ui.tree.BooleanTreeNodeAdapter(
-              ((coll.intAt(local.getSlot()) != 0) ? true : false), f, true
-            );
-            break;
-          }
-          case 'J': {
-            node = new sun.jvm.hotspot.ui.tree.LongTreeNodeAdapter(coll.longAt(local.getSlot()), f, true);
-            break;
-          }
-          default: {
-            try {
-              node = new sun.jvm.hotspot.ui.tree.OopTreeNodeAdapter(
-                VM.getVM().getObjectHeap().newOop(coll.oopHandleAt(local.getSlot())), f, true
-              );
-            } catch (AddressException e) {
-              node = new sun.jvm.hotspot.ui.tree.FieldTreeNodeAdapter(f, true) {
-                  public int getChildCount()                       { return 0;     }
-                  public SimpleTreeNode getChild(int i)            { return null;  }
-                  public boolean isLeaf()                          { return false; }
-                  public int getIndexOfChild(SimpleTreeNode child) { return 0;     }
-                  public String getValue() {
-                    return "<Bad oop>";
-                  }
-                };
-            }
-            break;
-          }
-          }
-          if (node != null) {
-            root.addChild(node);
-          }
-        }
-      }
-    }
-
-    model.fireTreeStructureChanged();
-  }
-
-  /** Update the contents of this VariablePanel from the given "this"
-      pointer of the given type */
-  public void update(Address thisAddr, Type type) {
-    // Collect fields
-    CCollector coll = new CCollector();
-    type.iterateObject(thisAddr, coll);
-    update(coll);
-  }
-
-  private void update(CCollector coll) {
-    root.removeAllChildren();
-    for (int i = 0; i < coll.getNumChildren(); i++) {
-      root.addChild(coll.getChild(i));
-    }
-    model.fireTreeStructureChanged();
-  }
-
-  static class CCollector extends DefaultObjectVisitor {
-    private java.util.List children;
-
-    public CCollector() {
-      children = new ArrayList();
-    }
-
-    public int getNumChildren() {
-      return children.size();
-    }
-
-    public SimpleTreeNode getChild(int i) {
-      return (SimpleTreeNode) children.get(i);
-    }
-
-    public void doBit(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val) {
-      children.add(new sun.jvm.hotspot.bugspot.tree.LongTreeNodeAdapter(val, f, true));
-    }
-    public void doInt(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val) {
-      children.add(new sun.jvm.hotspot.bugspot.tree.LongTreeNodeAdapter(val, f, true));
-    }
-    public void doEnum(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val, String enumName) {
-      children.add(new sun.jvm.hotspot.bugspot.tree.EnumTreeNodeAdapter(enumName, val, f, true));
-    }
-    public void doFloat(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, float val) {
-      children.add(new sun.jvm.hotspot.bugspot.tree.FloatTreeNodeAdapter(val, f, true));
-    }
-    public void doDouble(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, double val) {
-      children.add(new sun.jvm.hotspot.bugspot.tree.DoubleTreeNodeAdapter(val, f, true));
-    }
-    public void doPointer(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
-      children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true));
-    }
-    public void doArray(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
-      children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true));
-    }
-    public void doRef(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
-      children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true));
-    }
-    public void doCompound(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
-      children.add(new sun.jvm.hotspot.bugspot.tree.ObjectTreeNodeAdapter(val, f, true));
-    }
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/AddressTreeNodeAdapter.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot.tree;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
-
-/** Encapsulates a float value in a tree handled by SimpleTreeModel */
-
-public class AddressTreeNodeAdapter extends FieldTreeNodeAdapter {
-  private Address val;
-
-  public AddressTreeNodeAdapter(Address val, FieldIdentifier id) {
-    this(val, id, false);
-  }
-
-  public AddressTreeNodeAdapter(Address val, FieldIdentifier id, boolean treeTableMode) {
-    super(id, treeTableMode);
-    this.val = val;
-  }
-
-  public int getChildCount() {
-    return 0;
-  }
-
-  public SimpleTreeNode getChild(int index) {
-    return null;
-  }
-
-  public boolean isLeaf() {
-    return true;
-  }
-
-  public int getIndexOfChild(SimpleTreeNode child) {
-    return 0;
-  }
-
-  public String getValue() {
-    if (val != null) {
-      return val.toString();
-    }
-    return "NULL";
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/DoubleTreeNodeAdapter.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot.tree;
-
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
-
-/** Encapsulates a double value in a tree handled by SimpleTreeModel */
-
-public class DoubleTreeNodeAdapter extends FieldTreeNodeAdapter {
-  private double val;
-
-  public DoubleTreeNodeAdapter(double val, FieldIdentifier id) {
-    this(val, id, false);
-  }
-
-  public DoubleTreeNodeAdapter(double val, FieldIdentifier id, boolean treeTableMode) {
-    super(id, treeTableMode);
-    this.val = val;
-  }
-
-  public int getChildCount() {
-    return 0;
-  }
-
-  public SimpleTreeNode getChild(int index) {
-    return null;
-  }
-
-  public boolean isLeaf() {
-    return true;
-  }
-
-  public int getIndexOfChild(SimpleTreeNode child) {
-    return 0;
-  }
-
-  public String getValue() {
-    return Double.toString(val);
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/EnumTreeNodeAdapter.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot.tree;
-
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
-
-/** Encapsulates an enumerated value in a tree handled by SimpleTreeModel */
-
-public class EnumTreeNodeAdapter extends FieldTreeNodeAdapter {
-  private long val;
-  private String enumName;
-
-  public EnumTreeNodeAdapter(String enumName, long val, FieldIdentifier id) {
-    this(enumName, val, id, false);
-  }
-
-  public EnumTreeNodeAdapter(String enumName, long val, FieldIdentifier id, boolean treeTableMode) {
-    super(id, treeTableMode);
-    this.enumName = enumName;
-    this.val = val;
-  }
-
-  public int getChildCount() {
-    return 0;
-  }
-
-  public SimpleTreeNode getChild(int index) {
-    return null;
-  }
-
-  public boolean isLeaf() {
-    return true;
-  }
-
-  public int getIndexOfChild(SimpleTreeNode child) {
-    return 0;
-  }
-
-  public String getValue() {
-    if (enumName != null) {
-      return enumName;
-    } else {
-      return Long.toString(val);
-    }
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FieldTreeNodeAdapter.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot.tree;
-
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
-
-/** Abstract base class for all adapters for fields of C/C++ objects */
-
-public abstract class FieldTreeNodeAdapter implements SimpleTreeNode {
-  private FieldIdentifier id;
-  private boolean         treeTableMode;
-
-  /** The identifier may be null, i.e., for the root of the tree */
-  public FieldTreeNodeAdapter(FieldIdentifier id, boolean treeTableMode) {
-    this.id = id;
-    this.treeTableMode = treeTableMode;
-  }
-
-  public FieldIdentifier getID() {
-    return id;
-  }
-
-  /** Defaults to false in subclasses */
-  public boolean getTreeTableMode() {
-    return treeTableMode;
-  }
-
-  public Type getType() {
-    return getID().getType();
-  }
-
-  public String getName() {
-    if (getID() != null) {
-      return getID().toString();
-    }
-    return "";
-  }
-
-  public String toString() {
-    if (treeTableMode) {
-      return getName();
-    } else {
-      if (getID() != null) {
-        return getName() + ": " + getValue();
-      } else {
-        return getValue();
-      }
-    }
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FloatTreeNodeAdapter.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot.tree;
-
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
-
-/** Encapsulates a float value in a tree handled by SimpleTreeModel */
-
-public class FloatTreeNodeAdapter extends FieldTreeNodeAdapter {
-  private float val;
-
-  public FloatTreeNodeAdapter(float val, FieldIdentifier id) {
-    this(val, id, false);
-  }
-
-  public FloatTreeNodeAdapter(float val, FieldIdentifier id, boolean treeTableMode) {
-    super(id, treeTableMode);
-    this.val = val;
-  }
-
-  public int getChildCount() {
-    return 0;
-  }
-
-  public SimpleTreeNode getChild(int index) {
-    return null;
-  }
-
-  public boolean isLeaf() {
-    return true;
-  }
-
-  public int getIndexOfChild(SimpleTreeNode child) {
-    return 0;
-  }
-
-  public String getValue() {
-    return Float.toString(val);
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/LongTreeNodeAdapter.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot.tree;
-
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
-
-/** Encapsulates a long value in a tree handled by SimpleTreeModel */
-
-public class LongTreeNodeAdapter extends FieldTreeNodeAdapter {
-  private long val;
-
-  public LongTreeNodeAdapter(long val, FieldIdentifier id) {
-    this(val, id, false);
-  }
-
-  public LongTreeNodeAdapter(long val, FieldIdentifier id, boolean treeTableMode) {
-    super(id, treeTableMode);
-    this.val = val;
-  }
-
-  public int getChildCount() {
-    return 0;
-  }
-
-  public SimpleTreeNode getChild(int index) {
-    return null;
-  }
-
-  public boolean isLeaf() {
-    return true;
-  }
-
-  public int getIndexOfChild(SimpleTreeNode child) {
-    return 0;
-  }
-
-  public String getValue() {
-    return Long.toString(val);
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/ObjectTreeNodeAdapter.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.bugspot.tree;
-
-import java.io.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
-
-/** An adapter class which allows C/C++ objects to be displayed in a
-    tree via the SimpleTreeNode interface. */
-
-public class ObjectTreeNodeAdapter extends FieldTreeNodeAdapter {
-  // Address of object
-  private Address addr;
-
-  /** The address may be null (for object fields of objcets which are
-      null). The FieldIdentifier should not be null. treeTableMode
-      defaults to false. */
-  public ObjectTreeNodeAdapter(Address addr, FieldIdentifier id) {
-    this(addr, id, false);
-  }
-
-  /** The address may be null (for object fields of objcets which are
-      null). The FieldIdentifier should not be null. */
-  public ObjectTreeNodeAdapter(Address addr, FieldIdentifier id, boolean treeTableMode) {
-    super(id, treeTableMode);
-    this.addr = addr;
-  }
-
-  public int getChildCount() {
-    if (addr == null) {
-      return 0;
-    }
-
-    Counter c = new Counter();
-    getType().iterateObject(addr, c);
-    return c.getNumFields();
-  }
-
-  public SimpleTreeNode getChild(int index) {
-    if (addr == null) {
-      return null;
-    }
-
-    Fetcher f = new Fetcher(index);
-    getType().iterateObject(addr, f);
-    return f.getChild();
-  }
-
-  public boolean isLeaf() {
-    return (addr == null);
-  }
-
-  public int getIndexOfChild(SimpleTreeNode child) {
-    FieldIdentifier id = ((FieldTreeNodeAdapter) child).getID();
-    Finder f = new Finder(id);
-    getType().iterateObject(addr, f);
-    return f.getIndex();
-  }
-
-  public String getValue() {
-    if (addr != null) {
-      return addr.toString();
-    }
-    return "NULL";
-  }
-
-  /** Should be used only once, then have the number of fields
-      fetched. */
-  static class Counter extends DefaultObjectVisitor {
-    private int numFields;
-
-    public int getNumFields() {
-      return numFields;
-    }
-
-    public void doBit(FieldIdentifier f, long val)                   { ++numFields; }
-    public void doInt(FieldIdentifier f, long val)                   { ++numFields; }
-    public void doEnum(FieldIdentifier f, long val, String enumName) { ++numFields; }
-    public void doFloat(FieldIdentifier f, float val)                { ++numFields; }
-    public void doDouble(FieldIdentifier f, double val)              { ++numFields; }
-    public void doPointer(FieldIdentifier f, Address val)            { ++numFields; }
-    public void doArray(FieldIdentifier f, Address val)              { ++numFields; }
-    public void doRef(FieldIdentifier f, Address val)                { ++numFields; }
-    public void doCompound(FieldIdentifier f, Address addr)          { ++numFields; }
-  }
-
-  /** Creates a new SimpleTreeNode for the given field. */
-  class Fetcher extends DefaultObjectVisitor {
-    private int index;
-    private int curField;
-    private SimpleTreeNode child;
-
-    public Fetcher(int index) {
-      this.index = index;
-    }
-
-    public SimpleTreeNode getChild() {
-      return child;
-    }
-
-    public void doBit(FieldIdentifier f, long val) {
-      if (curField == index) {
-        child = new LongTreeNodeAdapter(val, f, getTreeTableMode());
-      }
-      ++curField;
-    }
-
-    public void doInt(FieldIdentifier f, long val) {
-      if (curField == index) {
-        child = new LongTreeNodeAdapter(val, f, getTreeTableMode());
-      }
-      ++curField;
-    }
-
-    public void doEnum(FieldIdentifier f, long val, String enumName) {
-      if (curField == index) {
-        child = new EnumTreeNodeAdapter(enumName, val, f, getTreeTableMode());
-      }
-      ++curField;
-    }
-
-    public void doFloat(FieldIdentifier f, float val) {
-      if (curField == index) {
-        child = new FloatTreeNodeAdapter(val, f, getTreeTableMode());
-      }
-      ++curField;
-    }
-
-    public void doDouble(FieldIdentifier f, double val) {
-      if (curField == index) {
-        child = new DoubleTreeNodeAdapter(val, f, getTreeTableMode());
-      }
-      ++curField;
-    }
-
-    public void doPointer(FieldIdentifier f, Address val) {
-      if (curField == index) {
-        child = new AddressTreeNodeAdapter(val, f, getTreeTableMode());
-      }
-      ++curField;
-    }
-
-    public void doArray(FieldIdentifier f, Address val) {
-      if (curField == index) {
-        child = new AddressTreeNodeAdapter(val, f, getTreeTableMode());
-      }
-      ++curField;
-    }
-
-    public void doRef(FieldIdentifier f, Address val) {
-      if (curField == index) {
-        child = new AddressTreeNodeAdapter(val, f, getTreeTableMode());
-      }
-      ++curField;
-    }
-
-    public void doCompound(FieldIdentifier f, Address val) {
-      if (curField == index) {
-        child = new ObjectTreeNodeAdapter(val, f, getTreeTableMode());
-      }
-      ++curField;
-    }
-  }
-
-  /** Finds the index of the given FieldIdentifier. */
-  static class Finder extends DefaultObjectVisitor {
-    private FieldIdentifier id;
-    private int curField;
-    private int index = -1;
-
-    public Finder(FieldIdentifier id) {
-      this.id = id;
-    }
-
-    /** Returns -1 if not found */
-    public int getIndex() {
-      return index;
-    }
-
-    public void doBit(FieldIdentifier f, long val)        { if (f.equals(id)) { index = curField; } ++curField; }
-    public void doInt(FieldIdentifier f, long val)        { if (f.equals(id)) { index = curField; } ++curField; }
-    public void doEnum(FieldIdentifier f, long val,
-                       String enumName)                   { if (f.equals(id)) { index = curField; } ++curField; }
-    public void doFloat(FieldIdentifier f, float val)     { if (f.equals(id)) { index = curField; } ++curField; }
-    public void doDouble(FieldIdentifier f, double val)   { if (f.equals(id)) { index = curField; } ++curField; }
-    public void doPointer(FieldIdentifier f, Address val) { if (f.equals(id)) { index = curField; } ++curField; }
-    public void doArray(FieldIdentifier f, Address val)   { if (f.equals(id)) { index = curField; } ++curField; }
-    public void doRef(FieldIdentifier f, Address val)     { if (f.equals(id)) { index = curField; } ++curField; }
-    public void doCompound(FieldIdentifier f,
-                           Address val)                   { if (f.equals(id)) { index = curField; } ++curField; }
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java	Thu Mar 21 14:11:13 2013 +0100
@@ -49,7 +49,7 @@
   public BsdAddress readCompKlassAddress(long address) throws DebuggerException;
   public BsdOopHandle readOopHandle(long address) throws DebuggerException;
   public BsdOopHandle readCompOopHandle(long address) throws DebuggerException;
-  public long[]       getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException;
+  public long[]       getThreadIntegerRegisterSet(long unique_thread_id) throws DebuggerException;
   public long         getAddressValue(Address addr) throws DebuggerException;
   public Address      newAddress(long value) throws DebuggerException;
 
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java	Thu Mar 21 14:11:13 2013 +0100
@@ -90,7 +90,7 @@
                                 throws DebuggerException;
     private native ClosestSymbol lookupByAddress0(long address)
                                 throws DebuggerException;
-    private native long[] getThreadIntegerRegisterSet0(int lwp_id)
+    private native long[] getThreadIntegerRegisterSet0(long unique_thread_id)
                                 throws DebuggerException;
     private native byte[] readBytesFromProcess0(long address, long numBytes)
                                 throws DebuggerException;
@@ -400,10 +400,15 @@
     //
 
     /** From the ThreadAccess interface via Debugger and JVMDebugger */
+    public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) {
+        return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr);
+    }
+    @Override
     public ThreadProxy getThreadForIdentifierAddress(Address addr) {
-        return new BsdThread(this, addr);
+        throw new RuntimeException("unimplemented");
     }
 
+
     /** From the ThreadAccess interface via Debugger and JVMDebugger */
     public ThreadProxy getThreadForThreadId(long id) {
         return new BsdThread(this, id);
@@ -455,22 +460,22 @@
     // Thread context access
     //
 
-    public synchronized long[] getThreadIntegerRegisterSet(int lwp_id)
+    public synchronized long[] getThreadIntegerRegisterSet(long unique_thread_id)
                                             throws DebuggerException {
         requireAttach();
         if (isCore) {
-            return getThreadIntegerRegisterSet0(lwp_id);
+            return getThreadIntegerRegisterSet0(unique_thread_id);
         } else {
             class GetThreadIntegerRegisterSetTask implements WorkerThreadTask {
-                int lwp_id;
+                long unique_thread_id;
                 long[] result;
                 public void doit(BsdDebuggerLocal debugger) {
-                    result = debugger.getThreadIntegerRegisterSet0(lwp_id);
+                    result = debugger.getThreadIntegerRegisterSet0(unique_thread_id);
                 }
             }
 
             GetThreadIntegerRegisterSetTask task = new GetThreadIntegerRegisterSetTask();
-            task.lwp_id = lwp_id;
+            task.unique_thread_id = unique_thread_id;
             workerThread.execute(task);
             return task.result;
         }
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,21 +28,23 @@
 
 class BsdThread implements ThreadProxy {
     private BsdDebugger debugger;
-    private int           lwp_id;
+    private int         thread_id;
+    private long        unique_thread_id;
 
     /** The address argument must be the address of the _thread_id in the
         OSThread. It's value is result ::gettid() call. */
-    BsdThread(BsdDebugger debugger, Address addr) {
+    BsdThread(BsdDebugger debugger, Address threadIdAddr, Address uniqueThreadIdAddr) {
         this.debugger = debugger;
         // FIXME: size of data fetched here should be configurable.
         // However, making it so would produce a dependency on the "types"
         // package from the debugger package, which is not desired.
-        this.lwp_id = (int) addr.getCIntegerAt(0, 4, true);
+        this.thread_id = (int) threadIdAddr.getCIntegerAt(0, 4, true);
+        this.unique_thread_id = uniqueThreadIdAddr.getCIntegerAt(0, 8, true);
     }
 
     BsdThread(BsdDebugger debugger, long id) {
         this.debugger = debugger;
-        this.lwp_id = (int) id;
+        this.thread_id = (int) id;
     }
 
     public boolean equals(Object obj) {
@@ -50,19 +52,19 @@
             return false;
         }
 
-        return (((BsdThread) obj).lwp_id == lwp_id);
+        return (((BsdThread) obj).thread_id == thread_id);
     }
 
     public int hashCode() {
-        return lwp_id;
+        return thread_id;
     }
 
     public String toString() {
-        return Integer.toString(lwp_id);
+        return Integer.toString(thread_id);
     }
 
     public ThreadContext getContext() throws IllegalThreadStateException {
-        long[] data = debugger.getThreadIntegerRegisterSet(lwp_id);
+        long[] data = debugger.getThreadIntegerRegisterSet(unique_thread_id);
         ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger);
         for (int i = 0; i < data.length; i++) {
             context.setRegister(i, data[i]);
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,21 +34,11 @@
   private boolean        gotID;
   private long           id;
 
-  /** The address argument must be the address of the HANDLE of the
-      desired thread in the target process. */
+  // The address argument must be the address of the OSThread::_thread_id
   WindbgAMD64Thread(WindbgDebugger debugger, Address addr) {
     this.debugger = debugger;
-    // FIXME: size of data fetched here should be configurable.
-    // However, making it so would produce a dependency on the "types"
-    // package from the debugger package, which is not desired.
-
-    // another hack here is that we use sys thread id instead of handle.
-    // windbg can't get details based on handles it seems.
-    // I assume that osThread_win32 thread struct has _thread_id (which
-    // sys thread id) just after handle field.
-
-    this.sysId   = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true);
-    gotID = false;
+    this.sysId    = (long)addr.getCIntegerAt(0, 4, true);
+    gotID         = false;
   }
 
   WindbgAMD64Thread(WindbgDebugger debugger, long sysId) {
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,21 +34,11 @@
   private boolean        gotID;
   private long           id;
 
-  /** The address argument must be the address of the HANDLE of the
-      desired thread in the target process. */
+  // The address argument must be the address of OSThread::_thread_id
   WindbgX86Thread(WindbgDebugger debugger, Address addr) {
     this.debugger = debugger;
-    // FIXME: size of data fetched here should be configurable.
-    // However, making it so would produce a dependency on the "types"
-    // package from the debugger package, which is not desired.
-
-    // another hack here is that we use sys thread id instead of handle.
-    // windbg can't get details based on handles it seems.
-    // I assume that osThread_win32 thread struct has _thread_id (which
-    // sys thread id) just after handle field.
-
-    this.sysId   = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true);
-    gotID = false;
+    this.sysId    = (long)addr.getCIntegerAt(0, 4, true);
+    gotID         = false;
   }
 
   WindbgX86Thread(WindbgDebugger debugger, long sysId) {
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/BreakpointEvent.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.livejvm;
-
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-
-public class BreakpointEvent extends Event {
-  private Oop thread;
-  private Oop clazz;
-  private JNIid method;
-  private int location;
-
-  public BreakpointEvent(Oop thread,
-                         Oop clazz,
-                         JNIid method,
-                         int location) {
-    super(Event.Type.BREAKPOINT);
-    this.thread = thread;
-    this.clazz = clazz;
-    this.method = method;
-    this.location = location;
-  }
-
-  public Oop thread()     { return thread;   }
-  public Oop clazz()      { return clazz;    }
-  public JNIid methodID() { return method;   }
-  public int location()   { return location; }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/CIntegerAccessor.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.livejvm;
-
-import sun.jvm.hotspot.debugger.*;
-
-class CIntegerAccessor {
-  private Address addr;
-  private long numBytes;
-  private boolean isUnsigned;
-
-  CIntegerAccessor(Address addr, long numBytes, boolean isUnsigned) {
-    this.addr = addr;
-    this.numBytes = numBytes;
-    this.isUnsigned = isUnsigned;
-  }
-
-  long getValue() {
-    return addr.getCIntegerAt(0, numBytes, isUnsigned);
-  }
-
-  void setValue(long value) {
-    addr.setCIntegerAt(0, numBytes, value);
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/CStringAccessor.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.livejvm;
-
-import java.io.UnsupportedEncodingException;
-import sun.jvm.hotspot.debugger.*;
-
-class CStringAccessor {
-  private Address addr;
-  private int bufLen;
-
-  CStringAccessor(Address addr, int bufLen) {
-    this.addr = addr;
-    this.bufLen = bufLen;
-  }
-
-  String getValue() throws DebuggerException {
-    int len = 0;
-    while ((addr.getCIntegerAt(len, 1, true) != 0) && (len < bufLen)) {
-      ++len;
-    }
-    byte[] res = new byte[len];
-    for (int i = 0; i < len; i++) {
-      res[i] = (byte) addr.getCIntegerAt(i, 1, true);
-    }
-    try {
-      return new String(res, "US-ASCII");
-    } catch (UnsupportedEncodingException e) {
-      throw new DebuggerException("Unable to use US-ASCII encoding");
-    }
-  }
-
-  void setValue(String value) throws DebuggerException {
-    try {
-      byte[] data = value.getBytes("US-ASCII");
-      if (data.length >= bufLen) {
-        throw new DebuggerException("String too long");
-      }
-      for (int i = 0; i < data.length; i++) {
-        addr.setCIntegerAt(i, 1, data[i]);
-      }
-      addr.setCIntegerAt(data.length, 1, 0);
-    } catch (UnsupportedEncodingException e) {
-      throw new DebuggerException("Unable to use US-ASCII encoding");
-    }
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/Event.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.livejvm;
-
-public class Event {
-  public static class Type {
-    private Type() {}
-    public static final Type BREAKPOINT = new Type();
-    public static final Type EXCEPTION  = new Type();
-  }
-
-  private Type type;
-
-  public Event(Type type) {
-    this.type = type;
-  }
-
-  public Type getType() { return type; }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/ExceptionEvent.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.livejvm;
-
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-
-public class ExceptionEvent extends Event {
-  private Oop thread;
-  private Oop clazz;
-  private JNIid method;
-  private int location;
-  private Oop exception;
-  private Oop catchClass;
-  private JNIid catchMethod;
-  private int catchLocation;
-
-  public ExceptionEvent(Oop thread,
-                        Oop clazz,
-                        JNIid method,
-                        int location,
-                        Oop exception,
-                        Oop catchClass,
-                        JNIid catchMethod,
-                        int catchLocation) {
-    super(Event.Type.EXCEPTION);
-    this.thread        = thread;
-    this.clazz         = clazz;
-    this.method        = method;
-    this.location      = location;
-    this.exception     = exception;
-    this.catchClass    = catchClass;
-    this.catchMethod   = catchMethod;
-    this.catchLocation = catchLocation;
-  }
-
-  public Oop   thread()        { return thread;        }
-  public Oop   clazz()         { return clazz;         }
-  public JNIid methodID()      { return method;        }
-  public int   location()      { return location;      }
-  public Oop   exception()     { return exception;     }
-  public Oop   catchClass()    { return catchClass;    }
-  public JNIid catchMethodID() { return catchMethod;   }
-  public int   catchLocation() { return catchLocation; }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/JNIHandleAccessor.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.livejvm;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.utilities.*;
-
-class JNIHandleAccessor {
-  private Address addr;
-  private ObjectHeap heap;
-
-  JNIHandleAccessor(Address addr, ObjectHeap heap) {
-    this.addr = addr;
-    this.heap = heap;
-  }
-
-  Oop getValue() {
-    // Accessing the contents of the JNIHandle is a double dereference
-    Address handle = addr.getAddressAt(0);
-    if (handle == null) return null;
-    return heap.newOop(handle.getOopHandleAt(0));
-  }
-
-  void setValue(Oop value) {
-    Address handle = addr.getAddressAt(0);
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(handle != null, "Must have valid global JNI handle for setting");
-    }
-    handle.setOopHandleAt(0, value.getHandle());
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/ServiceabilityAgentJVMDIModule.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,415 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.livejvm;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-
-/** Provides Java programming language-level interaction with a live
-    Java HotSpot VM via the use of the SA's JVMDI module. This is an
-    experimental mechanism. The BugSpot debugger should be converted
-    to use the JVMDI/JDWP-based JDI implementation for live process
-    interaction once the JDI binding for the SA is complete. */
-
-public class ServiceabilityAgentJVMDIModule {
-  private Debugger dbg;
-  private String[] saLibNames;
-  private String   saLibName;
-  private boolean  attached;
-
-  private boolean  suspended;
-
-  private static final int JVMDI_EVENT_BREAKPOINT = 2;
-  private static final int JVMDI_EVENT_EXCEPTION = 4;
-
-  private static long timeoutMillis = 3000;
-
-  // Values in target process
-  // Events sent from VM to SA
-  private CIntegerAccessor saAttached;
-  private CIntegerAccessor saEventPending;
-  private CIntegerAccessor saEventKind;
-  // Exception events
-  private JNIHandleAccessor saExceptionThread;
-  private JNIHandleAccessor saExceptionClass;
-  private JNIid             saExceptionMethod;
-  private CIntegerAccessor  saExceptionLocation;
-  private JNIHandleAccessor saExceptionException;
-  private JNIHandleAccessor saExceptionCatchClass;
-  private JNIid             saExceptionCatchMethod;
-  private CIntegerAccessor  saExceptionCatchLocation;
-  // Breakpoint events
-  private JNIHandleAccessor saBreakpointThread;
-  private JNIHandleAccessor saBreakpointClass;
-  private JNIid             saBreakpointMethod;
-  private CIntegerAccessor  saBreakpointLocation;
-  // Commands sent by the SA to the VM
-  private int               SA_CMD_SUSPEND_ALL;
-  private int               SA_CMD_RESUME_ALL;
-  private int               SA_CMD_TOGGLE_BREAKPOINT;
-  private int               SA_CMD_BUF_SIZE;
-  private CIntegerAccessor  saCmdPending;
-  private CIntegerAccessor  saCmdType;
-  private CIntegerAccessor  saCmdResult;
-  private CStringAccessor   saCmdResultErrMsg;
-  // Toggle breakpoint command arguments
-  private CStringAccessor   saCmdBkptSrcFileName;
-  private CStringAccessor   saCmdBkptPkgName;
-  private CIntegerAccessor  saCmdBkptLineNumber;
-  private CIntegerAccessor  saCmdBkptResWasError;
-  private CIntegerAccessor  saCmdBkptResLineNumber;
-  private CIntegerAccessor  saCmdBkptResBCI;
-  private CIntegerAccessor  saCmdBkptResWasSet;
-  private CStringAccessor   saCmdBkptResMethodName;
-  private CStringAccessor   saCmdBkptResMethodSig;
-
-  public ServiceabilityAgentJVMDIModule(Debugger dbg, String[] saLibNames) {
-    this.dbg = dbg;
-    this.saLibNames = saLibNames;
-  }
-
-  /** Indicates whether a call to attach() should complete without an
-      exception. */
-  public boolean canAttach() {
-    return setupLookup("SA_CMD_SUSPEND_ALL");
-  }
-
-  /** Attempt to initiate a connection with the JVMDI module in the
-      target VM. */
-  public void attach() throws DebuggerException {
-    if (!canAttach()) {
-      throw new DebuggerException("Unable to initiate symbol lookup in SA's JVMDI module");
-    }
-
-    if (attached) {
-      throw new DebuggerException("Already attached");
-    }
-
-    // Attempt to look up well-known symbols in the target VM.
-    SA_CMD_SUSPEND_ALL      = lookupConstInt("SA_CMD_SUSPEND_ALL");
-    SA_CMD_RESUME_ALL       = lookupConstInt("SA_CMD_RESUME_ALL");
-    SA_CMD_TOGGLE_BREAKPOINT = lookupConstInt("SA_CMD_TOGGLE_BREAKPOINT");
-    SA_CMD_BUF_SIZE         = lookupConstInt("SA_CMD_BUF_SIZE");
-
-    saAttached              = lookupCInt("saAttached");
-    saEventPending          = lookupCInt("saEventPending");
-    saEventKind             = lookupCInt("saEventKind");
-    saCmdPending            = lookupCInt("saCmdPending");
-    saCmdType               = lookupCInt("saCmdType");
-    saCmdResult             = lookupCInt("saCmdResult");
-    saCmdResultErrMsg       = lookupCString("saCmdResultErrMsg", SA_CMD_BUF_SIZE);
-    // Toggling of breakpoints
-    saCmdBkptSrcFileName    = lookupCString("saCmdBkptSrcFileName", SA_CMD_BUF_SIZE);
-    saCmdBkptPkgName        = lookupCString("saCmdBkptPkgName", SA_CMD_BUF_SIZE);
-    saCmdBkptLineNumber     = lookupCInt("saCmdBkptLineNumber");
-    saCmdBkptResWasError    = lookupCInt("saCmdBkptResWasError");
-    saCmdBkptResLineNumber  = lookupCInt("saCmdBkptResLineNumber");
-    saCmdBkptResBCI         = lookupCInt("saCmdBkptResBCI");
-    saCmdBkptResWasSet      = lookupCInt("saCmdBkptResWasSet");
-    saCmdBkptResMethodName  = lookupCString("saCmdBkptResMethodName", SA_CMD_BUF_SIZE);
-    saCmdBkptResMethodSig   = lookupCString("saCmdBkptResMethodSig", SA_CMD_BUF_SIZE);
-
-    // Check for existence of symbols needed later
-    // FIXME: should probably cache these since we can't support the
-    // -Xrun module or the VM getting unloaded anyway
-    lookup("saExceptionThread");
-    lookup("saExceptionClass");
-    lookup("saExceptionMethod");
-    lookup("saExceptionLocation");
-    lookup("saExceptionException");
-    lookup("saExceptionCatchClass");
-    lookup("saExceptionCatchMethod");
-    lookup("saExceptionCatchLocation");
-    lookup("saBreakpointThread");
-    lookup("saBreakpointClass");
-    lookup("saBreakpointMethod");
-    lookup("saBreakpointLocation");
-
-    saAttached.setValue(1);
-    attached = true;
-  }
-
-  public void detach() {
-    saAttached.setValue(0);
-    attached = false;
-    saLibName = null;
-  }
-
-  /** Set the timeout value (in milliseconds) for the VM to reply to
-      commands. Once this timeout has elapsed, the VM is assumed to
-      have disconnected. Defaults to 3000 milliseconds (3 seconds). */
-  public void setCommandTimeout(long millis) {
-    timeoutMillis = millis;
-  }
-
-  /** Get the timeout value (in milliseconds) for the VM to reply to
-      commands. Once this timeout has elapsed, the VM is assumed to
-      have disconnected. Defaults to 3000 milliseconds (3 seconds). */
-  public long getCommandTimeout() {
-    return timeoutMillis;
-  }
-
-  /** Indicates whether a Java debug event is pending */
-  public boolean eventPending() {
-    return (saEventPending.getValue() != 0);
-  }
-
-  /** Poll for event; returns null if none pending. */
-  public Event eventPoll() {
-    if (saEventPending.getValue() == 0) {
-      return null;
-    }
-
-    int kind = (int) saEventKind.getValue();
-    switch (kind) {
-    case JVMDI_EVENT_EXCEPTION: {
-      JNIHandleAccessor thread = lookupJNIHandle("saExceptionThread");
-      JNIHandleAccessor clazz = lookupJNIHandle("saExceptionClass");
-      JNIid method = lookupJNIid("saExceptionMethod");
-      CIntegerAccessor location = lookupCInt("saExceptionLocation");
-      JNIHandleAccessor exception = lookupJNIHandle("saExceptionException");
-      JNIHandleAccessor catchClass = lookupJNIHandle("saExceptionCatchClass");
-      JNIid catchMethod = lookupJNIid("saExceptionCatchMethod");
-      CIntegerAccessor catchLocation = lookupCInt("saExceptionCatchLocation");
-      return new ExceptionEvent(thread.getValue(), clazz.getValue(), method,
-                                (int) location.getValue(), exception.getValue(),
-                                catchClass.getValue(), catchMethod, (int) catchLocation.getValue());
-    }
-
-    case JVMDI_EVENT_BREAKPOINT: {
-      JNIHandleAccessor thread = lookupJNIHandle("saBreakpointThread");
-      JNIHandleAccessor clazz = lookupJNIHandle("saBreakpointClass");
-      JNIid method = lookupJNIid("saBreakpointMethod");
-      CIntegerAccessor location = lookupCInt("saBreakpointLocation");
-      return new BreakpointEvent(thread.getValue(), clazz.getValue(),
-                                 method, (int) location.getValue());
-    }
-
-    default:
-      throw new DebuggerException("Unsupported event type " + kind);
-    }
-  }
-
-  /** Continue past current event */
-  public void eventContinue() {
-    saEventPending.setValue(0);
-  }
-
-  /** Suspend all Java threads in the target VM. Throws
-      DebuggerException if the VM disconnected. */
-  public void suspend() {
-    saCmdType.setValue(SA_CMD_SUSPEND_ALL);
-    saCmdPending.setValue(1);
-    waitForCommandCompletion();
-    suspended = true;
-  }
-
-  /** Resume all Java threads in the target VM. Throws
-      DebuggerException if the VM disconnected. */
-  public void resume() {
-    saCmdType.setValue(SA_CMD_RESUME_ALL);
-    saCmdPending.setValue(1);
-    waitForCommandCompletion();
-    suspended = false;
-  }
-
-  /** Indicates whether all Java threads have been suspended via this
-      interface. */
-  public boolean isSuspended() {
-    return suspended;
-  }
-
-  /** Information about toggling of breakpoints */
-  public static class BreakpointToggleResult {
-    private boolean success;
-    private String errMsg;
-    private int lineNumber;
-    private int bci;
-    private boolean wasSet;
-    private String methodName;
-    private String methodSig;
-
-    /** Success constructor */
-    public BreakpointToggleResult(int lineNumber, int bci, boolean wasSet,
-                                  String methodName, String methodSig) {
-      this.lineNumber = lineNumber;
-      this.bci = bci;
-      this.wasSet = wasSet;
-      this.methodName = methodName;
-      this.methodSig = methodSig;
-      success = true;
-    }
-
-    /** Failure constructor */
-    public BreakpointToggleResult(String errMsg) {
-      this.errMsg = errMsg;
-      success = false;
-    }
-
-    /** Indicates whether this represents a successful return or not */
-    public boolean getSuccess() { return success; }
-
-    /** Valid only if getSuccess() returns false */
-    public String getErrMsg() { return errMsg; }
-
-    /** Line number at which breakpoint toggle occurred; valid only if
-        getSuccess() returns true. */
-    public int getLineNumber() { return lineNumber; }
-
-    /** BCI at which breakpoint toggle occurred; valid only if
-        getSuccess() returns true. */
-    public int getBCI() { return bci; }
-
-    /** Indicates whether the breakpoint toggle was the set of a
-        breakpoint or not; valid only if getSuccess() returns true. */
-    public boolean getWasSet() { return wasSet; }
-
-    /** Method name in which the breakpoint toggle occurred; valid
-        only if getSuccess() returns true. */
-    public String getMethodName() { return methodName; }
-
-    /** Method signature in which the breakpoint toggle occurred;
-        valid only if getSuccess() returns true. */
-    public String getMethodSignature() { return methodSig; }
-  }
-
-  /** Toggle a breakpoint. Throws DebuggerException if a real error
-      occurred; otherwise returns non-null BreakpointToggleResult. The
-      work of scanning the loaded classes is done in the target VM
-      because it turns out to be significantly faster than scanning
-      through the system dictionary from the SA, and interactivity
-      when setting breakpoints is important. */
-  public BreakpointToggleResult toggleBreakpoint(String srcFileName,
-                                                 String pkgName,
-                                                 int lineNo) {
-    saCmdBkptSrcFileName.setValue(srcFileName);
-    saCmdBkptPkgName.setValue(pkgName);
-    saCmdBkptLineNumber.setValue(lineNo);
-    saCmdType.setValue(SA_CMD_TOGGLE_BREAKPOINT);
-    saCmdPending.setValue(1);
-    if (waitForCommandCompletion(true)) {
-      return new BreakpointToggleResult((int) saCmdBkptResLineNumber.getValue(),
-                                        (int) saCmdBkptResBCI.getValue(),
-                                        (saCmdBkptResWasSet.getValue() != 0),
-                                        saCmdBkptResMethodName.getValue(),
-                                        saCmdBkptResMethodSig.getValue());
-    } else {
-      return new BreakpointToggleResult(saCmdResultErrMsg.getValue());
-    }
-  }
-
-
-  //----------------------------------------------------------------------
-  // Internals only below this point
-  //
-
-  private CIntegerAccessor lookupCInt(String symbolName) {
-    return new CIntegerAccessor(lookup(symbolName), 4, false);
-  }
-
-  private CStringAccessor lookupCString(String symbolName, int bufLen) {
-    return new CStringAccessor(lookup(symbolName), bufLen);
-  }
-
-  private JNIHandleAccessor lookupJNIHandle(String symbolName) {
-    return new JNIHandleAccessor(lookup(symbolName), VM.getVM().getObjectHeap());
-  }
-
-  private JNIid lookupJNIid(String symbolName) {
-    Address idAddr = lookup(symbolName).getAddressAt(0);
-    if (idAddr == null) {
-      return null;
-    }
-    return new JNIid(idAddr, VM.getVM().getObjectHeap());
-  }
-
-  private int lookupConstInt(String symbolName) {
-    Address addr = lookup(symbolName);
-    return (int) addr.getCIntegerAt(0, 4, false);
-  }
-
-  private boolean setupLookup(String symbolName) {
-    if (saLibName == null) {
-      for (int i = 0; i < saLibNames.length; i++) {
-        Address addr = dbg.lookup(saLibNames[i], symbolName);
-        if (addr != null) {
-          saLibName = saLibNames[i];
-          return true;
-        }
-      }
-      return false;
-    }
-    return true;
-  }
-
-  private Address lookup(String symbolName) {
-    if (saLibName == null) {
-      for (int i = 0; i < saLibNames.length; i++) {
-        Address addr = dbg.lookup(saLibNames[i], symbolName);
-        if (addr != null) {
-          saLibName = saLibNames[i];
-          return addr;
-        }
-      }
-      throw new DebuggerException("Unable to find symbol " + symbolName + " in any of the known names for the SA");
-    }
-
-    Address addr = dbg.lookup(saLibName, symbolName);
-    if (addr == null) {
-      throw new DebuggerException("Unable to find symbol " + symbolName + " in " + saLibName);
-    }
-    return addr;
-  }
-
-  private void waitForCommandCompletion() {
-    waitForCommandCompletion(false);
-  }
-
-  /** Returns true if command succeeded, false if not */
-  private boolean waitForCommandCompletion(boolean forBreakpoint) {
-    long start = System.currentTimeMillis();
-    long cur = start;
-    while ((saCmdPending.getValue() != 0) &&
-           (cur - start < timeoutMillis)) {
-      try {
-        java.lang.Thread.currentThread().sleep(10);
-      } catch (InterruptedException e) {
-      }
-      cur = System.currentTimeMillis();
-    }
-    if (saCmdPending.getValue() != 0) {
-      detach();
-      throw new DebuggerException("VM appears to have died");
-    }
-    boolean succeeded = saCmdResult.getValue() == 0;
-    if (!succeeded &&
-        (!forBreakpoint || saCmdBkptResWasError.getValue() != 0)) {
-      String err = saCmdResultErrMsg.getValue();
-      throw new DebuggerException("Error executing JVMDI command: " + err);
-    }
-    return succeeded;
-  }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,59 @@
+/*
+ * @(#)BinaryTreeDictionary.java
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.memory;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.runtime.*;
+
+public class AFLBinaryTreeDictionary extends VMObject {
+   static {
+      VM.registerVMInitializedObserver(new Observer() {
+         public void update(Observable o, Object data) {
+            initialize(VM.getVM().getTypeDataBase());
+         }
+      });
+   }
+
+   private static synchronized void initialize(TypeDataBase db) {
+      Type type = db.lookupType("AFLBinaryTreeDictionary");
+      totalSizeField = type.getCIntegerField("_total_size");
+   }
+
+   // Fields
+   private static CIntegerField totalSizeField;
+
+   // Accessors
+   public long size() {
+      return totalSizeField.getValue(addr);
+   }
+
+   // Constructor
+   public AFLBinaryTreeDictionary(Address addr) {
+      super(addr);
+   }
+}
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * @(#)BinaryTreeDictionary.java
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.runtime.*;
-
-public class BinaryTreeDictionary extends VMObject {
-   static {
-      VM.registerVMInitializedObserver(new Observer() {
-         public void update(Observable o, Object data) {
-            initialize(VM.getVM().getTypeDataBase());
-         }
-      });
-   }
-
-   private static synchronized void initialize(TypeDataBase db) {
-      Type type = db.lookupType("BinaryTreeDictionary");
-      totalSizeField = type.getCIntegerField("_totalSize");
-   }
-
-   // Fields
-   private static CIntegerField totalSizeField;
-
-   // Accessors
-   public long size() {
-      return totalSizeField.getValue(addr);
-   }
-
-   // Constructor
-   public BinaryTreeDictionary(Address addr) {
-      super(addr);
-   }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/CMSCollector.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CMSCollector.java	Thu Mar 21 14:11:13 2013 +0100
@@ -61,15 +61,13 @@
     CMSBitMap markBitMap = markBitMap();
     long addressSize = VM.getVM().getAddressSize();
     if ( markBitMap.isMarked(addr) &&  markBitMap.isMarked(addr.addOffsetTo(1*addressSize)) ) {
-       System.err.println("Printezis bits are set...");
       Address nextOneAddr = markBitMap.getNextMarkedWordAddress(addr.addOffsetTo(2*addressSize));
       //return size in bytes
       long size =  (nextOneAddr.addOffsetTo(1*addressSize)).minus(addr);
       return size;
     } else {
-     //missing Printezis marks
-     System.err.println("Missing Printszis marks...");
-     return -1;
+      //missing Printezis marks
+      return -1;
     }
 
   }
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -117,9 +117,9 @@
       }
 
       // large block
-      BinaryTreeDictionary bfbd = (BinaryTreeDictionary) VMObjectFactory.newObject(BinaryTreeDictionary.class,
+      AFLBinaryTreeDictionary aflbd = (AFLBinaryTreeDictionary) VMObjectFactory.newObject(AFLBinaryTreeDictionary.class,
                                                                                    dictionaryField.getValue(addr));
-      size += bfbd.size();
+      size += aflbd.size();
 
 
       // linear block in TLAB
@@ -191,7 +191,6 @@
             //Find the object size using Printezis bits and skip over
             long size = collector().blockSizeUsingPrintezisBits(cur);
             if (size == -1) {
-              System.err.println("Printezis bits not set...");
               break;
             }
             cur = cur.addOffsetTo(adjustObjectSizeInBytes(size));
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,7 +1,7 @@
 /*
  * @(#)FreeList.java
  *
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
    }
 
    private static synchronized void initialize(TypeDataBase db) {
-      Type type = db.lookupType("FreeList");
+      Type type = db.lookupType("FreeList<FreeChunk>");
       sizeField = type.getCIntegerField("_size");
       countField = type.getCIntegerField("_count");
       headerSize = type.getSize();
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,12 +49,18 @@
   private static int HAS_LOCALVARIABLE_TABLE;
   private static int HAS_EXCEPTION_TABLE;
   private static int HAS_GENERIC_SIGNATURE;
+  private static int HAS_METHOD_ANNOTATIONS;
+  private static int HAS_PARAMETER_ANNOTATIONS;
+  private static int HAS_DEFAULT_ANNOTATIONS;
+  private static int HAS_TYPE_ANNOTATIONS;
+
+  private static final int sizeofShort = 2;
 
   private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
     Type type                  = db.lookupType("ConstMethod");
     constants                  = new MetadataField(type.getAddressField("_constants"), 0);
     constMethodSize            = new CIntField(type.getCIntegerField("_constMethod_size"), 0);
-    flags                      = new ByteField(type.getJByteField("_flags"), 0);
+    flags                      = new CIntField(type.getCIntegerField("_flags"), 0);
 
     // enum constants for flags
     HAS_LINENUMBER_TABLE      = db.lookupIntConstant("ConstMethod::_has_linenumber_table").intValue();
@@ -62,6 +68,10 @@
     HAS_LOCALVARIABLE_TABLE   = db.lookupIntConstant("ConstMethod::_has_localvariable_table").intValue();
     HAS_EXCEPTION_TABLE       = db.lookupIntConstant("ConstMethod::_has_exception_table").intValue();
     HAS_GENERIC_SIGNATURE     = db.lookupIntConstant("ConstMethod::_has_generic_signature").intValue();
+    HAS_METHOD_ANNOTATIONS    = db.lookupIntConstant("ConstMethod::_has_method_annotations").intValue();
+    HAS_PARAMETER_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_parameter_annotations").intValue();
+    HAS_DEFAULT_ANNOTATIONS   = db.lookupIntConstant("ConstMethod::_has_default_annotations").intValue();
+    HAS_TYPE_ANNOTATIONS      = db.lookupIntConstant("ConstMethod::_has_type_annotations").intValue();
 
     // Size of Java bytecodes allocated immediately after ConstMethod*.
     codeSize                   = new CIntField(type.getCIntegerField("_code_size"), 0);
@@ -92,7 +102,7 @@
   // Fields
   private static MetadataField constants;
   private static CIntField constMethodSize;
-  private static ByteField flags;
+  private static CIntField flags;
   private static CIntField codeSize;
   private static CIntField nameIndex;
   private static CIntField signatureIndex;
@@ -123,7 +133,7 @@
     return constMethodSize.getValue(this);
   }
 
-  public byte getFlags() {
+  public long getFlags() {
     return flags.getValue(this);
   }
 
@@ -253,7 +263,7 @@
   public void iterateFields(MetadataVisitor visitor) {
     visitor.doMetadata(constants, true);
       visitor.doCInt(constMethodSize, true);
-      visitor.doByte(flags, true);
+      visitor.doCInt(flags, true);
       visitor.doCInt(codeSize, true);
       visitor.doCInt(nameIndex, true);
       visitor.doCInt(signatureIndex, true);
@@ -381,6 +391,22 @@
     return (getFlags() & HAS_GENERIC_SIGNATURE) != 0;
   }
 
+  private boolean hasMethodAnnotations() {
+    return (getFlags() & HAS_METHOD_ANNOTATIONS) != 0;
+  }
+
+  private boolean hasParameterAnnotations() {
+    return (getFlags() & HAS_PARAMETER_ANNOTATIONS) != 0;
+  }
+
+  private boolean hasDefaultAnnotations() {
+    return (getFlags() & HAS_DEFAULT_ANNOTATIONS) != 0;
+  }
+
+  private boolean hasTypeAnnotations() {
+    return (getFlags() & HAS_TYPE_ANNOTATIONS) != 0;
+  }
+
 
   //---------------------------------------------------------------------------
   // Internals only below this point
@@ -400,9 +426,15 @@
     return offsetOfCodeEnd() + (isNative() ? 2 * VM.getVM().getAddressSize() : 0);
   }
 
-  // Offset of last short in Method*
+  // Offset of last short in Method* before annotations, if present
   private long offsetOfLastU2Element() {
-    return getSize() * VM.getVM().getObjectHeap().getOopSize() - 2;
+    int offset = 0;
+    if (hasMethodAnnotations()) offset++;
+    if (hasParameterAnnotations()) offset++;
+    if (hasTypeAnnotations()) offset++;
+    if (hasDefaultAnnotations()) offset++;
+    long wordSize = VM.getVM().getObjectHeap().getOopSize();
+    return (getSize() * wordSize) - (offset * wordSize) - sizeofShort;
   }
 
   // Offset of the generic signature index
@@ -411,7 +443,7 @@
   }
 
   private long offsetOfCheckedExceptionsLength() {
-    return hasGenericSignature() ? offsetOfLastU2Element() - 2 :
+    return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
                                    offsetOfLastU2Element();
   }
 
@@ -461,11 +493,11 @@
     }
 
     if (hasExceptionTable()) {
-      return offsetOfExceptionTable() - 2;
+      return offsetOfExceptionTable() - sizeofShort;
     } else if (hasCheckedExceptions()) {
-      return offsetOfCheckedExceptions() - 2;
+      return offsetOfCheckedExceptions() - sizeofShort;
     } else {
-      return hasGenericSignature() ? offsetOfLastU2Element() - 2 :
+      return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
                                      offsetOfLastU2Element();
     }
   }
@@ -493,9 +525,9 @@
       Assert.that(hasExceptionTable(), "should only be called if table is present");
     }
     if (hasCheckedExceptions()) {
-      return offsetOfCheckedExceptions() - 2;
+      return offsetOfCheckedExceptions() - sizeofShort;
     } else {
-      return hasGenericSignature() ? offsetOfLastU2Element() - 2 :
+      return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
                                      offsetOfLastU2Element();
     }
   }
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -469,7 +469,6 @@
     case JVM_CONSTANT_UnresolvedClassInError:    return "JVM_CONSTANT_UnresolvedClassInError";
     case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError";
     case JVM_CONSTANT_MethodTypeInError:  return "JVM_CONSTANT_MethodTypeInError";
-    case JVM_CONSTANT_Object:             return "JVM_CONSTANT_Object";
     }
     throw new InternalError("Unknown tag: " + tag);
   }
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -184,7 +184,6 @@
       if (trapReasonName[index] == null) {
         throw new InternalError("missing reason for " + index);
       }
-      System.out.println(trapReasonName[index]);
     }
   }
 
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java	Thu Mar 21 14:11:13 2013 +0100
@@ -335,7 +335,6 @@
           }
           if (obj == null) {
              //Find the object size using Printezis bits and skip over
-             System.err.println("Finding object size using Printezis bits and skipping over...");
              long size = 0;
 
              if ( (cmsSpaceOld != null) && cmsSpaceOld.contains(handle) ){
@@ -467,7 +466,7 @@
               liveRegions.add(tlab.start());
               liveRegions.add(tlab.start());
               liveRegions.add(tlab.top());
-              liveRegions.add(tlab.end());
+              liveRegions.add(tlab.hardEnd());
             }
           }
         }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,7 +67,6 @@
     public static final int JVM_CONSTANT_UnresolvedClassInError   = 103;  // Error tag due to resolution error
     public static final int JVM_CONSTANT_MethodHandleInError      = 104;  // Error tag due to resolution error
     public static final int JVM_CONSTANT_MethodTypeInError        = 105;  // Error tag due to resolution error
-    public static final int JVM_CONSTANT_Object                   = 106;  // Required for BoundMethodHandle arguments.
 
     // 1.5 major/minor version numbers from JVM spec. 3rd edition
     public static final short MAJOR_VERSION = 49;
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 // to the sys_thread_t structure of the classic JVM implementation.
 public class OSThread extends VMObject {
     private static JIntField interruptedField;
+    private static JIntField threadIdField;
     static {
         VM.registerVMInitializedObserver(new Observer() {
             public void update(Observable o, Object data) {
@@ -43,6 +44,7 @@
     private static synchronized void initialize(TypeDataBase db) {
         Type type = db.lookupType("OSThread");
         interruptedField = type.getJIntField("_interrupted");
+        threadIdField = type.getJIntField("_thread_id");
     }
 
     public OSThread(Address addr) {
@@ -52,4 +54,9 @@
     public boolean interrupted() {
         return ((int)interruptedField.getValue(addr)) != 0;
     }
+
+    public int threadId() {
+        return (int)threadIdField.getValue(addr);
+    }
+
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java	Thu Mar 21 14:11:13 2013 +0100
@@ -27,6 +27,7 @@
 import java.io.*;
 import java.util.*;
 import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.types.*;
 
 /** <P> ThreadLocalAllocBuffer: a descriptor for thread-local storage
@@ -62,9 +63,22 @@
     super(addr);
   }
 
-  public Address start()                        { return startField.getValue(addr); }
-  public Address end()                          { return   endField.getValue(addr); }
-  public Address top()                          { return   topField.getValue(addr); }
+  public Address start()    { return startField.getValue(addr); }
+  public Address end()      { return   endField.getValue(addr); }
+  public Address top()      { return   topField.getValue(addr); }
+  public Address hardEnd()  { return end().addOffsetTo(alignmentReserve()); }
+
+  private long alignmentReserve() {
+    return Oop.alignObjectSize(endReserve());
+  }
+
+  private long endReserve() {
+    long minFillerArraySize = Array.baseOffsetInBytes(BasicType.T_INT);
+    long reserveForAllocationPrefetch = VM.getVM().getReserveForAllocationPrefetch();
+    long heapWordSize = VM.getVM().getHeapWordSize();
+
+    return Math.max(minFillerArraySize, reserveForAllocationPrefetch * heapWordSize);
+  }
 
   /** Support for iteration over heap -- not sure how this will
       interact with GC in reflective system, but necessary for the
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java	Thu Mar 21 14:11:13 2013 +0100
@@ -90,10 +90,6 @@
   /** Flags indicating whether we are attached to a core, C1, or C2 build */
   private boolean      usingClientCompiler;
   private boolean      usingServerCompiler;
-  /** Flag indicating whether UseTLAB is turned on */
-  private boolean      useTLAB;
-  /** Flag indicating whether invokedynamic support is on */
-  private boolean      enableInvokeDynamic;
   /** alignment constants */
   private boolean      isLP64;
   private int          bytesPerLong;
@@ -114,6 +110,7 @@
   private int          invalidOSREntryBCI;
   private ReversePtrs  revPtrs;
   private VMRegImpl    vmregImpl;
+  private int          reserveForAllocationPrefetch;
 
   // System.getProperties from debuggee VM
   private Properties   sysProps;
@@ -293,6 +290,10 @@
        vmRelease = CStringUtilities.getString(releaseAddr);
        Address vmInternalInfoAddr = vmVersion.getAddressField("_s_internal_vm_info_string").getValue();
        vmInternalInfo = CStringUtilities.getString(vmInternalInfoAddr);
+
+       CIntegerType intType = (CIntegerType) db.lookupType("int");
+       CIntegerField reserveForAllocationPrefetchField = vmVersion.getCIntegerField("_reserve_for_allocation_prefetch");
+       reserveForAllocationPrefetch = (int)reserveForAllocationPrefetchField.getCInteger(intType);
     } catch (Exception exp) {
        throw new RuntimeException("can't determine target's VM version : " + exp.getMessage());
     }
@@ -321,9 +322,6 @@
       }
     }
 
-    useTLAB = (db.lookupIntConstant("UseTLAB").intValue() != 0);
-    enableInvokeDynamic = (db.lookupIntConstant("EnableInvokeDynamic").intValue() != 0);
-
     if (debugger != null) {
       isLP64 = debugger.getMachineDescription().isLP64();
     }
@@ -574,15 +572,6 @@
     }
   }
 
-  /** Indicates whether Thread-Local Allocation Buffers are used */
-  public boolean getUseTLAB() {
-    return useTLAB;
-  }
-
-  public boolean getEnableInvokeDynamic() {
-    return enableInvokeDynamic;
-  }
-
   public TypeDataBase getTypeDataBase() {
     return db;
   }
@@ -778,6 +767,10 @@
     return vmInternalInfo;
   }
 
+  public int getReserveForAllocationPrefetch() {
+    return reserveForAllocationPrefetch;
+  }
+
   public boolean isSharingEnabled() {
     if (sharingEnabled == null) {
       Flag flag = getCommandLineFlag("UseSharedSpaces");
@@ -813,6 +806,12 @@
     return objectAlignmentInBytes;
   }
 
+  /** Indicates whether Thread-Local Allocation Buffers are used */
+  public boolean getUseTLAB() {
+      Flag flag = getCommandLineFlag("UseTLAB");
+      return (flag == null) ? false: flag.getBool();
+  }
+
   // returns null, if not available.
   public Flag[] getCommandLineFlags() {
     if (commandLineFlags == null) {
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,6 +28,8 @@
 import java.util.*;
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.debugger.amd64.*;
+import sun.jvm.hotspot.debugger.bsd.BsdDebugger;
+import sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.runtime.amd64.*;
 import sun.jvm.hotspot.runtime.x86.*;
@@ -38,8 +40,9 @@
   private static AddressField  lastJavaFPField;
   private static AddressField  osThreadField;
 
-  // Field from OSThread
+  // Fields from OSThread
   private static CIntegerField osThreadThreadIDField;
+  private static CIntegerField osThreadUniqueThreadIDField;
 
   // This is currently unneeded but is being kept in case we change
   // the currentFrameGuess algorithm
@@ -61,7 +64,8 @@
     lastJavaFPField         = anchorType.getAddressField("_last_Java_fp");
 
     Type osThreadType = db.lookupType("OSThread");
-    osThreadThreadIDField   = osThreadType.getCIntegerField("_thread_id");
+    osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
+    osThreadUniqueThreadIDField = osThreadType.getCIntegerField("_unique_thread_id");
   }
 
   public    Address getLastJavaFP(Address addr) {
@@ -125,8 +129,9 @@
     Address osThreadAddr = osThreadField.getValue(addr);
     // Get the address of the _thread_id from the OSThread
     Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
+    Address uniqueThreadIdAddr = osThreadAddr.addOffsetTo(osThreadUniqueThreadIDField.getOffset());
 
-    JVMDebugger debugger = VM.getVM().getDebugger();
-    return debugger.getThreadForIdentifierAddress(threadIdAddr);
+    BsdDebuggerLocal debugger = (BsdDebuggerLocal) VM.getVM().getDebugger();
+    return debugger.getThreadForIdentifierAddress(threadIdAddr, uniqueThreadIdAddr);
   }
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
   private static AddressField  osThreadField;
 
   // Field from OSThread
-  private static Field         osThreadThreadHandleField;
+  private static Field         osThreadThreadIdField;
 
   // This is currently unneeded but is being kept in case we change
   // the currentFrameGuess algorithm
@@ -64,7 +64,7 @@
     osThreadField           = type.getAddressField("_osthread");
 
     type = db.lookupType("OSThread");
-    osThreadThreadHandleField = type.getField("_thread_handle");
+    osThreadThreadIdField = type.getField("_thread_id");
   }
 
   public Address getLastJavaFP(Address addr) {
@@ -128,10 +128,10 @@
     // Fetch the OSThread (for now and for simplicity, not making a
     // separate "OSThread" class in this package)
     Address osThreadAddr = osThreadField.getValue(addr);
-    // Get the address of the HANDLE within the OSThread
-    Address threadHandleAddr =
-      osThreadAddr.addOffsetTo(osThreadThreadHandleField.getOffset());
+    // Get the address of the thread_id within the OSThread
+    Address threadIdAddr =
+      osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset());
     JVMDebugger debugger = VM.getVM().getDebugger();
-    return debugger.getThreadForIdentifierAddress(threadHandleAddr);
+    return debugger.getThreadForIdentifierAddress(threadIdAddr);
   }
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
   private static AddressField  osThreadField;
 
   // Field from OSThread
-  private static Field         osThreadThreadHandleField;
+  private static Field         osThreadThreadIdField;
 
   // This is currently unneeded but is being kept in case we change
   // the currentFrameGuess algorithm
@@ -63,7 +63,7 @@
     osThreadField           = type.getAddressField("_osthread");
 
     type = db.lookupType("OSThread");
-    osThreadThreadHandleField = type.getField("_thread_handle");
+    osThreadThreadIdField = type.getField("_thread_id");
   }
 
   public Address getLastJavaFP(Address addr) {
@@ -127,10 +127,10 @@
     // Fetch the OSThread (for now and for simplicity, not making a
     // separate "OSThread" class in this package)
     Address osThreadAddr = osThreadField.getValue(addr);
-    // Get the address of the HANDLE within the OSThread
-    Address threadHandleAddr =
-      osThreadAddr.addOffsetTo(osThreadThreadHandleField.getOffset());
+    // Get the address of the thread_id within the OSThread
+    Address threadIdAddr =
+      osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset());
     JVMDebugger debugger = VM.getVM().getDebugger();
-    return debugger.getThreadForIdentifierAddress(threadHandleAddr);
+    return debugger.getThreadForIdentifierAddress(threadIdAddr);
   }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.tools;
+
+import java.io.*;
+import java.util.*;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.memory.*;
+import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.tools.*;
+import sun.jvm.hotspot.utilities.*;
+
+/**
+  A command line tool to print class loader statistics.
+*/
+
+public class ClassLoaderStats extends Tool {
+   boolean verbose = true;
+
+   public static void main(String[] args) {
+      ClassLoaderStats cls = new ClassLoaderStats();
+      cls.start(args);
+      cls.stop();
+   }
+
+   private static class ClassData {
+      Klass klass;
+      long  size;
+
+      ClassData(Klass klass, long size) {
+         this.klass = klass; this.size = size;
+      }
+   }
+
+   private static class LoaderData {
+      long     numClasses;
+      long     classSize;
+      List     classDetail = new ArrayList(); // List<ClassData>
+   }
+
+   public void run() {
+      printClassLoaderStatistics();
+   }
+
+   private void printClassLoaderStatistics() {
+      final PrintStream out = System.out;
+      final PrintStream err = System.err;
+      final Map loaderMap = new HashMap();
+      // loader data for bootstrap class loader
+      final LoaderData bootstrapLoaderData = new LoaderData();
+      if (verbose) {
+         err.print("finding class loader instances ..");
+      }
+
+      VM vm = VM.getVM();
+      ObjectHeap heap = vm.getObjectHeap();
+      Klass classLoaderKlass = vm.getSystemDictionary().getClassLoaderKlass();
+      try {
+         heap.iterateObjectsOfKlass(new DefaultHeapVisitor() {
+                         public boolean doObj(Oop oop) {
+                            loaderMap.put(oop, new LoaderData());
+                                                        return false;
+                         }
+                      }, classLoaderKlass);
+      } catch (Exception se) {
+         se.printStackTrace();
+      }
+
+      if (verbose) {
+         err.println("done.");
+         err.print("computing per loader stat ..");
+      }
+
+      SystemDictionary dict = VM.getVM().getSystemDictionary();
+      dict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() {
+                        public void visit(Klass k, Oop loader) {
+                           if (! (k instanceof InstanceKlass)) {
+                              return;
+                           }
+                           LoaderData ld = (loader != null) ? (LoaderData)loaderMap.get(loader)
+                                                            : bootstrapLoaderData;
+                           if (ld != null) {
+                              ld.numClasses++;
+                              long size = computeSize((InstanceKlass)k);
+                              ld.classDetail.add(new ClassData(k, size));
+                              ld.classSize += size;
+                           }
+                        }
+                     });
+
+      if (verbose) {
+         err.println("done.");
+         err.print("please wait.. computing liveness");
+      }
+
+      // compute reverse pointer analysis (takes long time for larger app)
+      ReversePtrsAnalysis analysis = new ReversePtrsAnalysis();
+
+      if (verbose) {
+         analysis.setHeapProgressThunk(new HeapProgressThunk() {
+            public void heapIterationFractionUpdate(double fractionOfHeapVisited) {
+               err.print('.');
+            }
+            // This will be called after the iteration is complete
+            public void heapIterationComplete() {
+               err.println("done.");
+            }
+         });
+      }
+
+      try {
+         analysis.run();
+      } catch (Exception e) {
+         // e.printStackTrace();
+         if (verbose)
+           err.println("liveness analysis may be inaccurate ...");
+      }
+      ReversePtrs liveness = VM.getVM().getRevPtrs();
+
+      out.println("class_loader\tclasses\tbytes\tparent_loader\talive?\ttype");
+      out.println();
+
+      long numClassLoaders = 1L;
+      long totalNumClasses = bootstrapLoaderData.numClasses;
+      long totalClassSize  = bootstrapLoaderData.classSize;
+      long numAliveLoaders = 1L;
+      long numDeadLoaders  = 0L;
+
+      // print bootstrap loader details
+      out.print("<bootstrap>");
+      out.print('\t');
+      out.print(bootstrapLoaderData.numClasses);
+      out.print('\t');
+      out.print(bootstrapLoaderData.classSize);
+      out.print('\t');
+      out.print("  null  ");
+      out.print('\t');
+      // bootstrap loader is always alive
+      out.print("live");
+      out.print('\t');
+      out.println("<internal>");
+
+      for (Iterator keyItr = loaderMap.keySet().iterator(); keyItr.hasNext();) {
+         Oop loader = (Oop) keyItr.next();
+         LoaderData data = (LoaderData) loaderMap.get(loader);
+         numClassLoaders ++;
+         totalNumClasses += data.numClasses;
+         totalClassSize  += data.classSize;
+
+         out.print(loader.getHandle());
+         out.print('\t');
+         out.print(data.numClasses);
+         out.print('\t');
+         out.print(data.classSize);
+         out.print('\t');
+
+         class ParentFinder extends DefaultOopVisitor {
+            public void doOop(OopField field, boolean isVMField) {
+               if (field.getID().getName().equals("parent")) {
+                  parent = field.getValue(getObj());
+               }
+            }
+            private Oop parent = null;
+            public Oop getParent() { return parent; }
+         }
+
+         ParentFinder parentFinder = new ParentFinder();
+         loader.iterate(parentFinder, false);
+         Oop parent = parentFinder.getParent();
+         out.print((parent != null)? parent.getHandle().toString() : "  null  ");
+         out.print('\t');
+         boolean alive = (liveness != null) ? (liveness.get(loader) != null) : true;
+         out.print(alive? "live" : "dead");
+         if (alive) numAliveLoaders++; else numDeadLoaders++;
+         out.print('\t');
+         Klass loaderKlass = loader.getKlass();
+         if (loaderKlass != null) {
+            out.print(loaderKlass.getName().asString());
+            out.print('@');
+            out.print(loader.getKlass().getAddress());
+         } else {
+            out.print("    null!    ");
+         }
+         out.println();
+      }
+
+      out.println();
+      // summary line
+      out.print("total = ");
+      out.print(numClassLoaders);
+      out.print('\t');
+      out.print(totalNumClasses);
+      out.print('\t');
+      out.print(totalClassSize);
+      out.print('\t');
+      out.print("    N/A    ");
+      out.print('\t');
+      out.print("alive=");
+      out.print(numAliveLoaders);
+      out.print(", dead=");
+      out.print(numDeadLoaders);
+      out.print('\t');
+      out.print("    N/A    ");
+      out.println();
+   }
+
+   private static long objectSize(Oop oop) {
+      return oop == null ? 0L : oop.getObjectSize();
+   }
+
+   // Don't count the shared empty arrays
+   private static long arraySize(GenericArray arr) {
+     return arr.getLength() != 0L ? arr.getSize() : 0L;
+   }
+
+   private long computeSize(InstanceKlass k) {
+      long size = 0L;
+      // the InstanceKlass object itself
+      size += k.getSize();
+
+      // Constant pool
+      ConstantPool cp = k.getConstants();
+      size += cp.getSize();
+      if (cp.getCache() != null) {
+        size += cp.getCache().getSize();
+      }
+      size += arraySize(cp.getTags());
+
+      // Interfaces
+      size += arraySize(k.getLocalInterfaces());
+      size += arraySize(k.getTransitiveInterfaces());
+
+      // Inner classes
+      size += arraySize(k.getInnerClasses());
+
+      // Fields
+      size += arraySize(k.getFields());
+
+      // Methods
+      MethodArray methods = k.getMethods();
+      int nmethods = (int) methods.getLength();
+      if (nmethods != 0L) {
+         size += methods.getSize();
+         for (int i = 0; i < nmethods; ++i) {
+            Method m = methods.at(i);
+            size += m.getSize();
+            size += m.getConstMethod().getSize();
+         }
+      }
+
+      return size;
+   }
+}
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Thu Mar 21 14:11:13 2013 +0100
@@ -57,17 +57,18 @@
       printGCAlgorithm(flagMap);
       System.out.println();
       System.out.println("Heap Configuration:");
-      printValue("MinHeapFreeRatio = ", getFlagValue("MinHeapFreeRatio", flagMap));
-      printValue("MaxHeapFreeRatio = ", getFlagValue("MaxHeapFreeRatio", flagMap));
-      printValMB("MaxHeapSize      = ", getFlagValue("MaxHeapSize", flagMap));
-      printValMB("NewSize          = ", getFlagValue("NewSize", flagMap));
-      printValMB("MaxNewSize       = ", getFlagValue("MaxNewSize", flagMap));
-      printValMB("OldSize          = ", getFlagValue("OldSize", flagMap));
-      printValue("NewRatio         = ", getFlagValue("NewRatio", flagMap));
-      printValue("SurvivorRatio    = ", getFlagValue("SurvivorRatio", flagMap));
-      printValMB("MetaspaceSize    = ", getFlagValue("MetaspaceSize", flagMap));
-      printValMB("MaxMetaspaceSize = ", getFlagValue("MaxMetaspaceSize", flagMap));
-      printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes());
+      printValue("MinHeapFreeRatio   = ", getFlagValue("MinHeapFreeRatio", flagMap));
+      printValue("MaxHeapFreeRatio   = ", getFlagValue("MaxHeapFreeRatio", flagMap));
+      printValMB("MaxHeapSize        = ", getFlagValue("MaxHeapSize", flagMap));
+      printValMB("NewSize            = ", getFlagValue("NewSize", flagMap));
+      printValMB("MaxNewSize         = ", getFlagValue("MaxNewSize", flagMap));
+      printValMB("OldSize            = ", getFlagValue("OldSize", flagMap));
+      printValue("NewRatio           = ", getFlagValue("NewRatio", flagMap));
+      printValue("SurvivorRatio      = ", getFlagValue("SurvivorRatio", flagMap));
+      printValMB("MetaspaceSize      = ", getFlagValue("MetaspaceSize", flagMap));
+      printValMB("ClassMetaspaceSize = ", getFlagValue("ClassMetaspaceSize", flagMap));
+      printValMB("MaxMetaspaceSize   = ", getFlagValue("MaxMetaspaceSize", flagMap));
+      printValMB("G1HeapRegionSize   = ", HeapRegion.grainBytes());
 
       System.out.println();
       System.out.println("Heap Usage:");
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,7 @@
     }
 
     protected String getCommandFlags() {
-        return "-heap|-heap:format=b|-histo|-permstat|-finalizerinfo";
+        return "-heap|-heap:format=b|-histo|-clstats|-finalizerinfo";
     }
 
     protected void printFlagsUsage() {
@@ -53,14 +53,14 @@
         System.out.println("    -heap\tto print java heap summary");
         System.out.println("    -heap:format=b\tto dump java heap in hprof binary format");
         System.out.println("    -histo\tto print histogram of java object heap");
-        System.out.println("    -permstat\tto print permanent generation statistics");
+        System.out.println("    -clstats\tto print class loader statistics");
         System.out.println("    -finalizerinfo\tto print information on objects awaiting finalization");
         super.printFlagsUsage();
     }
 
     public static final int MODE_HEAP_SUMMARY = 0;
     public static final int MODE_HISTOGRAM = 1;
-    public static final int MODE_PERMSTAT = 2;
+    public static final int MODE_CLSTATS = 2;
     public static final int MODE_PMAP = 3;
     public static final int MODE_HEAP_GRAPH_HPROF_BIN = 4;
     public static final int MODE_HEAP_GRAPH_GXL = 5;
@@ -78,8 +78,8 @@
             tool = new ObjectHistogram();
             break;
 
-        case MODE_PERMSTAT:
-            tool = new PermStat();
+        case MODE_CLSTATS:
+            tool = new ClassLoaderStats();
             break;
 
         case MODE_PMAP:
@@ -118,7 +118,9 @@
             } else if (modeFlag.equals("-histo")) {
                 mode = MODE_HISTOGRAM;
             } else if (modeFlag.equals("-permstat")) {
-                mode = MODE_PERMSTAT;
+                mode = MODE_CLSTATS;
+            } else if (modeFlag.equals("-clstats")) {
+                mode = MODE_CLSTATS;
             } else if (modeFlag.equals("-finalizerinfo")) {
                 mode = MODE_FINALIZERINFO;
             } else {
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java	Thu Mar 21 14:11:13 2013 +0100
@@ -58,10 +58,6 @@
       }
    }
 
-   protected boolean requiresVM() {
-      return false;
-   }
-
    public static void main(String[] args) throws Exception {
       PMap t = new PMap();
       t.start(args);
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java	Thu Mar 21 14:11:13 2013 +0100
@@ -50,29 +50,23 @@
 
    public void run(PrintStream out) {
       Debugger dbg = getAgent().getDebugger();
-      run(out, dbg, getAgent().isJavaMode());
+      run(out, dbg);
    }
 
    public void run(PrintStream out, Debugger dbg) {
-      run(out, dbg, true);
-   }
-
-   private void run(PrintStream out, Debugger dbg, final boolean isJava) {
       CDebugger cdbg = dbg.getCDebugger();
       if (cdbg != null) {
          ConcurrentLocksPrinter concLocksPrinter = null;
-         if (isJava) {
-            // compute and cache java Vframes.
-            initJFrameCache();
-            if (concurrentLocks) {
-               concLocksPrinter = new ConcurrentLocksPrinter();
-            }
-            // print Java level deadlocks
-            try {
-               DeadlockDetector.print(out);
-            } catch (Exception exp) {
-               out.println("can't print deadlock information: " + exp.getMessage());
-            }
+         // compute and cache java Vframes.
+         initJFrameCache();
+         if (concurrentLocks) {
+            concLocksPrinter = new ConcurrentLocksPrinter();
+         }
+         // print Java level deadlocks
+         try {
+            DeadlockDetector.print(out);
+         } catch (Exception exp) {
+            out.println("can't print deadlock information: " + exp.getMessage());
          }
 
          List l = cdbg.getThreadList();
@@ -100,63 +94,59 @@
                      }
                      out.println();
                   } else {
-                     if (isJava) {
-                        // look for one or more java frames
-                        String[] names = null;
-                        // check interpreter frame
-                        Interpreter interp = VM.getVM().getInterpreter();
-                        if (interp.contains(pc)) {
-                           names = getJavaNames(th, f.localVariableBase());
-                           // print codelet name if we can't determine method
-                           if (names == null || names.length == 0) {
-                              out.print("<interpreter> ");
-                              InterpreterCodelet ic = interp.getCodeletContaining(pc);
-                              if (ic != null) {
-                                 String desc = ic.getDescription();
-                                 if (desc != null) out.print(desc);
-                              }
-                              out.println();
-                           }
-                        } else {
-                           // look for known code blobs
-                           CodeCache c = VM.getVM().getCodeCache();
-                           if (c.contains(pc)) {
-                              CodeBlob cb = c.findBlobUnsafe(pc);
-                              if (cb.isNMethod()) {
-                                 names = getJavaNames(th, f.localVariableBase());
-                                 // just print compiled code, if can't determine method
-                                 if (names == null || names.length == 0) {
-                                    out.println("<Unknown compiled code>");
-                                 }
-                              } else if (cb.isBufferBlob()) {
-                                 out.println("<StubRoutines>");
-                              } else if (cb.isRuntimeStub()) {
-                                 out.println("<RuntimeStub>");
-                              } else if (cb.isDeoptimizationStub()) {
-                                 out.println("<DeoptimizationStub>");
-                              } else if (cb.isUncommonTrapStub()) {
-                                 out.println("<UncommonTrap>");
-                              } else if (cb.isExceptionStub()) {
-                                 out.println("<ExceptionStub>");
-                              } else if (cb.isSafepointStub()) {
-                                 out.println("<SafepointStub>");
-                              } else {
-                                 out.println("<Unknown code blob>");
-                              }
-                           } else {
-                              printUnknown(out);
-                           }
-                        }
-                        // print java frames, if any
-                        if (names != null && names.length != 0) {
-                           // print java frame(s)
-                           for (int i = 0; i < names.length; i++) {
-                               out.println(names[i]);
-                           }
-                        }
-                     } else {
-                        printUnknown(out);
-                     }
+                      // look for one or more java frames
+                      String[] names = null;
+                      // check interpreter frame
+                      Interpreter interp = VM.getVM().getInterpreter();
+                      if (interp.contains(pc)) {
+                         names = getJavaNames(th, f.localVariableBase());
+                         // print codelet name if we can't determine method
+                         if (names == null || names.length == 0) {
+                            out.print("<interpreter> ");
+                            InterpreterCodelet ic = interp.getCodeletContaining(pc);
+                            if (ic != null) {
+                               String desc = ic.getDescription();
+                               if (desc != null) out.print(desc);
+                            }
+                            out.println();
+                         }
+                      } else {
+                         // look for known code blobs
+                         CodeCache c = VM.getVM().getCodeCache();
+                         if (c.contains(pc)) {
+                            CodeBlob cb = c.findBlobUnsafe(pc);
+                            if (cb.isNMethod()) {
+                               names = getJavaNames(th, f.localVariableBase());
+                               // just print compiled code, if can't determine method
+                               if (names == null || names.length == 0) {
+                                  out.println("<Unknown compiled code>");
+                               }
+                            } else if (cb.isBufferBlob()) {
+                               out.println("<StubRoutines>");
+                            } else if (cb.isRuntimeStub()) {
+                               out.println("<RuntimeStub>");
+                            } else if (cb.isDeoptimizationStub()) {
+                               out.println("<DeoptimizationStub>");
+                            } else if (cb.isUncommonTrapStub()) {
+                               out.println("<UncommonTrap>");
+                            } else if (cb.isExceptionStub()) {
+                               out.println("<ExceptionStub>");
+                            } else if (cb.isSafepointStub()) {
+                               out.println("<SafepointStub>");
+                            } else {
+                               out.println("<Unknown code blob>");
+                            }
+                         } else {
+                            printUnknown(out);
+                         }
+                      }
+                      // print java frames, if any
+                      if (names != null && names.length != 0) {
+                         // print java frame(s)
+                         for (int i = 0; i < names.length; i++) {
+                             out.println(names[i]);
+                         }
+                      }
                   }
                   f = f.sender(th);
                }
@@ -164,7 +154,7 @@
                exp.printStackTrace();
                // continue, may be we can do a better job for other threads
             }
-            if (isJava && concurrentLocks) {
+            if (concurrentLocks) {
                JavaThread jthread = (JavaThread) proxyToThread.get(th);
                if (jthread != null) {
                    concLocksPrinter.print(jthread, out);
@@ -180,10 +170,6 @@
       }
    }
 
-   protected boolean requiresVM() {
-      return false;
-   }
-
    public static void main(String[] args) throws Exception {
       PStack t = new PStack();
       t.start(args);
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/PermStat.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,277 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.tools;
-
-import java.io.*;
-import java.util.*;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.memory.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.tools.*;
-import sun.jvm.hotspot.utilities.*;
-
-/**
-  A command line tool to print perm. generation statistics.
-*/
-
-public class PermStat extends Tool {
-   boolean verbose = true;
-
-   public static void main(String[] args) {
-      PermStat ps = new PermStat();
-      ps.start(args);
-      ps.stop();
-   }
-
-   private static class ClassData {
-      Klass klass;
-      long  size;
-
-      ClassData(Klass klass, long size) {
-         this.klass = klass; this.size = size;
-      }
-   }
-
-   private static class LoaderData {
-      long     numClasses;
-      long     classSize;
-      List     classDetail = new ArrayList(); // List<ClassData>
-   }
-
-   public void run() {
-      printClassLoaderStatistics();
-   }
-
-   private void printClassLoaderStatistics() {
-      final PrintStream out = System.out;
-      final PrintStream err = System.err;
-      final Map loaderMap = new HashMap();
-      // loader data for bootstrap class loader
-      final LoaderData bootstrapLoaderData = new LoaderData();
-      if (verbose) {
-         err.print("finding class loader instances ..");
-      }
-
-      VM vm = VM.getVM();
-      ObjectHeap heap = vm.getObjectHeap();
-      Klass classLoaderKlass = vm.getSystemDictionary().getClassLoaderKlass();
-      try {
-         heap.iterateObjectsOfKlass(new DefaultHeapVisitor() {
-                         public boolean doObj(Oop oop) {
-                            loaderMap.put(oop, new LoaderData());
-                                                        return false;
-                         }
-                      }, classLoaderKlass);
-      } catch (Exception se) {
-         se.printStackTrace();
-      }
-
-      if (verbose) {
-         err.println("done.");
-         err.print("computing per loader stat ..");
-      }
-
-      SystemDictionary dict = VM.getVM().getSystemDictionary();
-      dict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() {
-                        public void visit(Klass k, Oop loader) {
-                           if (! (k instanceof InstanceKlass)) {
-                              return;
-                           }
-                           LoaderData ld = (loader != null) ? (LoaderData)loaderMap.get(loader)
-                                                            : bootstrapLoaderData;
-                           if (ld != null) {
-                              ld.numClasses++;
-                              long size = computeSize((InstanceKlass)k);
-                              ld.classDetail.add(new ClassData(k, size));
-                              ld.classSize += size;
-                           }
-                        }
-                     });
-
-      if (verbose) {
-         err.println("done.");
-         err.print("please wait.. computing liveness");
-      }
-
-      // compute reverse pointer analysis (takes long time for larger app)
-      ReversePtrsAnalysis analysis = new ReversePtrsAnalysis();
-
-      if (verbose) {
-         analysis.setHeapProgressThunk(new HeapProgressThunk() {
-            public void heapIterationFractionUpdate(double fractionOfHeapVisited) {
-               err.print('.');
-            }
-            // This will be called after the iteration is complete
-            public void heapIterationComplete() {
-               err.println("done.");
-            }
-         });
-      }
-
-      try {
-         analysis.run();
-      } catch (Exception e) {
-         // e.printStackTrace();
-         if (verbose)
-           err.println("liveness analysis may be inaccurate ...");
-      }
-      ReversePtrs liveness = VM.getVM().getRevPtrs();
-
-      out.println("class_loader\tclasses\tbytes\tparent_loader\talive?\ttype");
-      out.println();
-
-      long numClassLoaders = 1L;
-      long totalNumClasses = bootstrapLoaderData.numClasses;
-      long totalClassSize  = bootstrapLoaderData.classSize;
-      long numAliveLoaders = 1L;
-      long numDeadLoaders  = 0L;
-
-      // print bootstrap loader details
-      out.print("<bootstrap>");
-      out.print('\t');
-      out.print(bootstrapLoaderData.numClasses);
-      out.print('\t');
-      out.print(bootstrapLoaderData.classSize);
-      out.print('\t');
-      out.print("  null  ");
-      out.print('\t');
-      // bootstrap loader is always alive
-      out.print("live");
-      out.print('\t');
-      out.println("<internal>");
-
-      for (Iterator keyItr = loaderMap.keySet().iterator(); keyItr.hasNext();) {
-         Oop loader = (Oop) keyItr.next();
-         LoaderData data = (LoaderData) loaderMap.get(loader);
-         numClassLoaders ++;
-         totalNumClasses += data.numClasses;
-         totalClassSize  += data.classSize;
-
-         out.print(loader.getHandle());
-         out.print('\t');
-         out.print(data.numClasses);
-         out.print('\t');
-         out.print(data.classSize);
-         out.print('\t');
-
-         class ParentFinder extends DefaultOopVisitor {
-            public void doOop(OopField field, boolean isVMField) {
-               if (field.getID().getName().equals("parent")) {
-                  parent = field.getValue(getObj());
-               }
-            }
-            private Oop parent = null;
-            public Oop getParent() { return parent; }
-         }
-
-         ParentFinder parentFinder = new ParentFinder();
-         loader.iterate(parentFinder, false);
-         Oop parent = parentFinder.getParent();
-         out.print((parent != null)? parent.getHandle().toString() : "  null  ");
-         out.print('\t');
-         boolean alive = (liveness != null) ? (liveness.get(loader) != null) : true;
-         out.print(alive? "live" : "dead");
-         if (alive) numAliveLoaders++; else numDeadLoaders++;
-         out.print('\t');
-         Klass loaderKlass = loader.getKlass();
-         if (loaderKlass != null) {
-            out.print(loaderKlass.getName().asString());
-            out.print('@');
-            out.print(loader.getKlass().getAddress());
-         } else {
-            out.print("    null!    ");
-         }
-         out.println();
-      }
-
-      out.println();
-      // summary line
-      out.print("total = ");
-      out.print(numClassLoaders);
-      out.print('\t');
-      out.print(totalNumClasses);
-      out.print('\t');
-      out.print(totalClassSize);
-      out.print('\t');
-      out.print("    N/A    ");
-      out.print('\t');
-      out.print("alive=");
-      out.print(numAliveLoaders);
-      out.print(", dead=");
-      out.print(numDeadLoaders);
-      out.print('\t');
-      out.print("    N/A    ");
-      out.println();
-   }
-
-   private static long objectSize(Oop oop) {
-      return oop == null ? 0L : oop.getObjectSize();
-   }
-
-   // Don't count the shared empty arrays
-   private static long arraySize(GenericArray arr) {
-     return arr.getLength() != 0L ? arr.getSize() : 0L;
-   }
-
-   private long computeSize(InstanceKlass k) {
-      long size = 0L;
-      // the InstanceKlass object itself
-      size += k.getSize();
-
-      // Constant pool
-      ConstantPool cp = k.getConstants();
-      size += cp.getSize();
-      if (cp.getCache() != null) {
-        size += cp.getCache().getSize();
-      }
-      size += arraySize(cp.getTags());
-
-      // Interfaces
-      size += arraySize(k.getLocalInterfaces());
-      size += arraySize(k.getTransitiveInterfaces());
-
-      // Inner classes
-      size += arraySize(k.getInnerClasses());
-
-      // Fields
-      size += arraySize(k.getFields());
-
-      // Methods
-      MethodArray methods = k.getMethods();
-      int nmethods = (int) methods.getLength();
-      if (nmethods != 0L) {
-         size += methods.getSize();
-         for (int i = 0; i < nmethods; ++i) {
-            Method m = methods.at(i);
-            size += m.getSize();
-            size += m.getConstMethod().getSize();
-         }
-      }
-
-      return size;
-   }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java	Thu Mar 21 14:11:13 2013 +0100
@@ -27,7 +27,6 @@
 import java.io.PrintStream;
 import java.util.Hashtable;
 import sun.jvm.hotspot.*;
-import sun.jvm.hotspot.bugspot.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.debugger.*;
 
@@ -35,7 +34,7 @@
 // override run & code main as shown below.
 
 public abstract class Tool implements Runnable {
-   private BugSpotAgent agent;
+   private HotSpotAgent agent;
    private int debugeeType;
 
    // debugeeType is one of constants below
@@ -51,12 +50,7 @@
       return true;
    }
 
-   // whether this tool requires debuggee to be java process or core?
-   protected boolean requiresVM() {
-      return true;
-   }
-
-   protected void setAgent(BugSpotAgent a) {
+   protected void setAgent(HotSpotAgent a) {
       agent = a;
    }
 
@@ -64,7 +58,7 @@
       debugeeType = dt;
    }
 
-   protected BugSpotAgent getAgent() {
+   protected HotSpotAgent getAgent() {
       return agent;
    }
 
@@ -155,7 +149,7 @@
            usage();
       }
 
-      agent = new BugSpotAgent();
+      agent = new HotSpotAgent();
       try {
         switch (debugeeType) {
           case DEBUGEE_PID:
@@ -198,33 +192,24 @@
 
       err.println("Debugger attached successfully.");
 
-      boolean isJava = agent.isJavaMode();
-      if (isJava) {
-         VM vm = VM.getVM();
-         if (vm.isCore()) {
-           err.println("Core build detected.");
-         } else if (vm.isClientCompiler()) {
-           err.println("Client compiler detected.");
-         } else if (vm.isServerCompiler()) {
-           err.println("Server compiler detected.");
-         } else {
-           throw new RuntimeException("Fatal error: " +
-                                 "should have been able to detect core/C1/C2 build");
-         }
+      VM vm = VM.getVM();
+      if (vm.isCore()) {
+        err.println("Core build detected.");
+      } else if (vm.isClientCompiler()) {
+        err.println("Client compiler detected.");
+      } else if (vm.isServerCompiler()) {
+        err.println("Server compiler detected.");
+      } else {
+        throw new RuntimeException("Fatal error: "
+            + "should have been able to detect core/C1/C2 build");
+      }
 
-         String version = vm.getVMRelease();
-         if (version != null) {
-            err.print("JVM version is ");
-            err.println(version);
-         }
+      String version = vm.getVMRelease();
+      if (version != null) {
+        err.print("JVM version is ");
+        err.println(version);
+      }
 
-         run();
-      } else { // not a java process or core
-         if (requiresVM()) {
-            err.println(getName() + " requires a java VM process/core!");
-         } else {
-            run();
-         }
-      }
+      run();
    }
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/SAPanel.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/SAPanel.java	Thu Mar 21 14:11:13 2013 +0100
@@ -50,7 +50,7 @@
 /**
  * This base class encapsulates many of the events that are fired from
  * the various panels in this directory so they can easily be plugged
- * in to different containing frameworks (HSDB, BugSpot).
+ * in to different containing frameworks (HSDB).
  */
 public class SAPanel extends JPanel {
     protected List listeners = new ArrayList();
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,6 @@
   private static final int JVM_CONSTANT_UnresolvedClassInError  = 103; // Resolution failed
   private static final int JVM_CONSTANT_MethodHandleInError     = 104; // Error tag due to resolution error
   private static final int JVM_CONSTANT_MethodTypeInError       = 105; // Error tag due to resolution error
-  private static final int JVM_CONSTANT_Object                  = 106; // Required for BoundMethodHandle arguments.
 
   // JVM_CONSTANT_MethodHandle subtypes //FIXME: connect these to data structure
   private static int JVM_REF_getField                = 1;
@@ -96,8 +95,6 @@
   public boolean isKlassIndex()             { return tag == JVM_CONSTANT_ClassIndex; }
   public boolean isStringIndex()            { return tag == JVM_CONSTANT_StringIndex; }
 
-  public boolean isObject()                 { return tag == JVM_CONSTANT_Object; }
-
   public boolean isKlassReference()   { return isKlassIndex() || isUnresolvedKlass(); }
   public boolean isFieldOrMethod()    { return isField() || isMethod() || isInterfaceMethod(); }
   public boolean isSymbol()           { return isUtf8(); }
@@ -123,7 +120,6 @@
     case JVM_CONSTANT_StringIndex :
     case JVM_CONSTANT_MethodHandle :
     case JVM_CONSTANT_MethodType :
-    case JVM_CONSTANT_Object :
       return BasicType.T_OBJECT;
     default:
       throw new InternalError("unexpected tag: " + tag);
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Thu Mar 21 11:30:38 2013 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Thu Mar 21 14:11:13 2013 +0100
@@ -31,7 +31,6 @@
 
 sapkg.hotspot = Packages.sun.jvm.hotspot;
 sapkg.asm = sapkg.hotspot.asm;
-sapkg.bugspot = sapkg.hotspot.bugspot;
 sapkg.c1 = sapkg.hotspot.c1;
 sapkg.code = sapkg.hotspot.code;
 sapkg.compiler = sapkg.hotspot.compiler;
@@ -40,7 +39,6 @@
 // sapkg.debugger = sapkg.hotspot.debugger;
 
 sapkg.interpreter = sapkg.hotspot.interpreter;
-sapkg.livejvm = sapkg.hotspot.livejvm;
 sapkg.jdi = sapkg.hotspot.jdi;
 sapkg.memory = sapkg.hotspot.memory;
 sapkg.oops = sapkg.hotspot.oops;
--- a/agent/src/share/native/jvmdi/sa.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,601 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <vector>
-#include "sa.hpp"
-#include "jni.h"
-#include "jvmdi.h"
-
-#ifndef WIN32
- #include <inttypes.h>
-#else
- typedef int int32_t;
-#endif
-
-#ifdef WIN32
- #include <windows.h>
- #define YIELD() Sleep(0)
- #define SLEEP() Sleep(10)
- #define vsnprintf _vsnprintf
-#else
- Error: please port YIELD() and SLEEP() macros to your platform
-#endif
-
-using namespace std;
-
-//////////////////////////////////////////////////////////////////////
-//                                                                  //
-// Exported "interface" for Java language-level interaction between //
-// the SA and the VM. Note that the SA knows about the layout of    //
-// certain VM data structures and that knowledge is taken advantage //
-// of in this code, although this interfaces with the VM via JVMDI. //
-//                                                                  //
-//////////////////////////////////////////////////////////////////////
-
-extern "C" {
-  /////////////////////////////////////
-  //                                 //
-  // Events sent by the VM to the SA //
-  //                                 //
-  /////////////////////////////////////
-
-  // Set by the SA when it attaches. Indicates that events should be
-  // posted via these exported variables, and that the VM should wait
-  // for those events to be acknowledged by the SA (via its setting
-  // saEventPending to 0).
-  JNIEXPORT volatile int32_t saAttached     = 0;
-
-  // Set to nonzero value by the VM when an event has been posted; set
-  // back to 0 by the SA when it has processed that event.
-  JNIEXPORT volatile int32_t saEventPending = 0;
-
-  // Kind of the event (from jvmdi.h)
-  JNIEXPORT volatile int32_t saEventKind    = 0;
-
-  //
-  // Exception events
-  //
-  JNIEXPORT jthread   saExceptionThread;
-  JNIEXPORT jclass    saExceptionClass;
-  JNIEXPORT jmethodID saExceptionMethod;
-  JNIEXPORT int32_t   saExceptionLocation;
-  JNIEXPORT jobject   saExceptionException;
-  JNIEXPORT jclass    saExceptionCatchClass;
-  JNIEXPORT jmethodID saExceptionCatchMethod;
-  JNIEXPORT int32_t   saExceptionCatchLocation;
-
-  //
-  // Breakpoint events
-  //
-  JNIEXPORT jthread   saBreakpointThread;
-  JNIEXPORT jclass    saBreakpointClass;
-  JNIEXPORT jmethodID saBreakpointMethod;
-  JNIEXPORT jlocation saBreakpointLocation;
-
-  ///////////////////////////////////////
-  //                                   //
-  // Commands sent by the SA to the VM //
-  //                                   //
-  ///////////////////////////////////////
-
-  extern JNIEXPORT const int32_t SA_CMD_SUSPEND_ALL       = 0;
-  extern JNIEXPORT const int32_t SA_CMD_RESUME_ALL        = 1;
-  extern JNIEXPORT const int32_t SA_CMD_TOGGLE_BREAKPOINT = 2;
-  extern JNIEXPORT const int32_t SA_CMD_BUF_SIZE          = 1024;
-
-  // SA sets this to a nonzero value when it is requesting a command
-  // to be processed; VM sets it back to 0 when the command has been
-  // executed
-  JNIEXPORT volatile int32_t saCmdPending   = 0;
-
-  // SA sets this to one of the manifest constants above to indicate
-  // the kind of command to be executed
-  JNIEXPORT volatile int32_t saCmdType      = 0;
-
-  // VM sets this to 0 if the last command succeeded or a nonzero
-  // value if it failed
-  JNIEXPORT volatile int32_t saCmdResult    = 0;
-
-  // If last command failed, this buffer will contain a descriptive
-  // error message
-  JNIEXPORT char             saCmdResultErrMsg[SA_CMD_BUF_SIZE];
-
-  //
-  // Toggling of breakpoint command arguments.
-  //
-  // Originally there were separate set/clear breakpoint commands
-  // taking a class name, method name and signature, and the iteration
-  // through the debug information was done in the SA. It turns out
-  // that doing this work in the target VM is significantly faster,
-  // and since interactivity when setting and clearing breakpoints is
-  // important, the solution which resulted in more C/C++ code was used.
-  //
-
-  // Source file name
-  JNIEXPORT char    saCmdBkptSrcFileName[SA_CMD_BUF_SIZE];
-
-  // Package name ('/' as separator instead of '.')
-  JNIEXPORT char    saCmdBkptPkgName[SA_CMD_BUF_SIZE];
-
-  // Line number
-  JNIEXPORT int32_t saCmdBkptLineNumber;
-
-  // Output back to SA: indicator whether the last failure of a
-  // breakpoint toggle command was really an error or just a lack of
-  // debug information covering the requested line. 0 if not error.
-  // Valid only if saCmdResult != 0.
-  JNIEXPORT int32_t saCmdBkptResWasError;
-
-  // Output back to SA: resulting line number at which the breakpoint
-  // was set or cleared (valid only if saCmdResult == 0)
-  JNIEXPORT int32_t saCmdBkptResLineNumber;
-
-  // Output back to SA: resulting byte code index at which the
-  // breakpoint was set or cleared (valid only if saCmdResult == 0)
-  JNIEXPORT int32_t saCmdBkptResBCI;
-
-  // Output back to SA: indicator whether the breakpoint operation
-  // resulted in a set or cleared breakpoint; nonzero if set, zero if
-  // cleared (valid only if saCmdResult == 0)
-  JNIEXPORT int32_t saCmdBkptResWasSet;
-
-  // Output back to SA: method name the breakpoint was set in (valid
-  // only if saCmdResult == 0)
-  JNIEXPORT char    saCmdBkptResMethodName[SA_CMD_BUF_SIZE];
-
-  // Output back to SA: method signature (JNI style) the breakpoint
-  // was set in (valid only if saCmdResult == 0)
-  JNIEXPORT char    saCmdBkptResMethodSig[SA_CMD_BUF_SIZE];
-}
-
-// Internal state
-static JavaVM* jvm = NULL;
-static JVMDI_Interface_1* jvmdi = NULL;
-static jthread debugThreadObj = NULL;
-static bool suspended = false;
-static vector<jthread> suspendedThreads;
-static JVMDI_RawMonitor eventLock = NULL;
-
-class MonitorLocker {
-private:
-  JVMDI_RawMonitor lock;
-public:
-  MonitorLocker(JVMDI_RawMonitor lock) {
-    this->lock = lock;
-    if (lock != NULL) {
-      jvmdi->RawMonitorEnter(lock);
-    }
-  }
-  ~MonitorLocker() {
-    if (lock != NULL) {
-      jvmdi->RawMonitorExit(lock);
-    }
-  }
-};
-
-class JvmdiDeallocator {
-private:
-  void* ptr;
-public:
-  JvmdiDeallocator(void* ptr) {
-    this->ptr = ptr;
-  }
-  ~JvmdiDeallocator() {
-    jvmdi->Deallocate((jbyte*) ptr);
-  }
-};
-
-class JvmdiRefListDeallocator {
-private:
-  JNIEnv* env;
-  jobject* refList;
-  jint refCount;
-public:
-  JvmdiRefListDeallocator(JNIEnv* env, jobject* refList, jint refCount) {
-    this->env = env;
-    this->refList = refList;
-    this->refCount = refCount;
-  }
-  ~JvmdiRefListDeallocator() {
-    for (int i = 0; i < refCount; i++) {
-      env->DeleteGlobalRef(refList[i]);
-    }
-    jvmdi->Deallocate((jbyte*) refList);
-  }
-};
-
-static void
-stop(char* msg) {
-  fprintf(stderr, "%s", msg);
-  fprintf(stderr, "\n");
-  exit(1);
-}
-
-// This fills in the command result error message, sets the command
-// result to -1, and clears the pending command flag
-static void
-reportErrorToSA(const char* str, ...) {
-  va_list varargs;
-  va_start(varargs, str);
-  vsnprintf(saCmdResultErrMsg, sizeof(saCmdResultErrMsg), str, varargs);
-  va_end(varargs);
-  saCmdResult = -1;
-  saCmdPending = 0;
-}
-
-static bool
-packageNameMatches(char* clazzName, char* pkg) {
-  int pkgLen = strlen(pkg);
-  int clazzNameLen = strlen(clazzName);
-
-  if (pkgLen >= clazzNameLen + 1) {
-    return false;
-  }
-
-  if (strncmp(clazzName, pkg, pkgLen)) {
-    return false;
-  }
-
-  // Ensure that '/' is the next character if non-empty package name
-  int l = pkgLen;
-  if (l > 0) {
-    if (clazzName[l] != '/') {
-      return false;
-    }
-    l++;
-  }
-  // Ensure that there are no more trailing slashes
-  while (l < clazzNameLen) {
-    if (clazzName[l++] == '/') {
-      return false;
-    }
-  }
-  return true;
-}
-
-static void
-executeOneCommand(JNIEnv* env) {
-  switch (saCmdType) {
-  case SA_CMD_SUSPEND_ALL: {
-    if (suspended) {
-      reportErrorToSA("Target process already suspended");
-      return;
-    }
-
-    // We implement this by getting all of the threads and calling
-    // SuspendThread on each one, except for the thread object
-    // corresponding to this thread. Each thread for which the call
-    // succeeded (i.e., did not return JVMDI_ERROR_INVALID_THREAD)
-    // is added to a list which is remembered for later resumption.
-    // Note that this currently has race conditions since a thread
-    // might be started after we call GetAllThreads and since a
-    // thread for which we got an error earlier might be resumed by
-    // the VM while we are busy suspending other threads. We could
-    // solve this by looping until there are no more threads we can
-    // suspend, but a more robust and scalable solution is to add
-    // this functionality to the JVMDI interface (i.e.,
-    // "suspendAll"). Probably need to provide an exclude list for
-    // such a routine.
-    jint threadCount;
-    jthread* threads;
-    if (jvmdi->GetAllThreads(&threadCount, &threads) != JVMDI_ERROR_NONE) {
-      reportErrorToSA("Error while getting thread list");
-      return;
-    }
-
-
-    for (int i = 0; i < threadCount; i++) {
-      jthread thr = threads[i];
-      if (!env->IsSameObject(thr, debugThreadObj)) {
-        jvmdiError err = jvmdi->SuspendThread(thr);
-        if (err == JVMDI_ERROR_NONE) {
-          // Remember this thread and do not free it
-          suspendedThreads.push_back(thr);
-          continue;
-        } else {
-          fprintf(stderr, " SA: Error %d while suspending thread\n", err);
-          // FIXME: stop, resume all threads, report error
-        }
-      }
-      env->DeleteGlobalRef(thr);
-    }
-
-    // Free up threads
-    jvmdi->Deallocate((jbyte*) threads);
-
-    // Suspension is complete
-    suspended = true;
-    break;
-  }
-
-  case SA_CMD_RESUME_ALL: {
-    if (!suspended) {
-      reportErrorToSA("Target process already suspended");
-      return;
-    }
-
-    saCmdResult = 0;
-    bool errorOccurred = false;
-    jvmdiError firstError;
-    for (int i = 0; i < suspendedThreads.size(); i++) {
-      jthread thr = suspendedThreads[i];
-      jvmdiError err = jvmdi->ResumeThread(thr);
-      env->DeleteGlobalRef(thr);
-      if (err != JVMDI_ERROR_NONE) {
-        if (!errorOccurred) {
-          errorOccurred = true;
-          firstError = err;
-        }
-      }
-    }
-    suspendedThreads.clear();
-    suspended = false;
-    if (errorOccurred) {
-      reportErrorToSA("Error %d while resuming threads", firstError);
-      return;
-    }
-    break;
-  }
-
-  case SA_CMD_TOGGLE_BREAKPOINT: {
-    saCmdBkptResWasError = 1;
-
-    // Search line number info for all loaded classes
-    jint classCount;
-    jclass* classes;
-
-    jvmdiError glcRes = jvmdi->GetLoadedClasses(&classCount, &classes);
-    if (glcRes != JVMDI_ERROR_NONE) {
-      reportErrorToSA("Error %d while getting loaded classes", glcRes);
-      return;
-    }
-    JvmdiRefListDeallocator rld(env, (jobject*) classes, classCount);
-
-    bool done = false;
-    bool gotOne = false;
-    jclass targetClass;
-    jmethodID targetMethod;
-    jlocation targetLocation;
-    jint targetLineNumber;
-
-    for (int i = 0; i < classCount && !done; i++) {
-      fflush(stderr);
-      jclass clazz = classes[i];
-      char* srcName;
-      jvmdiError sfnRes = jvmdi->GetSourceFileName(clazz, &srcName);
-      if (sfnRes == JVMDI_ERROR_NONE) {
-        JvmdiDeallocator de1(srcName);
-        if (!strcmp(srcName, saCmdBkptSrcFileName)) {
-          // Got a match. Now see whether the package name of the class also matches
-          char* clazzName;
-          jvmdiError sigRes = jvmdi->GetClassSignature(clazz, &clazzName);
-          if (sigRes != JVMDI_ERROR_NONE) {
-            reportErrorToSA("Error %d while getting a class's signature", sigRes);
-            return;
-          }
-          JvmdiDeallocator de2(clazzName);
-          if (packageNameMatches(clazzName + 1, saCmdBkptPkgName)) {
-            // Iterate through all methods
-            jint methodCount;
-            jmethodID* methods;
-            if (jvmdi->GetClassMethods(clazz, &methodCount, &methods) != JVMDI_ERROR_NONE) {
-              reportErrorToSA("Error while getting methods of class %s", clazzName);
-              return;
-            }
-            JvmdiDeallocator de3(methods);
-            for (int j = 0; j < methodCount && !done; j++) {
-              jmethodID m = methods[j];
-              jint entryCount;
-              JVMDI_line_number_entry* table;
-              jvmdiError lnRes = jvmdi->GetLineNumberTable(clazz, m, &entryCount, &table);
-              if (lnRes == JVMDI_ERROR_NONE) {
-                JvmdiDeallocator de4(table);
-                // Look for line number greater than or equal to requested line
-                for (int k = 0; k < entryCount && !done; k++) {
-                  JVMDI_line_number_entry& entry = table[k];
-                  if (entry.line_number >= saCmdBkptLineNumber &&
-                      (!gotOne || entry.line_number < targetLineNumber)) {
-                    gotOne = true;
-                    targetClass = clazz;
-                    targetMethod = m;
-                    targetLocation = entry.start_location;
-                    targetLineNumber = entry.line_number;
-                    done = (targetLineNumber == saCmdBkptLineNumber);
-                  }
-                }
-              } else if (lnRes != JVMDI_ERROR_ABSENT_INFORMATION) {
-                reportErrorToSA("Unexpected error %d while fetching line number table", lnRes);
-                return;
-              }
-            }
-          }
-        }
-      } else if (sfnRes != JVMDI_ERROR_ABSENT_INFORMATION) {
-        reportErrorToSA("Unexpected error %d while fetching source file name", sfnRes);
-        return;
-      }
-    }
-
-    bool wasSet = true;
-    if (gotOne) {
-      // Really toggle this breakpoint
-      jvmdiError bpRes;
-      bpRes = jvmdi->SetBreakpoint(targetClass, targetMethod, targetLocation);
-      if (bpRes == JVMDI_ERROR_DUPLICATE) {
-        bpRes = jvmdi->ClearBreakpoint(targetClass, targetMethod, targetLocation);
-        wasSet = false;
-      }
-      if (bpRes != JVMDI_ERROR_NONE) {
-        reportErrorToSA("Unexpected error %d while setting or clearing breakpoint at bci %d, line %d",
-                        bpRes, targetLocation, targetLineNumber);
-        return;
-      }
-    } else {
-      saCmdBkptResWasError = 0;
-      reportErrorToSA("No debug information found covering this line");
-      return;
-    }
-
-    // Provide result
-    saCmdBkptResLineNumber = targetLineNumber;
-    saCmdBkptResBCI        = targetLocation;
-    saCmdBkptResWasSet     = (wasSet ? 1 : 0);
-    {
-      char* methodName;
-      char* methodSig;
-      if (jvmdi->GetMethodName(targetClass, targetMethod, &methodName, &methodSig)
-          == JVMDI_ERROR_NONE) {
-        JvmdiDeallocator mnd(methodName);
-        JvmdiDeallocator msd(methodSig);
-        strncpy(saCmdBkptResMethodName, methodName, SA_CMD_BUF_SIZE);
-        strncpy(saCmdBkptResMethodSig,  methodSig, SA_CMD_BUF_SIZE);
-      } else {
-        strncpy(saCmdBkptResMethodName, "<error>", SA_CMD_BUF_SIZE);
-        strncpy(saCmdBkptResMethodSig,  "<error>", SA_CMD_BUF_SIZE);
-      }
-    }
-    break;
-  }
-
-  default:
-    reportErrorToSA("Command %d not yet supported", saCmdType);
-    return;
-  }
-
-  // Successful command execution
-  saCmdResult = 0;
-  saCmdPending = 0;
-}
-
-static void
-saCommandThread(void *arg) {
-  JNIEnv* env = NULL;
-  if (jvm->GetEnv((void **) &env, JNI_VERSION_1_2) != JNI_OK) {
-    stop("Error while starting Serviceability Agent "
-         "command thread: could not get JNI environment");
-  }
-
-  while (1) {
-    // Wait for command
-    while (!saCmdPending) {
-      SLEEP();
-    }
-
-    executeOneCommand(env);
-  }
-}
-
-static void
-saEventHook(JNIEnv *env, JVMDI_Event *event)
-{
-  MonitorLocker ml(eventLock);
-
-  saEventKind = event->kind;
-
-  if (event->kind == JVMDI_EVENT_VM_INIT) {
-    // Create event lock
-    if (jvmdi->CreateRawMonitor("Serviceability Agent Event Lock", &eventLock)
-        != JVMDI_ERROR_NONE) {
-      stop("Unable to create Serviceability Agent's event lock");
-    }
-    // Start thread which receives commands from the SA.
-    jclass threadClass = env->FindClass("java/lang/Thread");
-    if (threadClass == NULL) stop("Unable to find class java/lang/Thread");
-    jstring threadName = env->NewStringUTF("Serviceability Agent Command Thread");
-    if (threadName == NULL) stop("Unable to allocate debug thread name");
-    jmethodID ctor = env->GetMethodID(threadClass, "<init>", "(Ljava/lang/String;)V");
-    if (ctor == NULL) stop("Unable to find appropriate constructor for java/lang/Thread");
-    // Allocate thread object
-    jthread thr = (jthread) env->NewObject(threadClass, ctor, threadName);
-    if (thr == NULL) stop("Unable to allocate debug thread's java/lang/Thread instance");
-    // Remember which thread this is
-    debugThreadObj = env->NewGlobalRef(thr);
-    if (debugThreadObj == NULL) stop("Unable to allocate global ref for debug thread object");
-    // Start thread
-    jvmdiError err;
-    if ((err = jvmdi->RunDebugThread(thr, &saCommandThread, NULL, JVMDI_THREAD_NORM_PRIORITY))
-        != JVMDI_ERROR_NONE) {
-      char buf[256];
-      sprintf(buf, "Error %d while starting debug thread", err);
-      stop(buf);
-    }
-    // OK, initialization is done
-    return;
-  }
-
-  if (!saAttached) {
-    return;
-  }
-
-  switch (event->kind) {
-  case JVMDI_EVENT_EXCEPTION: {
-    fprintf(stderr, "SA: Exception thrown -- ignoring\n");
-    saExceptionThread        = event->u.exception.thread;
-    saExceptionClass         = event->u.exception.clazz;
-    saExceptionMethod        = event->u.exception.method;
-    saExceptionLocation      = event->u.exception.location;
-    saExceptionException     = event->u.exception.exception;
-    saExceptionCatchClass    = event->u.exception.catch_clazz;
-    saExceptionCatchClass    = event->u.exception.catch_clazz;
-    saExceptionCatchMethod   = event->u.exception.catch_method;
-    saExceptionCatchLocation = event->u.exception.catch_location;
-    //    saEventPending = 1;
-    break;
-  }
-
-  case JVMDI_EVENT_BREAKPOINT: {
-    saBreakpointThread       = event->u.breakpoint.thread;
-    saBreakpointClass        = event->u.breakpoint.clazz;
-    saBreakpointMethod       = event->u.breakpoint.method;
-    saBreakpointLocation     = event->u.breakpoint.location;
-    saEventPending = 1;
-    break;
-  }
-
-  default:
-    break;
-  }
-
-  while (saAttached && saEventPending) {
-    SLEEP();
-  }
-}
-
-extern "C" {
-JNIEXPORT jint JNICALL
-JVM_OnLoad(JavaVM *vm, char *options, void *reserved)
-{
-  jvm = vm;
-  if (jvm->GetEnv((void**) &jvmdi, JVMDI_VERSION_1) != JNI_OK) {
-    return -1;
-  }
-  if (jvmdi->SetEventHook(&saEventHook) != JVMDI_ERROR_NONE) {
-    return -1;
-  }
-  return 0;
-}
-};
--- a/agent/src/share/native/jvmdi/sa.dsp	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-# Microsoft Developer Studio Project File - Name="sa" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=sa - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "sa.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "sa.mak" CFG="sa - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "sa - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "sa - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "sa - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "D:\jdk1.4\include" /I "D:\jdk1.4\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-
-!ELSEIF  "$(CFG)" == "sa - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /GZ  /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "D:\jdk1.4\include" /I "D:\jdk1.4\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /GZ  /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "sa - Win32 Release"
-# Name "sa - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\sa.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
--- a/agent/src/share/native/jvmdi/sa.dsw	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "sa"=.\sa.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
--- a/agent/src/share/native/jvmdi/sa.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "jni.h"
-
-extern "C" {
-JNIEXPORT jint JNICALL
-JVM_OnLoad(JavaVM *vm, char *options, void *reserved);
-}
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Thu Mar 21 14:11:13 2013 +0100
@@ -133,7 +133,7 @@
                 // scheduled.
                 double unscheduledSum = 0.0;
                 for (Block pred : mostLikelySuccessor.getPredecessors()) {
-                    if (!visitedBlocks.get(pred.getId())) {
+                    if (pred.getLinearScanNumber() == -1) {
                         unscheduledSum += pred.getBeginNode().probability();
                     }
                 }
--- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,12 +24,11 @@
 
 import static com.oracle.graal.api.code.MemoryBarriers.*;
 import static com.oracle.graal.api.code.Register.RegisterFlag.*;
-import static com.oracle.graal.api.meta.Kind.*;
 
 import java.nio.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.Register.*;
+import com.oracle.graal.api.code.Register.RegisterFlag;
 
 /**
  * Represents the AMD64 architecture.
@@ -106,8 +105,6 @@
         rip
     };
 
-    public static final RegisterValue RSP = rsp.asValue(Long);
-
     public AMD64() {
         super("AMD64",
               8,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/AbstractAddress.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.code;
+
+/**
+ * Abstract base class that represents a platform specific address.
+ */
+public abstract class AbstractAddress {
+}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.api.code;
-
-import static com.oracle.graal.api.code.ValueUtil.*;
-
-import com.oracle.graal.api.meta.*;
-
-/**
- * Represents an address in target machine memory, specified via some combination of a base
- * register, an index register, a displacement and a scale. Note that the base and index registers
- * may be a variable that will get a register assigned later by the register allocator.
- */
-public final class Address extends Value {
-
-    private static final long serialVersionUID = -1003772042519945089L;
-
-    /**
-     * A sentinel value used as a place holder in an instruction stream for an address that will be
-     * patched.
-     */
-    public static final Address Placeholder = new Address(Kind.Illegal, Value.ILLEGAL);
-
-    private Value base;
-    private Value index;
-    private final Scale scale;
-    private final int displacement;
-
-    /**
-     * Creates an {@link Address} with given base register, no scaling and no displacement.
-     * 
-     * @param kind the kind of the value being addressed
-     * @param base the base register
-     */
-    public Address(Kind kind, Value base) {
-        this(kind, base, ILLEGAL, Scale.Times1, 0);
-    }
-
-    /**
-     * Creates an {@link Address} with given base register, no scaling and a given displacement.
-     * 
-     * @param kind the kind of the value being addressed
-     * @param base the base register
-     * @param displacement the displacement
-     */
-    public Address(Kind kind, Value base, int displacement) {
-        this(kind, base, ILLEGAL, Scale.Times1, displacement);
-    }
-
-    /**
-     * Creates an {@link Address} with given base and index registers, scaling and displacement.
-     * This is the most general constructor.
-     * 
-     * @param kind the kind of the value being addressed
-     * @param base the base register
-     * @param index the index register
-     * @param scale the scaling factor
-     * @param displacement the displacement
-     */
-    public Address(Kind kind, Value base, Value index, Scale scale, int displacement) {
-        super(kind);
-        this.setBase(base);
-        this.setIndex(index);
-        this.scale = scale;
-        this.displacement = displacement;
-
-        assert !isConstant(base) && !isStackSlot(base);
-        assert !isConstant(index) && !isStackSlot(index);
-    }
-
-    /**
-     * A scaling factor used in complex addressing modes such as those supported by x86 platforms.
-     */
-    public enum Scale {
-        Times1(1, 0), Times2(2, 1), Times4(4, 2), Times8(8, 3);
-
-        private Scale(int value, int log2) {
-            this.value = value;
-            this.log2 = log2;
-        }
-
-        /**
-         * The value (or multiplier) of this scale.
-         */
-        public final int value;
-
-        /**
-         * The {@linkplain #value value} of this scale log 2.
-         */
-        public final int log2;
-
-        public static Scale fromInt(int scale) {
-            switch (scale) {
-                case 1:
-                    return Times1;
-                case 2:
-                    return Times2;
-                case 4:
-                    return Times4;
-                case 8:
-                    return Times8;
-                default:
-                    throw new IllegalArgumentException(String.valueOf(scale));
-            }
-        }
-    }
-
-    @Override
-    public String toString() {
-        if (this == Placeholder) {
-            return "[<placeholder>]";
-        }
-
-        StringBuilder s = new StringBuilder();
-        s.append(getKind().getJavaName()).append("[");
-        String sep = "";
-        if (isLegal(getBase())) {
-            s.append(getBase());
-            sep = " + ";
-        }
-        if (isLegal(getIndex())) {
-            s.append(sep).append(getIndex()).append(" * ").append(getScale().value);
-            sep = " + ";
-        }
-        if (getDisplacement() < 0) {
-            s.append(" - ").append(-getDisplacement());
-        } else if (getDisplacement() > 0) {
-            s.append(sep).append(getDisplacement());
-        }
-        s.append("]");
-        return s.toString();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof Address) {
-            Address addr = (Address) obj;
-            return getKind() == addr.getKind() && getDisplacement() == addr.getDisplacement() && getBase().equals(addr.getBase()) && getScale() == addr.getScale() &&
-                            getIndex().equals(addr.getIndex());
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return getBase().hashCode() ^ getIndex().hashCode() ^ (getDisplacement() << 4) ^ (getScale().value << 8) ^ (getKind().ordinal() << 12);
-    }
-
-    /**
-     * @return Base register that defines the start of the address computation. If not present, is
-     *         denoted by {@link Value#ILLEGAL}.
-     */
-    public Value getBase() {
-        return base;
-    }
-
-    public void setBase(Value base) {
-        this.base = base;
-    }
-
-    /**
-     * @return Index register, the value of which (possibly scaled by {@link #scale}) is added to
-     *         {@link #base}. If not present, is denoted by {@link Value#ILLEGAL}.
-     */
-    public Value getIndex() {
-        return index;
-    }
-
-    public void setIndex(Value index) {
-        this.index = index;
-    }
-
-    /**
-     * @return Scaling factor for indexing, dependent on target operand size.
-     */
-    public Scale getScale() {
-        return scale;
-    }
-
-    /**
-     * @return Optional additive displacement.
-     */
-    public int getDisplacement() {
-        return displacement;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/AllocatableValue.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.code;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Common base class for values that can be manipulated by the register allocator.
+ */
+public abstract class AllocatableValue extends Value {
+
+    private static final long serialVersionUID = 153019506717492133L;
+
+    /**
+     * Marker to tell the register allocator that no storage location needs to be allocated for this
+     * value.
+     */
+    @SuppressWarnings("serial") public static final AllocatableValue UNUSED = new AllocatableValue(Kind.Illegal) {
+
+        @Override
+        public String toString() {
+            return "-";
+        }
+    };
+
+    public AllocatableValue(Kind kind) {
+        super(kind);
+    }
+
+}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,9 +23,6 @@
 package com.oracle.graal.api.code;
 
 import java.nio.*;
-import java.util.*;
-
-import com.oracle.graal.api.code.Register.RegisterFlag;
 
 /**
  * Represents a CPU architecture, including information such as its endianness, CPU registers, word
@@ -79,22 +76,6 @@
      */
     private final int returnAddressSize;
 
-    private final EnumMap<RegisterFlag, Register[]> registersByTypeAndEncoding;
-
-    /**
-     * Gets the register for a given {@linkplain Register#encoding encoding} and type.
-     * 
-     * @param encoding a register value as used in a machine instruction
-     * @param type the type of the register
-     */
-    public Register registerFor(int encoding, RegisterFlag type) {
-        Register[] regs = registersByTypeAndEncoding.get(type);
-        assert encoding >= 0 && encoding < regs.length;
-        Register reg = regs[encoding];
-        assert reg != null;
-        return reg;
-    }
-
     protected Architecture(String name, int wordSize, ByteOrder byteOrder, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset, int registerReferenceMapBitCount,
                     int returnAddressSize) {
         this.name = name;
@@ -105,18 +86,6 @@
         this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset;
         this.registerReferenceMapBitCount = registerReferenceMapBitCount;
         this.returnAddressSize = returnAddressSize;
-
-        registersByTypeAndEncoding = new EnumMap<>(RegisterFlag.class);
-        EnumMap<RegisterFlag, Register[]> categorizedRegs = Register.categorize(registers);
-        for (RegisterFlag type : RegisterFlag.values()) {
-            Register[] regs = categorizedRegs.get(type);
-            int max = Register.maxRegisterEncoding(regs);
-            Register[] regsByEnc = new Register[max + 1];
-            for (Register reg : regs) {
-                regsByEnc[reg.encoding] = reg;
-            }
-            registersByTypeAndEncoding.put(type, regsByEnc);
-        }
     }
 
     /**
@@ -161,14 +130,6 @@
     }
 
     /**
-     * Gets a mask of the barrier constants denoting the barriers that are not required to be
-     * explicitly inserted under this architecture.
-     */
-    public int getImplicitMemoryBarriers() {
-        return implicitMemoryBarriers;
-    }
-
-    /**
      * Gets the size of the return address pushed to the stack by a call instruction. A value of 0
      * denotes that call linkage uses registers instead.
      */
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Thu Mar 21 14:11:13 2013 +0100
@@ -37,12 +37,10 @@
      * 
      * @param method a method to which the executable code is begin added
      * @param compResult the compilation result to be added
-     * @param info the object into which details of the installed code will be written. Ignored if
-     *            null, otherwise the info is written to index 0 of this array.
      * @return a reference to the compiled and ready-to-run code or null if the code installation
      *         failed
      */
-    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info);
+    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult);
 
     /**
      * Returns the size in bytes for locking information on the stack.
@@ -50,20 +48,21 @@
     int getSizeOfLockData();
 
     /**
-     * Returns a disassembly of the given installed code.
+     * Returns a disassembly of some compiled code.
      * 
-     * @param code the code that should be disassembled
+     * @param compResult some compiled code
+     * @param installedCode the result of installing the code in {@code compResult} or null if the
+     *            code has not yet been installed
+     * 
      * @return a disassembly. This will be of length 0 if the runtime does not support
      *         disassembling.
      */
-    String disassemble(CodeInfo code, CompilationResult tm);
+    String disassemble(CompilationResult compResult, InstalledCode installedCode);
 
     /**
      * Gets the register configuration to use when compiling a given method.
-     * 
-     * @param method the top level method of a compilation
      */
-    RegisterConfig lookupRegisterConfig(ResolvedJavaMethod method);
+    RegisterConfig lookupRegisterConfig();
 
     /**
      * Custom area on the stack of each compiled method that the VM can use for its own purposes.
@@ -81,11 +80,6 @@
     int getMinimumOutgoingSize();
 
     /**
-     * Performs any runtime-specific conversion on the object used to describe the target of a call.
-     */
-    Object lookupCallTarget(Object callTarget);
-
-    /**
      * Gets the signature and linkage information for a runtime call.
      */
     RuntimeCallTarget lookupRuntimeCall(Descriptor descriptor);
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeInfo.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.api.code;
-
-import com.oracle.graal.api.meta.*;
-
-/**
- * Represents some code installed in the code cache of the runtime. This encapsulated details are
- * only for informational purposes. At any time, the runtime may invalidate the underlying code
- * (e.g. due to deopt etc).
- */
-public interface CodeInfo {
-
-    /**
-     * Returns the start address of this installed code.
-     */
-    long getStart();
-
-    /**
-     * Returns a copy of this installed code.
-     */
-    byte[] getCode();
-
-    /**
-     * Returns the method (if any) from which this installed code was compiled.
-     */
-    ResolvedJavaMethod getMethod();
-}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.api.code;
 
+import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -310,4 +311,19 @@
         }
         return sb;
     }
+
+    /**
+     * Create a calling convention from a {@link ResolvedJavaMethod}.
+     */
+    public static CallingConvention getCallingConvention(CodeCacheProvider codeCache, CallingConvention.Type type, ResolvedJavaMethod method, boolean stackOnly) {
+        Signature sig = method.getSignature();
+        JavaType retType = sig.getReturnType(null);
+        JavaType[] argTypes = new JavaType[sig.getParameterCount(!Modifier.isStatic(method.getModifiers()))];
+        for (int i = 0; i < argTypes.length; i++) {
+            argTypes[i] = sig.getParameterType(i, null);
+        }
+
+        RegisterConfig registerConfig = codeCache.lookupRegisterConfig();
+        return registerConfig.getCallingConvention(type, retType, argTypes, codeCache.getTarget(), stackOnly);
+    }
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Thu Mar 21 14:11:13 2013 +0100
@@ -94,7 +94,7 @@
         /**
          * The target of the call.
          */
-        public final Object target;
+        public final InvokeTarget target;
 
         /**
          * The size of the call instruction.
@@ -108,7 +108,7 @@
          */
         public final boolean direct;
 
-        public Call(Object target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) {
+        public Call(InvokeTarget target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) {
             super(pcOffset, debugInfo);
             this.size = size;
             this.target = target;
@@ -196,25 +196,6 @@
     }
 
     /**
-     * Labels some inline data in the code.
-     */
-    public static final class InlineData extends CodeAnnotation {
-
-        private static final long serialVersionUID = 305997507263827108L;
-        public final int size;
-
-        public InlineData(int position, int size) {
-            super(position);
-            this.size = size;
-        }
-
-        @Override
-        public String toString() {
-            return getClass().getSimpleName() + "@" + position + ": size=" + size;
-        }
-    }
-
-    /**
      * Describes a table of signed offsets embedded in the code. The offsets are relative to the
      * starting address of the table. This type of table maybe generated when translating a
      * multi-way branch based on a key value from a dense value set (e.g. the {@code tableswitch}
@@ -256,43 +237,6 @@
     }
 
     /**
-     * Describes a table of key and offset pairs. The offset in each table entry is relative to the
-     * address of the table. This type of table maybe generated when translating a multi-way branch
-     * based on a key value from a sparse value set (e.g. the {@code lookupswitch} JVM instruction).
-     */
-    public static final class LookupTable extends CodeAnnotation {
-
-        private static final long serialVersionUID = 8367952567559116160L;
-
-        /**
-         * The number of entries in the table.
-         */
-        public final int npairs;
-
-        /**
-         * The size (in bytes) of entry's key.
-         */
-        public final int keySize;
-
-        /**
-         * The size (in bytes) of entry's offset value.
-         */
-        public final int offsetSize;
-
-        public LookupTable(int position, int npairs, int keySize, int offsetSize) {
-            super(position);
-            this.npairs = npairs;
-            this.keySize = keySize;
-            this.offsetSize = offsetSize;
-        }
-
-        @Override
-        public String toString() {
-            return getClass().getSimpleName() + "@" + position + ": [npairs=" + npairs + ", keySize=" + keySize + ", offsetSize=" + offsetSize + "]";
-        }
-    }
-
-    /**
      * Represents exception handler information for a specific code position. It includes the catch
      * code position as well as the caught exception type.
      */
@@ -349,8 +293,6 @@
     private int customStackAreaOffset = -1;
     private int registerRestoreEpilogueOffset = -1;
 
-    private CalleeSaveLayout calleeSaveLayout;
-
     /**
      * The buffer containing the emitted machine code.
      */
@@ -410,15 +352,6 @@
     }
 
     /**
-     * Sets the info on callee-saved registers used by this method.
-     * 
-     * @param csl the register-saving info.
-     */
-    public void setCalleeSaveLayout(CalleeSaveLayout csl) {
-        calleeSaveLayout = csl;
-    }
-
-    /**
      * Records a reference to the data section in the code section (e.g. to load an integer or
      * floating point constant).
      * 
@@ -438,11 +371,11 @@
      * 
      * @param codePos the position of the call in the code array
      * @param size the size of the call instruction
-     * @param target the {@link CodeCacheProvider#lookupCallTarget(Object) target} being called
+     * @param target the being called
      * @param debugInfo the debug info for the call
      * @param direct specifies if this is a {@linkplain Call#direct direct} call
      */
-    public void recordCall(int codePos, int size, Object target, DebugInfo debugInfo, boolean direct) {
+    public void recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) {
         final Call call = new Call(target, codePos, size, direct, debugInfo);
         addSafepoint(call);
     }
@@ -537,13 +470,6 @@
     }
 
     /**
-     * @return the layout information for callee-saved registers used by this method.
-     */
-    public CalleeSaveLayout getCalleeSaveLayout() {
-        return calleeSaveLayout;
-    }
-
-    /**
      * @return the machine code generated for this method
      */
     public byte[] getTargetCode() {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Thu Mar 21 14:11:13 2013 +0100
@@ -36,6 +36,7 @@
     private final BytecodePosition bytecodePosition;
     private final BitSet registerRefMap;
     private final BitSet frameRefMap;
+    private final short deoptimizationReason;
 
     /**
      * Creates a new {@link DebugInfo} from the given values.
@@ -45,10 +46,11 @@
      * @param registerRefMap the register map
      * @param frameRefMap the reference map for {@code frame}, which may be {@code null}
      */
-    public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap) {
+    public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, short deoptimizationReason) {
         this.bytecodePosition = codePos;
         this.registerRefMap = registerRefMap;
         this.frameRefMap = frameRefMap;
+        this.deoptimizationReason = deoptimizationReason;
     }
 
     /**
@@ -114,4 +116,13 @@
     public BitSet getFrameRefMap() {
         return frameRefMap;
     }
+
+    /**
+     * Identifies the reason in case a deoptimization happens at this program counter.
+     * 
+     * @return the reason of the deoptimization
+     */
+    public short getDeoptimizationReason() {
+        return deoptimizationReason;
+    }
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DisassemblerProvider.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DisassemblerProvider.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,6 +29,10 @@
 
     /**
      * Gets a textual disassembly of some given installed code.
+     * 
+     * @return a non-zero length string containing a disassembly of {@code code} or null if
+     *         {@code code} is {@link InstalledCode#isValid() invalid} or it could not be
+     *         disassembled for some other reason
      */
     String disassemble(InstalledCode code);
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -39,11 +39,22 @@
     }
 
     /**
-     * Returns the method to which the compiled code belongs.
+     * Returns the method (if any) to which the installed code belongs.
      */
     ResolvedJavaMethod getMethod();
 
     /**
+     * Returns the start address of this installed code if it is {@linkplain #isValid() valid}, 0
+     * otherwise.
+     */
+    long getStart();
+
+    /**
+     * Returns a copy of this installed code if it is {@linkplain #isValid() valid}, null otherwise.
+     */
+    byte[] getCode();
+
+    /**
      * @return true if the code represented by this object is still valid, false otherwise (may
      *         happen due to deopt, etc.)
      */
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java	Thu Mar 21 14:11:13 2013 +0100
@@ -65,6 +65,13 @@
     public final int encoding;
 
     /**
+     * The assembler calls this method to get the register's encoding.
+     */
+    public int encoding() {
+        return encoding;
+    }
+
+    /**
      * The size of the stack slot used to spill the value of this register.
      */
     public final int spillSlotSize;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java	Thu Mar 21 14:11:13 2013 +0100
@@ -44,8 +44,6 @@
      */
     Register getFrameRegister();
 
-    Register getScratchRegister();
-
     /**
      * Gets the calling convention describing how arguments are passed.
      * 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,7 +30,7 @@
  * {@link Register#asValue(Kind)} to retrieve the canonical {@link RegisterValue} instance for a
  * given (register,kind) pair.
  */
-public final class RegisterValue extends Value {
+public final class RegisterValue extends AllocatableValue {
 
     private static final long serialVersionUID = 7999341472196897163L;
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,11 +24,13 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
+
 /**
  * The name, signature and calling convention of a call from compiled code to the runtime. The
  * target of such a call may be a leaf stub or a call into the runtime code proper.
  */
-public interface RuntimeCallTarget {
+public interface RuntimeCallTarget extends InvokeTarget {
 
     /**
      * The name and signature of a runtime call.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.code;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Manages a list of unique deoptimization reasons and returns a unique index for each reason. This
+ * class is not thread safe and assumes that at every point in time there is only a single Graal
+ * compilation accessing this object.
+ * 
+ */
+public final class SpeculationLog {
+
+    public static final int MAX_CACHE_SIZE = 1 << 15;
+
+    private List<DeoptimizationReason> speculations = new ArrayList<>();
+    private boolean[] map = new boolean[10];
+    private Set<DeoptimizationReason> snapshot = new HashSet<>();
+
+    public short addSpeculation(DeoptimizationReason reason) {
+        short index = (short) speculations.indexOf(reason);
+        if (index != -1) {
+            // Nothing to add, reason already registered.
+            return index;
+        }
+        if (speculations.size() >= MAX_CACHE_SIZE) {
+            throw new BailoutException("Too many deoptimization reasons recorded");
+        }
+        speculations.add(reason);
+        if (map.length < speculations.size()) {
+            map = Arrays.copyOf(map, map.length * 2);
+        }
+        return (short) (speculations.size() - 1);
+    }
+
+    public boolean[] getRawMap() {
+        return map;
+    }
+
+    public void snapshot() {
+        for (int i = 0; i < speculations.size(); ++i) {
+            if (map[i]) {
+                snapshot.add(speculations.get(i));
+            }
+        }
+    }
+
+    public boolean maySpeculate(DeoptimizationReason reason) {
+        return !snapshot.contains(reason);
+    }
+}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,7 +30,7 @@
  * Represents a compiler spill slot or an outgoing stack-based argument in a method's frame or an
  * incoming stack-based argument in a method's {@linkplain #isInCallerFrame() caller's frame}.
  */
-public final class StackSlot extends Value {
+public final class StackSlot extends AllocatableValue {
 
     private static final long serialVersionUID = -7725071921307318433L;
 
@@ -165,7 +165,7 @@
 
     private static StackSlot[][] makeCache(int cachePerKindSize, int sign, boolean addFrameSize) {
         StackSlot[][] cache = new StackSlot[Kind.values().length][];
-        for (Kind kind : new Kind[]{Illegal, Int, Long, Float, Double, Object, Jsr}) {
+        for (Kind kind : new Kind[]{Illegal, Int, Long, Float, Double, Object}) {
             StackSlot[] slots = new StackSlot[cachePerKindSize];
             for (int i = 0; i < cachePerKindSize; i++) {
                 slots[i] = new StackSlot(kind, sign * i * CACHE_GRANULARITY, addFrameSize);
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java	Thu Mar 21 14:11:13 2013 +0100
@@ -33,11 +33,6 @@
     public final Architecture arch;
 
     /**
-     * The OS page size.
-     */
-    public final int pageSize;
-
-    /**
      * Specifies if this is a multi-processor system.
      */
     public final boolean isMP;
@@ -72,44 +67,19 @@
     public final int stackAlignment;
 
     /**
-     * @see "http://docs.oracle.com/cd/E19455-01/806-0477/overview-4/index.html"
-     */
-    public final int stackBias;
-
-    /**
-     * The cache alignment.
-     */
-    public final int cacheAlignment;
-
-    /**
      * Maximum constant displacement at which a memory access can no longer be an implicit null
      * check.
      */
     public final int implicitNullCheckLimit;
 
-    /**
-     * Specifies how {@code long} and {@code double} constants are to be stored in
-     * {@linkplain BytecodeFrame frames}. This is useful for VMs such as HotSpot where convention
-     * the interpreter uses is that the second local holds the first raw word of the native long or
-     * double representation. This is actually reasonable, since locals and stack arrays grow
-     * downwards in all implementations. If, on some machine, the interpreter's Java locals or stack
-     * were to grow upwards, the embedded doubles would be word-swapped.)
-     */
-    public final boolean debugInfoDoubleWordsInSecondSlot;
-
-    public TargetDescription(Architecture arch, boolean isMP, int stackAlignment, int stackBias, int implicitNullCheckLimit, int pageSize, int cacheAlignment, boolean inlineObjects,
-                    boolean debugInfoDoubleWordsInSecondSlot) {
+    public TargetDescription(Architecture arch, boolean isMP, int stackAlignment, int implicitNullCheckLimit, boolean inlineObjects) {
         this.arch = arch;
-        this.pageSize = pageSize;
         this.isMP = isMP;
         this.wordSize = arch.getWordSize();
         this.wordKind = Kind.fromWordSize(wordSize);
         this.stackAlignment = stackAlignment;
-        this.stackBias = stackBias;
         this.implicitNullCheckLimit = implicitNullCheckLimit;
-        this.cacheAlignment = cacheAlignment;
         this.inlineObjects = inlineObjects;
-        this.debugInfoDoubleWordsInSecondSlot = debugInfoDoubleWordsInSecondSlot;
     }
 
     /**
@@ -139,8 +109,6 @@
                 return 8;
             case Object:
                 return wordSize;
-            case Jsr:
-                return 4;
             default:
                 return 0;
         }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Thu Mar 21 14:11:13 2013 +0100
@@ -58,6 +58,16 @@
         return (Constant) value;
     }
 
+    public static boolean isAllocatableValue(Value value) {
+        assert value != null;
+        return value instanceof AllocatableValue;
+    }
+
+    public static AllocatableValue asAllocatableValue(Value value) {
+        assert value != null;
+        return (AllocatableValue) value;
+    }
+
     public static boolean isStackSlot(Value value) {
         assert value != null;
         return value instanceof StackSlot;
@@ -68,16 +78,6 @@
         return (StackSlot) value;
     }
 
-    public static boolean isAddress(Value value) {
-        assert value != null;
-        return value instanceof Address;
-    }
-
-    public static Address asAddress(Value value) {
-        assert value != null;
-        return (Address) value;
-    }
-
     public static boolean isRegister(Value value) {
         assert value != null;
         return value instanceof RegisterValue;
@@ -89,7 +89,7 @@
     }
 
     public static Register asIntReg(Value value) {
-        assert value.getKind() == Kind.Int || value.getKind() == Kind.Jsr;
+        assert value.getKind() == Kind.Int;
         return asRegister(value);
     }
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.api.code;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -65,31 +67,48 @@
         this.id = id;
     }
 
+    private static StringBuilder appendValue(StringBuilder buf, Value value, Set<VirtualObject> visited) {
+        if (value instanceof VirtualObject) {
+            VirtualObject vo = (VirtualObject) value;
+            buf.append("vobject:").append(toJavaName(vo.type, false)).append(':').append(vo.id);
+            if (!visited.contains(vo)) {
+                visited.add(vo);
+                buf.append('{');
+                if (vo.values == null) {
+                    buf.append("<uninitialized>");
+                } else {
+                    if (vo.type.isArray()) {
+                        for (int i = 0; i < vo.values.length; i++) {
+                            if (i != 0) {
+                                buf.append(',');
+                            }
+                            buf.append(i).append('=');
+                            appendValue(buf, vo.values[i], visited);
+                        }
+                    } else {
+                        ResolvedJavaField[] fields = vo.type.getInstanceFields(true);
+                        assert fields.length == vo.values.length : vo.type + ", fields=" + Arrays.toString(fields) + ", values=" + vo.values;
+                        for (int i = 0; i < vo.values.length; i++) {
+                            if (i != 0) {
+                                buf.append(',');
+                            }
+                            buf.append(fields[i].getName()).append('=');
+                            appendValue(buf, vo.values[i], visited);
+                        }
+                    }
+                }
+                buf.append('}');
+            }
+        } else {
+            buf.append(value);
+        }
+        return buf;
+    }
+
     @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder("vobject:").append(MetaUtil.toJavaName(type, false)).append(':').append(id).append('{');
-        if (values == null) {
-            buf.append("<uninitialized>");
-        } else {
-            if (type.isArray()) {
-                for (int i = 0; i < values.length; i++) {
-                    if (i != 0) {
-                        buf.append(',');
-                    }
-                    buf.append(i).append('=').append(values[i]);
-                }
-            } else {
-                ResolvedJavaField[] fields = type.getInstanceFields(true);
-                assert fields.length == values.length : type + ", fields=" + Arrays.toString(fields) + ", values=" + values;
-                for (int i = 0; i < values.length; i++) {
-                    if (i != 0) {
-                        buf.append(',');
-                    }
-                    buf.append(fields[i].getName()).append('=').append(values[i]);
-                }
-            }
-        }
-        return buf.append('}').toString();
+        Set<VirtualObject> visited = Collections.newSetFromMap(new IdentityHashMap<VirtualObject, Boolean>());
+        return appendValue(new StringBuilder(), this, visited).toString();
     }
 
     /**
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/package-info.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/package-info.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,7 +23,7 @@
 /**
  * Package that defines the interface between a Java application that wants to install code and the runtime.
  * The runtime provides in implementation of the {@link com.oracle.graal.api.code.CodeCacheProvider} interface.
- * The method {@link com.oracle.graal.api.code.CodeCacheProvider#addMethod(com.oracle.graal.api.meta.ResolvedJavaMethod, CompilationResult, CodeInfo[])}
+ * The method {@link com.oracle.graal.api.code.CodeCacheProvider#addMethod(com.oracle.graal.api.meta.ResolvedJavaMethod, CompilationResult)}
  * can be used to install code for a given method.
  */
 package com.oracle.graal.api.code;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.meta.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+
+/**
+ * Tests for {@link BytecodeDisassemblerProvider}.
+ */
+public class TestBytecodeDisassemblerProvider {
+
+    public TestBytecodeDisassemblerProvider() {
+    }
+
+    /**
+     * Tests that successive disassembling of the same method produces the same result.
+     */
+    @Test
+    public void disassembleTest() {
+        BytecodeDisassemblerProvider dis = Graal.getRuntime().getCapability(BytecodeDisassemblerProvider.class);
+        if (dis != null) {
+            int count = 0;
+            for (ResolvedJavaMethod m : TestJavaMethod.methods.values()) {
+                String disasm1 = dis.disassemble(m);
+                String disasm2 = dis.disassemble(m);
+                if (disasm1 == null) {
+                    Assert.assertTrue(disasm2 == null);
+                } else {
+                    Assert.assertTrue(String.valueOf(m), disasm1.length() > 0);
+                    Assert.assertEquals(String.valueOf(m), disasm1, disasm2);
+                }
+                if (count++ > 20) {
+                    break;
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Thu Mar 21 14:11:13 2013 +0100
@@ -49,11 +49,14 @@
         for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
             ResolvedJavaMethod m = e.getValue();
             byte[] code = m.getCode();
-            assertNotNull(code);
-            if (isAbstract(m.getModifiers())) {
-                assertTrue(code.length == 0);
-            } else if (!isNative(m.getModifiers())) {
-                assertTrue(code.length > 0);
+            if (code == null) {
+                assertTrue(m.getCodeSize() == 0);
+            } else {
+                if (isAbstract(m.getModifiers())) {
+                    assertTrue(code.length == 0);
+                } else if (!isNative(m.getModifiers())) {
+                    assertTrue(code.length > 0);
+                }
             }
         }
     }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,6 +29,7 @@
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.net.*;
 import java.util.*;
 
 import org.junit.*;
@@ -541,4 +542,36 @@
             }
         }
     }
+
+    @Test
+    public void memberClassesTest() {
+        for (Class c : classes) {
+            ResolvedJavaType type = runtime.lookupJavaType(c);
+            assertEquals(c.isLocalClass(), type.isLocal());
+            assertEquals(c.isMemberClass(), type.isMember());
+            Class enclc = c.getEnclosingClass();
+            ResolvedJavaType enclt = type.getEnclosingType();
+            assertFalse(enclc == null ^ enclt == null);
+            if (enclc != null) {
+                assertEquals(enclt, runtime.lookupJavaType(enclc));
+            }
+        }
+    }
+
+    @Test
+    public void classFilePathTest() {
+        for (Class c : classes) {
+            ResolvedJavaType type = runtime.lookupJavaType(c);
+            URL path = type.getClassFilePath();
+            if (type.isPrimitive() || type.isArray()) {
+                assertEquals(null, path);
+            } else {
+                assertNotNull(path);
+                String pathString = path.getPath();
+                if (type.isLocal() || type.isMember()) {
+                    assertTrue(pathString.indexOf('$') > 0);
+                }
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/BytecodeDisassemblerProvider.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/BytecodeDisassemblerProvider.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,7 +28,11 @@
 public interface BytecodeDisassemblerProvider {
 
     /**
-     * Gets a textual disassembly of the bytecode for a given method.
+     * Gets a textual disassembly of the bytecode for a given method. In the absence of bytecode
+     * rewriting, disassembling a method will produce the same result.
+     * 
+     * @return a non-zero length string containing a disassembly of {@code method}'s bytecode or
+     *         null if {@code method} has no bytecode (i.e., {@code method.getCodeSize() == 0})
      */
     String disassemble(ResolvedJavaMethod method);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Thu Mar 21 14:11:13 2013 +0100
@@ -134,8 +134,6 @@
                 return (short) primitive;
             case Char:
                 return (char) primitive;
-            case Jsr:
-                return (int) primitive;
             case Int:
                 return (int) primitive;
             case Long:
@@ -163,12 +161,12 @@
 
     /**
      * Returns the primitive int value this constant represents. The constant must have a
-     * {@link Kind#getStackKind()} of {@link Kind#Int}, or kind {@link Kind#Jsr}.
+     * {@link Kind#getStackKind()} of {@link Kind#Int}.
      * 
      * @return the constant value
      */
     public int asInt() {
-        assert getKind().getStackKind() == Kind.Int || getKind() == Kind.Jsr;
+        assert getKind().getStackKind() == Kind.Int;
         return (int) primitive;
     }
 
@@ -185,13 +183,12 @@
 
     /**
      * Returns the primitive long value this constant represents. The constant must have kind
-     * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}, or kind
-     * {@link Kind#Jsr}.
+     * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}.
      * 
      * @return the constant value
      */
     public long asLong() {
-        assert getKind() == Kind.Long || getKind().getStackKind() == Kind.Int || getKind() == Kind.Jsr;
+        assert getKind() == Kind.Long || getKind().getStackKind() == Kind.Int;
         return primitive;
     }
 
@@ -365,16 +362,6 @@
     }
 
     /**
-     * Creates a boxed address (jsr/ret address) constant.
-     * 
-     * @param i the address value to box
-     * @return a boxed copy of {@code value}
-     */
-    public static Constant forJsr(int i) {
-        return new Constant(Kind.Jsr, null, i);
-    }
-
-    /**
      * Creates a boxed object constant.
      * 
      * @param o the object value to box
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/InvokeTarget.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.meta;
+
+/**
+ * Represents the resolved target of an invocation.
+ */
+public interface InvokeTarget {
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Thu Mar 21 14:11:13 2013 +0100
@@ -60,9 +60,6 @@
     /** The void float kind. */
     Void('v', "void", false, java.lang.Void.TYPE, java.lang.Void.class),
 
-    /** Denote a bytecode address in a {@code JSR} bytecode. */
-    Jsr('r', "jsr", false, null, null),
-
     /** The non-type. */
     Illegal('-', "illegal", false, null, null);
 
@@ -318,7 +315,6 @@
                 return java.lang.Character.MIN_VALUE;
             case Short:
                 return java.lang.Short.MIN_VALUE;
-            case Jsr:
             case Int:
                 return java.lang.Integer.MIN_VALUE;
             case Long:
@@ -343,7 +339,6 @@
                 return java.lang.Character.MAX_VALUE;
             case Short:
                 return java.lang.Short.MAX_VALUE;
-            case Jsr:
             case Int:
                 return java.lang.Integer.MAX_VALUE;
             case Long:
@@ -367,7 +362,6 @@
             case Char:
             case Short:
                 return 16;
-            case Jsr:
             case Int:
                 return 32;
             case Long:
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Thu Mar 21 14:11:13 2013 +0100
@@ -87,10 +87,11 @@
 
     /**
      * Reads a value of this kind using a base address and a displacement.
-     *
+     * 
      * @param base the base address from which the value is read
      * @param displacement the displacement within the object in bytes
-     * @return the read value encapsulated in a {@link Constant} object, or {@code null} if the value cannot be read.
+     * @return the read value encapsulated in a {@link Constant} object, or {@code null} if the
+     *         value cannot be read.
      */
     Constant readUnsafeConstant(Kind kind, Object base, long displacement);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Thu Mar 21 14:11:13 2013 +0100
@@ -135,7 +135,7 @@
                 String prefix = "";
                 Class<?> enclosingClass = clazz;
                 while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) {
-                    prefix = prefix + enclosingClass.getSimpleName() + ".";
+                    prefix = enclosingClass.getSimpleName() + "." + prefix;
                 }
                 return prefix + simpleName;
             }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,21 +31,21 @@
  * Represents a resolved Java method. Methods, like fields and types, are resolved through
  * {@link ConstantPool constant pools}.
  */
-public interface ResolvedJavaMethod extends JavaMethod {
+public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget {
 
     /**
-     * Returns the bytecodes of this method, if the method has code. The returned byte array does
-     * not contain breakpoints or non-Java bytecodes.
+     * Returns the bytecode of this method, if the method has code. The returned byte array does not
+     * contain breakpoints or non-Java bytecodes.
      * 
-     * @return the bytecodes of the method, or {@code null} if none is available
+     * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0}
      */
     byte[] getCode();
 
     /**
-     * Returns the size of the bytecodes of this method, if the method has code. This is equivalent
+     * Returns the size of the bytecode of this method, if the method has code. This is equivalent
      * to {@link #getCode()}. {@code length} if the method has code.
      * 
-     * @return the size of the bytecodes in bytes, or 0 if no bytecodes is available
+     * @return the size of the bytecode in bytes, or 0 if no bytecode is available
      */
     int getCodeSize();
 
@@ -175,5 +175,4 @@
      * Returns the localvariable table of this method.
      */
     LocalVariableTable getLocalVariableTable();
-
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.net.*;
 
 /**
  * Represents a resolved Java type. Types include primitives, objects, {@code void}, and arrays
@@ -253,4 +254,24 @@
      * Returns name of source file of this type.
      */
     String getSourceFileName();
+
+    /**
+     * Returns the class file path - if available - of this type, or {@code null}.
+     */
+    URL getClassFilePath();
+
+    /**
+     * Returns {@code true} if the type is a local type.
+     */
+    boolean isLocal();
+
+    /**
+     * Returns {@code true} if the type is a member type.
+     */
+    boolean isMember();
+
+    /**
+     * Returns the enclosing type of this type, if it exists, or {@code null}.
+     */
+    ResolvedJavaType getEnclosingType();
 }
--- a/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -57,7 +57,7 @@
                 AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig);
                 Register ret = registerConfig.getReturnRegister(Kind.Double);
                 compResult.recordDataReference(asm.codeBuffer.position(), Constant.forDouble(84.72), 8, false);
-                asm.movdbl(ret, Address.Placeholder);
+                asm.movdbl(ret, asm.getPlaceholder());
                 asm.ret(0);
                 return asm.codeBuffer;
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.asm.amd64;
+
+import com.oracle.graal.api.code.*;
+
+/**
+ * Represents an address in target machine memory, specified via some combination of a base
+ * register, an index register, a displacement and a scale. Note that the base and index registers
+ * may be a variable that will get a register assigned later by the register allocator.
+ */
+public final class AMD64Address extends AbstractAddress {
+
+    private final Register base;
+    private final Register index;
+    private final Scale scale;
+    private final int displacement;
+
+    /**
+     * Creates an {@link AMD64Address} with given base register, no scaling and no displacement.
+     * 
+     * @param base the base register
+     */
+    public AMD64Address(Register base) {
+        this(base, Register.None, Scale.Times1, 0);
+    }
+
+    /**
+     * Creates an {@link AMD64Address} with given base register, no scaling and a given
+     * displacement.
+     * 
+     * @param base the base register
+     * @param displacement the displacement
+     */
+    public AMD64Address(Register base, int displacement) {
+        this(base, Register.None, Scale.Times1, displacement);
+    }
+
+    /**
+     * Creates an {@link AMD64Address} with given base and index registers, scaling and
+     * displacement. This is the most general constructor.
+     * 
+     * @param base the base register
+     * @param index the index register
+     * @param scale the scaling factor
+     * @param displacement the displacement
+     */
+    public AMD64Address(Register base, Register index, Scale scale, int displacement) {
+        this.base = base;
+        this.index = index;
+        this.scale = scale;
+        this.displacement = displacement;
+    }
+
+    /**
+     * A scaling factor used in the SIB addressing mode.
+     */
+    public enum Scale {
+        Times1(1, 0), Times2(2, 1), Times4(4, 2), Times8(8, 3);
+
+        private Scale(int value, int log2) {
+            this.value = value;
+            this.log2 = log2;
+        }
+
+        /**
+         * The value (or multiplier) of this scale.
+         */
+        public final int value;
+
+        /**
+         * The {@linkplain #value value} of this scale log 2.
+         */
+        public final int log2;
+
+        public static Scale fromInt(int scale) {
+            switch (scale) {
+                case 1:
+                    return Times1;
+                case 2:
+                    return Times2;
+                case 4:
+                    return Times4;
+                case 8:
+                    return Times8;
+                default:
+                    throw new IllegalArgumentException(String.valueOf(scale));
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("[");
+        String sep = "";
+        if (getBase() != Register.None) {
+            s.append(getBase());
+            sep = " + ";
+        }
+        if (getIndex() != Register.None) {
+            s.append(sep).append(getIndex()).append(" * ").append(getScale().value);
+            sep = " + ";
+        }
+        if (getDisplacement() < 0) {
+            s.append(" - ").append(-getDisplacement());
+        } else if (getDisplacement() > 0) {
+            s.append(sep).append(getDisplacement());
+        }
+        s.append("]");
+        return s.toString();
+    }
+
+    /**
+     * @return Base register that defines the start of the address computation. If not present, is
+     *         denoted by {@link Register#None}.
+     */
+    public Register getBase() {
+        return base;
+    }
+
+    /**
+     * @return Index register, the value of which (possibly scaled by {@link #getScale}) is added to
+     *         {@link #getBase}. If not present, is denoted by {@link Register#None}.
+     */
+    public Register getIndex() {
+        return index;
+    }
+
+    /**
+     * @return Scaling factor for indexing, dependent on target operand size.
+     */
+    public Scale getScale() {
+        return scale;
+    }
+
+    /**
+     * @return Optional additive displacement.
+     */
+    public int getDisplacement() {
+        return displacement;
+    }
+}
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,13 +24,11 @@
 
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.MemoryBarriers.*;
-import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.asm.NumUtil.*;
 import static com.oracle.graal.asm.amd64.AMD64AsmOptions.*;
 
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 
 /**
@@ -38,24 +36,41 @@
  */
 public class AMD64Assembler extends AbstractAssembler {
 
+    private static final int MinEncodingNeedsRex = 8;
+
     /**
-     * The kind for pointers and raw registers. Since we know we are 64 bit here, we can hardcode
-     * it.
+     * A sentinel value used as a place holder in an instruction stream for an address that will be
+     * patched.
      */
-    private static final Kind Word = Kind.Long;
-
-    private static final int MinEncodingNeedsRex = 8;
+    private static final AMD64Address Placeholder = new AMD64Address(rip);
 
     /**
      * The x86 condition codes used for conditional jumps/moves.
      */
     public enum ConditionFlag {
-        zero(0x4, "|zero|"), notZero(0x5, "|nzero|"), equal(0x4, "="), notEqual(0x5, "!="), less(0xc, "<"), lessEqual(0xe, "<="), greater(0xf, ">"), greaterEqual(0xd, ">="), below(0x2, "|<|"), belowEqual(
-                        0x6, "|<=|"), above(0x7, "|>|"), aboveEqual(0x3, "|>=|"), overflow(0x0, "|of|"), noOverflow(0x1, "|nof|"), carrySet(0x2, "|carry|"), carryClear(0x3, "|ncarry|"), negative(0x8,
-                        "|neg|"), positive(0x9, "|pos|"), parity(0xa, "|par|"), noParity(0xb, "|npar|");
+        Zero(0x4, "|zero|"),
+        NotZero(0x5, "|nzero|"),
+        Equal(0x4, "="),
+        NotEqual(0x5, "!="),
+        Less(0xc, "<"),
+        LessEqual(0xe, "<="),
+        Greater(0xf, ">"),
+        GreaterEqual(0xd, ">="),
+        Below(0x2, "|<|"),
+        BelowEqual(0x6, "|<=|"),
+        Above(0x7, "|>|"),
+        AboveEqual(0x3, "|>=|"),
+        Overflow(0x0, "|of|"),
+        NoOverflow(0x1, "|nof|"),
+        CarrySet(0x2, "|carry|"),
+        CarryClear(0x3, "|ncarry|"),
+        Negative(0x8, "|neg|"),
+        Positive(0x9, "|pos|"),
+        Parity(0xa, "|par|"),
+        NoParity(0xb, "|npar|");
 
-        public final int value;
-        public final String operator;
+        private final int value;
+        private final String operator;
 
         private ConditionFlag(int value, String operator) {
             this.value = value;
@@ -64,49 +79,58 @@
 
         public ConditionFlag negate() {
             switch (this) {
-                case zero:
-                    return notZero;
-                case notZero:
-                    return zero;
-                case equal:
-                    return notEqual;
-                case notEqual:
-                    return equal;
-                case less:
-                    return greaterEqual;
-                case lessEqual:
-                    return greater;
-                case greater:
-                    return lessEqual;
-                case greaterEqual:
-                    return less;
-                case below:
-                    return aboveEqual;
-                case belowEqual:
-                    return above;
-                case above:
-                    return belowEqual;
-                case aboveEqual:
-                    return below;
-                case overflow:
-                    return noOverflow;
-                case noOverflow:
-                    return overflow;
-                case carrySet:
-                    return carryClear;
-                case carryClear:
-                    return carrySet;
-                case negative:
-                    return positive;
-                case positive:
-                    return negative;
-                case parity:
-                    return noParity;
-                case noParity:
-                    return parity;
+                case Zero:
+                    return NotZero;
+                case NotZero:
+                    return Zero;
+                case Equal:
+                    return NotEqual;
+                case NotEqual:
+                    return Equal;
+                case Less:
+                    return GreaterEqual;
+                case LessEqual:
+                    return Greater;
+                case Greater:
+                    return LessEqual;
+                case GreaterEqual:
+                    return Less;
+                case Below:
+                    return AboveEqual;
+                case BelowEqual:
+                    return Above;
+                case Above:
+                    return BelowEqual;
+                case AboveEqual:
+                    return Below;
+                case Overflow:
+                    return NoOverflow;
+                case NoOverflow:
+                    return Overflow;
+                case CarrySet:
+                    return CarryClear;
+                case CarryClear:
+                    return CarrySet;
+                case Negative:
+                    return Positive;
+                case Positive:
+                    return Negative;
+                case Parity:
+                    return NoParity;
+                case NoParity:
+                    return Parity;
             }
             throw new IllegalArgumentException();
         }
+
+        public int getValue() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return operator;
+        }
     }
 
     /**
@@ -155,16 +179,6 @@
         return r.encoding & 0x7;
     }
 
-    private void emitArithB(int op1, int op2, Register dst, int imm8) {
-        assert dst.isByte() : "must have byte register";
-        assert isUByte(op1) && isUByte(op2) : "wrong opcode";
-        assert isUByte(imm8) : "not a byte";
-        assert (op1 & 0x01) == 0 : "should be 8bit operation";
-        emitByte(op1);
-        emitByte(op2 | encode(dst));
-        emitByte(imm8);
-    }
-
     private void emitArith(int op1, int op2, Register dst, int imm32) {
         assert isUByte(op1) && isUByte(op2) : "wrong opcode";
         assert (op1 & 0x01) == 1 : "should be 32bit operation";
@@ -181,16 +195,16 @@
     }
 
     // immediate-to-memory forms
-    private void emitArithOperand(int op1, Register rm, Address adr, int imm32) {
+    private void emitArithOperand(int op1, int op2, AMD64Address adr, int imm32) {
         assert (op1 & 0x01) == 1 : "should be 32bit operation";
         assert (op1 & 0x02) == 0 : "sign-extension bit should not be set";
         if (isByte(imm32)) {
             emitByte(op1 | 0x02); // set sign bit
-            emitOperandHelper(rm, adr);
+            emitOperandHelper(op2, adr);
             emitByte(imm32 & 0xFF);
         } else {
             emitByte(op1);
-            emitOperandHelper(rm, adr);
+            emitOperandHelper(op2, adr);
             emitInt(imm32);
         }
     }
@@ -201,37 +215,31 @@
         emitByte(op2 | encode(dst) << 3 | encode(src));
     }
 
-    protected void emitOperandHelper(Register reg, Address addr) {
-        Register base = isLegal(addr.getBase()) ? asRegister(addr.getBase()) : Register.None;
-        Register index = isLegal(addr.getIndex()) ? asRegister(addr.getIndex()) : Register.None;
+    protected void emitOperandHelper(Register reg, AMD64Address addr) {
+        assert reg != Register.None;
+        emitOperandHelper(encode(reg), addr);
+    }
 
-        Address.Scale scale = addr.getScale();
+    protected void emitOperandHelper(int reg, AMD64Address addr) {
+        assert (reg & 0x07) == reg;
+        int regenc = reg << 3;
+
+        Register base = addr.getBase();
+        Register index = addr.getIndex();
+
+        AMD64Address.Scale scale = addr.getScale();
         int disp = addr.getDisplacement();
 
         if (base == Register.Frame) {
             assert frameRegister != null : "cannot use register " + Register.Frame + " in assembler with null register configuration";
             base = frameRegister;
-            // } else if (base == Register.CallerFrame) {
-            // assert frameRegister != null : "cannot use register " + Register.Frame +
-            // " in assembler with null register configuration";
-            // base = frameRegister;
-            // disp += targetMethod.frameSize() + 8;
         }
 
-        // Encode the registers as needed in the fields they are used in
-
-        assert reg != Register.None;
-        int regenc = encode(reg) << 3;
-
-        if (base == AMD64.rip) {
+        if (base == AMD64.rip) { // also matches Placeholder
             // [00 000 101] disp32
+            assert index == Register.None : "cannot use RIP relative addressing with index register";
             emitByte(0x05 | regenc);
             emitInt(disp);
-        } else if (addr == Address.Placeholder) {
-            // [00 000 101] disp32
-            emitByte(0x05 | regenc);
-            emitInt(0);
-
         } else if (base.isValid()) {
             int baseenc = base.isValid() ? encode(base) : 0;
             if (index.isValid()) {
@@ -316,15 +324,9 @@
         }
     }
 
-    public final void addl(Address dst, int imm32) {
+    public final void addl(AMD64Address dst, int imm32) {
         prefix(dst);
-        emitArithOperand(0x81, rax, dst, imm32);
-    }
-
-    public final void addl(Address dst, Register src) {
-        prefix(dst, src);
-        emitByte(0x01);
-        emitOperandHelper(src, dst);
+        emitArithOperand(0x81, 0, dst, imm32);
     }
 
     public final void addl(Register dst, int imm32) {
@@ -332,7 +334,7 @@
         emitArith(0x81, 0xC0, dst, imm32);
     }
 
-    public final void addl(Register dst, Address src) {
+    public final void addl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x03);
         emitOperandHelper(dst, src);
@@ -386,7 +388,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void addsd(Register dst, Address src) {
+    public final void addsd(Register dst, AMD64Address src) {
         assert dst.isFpu();
         emitByte(0xF2);
         prefix(src, dst);
@@ -404,7 +406,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void addss(Register dst, Address src) {
+    public final void addss(Register dst, AMD64Address src) {
         assert dst.isFpu();
         emitByte(0xF3);
         prefix(src, dst);
@@ -418,7 +420,7 @@
         emitArith(0x81, 0xE0, dst, imm32);
     }
 
-    public final void andl(Register dst, Address src) {
+    public final void andl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x23);
         emitOperandHelper(dst, src);
@@ -436,8 +438,9 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void bsfq(Register dst, Address src) {
+    public final void bsfq(Register dst, AMD64Address src) {
         prefixq(src, dst);
+        emitByte(0x0F);
         emitByte(0xBC);
         emitOperandHelper(dst, src);
     }
@@ -449,8 +452,9 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void bsrq(Register dst, Address src) {
+    public final void bsrq(Register dst, AMD64Address src) {
         prefixq(src, dst);
+        emitByte(0x0F);
         emitByte(0xBD);
         emitOperandHelper(dst, src);
     }
@@ -462,26 +466,19 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void bsrl(Register dst, Address src) {
+    public final void bsrl(Register dst, AMD64Address src) {
         prefix(src, dst);
+        emitByte(0x0F);
         emitByte(0xBD);
         emitOperandHelper(dst, src);
     }
 
-    public final void bswapl(Register reg) { // bswap
+    public final void bswapl(Register reg) {
         int encode = prefixAndEncode(reg.encoding);
         emitByte(0x0F);
         emitByte(0xC8 | encode);
     }
 
-    public final void btli(Address src, int imm8) {
-        prefixq(src);
-        emitByte(0x0F);
-        emitByte(0xBA);
-        emitOperandHelper(rsp, src);
-        emitByte(imm8);
-    }
-
     public final void cdql() {
         emitByte(0x99);
     }
@@ -489,31 +486,17 @@
     public final void cmovl(ConditionFlag cc, Register dst, Register src) {
         int encode = prefixAndEncode(dst.encoding, src.encoding);
         emitByte(0x0F);
-        emitByte(0x40 | cc.value);
+        emitByte(0x40 | cc.getValue());
         emitByte(0xC0 | encode);
     }
 
-    public final void cmovl(ConditionFlag cc, Register dst, Address src) {
+    public final void cmovl(ConditionFlag cc, Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x0F);
-        emitByte(0x40 | cc.value);
+        emitByte(0x40 | cc.getValue());
         emitOperandHelper(dst, src);
     }
 
-    public final void cmpb(Address dst, int imm8) {
-        prefix(dst);
-        emitByte(0x80);
-        emitOperandHelper(rdi, dst);
-        emitByte(imm8);
-    }
-
-    public final void cmpl(Address dst, int imm32) {
-        prefix(dst);
-        emitByte(0x81);
-        emitOperandHelper(rdi, dst);
-        emitInt(imm32);
-    }
-
     public final void cmpl(Register dst, int imm32) {
         prefix(dst);
         emitArith(0x81, 0xF8, dst, imm32);
@@ -524,7 +507,7 @@
         emitArith(0x3B, 0xC0, dst, src);
     }
 
-    public final void cmpl(Register dst, Address src) {
+    public final void cmpl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x3B);
         emitOperandHelper(dst, src);
@@ -533,7 +516,7 @@
     // The 32-bit cmpxchg compares the value at adr with the contents of X86.rax,
     // and stores reg into adr if so; otherwise, the value at adr is loaded into X86.rax,.
     // The ZF is set if the compared values were equal, and cleared otherwise.
-    public final void cmpxchgl(Register reg, Address adr) { // cmpxchg
+    public final void cmpxchgl(Register reg, AMD64Address adr) { // cmpxchg
         if ((Atomics & 2) != 0) {
             // caveat: no instructionmark, so this isn't relocatable.
             // Emit a synthetic, non-atomic, CAS equivalent.
@@ -543,7 +526,7 @@
             movl(rax, adr);
             if (reg != rax) {
                 Label l = new Label();
-                jcc(ConditionFlag.notEqual, l);
+                jccb(ConditionFlag.NotEqual, l);
                 movl(adr, reg);
                 bind(l);
             }
@@ -556,43 +539,15 @@
         }
     }
 
-    public final void comisd(Register dst, Address src) {
+    public final void cvtsd2ss(Register dst, AMD64Address src) {
         assert dst.isFpu();
-        // NOTE: dbx seems to decode this as comiss even though the
-        // 0x66 is there. Strangly ucomisd comes out correct
-        emitByte(0x66);
-        comiss(dst, src);
-    }
-
-    public final void comiss(Register dst, Address src) {
-        assert dst.isFpu();
-
+        emitByte(0xF2);
         prefix(src, dst);
         emitByte(0x0F);
-        emitByte(0x2F);
+        emitByte(0x5A);
         emitOperandHelper(dst, src);
     }
 
-    public final void cvtdq2pd(Register dst, Register src) {
-        assert dst.isFpu();
-        assert src.isFpu();
-
-        emitByte(0xF3);
-        int encode = prefixAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0xE6);
-        emitByte(0xC0 | encode);
-    }
-
-    public final void cvtdq2ps(Register dst, Register src) {
-        assert dst.isFpu();
-        assert src.isFpu();
-        int encode = prefixAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0x5B);
-        emitByte(0xC0 | encode);
-    }
-
     public final void cvtsd2ss(Register dst, Register src) {
         assert dst.isFpu();
         assert src.isFpu();
@@ -603,6 +558,15 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvtsi2sdl(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtsi2sdl(Register dst, Register src) {
         assert dst.isFpu();
         emitByte(0xF2);
@@ -612,6 +576,15 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvtsi2ssl(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtsi2ssl(Register dst, Register src) {
         assert dst.isFpu();
         emitByte(0xF3);
@@ -621,6 +594,15 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvtss2sd(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x5A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtss2sd(Register dst, Register src) {
         assert dst.isFpu();
         assert src.isFpu();
@@ -631,6 +613,14 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvttsd2sil(Register dst, AMD64Address src) {
+        emitByte(0xF2);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvttsd2sil(Register dst, Register src) {
         assert src.isFpu();
         emitByte(0xF2);
@@ -640,6 +630,14 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvttss2sil(Register dst, AMD64Address src) {
+        emitByte(0xF3);
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvttss2sil(Register dst, Register src) {
         assert src.isFpu();
         emitByte(0xF3);
@@ -649,14 +647,13 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void decl(Address dst) {
-        // Don't use it directly. Use Macrodecrement() instead.
+    protected final void decl(AMD64Address dst) {
         prefix(dst);
         emitByte(0xFF);
-        emitOperandHelper(rcx, dst);
+        emitOperandHelper(1, dst);
     }
 
-    public final void divsd(Register dst, Address src) {
+    public final void divsd(Register dst, AMD64Address src) {
         assert dst.isFpu();
         emitByte(0xF2);
         prefix(src, dst);
@@ -675,7 +672,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void divss(Register dst, Address src) {
+    public final void divss(Register dst, AMD64Address src) {
         assert dst.isFpu();
         emitByte(0xF3);
         prefix(src, dst);
@@ -717,6 +714,13 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void imull(Register dst, AMD64Address src) {
+        prefix(src, dst);
+        emitByte(0x0F);
+        emitByte(0xAF);
+        emitOperandHelper(dst, src);
+    }
+
     public final void imull(Register dst, Register src, int value) {
         int encode = prefixAndEncode(dst.encoding, src.encoding);
         if (isByte(value)) {
@@ -730,32 +734,31 @@
         }
     }
 
-    public final void incl(Address dst) {
-        // Don't use it directly. Use Macroincrement() instead.
+    protected final void incl(AMD64Address dst) {
         prefix(dst);
         emitByte(0xFF);
-        emitOperandHelper(rax, dst);
+        emitOperandHelper(0, dst);
     }
 
-    public final void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) {
+    private void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) {
         int shortSize = 2;
         int longSize = 6;
         long disp = jumpTarget - codeBuffer.position();
         if (!forceDisp32 && isByte(disp - shortSize)) {
             // 0111 tttn #8-bit disp
-            emitByte(0x70 | cc.value);
+            emitByte(0x70 | cc.getValue());
             emitByte((int) ((disp - shortSize) & 0xFF));
         } else {
             // 0000 1111 1000 tttn #32-bit disp
             assert isInt(disp - longSize) : "must be 32bit offset (call4)";
             emitByte(0x0F);
-            emitByte(0x80 | cc.value);
+            emitByte(0x80 | cc.getValue());
             emitInt((int) (disp - longSize));
         }
     }
 
     public final void jcc(ConditionFlag cc, Label l) {
-        assert (0 <= cc.value) && (cc.value < 16) : "illegal cc";
+        assert (0 <= cc.getValue()) && (cc.getValue() < 16) : "illegal cc";
         if (l.isBound()) {
             jcc(cc, l.position(), false);
         } else {
@@ -765,7 +768,7 @@
             // an 8-bit displacement
             l.addPatchAt(codeBuffer.position());
             emitByte(0x0F);
-            emitByte(0x80 | cc.value);
+            emitByte(0x80 | cc.getValue());
             emitInt(0);
         }
 
@@ -778,22 +781,16 @@
             assert isByte(entry - (codeBuffer.position() + shortSize)) : "Dispacement too large for a short jmp";
             long disp = entry - codeBuffer.position();
             // 0111 tttn #8-bit disp
-            emitByte(0x70 | cc.value);
+            emitByte(0x70 | cc.getValue());
             emitByte((int) ((disp - shortSize) & 0xFF));
         } else {
 
             l.addPatchAt(codeBuffer.position());
-            emitByte(0x70 | cc.value);
+            emitByte(0x70 | cc.getValue());
             emitByte(0);
         }
     }
 
-    public final void jmp(Address adr) {
-        prefix(adr);
-        emitByte(0xFF);
-        emitOperandHelper(rsp, adr);
-    }
-
     public final void jmp(int jumpTarget, boolean forceDisp32) {
         int shortSize = 2;
         int longSize = 5;
@@ -845,18 +842,12 @@
         }
     }
 
-    public final void leaq(Register dst, Address src) {
+    public final void leaq(Register dst, AMD64Address src) {
         prefixq(src, dst);
         emitByte(0x8D);
         emitOperandHelper(dst, src);
     }
 
-    public final void enter(int imm16, int imm8) {
-        emitByte(0xC8);
-        emitShort(imm16);
-        emitByte(imm8);
-    }
-
     public final void leave() {
         emitByte(0xC9);
     }
@@ -870,17 +861,6 @@
         }
     }
 
-    // Emit mfence instruction
-    public final void mfence() {
-        emitByte(0x0F);
-        emitByte(0xAE);
-        emitByte(0xF0);
-    }
-
-    public final void mov(Register dst, Register src) {
-        movq(dst, src);
-    }
-
     public final void movapd(Register dst, Register src) {
         assert dst.isFpu();
         assert src.isFpu();
@@ -930,20 +910,14 @@
         emitByte(0xC0 | dstenc << 3 | srcenc);
     }
 
-    public final void movb(Register dst, Address src) {
-        prefix(src, dst); // , true)
-        emitByte(0x8A);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void movb(Address dst, int imm8) {
+    public final void movb(AMD64Address dst, int imm8) {
         prefix(dst);
         emitByte(0xC6);
-        emitOperandHelper(rax, dst);
+        emitOperandHelper(0, dst);
         emitByte(imm8);
     }
 
-    public final void movb(Address dst, Register src) {
+    public final void movb(AMD64Address dst, Register src) {
         assert src.isByte() : "must have byte register";
         prefix(dst, src); // , true)
         emitByte(0x88);
@@ -969,63 +943,6 @@
         }
     }
 
-    public final void movdqa(Register dst, Address src) {
-        assert dst.isFpu();
-        emitByte(0x66);
-        prefix(src, dst);
-        emitByte(0x0F);
-        emitByte(0x6F);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void movdqa(Register dst, Register src) {
-        assert dst.isFpu();
-        emitByte(0x66);
-        int encode = prefixqAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0x6F);
-        emitByte(0xC0 | encode);
-    }
-
-    public final void movdqa(Address dst, Register src) {
-        assert src.isFpu();
-        emitByte(0x66);
-        prefix(dst, src);
-        emitByte(0x0F);
-        emitByte(0x7F);
-        emitOperandHelper(src, dst);
-    }
-
-    public final void movdqu(Register dst, Address src) {
-        assert dst.isFpu();
-        emitByte(0xF3);
-        prefix(src, dst);
-        emitByte(0x0F);
-        emitByte(0x6F);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void movdqu(Register dst, Register src) {
-        assert dst.isFpu();
-        assert src.isFpu();
-
-        emitByte(0xF3);
-        int encode = prefixqAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0x6F);
-        emitByte(0xC0 | encode);
-    }
-
-    public final void movdqu(Address dst, Register src) {
-        assert src.isFpu();
-
-        emitByte(0xF3);
-        prefix(dst, src);
-        emitByte(0x0F);
-        emitByte(0x7F);
-        emitOperandHelper(src, dst);
-    }
-
     public final void movl(Register dst, int imm32) {
         int encode = prefixAndEncode(dst.encoding);
         emitByte(0xB8 | encode);
@@ -1038,20 +955,20 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void movl(Register dst, Address src) {
+    public final void movl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x8B);
         emitOperandHelper(dst, src);
     }
 
-    public final void movl(Address dst, int imm32) {
+    public final void movl(AMD64Address dst, int imm32) {
         prefix(dst);
         emitByte(0xC7);
-        emitOperandHelper(rax, dst);
+        emitOperandHelper(0, dst);
         emitInt(imm32);
     }
 
-    public final void movl(Address dst, Register src) {
+    public final void movl(AMD64Address dst, Register src) {
         prefix(dst, src);
         emitByte(0x89);
         emitOperandHelper(src, dst);
@@ -1060,10 +977,10 @@
     /**
      * New CPUs require use of movsd and movss to avoid partial register stall when loading from
      * memory. But for old Opteron use movlpd instead of movsd. The selection is done in
-     * {@link AMD64MacroAssembler#movdbl(Register, Address)} and
+     * {@link AMD64MacroAssembler#movdbl(Register, AMD64Address)} and
      * {@link AMD64MacroAssembler#movflt(Register, Register)}.
      */
-    public final void movlpd(Register dst, Address src) {
+    public final void movlpd(Register dst, AMD64Address src) {
         assert dst.isFpu();
         emitByte(0x66);
         prefix(src, dst);
@@ -1072,16 +989,7 @@
         emitOperandHelper(dst, src);
     }
 
-    public final void movlpd(Address dst, Register src) {
-        assert src.isFpu();
-        emitByte(0x66);
-        prefix(dst, src);
-        emitByte(0x0F);
-        emitByte(0x13);
-        emitOperandHelper(src, dst);
-    }
-
-    public final void movq(Register dst, Address src) {
+    public final void movq(Register dst, AMD64Address src) {
         if (dst.isFpu()) {
             emitByte(0xF3);
             prefixq(src, dst);
@@ -1101,7 +1009,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void movq(Address dst, Register src) {
+    public final void movq(AMD64Address dst, Register src) {
         if (src.isFpu()) {
             emitByte(0x66);
             prefixq(dst, src);
@@ -1115,14 +1023,14 @@
         }
     }
 
-    public final void movsxb(Register dst, Address src) { // movsxb
+    public final void movsxb(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x0F);
         emitByte(0xBE);
         emitOperandHelper(dst, src);
     }
 
-    public final void movsxb(Register dst, Register src) { // movsxb
+    public final void movsxb(Register dst, Register src) {
         int encode = prefixAndEncode(dst.encoding, src.encoding, true);
         emitByte(0x0F);
         emitByte(0xBE);
@@ -1139,7 +1047,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void movsd(Register dst, Address src) {
+    public final void movsd(Register dst, AMD64Address src) {
         assert dst.isFpu();
         emitByte(0xF2);
         prefix(src, dst);
@@ -1148,7 +1056,7 @@
         emitOperandHelper(dst, src);
     }
 
-    public final void movsd(Address dst, Register src) {
+    public final void movsd(AMD64Address dst, Register src) {
         assert src.isFpu();
         emitByte(0xF2);
         prefix(dst, src);
@@ -1167,7 +1075,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void movss(Register dst, Address src) {
+    public final void movss(Register dst, AMD64Address src) {
         assert dst.isFpu();
         emitByte(0xF3);
         prefix(src, dst);
@@ -1176,7 +1084,7 @@
         emitOperandHelper(dst, src);
     }
 
-    public final void movss(Address dst, Register src) {
+    public final void movss(AMD64Address dst, Register src) {
         assert src.isFpu();
         emitByte(0xF3);
         prefix(dst, src);
@@ -1185,96 +1093,50 @@
         emitOperandHelper(src, dst);
     }
 
-    public final void movswl(Register dst, Address src) {
+    public final void movswl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x0F);
         emitByte(0xBF);
         emitOperandHelper(dst, src);
     }
 
-    public final void movsxw(Register dst, Register src) { // movsxw
+    public final void movsxw(Register dst, Register src) {
         int encode = prefixAndEncode(dst.encoding, src.encoding);
         emitByte(0x0F);
         emitByte(0xBF);
         emitByte(0xC0 | encode);
     }
 
-    public final void movsxw(Register dst, Address src) { // movsxw
+    public final void movsxw(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x0F);
         emitByte(0xBF);
         emitOperandHelper(dst, src);
     }
 
-    public final void movzxd(Register dst, Register src) { // movzxd
-        int encode = prefixAndEncode(dst.encoding, src.encoding);
-        emitByte(0x63);
-        emitByte(0xC0 | encode);
-    }
-
-    public final void movzxd(Register dst, Address src) { // movzxd
-        prefix(src, dst);
-        emitByte(0x63);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void movw(Address dst, int imm16) {
+    public final void movw(AMD64Address dst, int imm16) {
         emitByte(0x66); // switch to 16-bit mode
         prefix(dst);
         emitByte(0xC7);
-        emitOperandHelper(rax, dst);
+        emitOperandHelper(0, dst);
         emitShort(imm16);
     }
 
-    public final void movw(Register dst, Address src) {
-        emitByte(0x66);
-        prefix(src, dst);
-        emitByte(0x8B);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void movw(Address dst, Register src) {
+    public final void movw(AMD64Address dst, Register src) {
         emitByte(0x66);
         prefix(dst, src);
         emitByte(0x89);
         emitOperandHelper(src, dst);
     }
 
-    public final void movzxb(Register dst, Address src) { // movzxb
-        prefix(src, dst);
-        emitByte(0x0F);
-        emitByte(0xB6);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void movzxb(Register dst, Register src) { // movzxb
-        int encode = prefixAndEncode(dst.encoding, src.encoding, true);
-        emitByte(0x0F);
-        emitByte(0xB6);
-        emitByte(0xC0 | encode);
-    }
-
-    public final void movzxl(Register dst, Address src) { // movzxw
+    public final void movzxl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x0F);
         emitByte(0xB7);
         emitOperandHelper(dst, src);
     }
 
-    public final void movzxl(Register dst, Register src) { // movzxw
-        int encode = prefixAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0xB7);
-        emitByte(0xC0 | encode);
-    }
-
-    public final void mull(Address src) {
-        prefix(src);
-        emitByte(0xF7);
-        emitOperandHelper(rsp, src);
-    }
-
-    public final void mulsd(Register dst, Address src) {
+    public final void mulsd(Register dst, AMD64Address src) {
         assert dst.isFpu();
         emitByte(0xF2);
         prefix(src, dst);
@@ -1294,7 +1156,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void mulss(Register dst, Address src) {
+    public final void mulss(Register dst, AMD64Address src) {
         assert dst.isFpu();
 
         emitByte(0xF3);
@@ -1530,25 +1392,12 @@
         }
     }
 
-    public final void notl(Register dst) {
-        int encode = prefixAndEncode(dst.encoding);
-        emitByte(0xF7);
-        emitByte(0xD0 | encode);
-    }
-
-    public final void orl(Address dst, int imm32) {
-        prefix(dst);
-        emitByte(0x81);
-        emitOperandHelper(rcx, dst);
-        emitInt(imm32);
-    }
-
     public final void orl(Register dst, int imm32) {
         prefix(dst);
         emitArith(0x81, 0xC8, dst, imm32);
     }
 
-    public final void orl(Register dst, Address src) {
+    public final void orl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x0B);
         emitOperandHelper(dst, src);
@@ -1559,7 +1408,7 @@
         emitArith(0x0B, 0xC0, dst, src);
     }
 
-    public final void popcntl(Register dst, Address src) {
+    public final void popcntl(Register dst, AMD64Address src) {
         emitByte(0xF3);
         prefix(src, dst);
         emitByte(0x0F);
@@ -1575,7 +1424,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void popcntq(Register dst, Address src) {
+    public final void popcntq(Register dst, AMD64Address src) {
         emitByte(0xF3);
         prefixq(src, dst);
         emitByte(0x0F);
@@ -1591,223 +1440,16 @@
         emitByte(0xC0 | encode);
     }
 
-    // generic
     public final void pop(Register dst) {
         int encode = prefixAndEncode(dst.encoding);
         emitByte(0x58 | encode);
     }
 
-    public final void prefetchPrefix(Address src) {
-        prefix(src);
-        emitByte(0x0F);
-    }
-
-    public final void prefetchnta(Address src) {
-        prefetchPrefix(src);
-        emitByte(0x18);
-        emitOperandHelper(rax, src); // 0, src
-    }
-
-    public final void prefetchr(Address src) {
-        prefetchPrefix(src);
-        emitByte(0x0D);
-        emitOperandHelper(rax, src); // 0, src
-    }
-
-    public final void prefetcht0(Address src) {
-        prefetchPrefix(src);
-        emitByte(0x18);
-        emitOperandHelper(rcx, src); // 1, src
-
-    }
-
-    public final void prefetcht1(Address src) {
-        prefetchPrefix(src);
-        emitByte(0x18);
-        emitOperandHelper(rdx, src); // 2, src
-    }
-
-    public final void prefetcht2(Address src) {
-        prefetchPrefix(src);
-        emitByte(0x18);
-        emitOperandHelper(rbx, src); // 3, src
-    }
-
-    public final void prefetchw(Address src) {
-        prefetchPrefix(src);
-        emitByte(0x0D);
-        emitOperandHelper(rcx, src); // 1, src
-    }
-
-    public final void pshufd(Register dst, Register src, int mode) {
-        assert dst.isFpu();
-        assert src.isFpu();
-        assert isUByte(mode) : "invalid value";
-
-        emitByte(0x66);
-        int encode = prefixAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0x70);
-        emitByte(0xC0 | encode);
-        emitByte(mode & 0xFF);
-    }
-
-    public final void pshufd(Register dst, Address src, int mode) {
-        assert dst.isFpu();
-        assert isUByte(mode) : "invalid value";
-
-        emitByte(0x66);
-        prefix(src, dst);
-        emitByte(0x0F);
-        emitByte(0x70);
-        emitOperandHelper(dst, src);
-        emitByte(mode & 0xFF);
-
-    }
-
-    public final void pshuflw(Register dst, Register src, int mode) {
-        assert dst.isFpu();
-        assert src.isFpu();
-        assert isUByte(mode) : "invalid value";
-
-        emitByte(0xF2);
-        int encode = prefixAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0x70);
-        emitByte(0xC0 | encode);
-        emitByte(mode & 0xFF);
-    }
-
-    public final void pshuflw(Register dst, Address src, int mode) {
-        assert dst.isFpu();
-        assert isUByte(mode) : "invalid value";
-
-        emitByte(0xF2);
-        prefix(src, dst); // QQ new
-        emitByte(0x0F);
-        emitByte(0x70);
-        emitOperandHelper(dst, src);
-        emitByte(mode & 0xFF);
-    }
-
-    public final void psrlq(Register dst, int shift) {
-        assert dst.isFpu();
-        // HMM Table D-1 says sse2 or mmx
-
-        int encode = prefixqAndEncode(xmm2.encoding, dst.encoding);
-        emitByte(0x66);
-        emitByte(0x0F);
-        emitByte(0x73);
-        emitByte(0xC0 | encode);
-        emitByte(shift);
-    }
-
-    public final void punpcklbw(Register dst, Register src) {
-        assert dst.isFpu();
-        assert src.isFpu();
-        emitByte(0x66);
-        int encode = prefixAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0x60);
-        emitByte(0xC0 | encode);
-    }
-
-    public final void push(int imm32) {
-        // in 64bits we push 64bits onto the stack but only
-        // take a 32bit immediate
-        emitByte(0x68);
-        emitInt(imm32);
-    }
-
     public final void push(Register src) {
         int encode = prefixAndEncode(src.encoding);
         emitByte(0x50 | encode);
     }
 
-    public final void pushf() {
-        emitByte(0x9C);
-    }
-
-    public final void pxor(Register dst, Address src) {
-        assert dst.isFpu();
-
-        emitByte(0x66);
-        prefix(src, dst);
-        emitByte(0x0F);
-        emitByte(0xEF);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void pxor(Register dst, Register src) {
-        assert dst.isFpu();
-        assert src.isFpu();
-
-        emitByte(0x66);
-        int encode = prefixAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0xEF);
-        emitByte(0xC0 | encode);
-
-    }
-
-    public final void rcll(Register dst, int imm8) {
-        assert isShiftCount(imm8) : "illegal shift count";
-        int encode = prefixAndEncode(dst.encoding);
-        if (imm8 == 1) {
-            emitByte(0xD1);
-            emitByte(0xD0 | encode);
-        } else {
-            emitByte(0xC1);
-            emitByte(0xD0 | encode);
-            emitByte(imm8);
-        }
-    }
-
-    public final void pause() {
-        emitByte(0xF3);
-        emitByte(0x90);
-    }
-
-    // Copies data from [X86.rsi] to [X86.rdi] using X86.rcx heap words.
-    public final void repeatMoveWords() {
-        emitByte(0xF3);
-        emitByte(Prefix.REXW);
-        emitByte(0xA5);
-    }
-
-    // Copies data from [X86.rsi] to [X86.rdi] using X86.rcx bytes.
-    public final void repeatMoveBytes() {
-        emitByte(0xF3);
-        emitByte(Prefix.REXW);
-        emitByte(0xA4);
-    }
-
-    // sets X86.rcx pointer sized words with X86.rax, value at [edi]
-    // generic
-    public final void repSet() { // repSet
-        emitByte(0xF3);
-        // STOSQ
-        emitByte(Prefix.REXW);
-        emitByte(0xAB);
-    }
-
-    // scans X86.rcx pointer sized words at [edi] for occurance of X86.rax,
-    // generic
-    public final void repneScan() { // repneScan
-        emitByte(0xF2);
-        // SCASQ
-        emitByte(Prefix.REXW);
-        emitByte(0xAF);
-    }
-
-    // scans X86.rcx 4 byte words at [edi] for occurance of X86.rax,
-    // generic
-    public final void repneScanl() { // repneScan
-        emitByte(0xF2);
-        // SCASL
-        emitByte(0xAF);
-    }
-
     public final void ret(int imm16) {
         if (imm16 == 0) {
             emitByte(0xC3);
@@ -1836,35 +1478,6 @@
         emitByte(0xF8 | encode);
     }
 
-    public final void sbbl(Address dst, int imm32) {
-        prefix(dst);
-        emitArithOperand(0x81, rbx, dst, imm32);
-    }
-
-    public final void sbbl(Register dst, int imm32) {
-        prefix(dst);
-        emitArith(0x81, 0xD8, dst, imm32);
-    }
-
-    public final void sbbl(Register dst, Address src) {
-        prefix(src, dst);
-        emitByte(0x1B);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void sbbl(Register dst, Register src) {
-        prefixAndEncode(dst.encoding, src.encoding);
-        emitArith(0x1B, 0xC0, dst, src);
-    }
-
-    public final void setb(ConditionFlag cc, Register dst) {
-        assert 0 <= cc.value && cc.value < 16 : "illegal cc";
-        int encode = prefixAndEncode(dst.encoding, true);
-        emitByte(0x0F);
-        emitByte(0x90 | cc.value);
-        emitByte(0xC0 | encode);
-    }
-
     public final void shll(Register dst, int imm8) {
         assert isShiftCount(imm8) : "illegal shift count";
         int encode = prefixAndEncode(dst.encoding);
@@ -1898,11 +1511,6 @@
         emitByte(0xE8 | encode);
     }
 
-    // copies a single word from [esi] to [edi]
-    public final void smovl() {
-        emitByte(0xA5);
-    }
-
     public final void sqrtsd(Register dst, Register src) {
         assert dst.isFpu();
         assert src.isFpu();
@@ -1915,17 +1523,9 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void subl(Address dst, int imm32) {
+    public final void subl(AMD64Address dst, int imm32) {
         prefix(dst);
-        if (isByte(imm32)) {
-            emitByte(0x83);
-            emitOperandHelper(rbp, dst);
-            emitByte(imm32 & 0xFF);
-        } else {
-            emitByte(0x81);
-            emitOperandHelper(rbp, dst);
-            emitInt(imm32);
-        }
+        emitArithOperand(0x81, 5, dst, imm32);
     }
 
     public final void subl(Register dst, int imm32) {
@@ -1933,13 +1533,7 @@
         emitArith(0x81, 0xE8, dst, imm32);
     }
 
-    public final void subl(Address dst, Register src) {
-        prefix(dst, src);
-        emitByte(0x29);
-        emitOperandHelper(src, dst);
-    }
-
-    public final void subl(Register dst, Address src) {
+    public final void subl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x2B);
         emitOperandHelper(dst, src);
@@ -1960,7 +1554,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void subsd(Register dst, Address src) {
+    public final void subsd(Register dst, AMD64Address src) {
         assert dst.isFpu();
 
         emitByte(0xF2);
@@ -1980,7 +1574,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void subss(Register dst, Address src) {
+    public final void subss(Register dst, AMD64Address src) {
         assert dst.isFpu();
 
         emitByte(0xF3);
@@ -1990,11 +1584,6 @@
         emitOperandHelper(dst, src);
     }
 
-    public final void testb(Register dst, int imm8) {
-        prefixAndEncode(dst.encoding, true);
-        emitArithB(0xF6, 0xC0, dst, imm8);
-    }
-
     public final void testl(Register dst, int imm32) {
         // not using emitArith because test
         // doesn't support sign-extension of
@@ -2015,13 +1604,13 @@
         emitArith(0x85, 0xC0, dst, src);
     }
 
-    public final void testl(Register dst, Address src) {
+    public final void testl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x85);
         emitOperandHelper(dst, src);
     }
 
-    public final void ucomisd(Register dst, Address src) {
+    public final void ucomisd(Register dst, AMD64Address src) {
         assert dst.isFpu();
         emitByte(0x66);
         ucomiss(dst, src);
@@ -2034,7 +1623,7 @@
         ucomiss(dst, src);
     }
 
-    public final void ucomiss(Register dst, Address src) {
+    public final void ucomiss(Register dst, AMD64Address src) {
         assert dst.isFpu();
 
         prefix(src, dst);
@@ -2052,33 +1641,12 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void xaddl(Address dst, Register src) {
-        assert src.isFpu();
-
-        prefix(dst, src);
-        emitByte(0x0F);
-        emitByte(0xC1);
-        emitOperandHelper(src, dst);
-    }
-
-    public final void xchgl(Register dst, Address src) { // xchg
-        prefix(src, dst);
-        emitByte(0x87);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void xchgl(Register dst, Register src) {
-        int encode = prefixAndEncode(dst.encoding, src.encoding);
-        emitByte(0x87);
-        emitByte(0xc0 | encode);
-    }
-
     public final void xorl(Register dst, int imm32) {
         prefix(dst);
         emitArith(0x81, 0xF0, dst, imm32);
     }
 
-    public final void xorl(Register dst, Address src) {
+    public final void xorl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x33);
         emitOperandHelper(dst, src);
@@ -2094,7 +1662,7 @@
         andps(dst, src);
     }
 
-    public final void andpd(Register dst, Address src) {
+    public final void andpd(Register dst, AMD64Address src) {
         emitByte(0x66);
         andps(dst, src);
     }
@@ -2107,7 +1675,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void andps(Register dst, Address src) {
+    public final void andps(Register dst, AMD64Address src) {
         assert dst.isFpu();
         prefix(src, dst);
         emitByte(0x0F);
@@ -2120,7 +1688,7 @@
         orps(dst, src);
     }
 
-    public final void orpd(Register dst, Address src) {
+    public final void orpd(Register dst, AMD64Address src) {
         emitByte(0x66);
         orps(dst, src);
     }
@@ -2133,7 +1701,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void orps(Register dst, Address src) {
+    public final void orps(Register dst, AMD64Address src) {
         assert dst.isFpu();
         prefix(src, dst);
         emitByte(0x0F);
@@ -2146,7 +1714,7 @@
         xorps(dst, src);
     }
 
-    public final void xorpd(Register dst, Address src) {
+    public final void xorpd(Register dst, AMD64Address src) {
         emitByte(0x66);
         xorps(dst, src);
     }
@@ -2159,7 +1727,7 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void xorps(Register dst, Address src) {
+    public final void xorps(Register dst, AMD64Address src) {
         assert dst.isFpu();
         prefix(src, dst);
         emitByte(0x0F);
@@ -2167,29 +1735,25 @@
         emitOperandHelper(dst, src);
     }
 
-    // 32bit only pieces of the assembler
-
-    public final void decl(Register dst) {
-        // Don't use it directly. Use Macrodecrementl() instead.
+    protected final void decl(Register dst) {
         // Use two-byte form (one-byte form is a REX prefix in 64-bit mode)
         int encode = prefixAndEncode(dst.encoding);
         emitByte(0xFF);
         emitByte(0xC8 | encode);
     }
 
-    public final void incl(Register dst) {
-        // Don't use it directly. Use Macroincrementl() instead.
+    protected final void incl(Register dst) {
         // Use two-byte form (one-byte from is a REX prefix in 64-bit mode)
         int encode = prefixAndEncode(dst.encoding);
         emitByte(0xFF);
         emitByte(0xC0 | encode);
     }
 
-    int prefixAndEncode(int regEnc) {
+    private int prefixAndEncode(int regEnc) {
         return prefixAndEncode(regEnc, false);
     }
 
-    int prefixAndEncode(int regEnc, boolean byteinst) {
+    private int prefixAndEncode(int regEnc, boolean byteinst) {
         if (regEnc >= 8) {
             emitByte(Prefix.REXB);
             return regEnc - 8;
@@ -2199,7 +1763,7 @@
         return regEnc;
     }
 
-    int prefixqAndEncode(int regEnc) {
+    private int prefixqAndEncode(int regEnc) {
         if (regEnc < 8) {
             emitByte(Prefix.REXW);
             return regEnc;
@@ -2209,11 +1773,11 @@
         }
     }
 
-    int prefixAndEncode(int dstEnc, int srcEnc) {
+    private int prefixAndEncode(int dstEnc, int srcEnc) {
         return prefixAndEncode(dstEnc, srcEnc, false);
     }
 
-    int prefixAndEncode(int dstEncoding, int srcEncoding, boolean byteinst) {
+    private int prefixAndEncode(int dstEncoding, int srcEncoding, boolean byteinst) {
         int srcEnc = srcEncoding;
         int dstEnc = dstEncoding;
         if (dstEnc < 8) {
@@ -2271,11 +1835,11 @@
         }
     }
 
-    private static boolean needsRex(Value value) {
-        return isRegister(value) && asRegister(value).encoding >= MinEncodingNeedsRex;
+    private static boolean needsRex(Register reg) {
+        return reg.encoding >= MinEncodingNeedsRex;
     }
 
-    private void prefix(Address adr) {
+    private void prefix(AMD64Address adr) {
         if (needsRex(adr.getBase())) {
             if (needsRex(adr.getIndex())) {
                 emitByte(Prefix.REXXB);
@@ -2289,7 +1853,7 @@
         }
     }
 
-    private void prefixq(Address adr) {
+    private void prefixq(AMD64Address adr) {
         if (needsRex(adr.getBase())) {
             if (needsRex(adr.getIndex())) {
                 emitByte(Prefix.REXWXB);
@@ -2305,7 +1869,7 @@
         }
     }
 
-    private void prefix(Address adr, Register reg) {
+    private void prefix(AMD64Address adr, Register reg) {
         if (reg.encoding < 8) {
             if (needsRex(adr.getBase())) {
                 if (needsRex(adr.getIndex())) {
@@ -2337,7 +1901,7 @@
         }
     }
 
-    private void prefixq(Address adr, Register src) {
+    private void prefixq(AMD64Address adr, Register src) {
         if (src.encoding < 8) {
             if (needsRex(adr.getBase())) {
                 if (needsRex(adr.getIndex())) {
@@ -2369,23 +1933,12 @@
         }
     }
 
-    public final void addq(Address dst, int imm32) {
-        prefixq(dst);
-        emitArithOperand(0x81, rax, dst, imm32);
-    }
-
-    public final void addq(Address dst, Register src) {
-        prefixq(dst, src);
-        emitByte(0x01);
-        emitOperandHelper(src, dst);
-    }
-
     public final void addq(Register dst, int imm32) {
         prefixqAndEncode(dst.encoding);
         emitArith(0x81, 0xC0, dst, imm32);
     }
 
-    public final void addq(Register dst, Address src) {
+    public final void addq(Register dst, AMD64Address src) {
         prefixq(src, dst);
         emitByte(0x03);
         emitOperandHelper(dst, src);
@@ -2401,7 +1954,7 @@
         emitArith(0x81, 0xE0, dst, imm32);
     }
 
-    public final void andq(Register dst, Address src) {
+    public final void andq(Register dst, AMD64Address src) {
         prefixq(src, dst);
         emitByte(0x23);
         emitOperandHelper(dst, src);
@@ -2426,53 +1979,49 @@
     public final void cmovq(ConditionFlag cc, Register dst, Register src) {
         int encode = prefixqAndEncode(dst.encoding, src.encoding);
         emitByte(0x0F);
-        emitByte(0x40 | cc.value);
+        emitByte(0x40 | cc.getValue());
         emitByte(0xC0 | encode);
     }
 
-    public final void cmovq(ConditionFlag cc, Register dst, Address src) {
+    public final void cmovq(ConditionFlag cc, Register dst, AMD64Address src) {
         prefixq(src, dst);
         emitByte(0x0F);
-        emitByte(0x40 | cc.value);
+        emitByte(0x40 | cc.getValue());
         emitOperandHelper(dst, src);
     }
 
-    public final void cmpq(Address dst, int imm32) {
-        prefixq(dst);
-        emitByte(0x81);
-        emitOperandHelper(rdi, dst);
-        emitInt(imm32);
-    }
-
     public final void cmpq(Register dst, int imm32) {
         prefixqAndEncode(dst.encoding);
         emitArith(0x81, 0xF8, dst, imm32);
     }
 
-    public final void cmpq(Address dst, Register src) {
-        prefixq(dst, src);
-        emitByte(0x3B);
-        emitOperandHelper(src, dst);
-    }
-
     public final void cmpq(Register dst, Register src) {
         prefixqAndEncode(dst.encoding, src.encoding);
         emitArith(0x3B, 0xC0, dst, src);
     }
 
-    public final void cmpq(Register dst, Address src) {
+    public final void cmpq(Register dst, AMD64Address src) {
         prefixq(src, dst);
         emitByte(0x3B);
         emitOperandHelper(dst, src);
     }
 
-    public final void cmpxchgq(Register reg, Address adr) {
+    public final void cmpxchgq(Register reg, AMD64Address adr) {
         prefixq(adr, reg);
         emitByte(0x0F);
         emitByte(0xB1);
         emitOperandHelper(reg, adr);
     }
 
+    public final void cvtsi2sdq(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF2);
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtsi2sdq(Register dst, Register src) {
         assert dst.isFpu();
         emitByte(0xF2);
@@ -2482,6 +2031,15 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvtsi2ssq(Register dst, AMD64Address src) {
+        assert dst.isFpu();
+        emitByte(0xF3);
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2A);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvtsi2ssq(Register dst, Register src) {
         assert dst.isFpu();
         emitByte(0xF3);
@@ -2491,6 +2049,14 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvttsd2siq(Register dst, AMD64Address src) {
+        emitByte(0xF2);
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvttsd2siq(Register dst, Register src) {
         assert src.isFpu();
         emitByte(0xF2);
@@ -2500,6 +2066,14 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void cvttss2siq(Register dst, AMD64Address src) {
+        emitByte(0xF3);
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0x2C);
+        emitOperandHelper(dst, src);
+    }
+
     public final void cvttss2siq(Register dst, Register src) {
         assert src.isFpu();
         emitByte(0xF3);
@@ -2509,19 +2083,17 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void decq(Register dst) {
-        // Don't use it directly. Use Macrodecrementq() instead.
+    protected final void decq(Register dst) {
         // Use two-byte form (one-byte from is a REX prefix in 64-bit mode)
         int encode = prefixqAndEncode(dst.encoding);
         emitByte(0xFF);
         emitByte(0xC8 | encode);
     }
 
-    public final void decq(Address dst) {
-        // Don't use it directly. Use Macrodecrementq() instead.
+    protected final void decq(AMD64Address dst) {
         prefixq(dst);
         emitByte(0xFF);
-        emitOperandHelper(rcx, dst);
+        emitOperandHelper(1, dst);
     }
 
     public final void divq(Register src) {
@@ -2543,6 +2115,13 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void imulq(Register dst, AMD64Address src) {
+        prefixq(src, dst);
+        emitByte(0x0F);
+        emitByte(0xAF);
+        emitOperandHelper(dst, src);
+    }
+
     public final void imulq(Register dst, Register src, int value) {
         int encode = prefixqAndEncode(dst.encoding, src.encoding);
         if (isByte(value)) {
@@ -2564,13 +2143,6 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void incq(Address dst) {
-        // Don't use it directly. Use Macroincrementq() instead.
-        prefixq(dst);
-        emitByte(0xFF);
-        emitOperandHelper(rax, dst);
-    }
-
     public final void movq(Register dst, long imm64) {
         int encode = prefixqAndEncode(dst.encoding);
         emitByte(0xB8 | encode);
@@ -2600,38 +2172,14 @@
         }
     }
 
-    public final void movsbq(Register dst, Address src) {
-        prefixq(src, dst);
-        emitByte(0x0F);
-        emitByte(0xBE);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void movsbq(Register dst, Register src) {
-        int encode = prefixqAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0xBE);
-        emitByte(0xC0 | encode);
-    }
-
-    public final void movslq(Register dst, int imm32) {
-        int encode = prefixqAndEncode(dst.encoding);
-        emitByte(0xC7 | encode);
-        emitInt(imm32);
-        // dbx shows movslq(X86.rcx, 3) as movq $0x0000000049000000,(%X86.rbx)
-        // and movslq(X86.r8, 3); as movl $0x0000000048000000,(%X86.rbx)
-        // as a result we shouldn't use until tested at runtime...
-        throw new InternalError("untested");
-    }
-
-    public final void movslq(Address dst, int imm32) {
+    public final void movslq(AMD64Address dst, int imm32) {
         prefixq(dst);
         emitByte(0xC7);
-        emitOperandHelper(rax, dst);
+        emitOperandHelper(0, dst);
         emitInt(imm32);
     }
 
-    public final void movslq(Register dst, Address src) {
+    public final void movslq(Register dst, AMD64Address src) {
         prefixq(src, dst);
         emitByte(0x63);
         emitOperandHelper(dst, src);
@@ -2643,73 +2191,18 @@
         emitByte(0xC0 | encode);
     }
 
-    public final void movswq(Register dst, Address src) {
-        prefixq(src, dst);
-        emitByte(0x0F);
-        emitByte(0xBF);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void movswq(Register dst, Register src) {
-        int encode = prefixqAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0xBF);
-        emitByte(0xC0 | encode);
-    }
-
-    public final void movzbq(Register dst, Address src) {
-        prefixq(src, dst);
-        emitByte(0x0F);
-        emitByte(0xB6);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void movzbq(Register dst, Register src) {
-        int encode = prefixqAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0xB6);
-        emitByte(0xC0 | encode);
-    }
-
-    public final void movzwq(Register dst, Address src) {
-        prefixq(src, dst);
-        emitByte(0x0F);
-        emitByte(0xB7);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void movzwq(Register dst, Register src) {
-        int encode = prefixqAndEncode(dst.encoding, src.encoding);
-        emitByte(0x0F);
-        emitByte(0xB7);
-        emitByte(0xC0 | encode);
-    }
-
     public final void negq(Register dst) {
         int encode = prefixqAndEncode(dst.encoding);
         emitByte(0xF7);
         emitByte(0xD8 | encode);
     }
 
-    public final void notq(Register dst) {
-        int encode = prefixqAndEncode(dst.encoding);
-        emitByte(0xF7);
-        emitByte(0xD0 | encode);
-    }
-
-    public final void orq(Address dst, int imm32) {
-        prefixq(dst);
-        emitByte(0x81);
-        emitOperandHelper(rcx, dst);
-        emitInt(imm32);
-    }
-
     public final void orq(Register dst, int imm32) {
         prefixqAndEncode(dst.encoding);
         emitArith(0x81, 0xC8, dst, imm32);
     }
 
-    public final void orq(Register dst, Address src) {
+    public final void orq(Register dst, AMD64Address src) {
         prefixq(src, dst);
         emitByte(0x0B);
         emitOperandHelper(dst, src);
@@ -2720,31 +2213,6 @@
         emitArith(0x0B, 0xC0, dst, src);
     }
 
-    public final void popq(Address dst) {
-        prefixq(dst);
-        emitByte(0x8F);
-        emitOperandHelper(rax, dst);
-    }
-
-    public final void pushq(Address src) {
-        prefixq(src);
-        emitByte(0xFF);
-        emitOperandHelper(rsi, src);
-    }
-
-    public final void rclq(Register dst, int imm8) {
-        assert isShiftCount(imm8 >> 1) : "illegal shift count";
-        int encode = prefixqAndEncode(dst.encoding);
-        if (imm8 == 1) {
-            emitByte(0xD1);
-            emitByte(0xD0 | encode);
-        } else {
-            emitByte(0xC1);
-            emitByte(0xD0 | encode);
-            emitByte(imm8);
-        }
-    }
-
     public final void sarq(Register dst, int imm8) {
         assert isShiftCount(imm8 >> 1) : "illegal shift count";
         int encode = prefixqAndEncode(dst.encoding);
@@ -2797,41 +2265,12 @@
         emitByte(0xE8 | encode);
     }
 
-    public final void sqrtsd(Register dst, Address src) {
-        assert dst.isFpu();
-
-        emitByte(0xF2);
-        prefix(src, dst);
-        emitByte(0x0F);
-        emitByte(0x51);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void subq(Address dst, int imm32) {
-        prefixq(dst);
-        if (isByte(imm32)) {
-            emitByte(0x83);
-            emitOperandHelper(rbp, dst);
-            emitByte(imm32 & 0xFF);
-        } else {
-            emitByte(0x81);
-            emitOperandHelper(rbp, dst);
-            emitInt(imm32);
-        }
-    }
-
     public final void subq(Register dst, int imm32) {
         prefixqAndEncode(dst.encoding);
         emitArith(0x81, 0xE8, dst, imm32);
     }
 
-    public final void subq(Address dst, Register src) {
-        prefixq(dst, src);
-        emitByte(0x29);
-        emitOperandHelper(src, dst);
-    }
-
-    public final void subq(Register dst, Address src) {
+    public final void subq(Register dst, AMD64Address src) {
         prefixq(src, dst);
         emitByte(0x2B);
         emitOperandHelper(dst, src);
@@ -2863,31 +2302,12 @@
         emitArith(0x85, 0xC0, dst, src);
     }
 
-    public final void testq(Register dst, Address src) {
+    public final void testq(Register dst, AMD64Address src) {
         prefixq(src, dst);
         emitByte(0x85);
         emitOperandHelper(dst, src);
     }
 
-    public final void xaddq(Address dst, Register src) {
-        prefixq(dst, src);
-        emitByte(0x0F);
-        emitByte(0xC1);
-        emitOperandHelper(src, dst);
-    }
-
-    public final void xchgq(Register dst, Address src) {
-        prefixq(src, dst);
-        emitByte(0x87);
-        emitOperandHelper(dst, src);
-    }
-
-    public final void xchgq(Register dst, Register src) {
-        int encode = prefixqAndEncode(dst.encoding, src.encoding);
-        emitByte(0x87);
-        emitByte(0xc0 | encode);
-    }
-
     public final void xorq(Register dst, int imm32) {
         prefixqAndEncode(dst.encoding);
         emitArith(0x81, 0xF0, dst, imm32);
@@ -2898,12 +2318,10 @@
         emitArith(0x33, 0xC0, dst, src);
     }
 
-    public final void xorq(Register dst, Address src) {
-
+    public final void xorq(Register dst, AMD64Address src) {
         prefixq(src, dst);
         emitByte(0x33);
         emitOperandHelper(dst, src);
-
     }
 
     public final void membar(int barriers) {
@@ -2919,7 +2337,7 @@
                 // the code where this idiom is used, in particular the
                 // orderAccess code.
                 lock();
-                addl(new Address(Word, RSP, 0), 0); // Assert the lock# signal here
+                addl(new AMD64Address(rsp, 0), 0); // Assert the lock# signal here
             }
         }
     }
@@ -2960,7 +2378,7 @@
     }
 
     public void nullCheck(Register r) {
-        testl(AMD64.rax, new Address(Word, r.asValue(Word), 0));
+        testl(AMD64.rax, new AMD64Address(r, 0));
     }
 
     @Override
@@ -2970,26 +2388,6 @@
         }
     }
 
-    public void pushfq() {
-        emitByte(0x9c);
-    }
-
-    public void popfq() {
-        emitByte(0x9D);
-    }
-
-    /**
-     * Makes sure that a subsequent {@linkplain #call} does not fail the alignment check.
-     */
-    public final void alignForPatchableDirectCall() {
-        int dispStart = codeBuffer.position() + 1;
-        int mask = target.wordSize - 1;
-        if ((dispStart & ~mask) != ((dispStart + 3) & ~mask)) {
-            nop(target.wordSize - (dispStart & mask));
-            assert ((codeBuffer.position() + 1) & mask) == 0;
-        }
-    }
-
     /**
      * Emits a direct call instruction. Note that the actual call target is not specified, because
      * all calls need patching anyway. Therefore, 0 is emitted as the call target, and the user is
@@ -3006,74 +2404,67 @@
         emitByte(0xD0 | encode);
     }
 
-    public void int3() {
+    public final void int3() {
         emitByte(0xCC);
     }
 
-    public void enter(short imm16, byte imm8) {
-        emitByte(0xC8);
-        // appended:
-        emitByte(imm16 & 0xff);
-        emitByte((imm16 >> 8) & 0xff);
-        emitByte(imm8);
-    }
-
     private void emitx87(int b1, int b2, int i) {
         assert 0 <= i && i < 8 : "illegal stack offset";
         emitByte(b1);
         emitByte(b2 + i);
     }
 
-    public void fld(Address src) {
+    public final void fld(AMD64Address src) {
         emitByte(0xDD);
-        emitOperandHelper(rax, src);
+        emitOperandHelper(0, src);
     }
 
-    public void fld(int i) {
-        emitx87(0xD9, 0xC0, i);
-    }
-
-    public void fldln2() {
+    public final void fldln2() {
         emitByte(0xD9);
         emitByte(0xED);
     }
 
-    public void fldlg2() {
+    public final void fldlg2() {
         emitByte(0xD9);
         emitByte(0xEC);
     }
 
-    public void fyl2x() {
+    public final void fyl2x() {
         emitByte(0xD9);
         emitByte(0xF1);
     }
 
-    public void fstp(Address src) {
+    public final void fstp(AMD64Address src) {
         emitByte(0xDD);
-        emitOperandHelper(rbx, src);
+        emitOperandHelper(3, src);
     }
 
-    public void fsin() {
+    public final void fsin() {
         emitByte(0xD9);
         emitByte(0xFE);
     }
 
-    public void fcos() {
+    public final void fcos() {
         emitByte(0xD9);
         emitByte(0xFF);
     }
 
-    public void fptan() {
+    public final void fptan() {
         emitByte(0xD9);
         emitByte(0xF2);
     }
 
-    public void fstp(int i) {
+    public final void fstp(int i) {
         emitx87(0xDD, 0xD8, i);
     }
 
     @Override
-    public void bangStack(int disp) {
-        movq(new Address(target.wordKind, AMD64.RSP, -disp), AMD64.rax);
+    public AMD64Address makeAddress(Register base, int displacement) {
+        return new AMD64Address(base, displacement);
+    }
+
+    @Override
+    public AMD64Address getPlaceholder() {
+        return Placeholder;
     }
 }
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,6 @@
 
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
 
 /**
  * This class implements commonly used X86 code patterns.
@@ -38,25 +36,11 @@
         super(target, registerConfig);
     }
 
-    public void pushptr(Address src) {
-        pushq(src);
-    }
-
-    public void popptr(Address src) {
-        popq(src);
-    }
-
-    public void xorptr(Register dst, Register src) {
+    public final void xorptr(Register dst, Register src) {
         xorq(dst, src);
     }
 
-    public void xorptr(Register dst, Address src) {
-        xorq(dst, src);
-    }
-
-    // 64 bit versions
-
-    public void decrementq(Register reg, int value) {
+    public final void decrementq(Register reg, int value) {
         if (value == Integer.MIN_VALUE) {
             subq(reg, value);
             return;
@@ -94,83 +78,19 @@
         }
     }
 
-    // These are mostly for initializing null
-    public void movptr(Address dst, int src) {
+    public final void movptr(AMD64Address dst, int src) {
         movslq(dst, src);
     }
 
-    public final void cmp32(Register src1, int imm) {
-        cmpl(src1, imm);
-    }
-
-    public final void cmp32(Register src1, Address src2) {
-        cmpl(src1, src2);
-    }
-
-    public void cmpsd2int(Register opr1, Register opr2, Register dst, boolean unorderedIsLess) {
-        assert opr1.isFpu() && opr2.isFpu();
-        ucomisd(opr1, opr2);
-
-        Label l = new Label();
-        if (unorderedIsLess) {
-            movl(dst, -1);
-            jcc(AMD64Assembler.ConditionFlag.parity, l);
-            jcc(AMD64Assembler.ConditionFlag.below, l);
-            movl(dst, 0);
-            jcc(AMD64Assembler.ConditionFlag.equal, l);
-            incrementl(dst, 1);
-        } else { // unordered is greater
-            movl(dst, 1);
-            jcc(AMD64Assembler.ConditionFlag.parity, l);
-            jcc(AMD64Assembler.ConditionFlag.above, l);
-            movl(dst, 0);
-            jcc(AMD64Assembler.ConditionFlag.equal, l);
-            decrementl(dst, 1);
-        }
-        bind(l);
-    }
-
-    public void cmpss2int(Register opr1, Register opr2, Register dst, boolean unorderedIsLess) {
-        assert opr1.isFpu();
-        assert opr2.isFpu();
-        ucomiss(opr1, opr2);
-
-        Label l = new Label();
-        if (unorderedIsLess) {
-            movl(dst, -1);
-            jcc(AMD64Assembler.ConditionFlag.parity, l);
-            jcc(AMD64Assembler.ConditionFlag.below, l);
-            movl(dst, 0);
-            jcc(AMD64Assembler.ConditionFlag.equal, l);
-            incrementl(dst, 1);
-        } else { // unordered is greater
-            movl(dst, 1);
-            jcc(AMD64Assembler.ConditionFlag.parity, l);
-            jcc(AMD64Assembler.ConditionFlag.above, l);
-            movl(dst, 0);
-            jcc(AMD64Assembler.ConditionFlag.equal, l);
-            decrementl(dst, 1);
-        }
-        bind(l);
-    }
-
-    public void cmpptr(Register src1, Register src2) {
+    public final void cmpptr(Register src1, Register src2) {
         cmpq(src1, src2);
     }
 
-    public void cmpptr(Register src1, Address src2) {
+    public final void cmpptr(Register src1, AMD64Address src2) {
         cmpq(src1, src2);
     }
 
-    public void cmpptr(Register src1, int src2) {
-        cmpq(src1, src2);
-    }
-
-    public void cmpptr(Address src1, int src2) {
-        cmpq(src1, src2);
-    }
-
-    public void decrementl(Register reg, int value) {
+    public final void decrementl(Register reg, int value) {
         if (value == Integer.MIN_VALUE) {
             subl(reg, value);
             return;
@@ -189,7 +109,7 @@
         }
     }
 
-    public void decrementl(Address dst, int value) {
+    public final void decrementl(AMD64Address dst, int value) {
         if (value == Integer.MIN_VALUE) {
             subl(dst, value);
             return;
@@ -208,7 +128,7 @@
         }
     }
 
-    public void incrementl(Register reg, int value) {
+    public final void incrementl(Register reg, int value) {
         if (value == Integer.MIN_VALUE) {
             addl(reg, value);
             return;
@@ -227,7 +147,7 @@
         }
     }
 
-    public void incrementl(Address dst, int value) {
+    public final void incrementl(AMD64Address dst, int value) {
         if (value == Integer.MIN_VALUE) {
             addl(dst, value);
             return;
@@ -246,21 +166,20 @@
         }
     }
 
-    public void signExtendByte(Register reg) {
+    public final void signExtendByte(Register reg) {
         if (reg.isByte()) {
-            movsxb(reg, reg); // movsxb
+            movsxb(reg, reg);
         } else {
             shll(reg, 24);
             sarl(reg, 24);
         }
     }
 
-    public void signExtendShort(Register reg) {
-        movsxw(reg, reg); // movsxw
+    public final void signExtendShort(Register reg) {
+        movsxw(reg, reg);
     }
 
-    // Support optimal SSE move instructions.
-    public void movflt(Register dst, Register src) {
+    public final void movflt(Register dst, Register src) {
         assert dst.isFpu() && src.isFpu();
         if (UseXmmRegToRegMoveAll) {
             movaps(dst, src);
@@ -269,17 +188,17 @@
         }
     }
 
-    public void movflt(Register dst, Address src) {
+    public final void movflt(Register dst, AMD64Address src) {
         assert dst.isFpu();
         movss(dst, src);
     }
 
-    public void movflt(Address dst, Register src) {
+    public final void movflt(AMD64Address dst, Register src) {
         assert src.isFpu();
         movss(dst, src);
     }
 
-    public void movdbl(Register dst, Register src) {
+    public final void movdbl(Register dst, Register src) {
         assert dst.isFpu() && src.isFpu();
         if (UseXmmRegToRegMoveAll) {
             movapd(dst, src);
@@ -288,7 +207,7 @@
         }
     }
 
-    public void movdbl(Register dst, Address src) {
+    public final void movdbl(Register dst, AMD64Address src) {
         assert dst.isFpu();
         if (UseXmmLoadAndClearUpper) {
             movsd(dst, src);
@@ -297,75 +216,65 @@
         }
     }
 
-    public void movdbl(Address dst, Register src) {
-        assert src.isFpu();
-        movsd(dst, src);
-    }
-
     /**
      * Non-atomic write of a 64-bit constant to memory. Do not use if the address might be a
      * volatile field!
      */
-    public void movlong(Address dst, long src) {
-        Address high = new Address(dst.getKind(), dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4);
+    public final void movlong(AMD64Address dst, long src) {
+        AMD64Address high = new AMD64Address(dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4);
         movl(dst, (int) (src & 0xFFFFFFFF));
         movl(high, (int) (src >> 32));
     }
 
-    public void xchgptr(Register src1, Register src2) {
-        xchgq(src1, src2);
-    }
+    public final void flog(Register dest, Register value, boolean base10) {
+        assert dest.isFpu() && value.isFpu();
 
-    public void flog(Register dest, Register value, boolean base10) {
-        assert value.spillSlotSize == dest.spillSlotSize;
-
-        Address tmp = new Address(Kind.Double, AMD64.RSP);
+        AMD64Address tmp = new AMD64Address(AMD64.rsp);
         if (base10) {
             fldlg2();
         } else {
             fldln2();
         }
-        subq(AMD64.rsp, value.spillSlotSize);
+        subq(AMD64.rsp, 8);
         movsd(tmp, value);
         fld(tmp);
         fyl2x();
-        fstp(tmp);
-        movsd(dest, tmp);
-        addq(AMD64.rsp, dest.spillSlotSize);
+        trigEpilogue(dest, tmp);
     }
 
-    public void fsin(Register dest, Register value) {
-        ftrig(dest, value, 's');
+    public final void fsin(Register dest, Register value) {
+        AMD64Address tmp = trigPrologue(value);
+        fsin();
+        trigEpilogue(dest, tmp);
     }
 
-    public void fcos(Register dest, Register value) {
-        ftrig(dest, value, 'c');
-    }
-
-    public void ftan(Register dest, Register value) {
-        ftrig(dest, value, 't');
+    public final void fcos(Register dest, Register value) {
+        AMD64Address tmp = trigPrologue(value);
+        fcos();
+        trigEpilogue(dest, tmp);
     }
 
-    private void ftrig(Register dest, Register value, char op) {
-        assert value.spillSlotSize == dest.spillSlotSize;
+    public final void ftan(Register dest, Register value) {
+        AMD64Address tmp = trigPrologue(value);
+        fptan();
+        fstp(0); // ftan pushes 1.0 in addition to the actual result, pop
+        trigEpilogue(dest, tmp);
+    }
 
-        Address tmp = new Address(Kind.Double, AMD64.RSP);
-        subq(AMD64.rsp, value.spillSlotSize);
+    private AMD64Address trigPrologue(Register value) {
+        assert value.isFpu();
+        AMD64Address tmp = new AMD64Address(AMD64.rsp);
+        subq(AMD64.rsp, 8);
         movsd(tmp, value);
         fld(tmp);
-        if (op == 's') {
-            fsin();
-        } else if (op == 'c') {
-            fcos();
-        } else if (op == 't') {
-            fptan();
-            fstp(0); // ftan pushes 1.0 in addition to the actual result, pop
-        } else {
-            throw new InternalError("should not reach here");
-        }
+        return tmp;
+    }
+
+    private void trigEpilogue(Register dest, AMD64Address tmp) {
+        assert dest.isFpu();
         fstp(tmp);
         movsd(dest, tmp);
-        addq(AMD64.rsp, dest.spillSlotSize);
+        addq(AMD64.rsp, 8);
     }
 
     /**
@@ -375,19 +284,17 @@
      * @param csl the description of the CSA
      * @param frameToCSA offset from the frame pointer to the CSA
      */
-    public void save(CalleeSaveLayout csl, int frameToCSA) {
-        RegisterValue frame = frameRegister.asValue();
+    public final void save(CalleeSaveLayout csl, int frameToCSA) {
         for (Register r : csl.registers) {
             int offset = csl.offsetOf(r);
-            movq(new Address(target.wordKind, frame, frameToCSA + offset), r);
+            movq(new AMD64Address(frameRegister, frameToCSA + offset), r);
         }
     }
 
-    public void restore(CalleeSaveLayout csl, int frameToCSA) {
-        RegisterValue frame = frameRegister.asValue();
+    public final void restore(CalleeSaveLayout csl, int frameToCSA) {
         for (Register r : csl.registers) {
             int offset = csl.offsetOf(r);
-            movq(r, new Address(target.wordKind, frame, frameToCSA + offset));
+            movq(r, new AMD64Address(frameRegister, frameToCSA + offset));
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/AbstractPTXAssembler.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.asm.ptx;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.*;
+
+/**
+ * The platform-dependent base class for the PTX assembler.
+ */
+public abstract class AbstractPTXAssembler extends AbstractAssembler {
+
+    public AbstractPTXAssembler(TargetDescription target) {
+        super(target);
+    }
+
+    public static final String UNBOUND_TARGET = "L" + Integer.MAX_VALUE;
+
+    @Override
+    public final void bind(Label l) {
+        super.bind(l);
+        emitString0("L" + l.toString() + ":\n");
+    }
+
+    @Override
+    public void align(int modulus) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void jmp(Label l) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    protected void patchJumpTarget(int branch, int jumpTarget) {
+        final int spaces = UNBOUND_TARGET.length();
+        String targetString = String.format("L%-" + spaces + "s", jumpTarget + ";");
+        int offset = "\tbra ".length();  // XXX we need a better way to figure this out
+        codeBuffer.emitString(targetString, branch + offset);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAddress.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.asm.ptx;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Represents an address in target machine memory, specified via some combination of a base register
+ * and a displacement.
+ */
+public final class PTXAddress extends AbstractAddress {
+
+    private final Register base;
+    private final long displacement;
+
+    /**
+     * Creates an {@link PTXAddress} with given base register and no displacement.
+     * 
+     * @param base the base register
+     */
+    public PTXAddress(Register base) {
+        this(base, 0);
+    }
+
+    /**
+     * Creates an {@link PTXAddress} with given base register and a displacement. This is the most
+     * general constructor.
+     * 
+     * @param base the base register
+     * @param displacement the displacement
+     */
+    public PTXAddress(Register base, long displacement) {
+        this.base = base;
+        this.displacement = displacement;
+    }
+
+    /**
+     * @return Base register that defines the start of the address computation. If not present, is
+     *         denoted by {@link Value#ILLEGAL}.
+     */
+    public Register getBase() {
+        return base;
+    }
+
+    /**
+     * @return Optional additive displacement.
+     */
+    public long getDisplacement() {
+        return displacement;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAsmOptions.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.asm.ptx;
+
+public class PTXAsmOptions {
+    // Nothing for now
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,752 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.asm.ptx;
+
+import com.oracle.graal.api.code.*;
+
+public class PTXAssembler extends AbstractPTXAssembler {
+
+    @SuppressWarnings("unused")
+    public PTXAssembler(TargetDescription target, RegisterConfig registerConfig) {
+        super(target);
+    }
+
+    public final void at() {
+        emitString("@%p" + " " + "");
+    }
+
+    public final void add_s16(Register d, Register a, Register b) {
+        emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void add_s32(Register d, Register a, Register b) {
+        emitString("add.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void add_s64(Register d, Register a, Register b) {
+        emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void add_s16(Register d, Register a, short s16) {
+        emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
+    }
+
+    public final void add_s32(Register d, Register a, int s32) {
+        emitString("add.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void add_s64(Register d, Register a, long s64) {
+        emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
+    }
+
+    public final void add_u16(Register d, Register a, Register b) {
+        emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void add_u32(Register d, Register a, Register b) {
+        emitString("add.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void add_u64(Register d, Register a, Register b) {
+        emitString("add.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void add_u16(Register d, Register a, short u16) {
+        emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + "");
+    }
+
+    public final void add_u32(Register d, Register a, int u32) {
+        emitString("add.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void add_u64(Register d, Register a, long u64) {
+        emitString("add.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
+    }
+
+    public final void add_sat_s32(Register d, Register a, Register b) {
+        emitString("add.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void add_sat_s32(Register d, Register a, int s32) {
+        emitString("add.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void and_b16(Register d, Register a, Register b) {
+        emitString("and.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void and_b32(Register d, Register a, Register b) {
+        emitString("and.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void and_b64(Register d, Register a, Register b) {
+        emitString("and.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void and_b16(Register d, Register a, short b16) {
+        emitString("and.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + "");
+    }
+
+    public final void and_b32(Register d, Register a, int b32) {
+        emitString("and.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + "");
+    }
+
+    public final void and_b64(Register d, Register a, long b64) {
+        emitString("and.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + "");
+    }
+
+    public final void bra(String tgt) {
+        emitString("bra" + " " + tgt + ";" + "");
+    }
+
+    public final void bra_uni(String tgt) {
+        emitString("bra.uni" + " " + tgt + ";" + "");
+    }
+
+    public final void div_s16(Register d, Register a, Register b) {
+        emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_s32(Register d, Register a, Register b) {
+        emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_s64(Register d, Register a, Register b) {
+        emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_s16(Register d, Register a, short s16) {
+        emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
+    }
+
+    public final void div_s32(Register d, Register a, int s32) {
+        emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void div_s64(Register d, Register a, long s64) {
+        emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
+    }
+
+    public final void div_u16(Register d, Register a, Register b) {
+        emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_u32(Register d, Register a, Register b) {
+        emitString("div.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_u64(Register d, Register a, Register b) {
+        emitString("div.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void div_u16(Register d, Register a, short u16) {
+        emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + "");
+    }
+
+    public final void div_u32(Register d, Register a, int u32) {
+        emitString("div.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void div_u64(Register d, Register a, long u64) {
+        emitString("div.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
+    }
+
+    public final void exit() {
+        emitString("exit;" + " " + "");
+    }
+
+    public final void ld_global_b8(Register d, Register a, long immOff) {
+        emitString("ld.global.b8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_b16(Register d, Register a, long immOff) {
+        emitString("ld.global.b16" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_b32(Register d, Register a, long immOff) {
+        emitString("ld.global.b32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_b64(Register d, Register a, long immOff) {
+        emitString("ld.global.b64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_u8(Register d, Register a, long immOff) {
+        emitString("ld.global.u8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_u16(Register d, Register a, long immOff) {
+        emitString("ld.global.u16" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_u32(Register d, Register a, long immOff) {
+        emitString("ld.global.u32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_u64(Register d, Register a, long immOff) {
+        emitString("ld.global.u64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_s8(Register d, Register a, long immOff) {
+        emitString("ld.global.s8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_s16(Register d, Register a, long immOff) {
+        emitString("ld.global.s16" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_s32(Register d, Register a, long immOff) {
+        emitString("ld.global.s32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_s64(Register d, Register a, long immOff) {
+        emitString("ld.global.s64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_f32(Register d, Register a, long immOff) {
+        emitString("ld.global.f32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void ld_global_f64(Register d, Register a, long immOff) {
+        emitString("ld.global.f64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + "");
+    }
+
+    public final void mov_b16(Register d, Register a) {
+        emitString("mov.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_b32(Register d, Register a) {
+        emitString("mov.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_b64(Register d, Register a) {
+        emitString("mov.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_u16(Register d, Register a) {
+        emitString("mov.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_u32(Register d, Register a) {
+        emitString("mov.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_u64(Register d, Register a) {
+        emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_s16(Register d, Register a) {
+        emitString("mov.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_s32(Register d, Register a) {
+        emitString("mov.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_s64(Register d, Register a) {
+        emitString("mov.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_f32(Register d, Register a) {
+        emitString("mov.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_f64(Register d, Register a) {
+        emitString("mov.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void mov_b16(Register d, short b16) {
+        emitString("mov.b16" + " " + "%r" + d.encoding() + ", " + b16 + ";" + "");
+    }
+
+    public final void mov_b32(Register d, int b32) {
+        emitString("mov.b32" + " " + "%r" + d.encoding() + ", " + b32 + ";" + "");
+    }
+
+    public final void mov_b64(Register d, long b64) {
+        emitString("mov.b64" + " " + "%r" + d.encoding() + ", " + b64 + ";" + "");
+    }
+
+    public final void mov_u16(Register d, short u16) {
+        emitString("mov.u16" + " " + "%r" + d.encoding() + ", " + u16 + ";" + "");
+    }
+
+    public final void mov_u32(Register d, int u32) {
+        emitString("mov.u32" + " " + "%r" + d.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void mov_u64(Register d, long u64) {
+        emitString("mov.u64" + " " + "%r" + d.encoding() + ", " + u64 + ";" + "");
+    }
+
+    public final void mov_s16(Register d, short s16) {
+        emitString("mov.s16" + " " + "%r" + d.encoding() + ", " + s16 + ";" + "");
+    }
+
+    public final void mov_s32(Register d, int s32) {
+        emitString("mov.s32" + " " + "%r" + d.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void mov_s64(Register d, long s64) {
+        emitString("mov.s64" + " " + "%r" + d.encoding() + ", " + s64 + ";" + "");
+    }
+
+    public final void mov_f32(Register d, float f32) {
+        emitString("mov.f32" + " " + "%r" + d.encoding() + ", " + f32 + ";" + "");
+    }
+
+    public final void mov_f64(Register d, double f64) {
+        emitString("mov.f64" + " " + "%r" + d.encoding() + ", " + f64 + ";" + "");
+    }
+
+    public final void mul_s16(Register d, Register a, Register b) {
+        emitString("mul.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void mul_s32(Register d, Register a, Register b) {
+        emitString("mul.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void mul_s64(Register d, Register a, Register b) {
+        emitString("mul.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void mul_s16(Register d, Register a, short s16) {
+        emitString("mul.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
+    }
+
+    public final void mul_s32(Register d, Register a, int s32) {
+        emitString("mul.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void mul_s64(Register d, Register a, long s64) {
+        emitString("mul.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
+    }
+
+    public final void mul_u16(Register d, Register a, Register b) {
+        emitString("mul.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void mul_u32(Register d, Register a, Register b) {
+        emitString("mul.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void mul_u64(Register d, Register a, Register b) {
+        emitString("mul.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void mul_u16(Register d, Register a, short u16) {
+        emitString("mul.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + "");
+    }
+
+    public final void mul_u32(Register d, Register a, int u32) {
+        emitString("mul.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void mul_u64(Register d, Register a, long u64) {
+        emitString("mul.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
+    }
+
+    public final void neg_s16(Register d, Register a) {
+        emitString("neg.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void neg_s32(Register d, Register a) {
+        emitString("neg.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void neg_s64(Register d, Register a) {
+        emitString("neg.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void popc_b32(Register d, Register a) {
+        emitString("popc.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void popc_b64(Register d, Register a) {
+        emitString("popc.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    }
+
+    public final void rem_s16(Register d, Register a, Register b) {
+        emitString("rem.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void rem_s32(Register d, Register a, Register b) {
+        emitString("rem.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void rem_s64(Register d, Register a, Register b) {
+        emitString("rem.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void rem_s16(Register d, Register a, short s16) {
+        emitString("rem.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
+    }
+
+    public final void rem_s32(Register d, Register a, int s32) {
+        emitString("rem.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void rem_s64(Register d, Register a, long s64) {
+        emitString("rem.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
+    }
+
+    public final void rem_u16(Register d, Register a, Register b) {
+        emitString("rem.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void rem_u32(Register d, Register a, Register b) {
+        emitString("rem.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void rem_u64(Register d, Register a, Register b) {
+        emitString("rem.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void rem_u16(Register d, Register a, short u16) {
+        emitString("rem.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + "");
+    }
+
+    public final void rem_u32(Register d, Register a, int u32) {
+        emitString("rem.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void rem_u64(Register d, Register a, long u64) {
+        emitString("rem.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
+    }
+
+    public final void ret() {
+        emitString("ret;" + " " + "");
+    }
+
+    public final void ret_uni() {
+        emitString("ret.uni;" + " " + "");
+    }
+
+    public final void setp_eq_s32(Register a, Register b) {
+        emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ne_s32(Register a, Register b) {
+        emitString("setp.ne.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_lt_s32(Register a, Register b) {
+        emitString("setp.lt.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_le_s32(Register a, Register b) {
+        emitString("setp.le.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_gt_s32(Register a, Register b) {
+        emitString("setp.gt.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ge_s32(Register a, Register b) {
+        emitString("setp.ge.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_s32(Register a, int s32) {
+        emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void setp_ne_s32(Register a, int s32) {
+        emitString("setp.ne.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void setp_lt_s32(Register a, int s32) {
+        emitString("setp.lt.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void setp_le_s32(Register a, int s32) {
+        emitString("setp.le.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void setp_gt_s32(Register a, int s32) {
+        emitString("setp.gt.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void setp_ge_s32(Register a, int s32) {
+        emitString("setp.ge.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void setp_eq_s32(int s32, Register b) {
+        emitString("setp.eq.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ne_s32(int s32, Register b) {
+        emitString("setp.ne.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_lt_s32(int s32, Register b) {
+        emitString("setp.lt.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_le_s32(int s32, Register b) {
+        emitString("setp.le.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_gt_s32(int s32, Register b) {
+        emitString("setp.gt.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ge_s32(int s32, Register b) {
+        emitString("setp.ge.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_u32(Register a, Register b) {
+        emitString("setp.eq.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ne_u32(Register a, Register b) {
+        emitString("setp.ne.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_lt_u32(Register a, Register b) {
+        emitString("setp.lt.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_le_u32(Register a, Register b) {
+        emitString("setp.le.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_gt_u32(Register a, Register b) {
+        emitString("setp.gt.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ge_u32(Register a, Register b) {
+        emitString("setp.ge.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_eq_u32(Register a, int u32) {
+        emitString("setp.eq.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void setp_ne_u32(Register a, int u32) {
+        emitString("setp.ne.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void setp_lt_u32(Register a, int u32) {
+        emitString("setp.lt.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void setp_le_u32(Register a, int u32) {
+        emitString("setp.le.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void setp_gt_u32(Register a, int u32) {
+        emitString("setp.gt.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void setp_ge_u32(Register a, int u32) {
+        emitString("setp.ge.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void setp_eq_u32(int u32, Register b) {
+        emitString("setp.eq.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ne_u32(int u32, Register b) {
+        emitString("setp.ne.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_lt_u32(int u32, Register b) {
+        emitString("setp.lt.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_le_u32(int u32, Register b) {
+        emitString("setp.le.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_gt_u32(int u32, Register b) {
+        emitString("setp.gt.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void setp_ge_u32(int u32, Register b) {
+        emitString("setp.ge.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shr_s16(Register d, Register a, Register b) {
+        emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shr_s32(Register d, Register a, Register b) {
+        emitString("shr.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shr_s64(Register d, Register a, Register b) {
+        emitString("shr.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shr_s16(Register d, Register a, int u32) {
+        emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shr_s32(Register d, Register a, int u32) {
+        emitString("shr.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shr_s64(Register d, Register a, int u32) {
+        emitString("shr.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shr_u16(Register d, Register a, Register b) {
+        emitString("shr.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shr_u32(Register d, Register a, Register b) {
+        emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shr_u64(Register d, Register a, Register b) {
+        emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void shr_u16(Register d, Register a, int u32) {
+        emitString("shr.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shr_u32(Register d, Register a, int u32) {
+        emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void shr_u64(Register d, Register a, int u32) {
+        emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
+    }
+
+    public final void st_global_b8(Register a, long immOff, Register b) {
+        emitString("st.global.b8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_b16(Register a, long immOff, Register b) {
+        emitString("st.global.b16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_b32(Register a, long immOff, Register b) {
+        emitString("st.global.b32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_b64(Register a, long immOff, Register b) {
+        emitString("st.global.b64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_u8(Register a, long immOff, Register b) {
+        emitString("st.global.u8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_u16(Register a, long immOff, Register b) {
+        emitString("st.global.u16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_u32(Register a, long immOff, Register b) {
+        emitString("st.global.u32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_u64(Register a, long immOff, Register b) {
+        emitString("st.global.u64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_s8(Register a, long immOff, Register b) {
+        emitString("st.global.s8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_s16(Register a, long immOff, Register b) {
+        emitString("st.global.s16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_s32(Register a, long immOff, Register b) {
+        emitString("st.global.s32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_s64(Register a, long immOff, Register b) {
+        emitString("st.global.s64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_f32(Register a, long immOff, Register b) {
+        emitString("st.global.f32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void st_global_f64(Register a, long immOff, Register b) {
+        emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
+    }
+
+    public final void sub_s16(Register d, Register a, Register b) {
+        emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void sub_s32(Register d, Register a, Register b) {
+        emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void sub_s64(Register d, Register a, Register b) {
+        emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void sub_s16(Register d, Register a, short s16) {
+        emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
+    }
+
+    public final void sub_s32(Register d, Register a, int s32) {
+        emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void sub_s64(Register d, Register a, long s64) {
+        emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
+    }
+
+    public final void sub_s16(Register d, short s16, Register b) {
+        emitString("sub.s16" + " " + "%r" + d.encoding() + ", " + s16 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void sub_s32(Register d, int s32, Register b) {
+        emitString("sub.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void sub_s64(Register d, long s64, Register b) {
+        emitString("sub.s64" + " " + "%r" + d.encoding() + ", " + s64 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void sub_sat_s32(Register d, Register a, Register b) {
+        emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    }
+
+    public final void sub_sat_s32(Register d, Register a, int s32) {
+        emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
+    }
+
+    public final void sub_sat_s32(Register d, int s32, Register b) {
+        emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + "");
+    }
+
+    @Override
+    public PTXAddress makeAddress(Register base, int displacement) {
+        return new PTXAddress(base, displacement);
+    }
+
+    @Override
+    public PTXAddress getPlaceholder() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Thu Mar 21 14:11:13 2013 +0100
@@ -54,7 +54,14 @@
     }
 
     @Override
-    public void bangStack(int disp) {
-        // SPARC: Implement stack banging.
+    public AbstractAddress makeAddress(Register base, int displacement) {
+        // SPARC: Implement address calculation.
+        return null;
+    }
+
+    @Override
+    public AbstractAddress getPlaceholder() {
+        // SPARC: Implement address patching.
+        return null;
     }
 }
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -47,22 +47,21 @@
 
     protected InstalledCode assembleMethod(Method m, CodeGenTest test) {
         ResolvedJavaMethod method = codeCache.lookupJavaMethod(m);
-        RegisterConfig registerConfig = codeCache.lookupRegisterConfig(method);
+        RegisterConfig registerConfig = codeCache.lookupRegisterConfig();
+        CallingConvention cc = CodeUtil.getCallingConvention(codeCache, CallingConvention.Type.JavaCallee, method, false);
 
         CompilationResult compResult = new CompilationResult();
-
-        Signature sig = method.getSignature();
-        JavaType retType = sig.getReturnType(null);
-        JavaType[] argTypes = new JavaType[sig.getParameterCount(false)];
-        for (int i = 0; i < argTypes.length; i++) {
-            argTypes[i] = sig.getParameterType(i, null);
-        }
-        CallingConvention cc = registerConfig.getCallingConvention(CallingConvention.Type.JavaCallee, retType, argTypes, codeCache.getTarget(), false);
-
         Buffer codeBuffer = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
         compResult.setTargetCode(codeBuffer.close(true), codeBuffer.position());
 
-        return codeCache.addMethod(method, compResult, null);
+        InstalledCode code = codeCache.addMethod(method, compResult);
+
+        DisassemblerProvider dis = Graal.getRuntime().getCapability(DisassemblerProvider.class);
+        if (dis != null) {
+            String disasm = dis.disassemble(code);
+            Assert.assertTrue(String.valueOf(code.getMethod()), disasm == null || disasm.length() > 0);
+        }
+        return code;
     }
 
     protected Object runTest(String methodName, CodeGenTest test, Object... args) {
@@ -73,6 +72,6 @@
 
     protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) {
         Object actual = runTest(methodName, test, args);
-        Assert.assertEquals("unexpected return value: " + actual, actual, expected);
+        Assert.assertEquals("unexpected return value", expected, actual);
     }
 }
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java	Thu Mar 21 14:11:13 2013 +0100
@@ -44,7 +44,7 @@
         }
     }
 
-    public final void bind(Label l) {
+    public void bind(Label l) {
         assert !l.isBound() : "can bind label only once";
         l.bind(codeBuffer.position());
         l.patchInstructions(this);
@@ -56,14 +56,6 @@
 
     protected abstract void patchJumpTarget(int branch, int jumpTarget);
 
-    /**
-     * Emits instruction(s) that access an address specified by a given displacement from the stack
-     * pointer in the direction that the stack grows (which is down on most architectures).
-     * 
-     * @param disp the displacement from the stack pointer at which the stack should be accessed
-     */
-    public abstract void bangStack(int disp);
-
     protected final void emitByte(int x) {
         codeBuffer.emitByte(x);
     }
@@ -79,4 +71,27 @@
     protected final void emitLong(long x) {
         codeBuffer.emitLong(x);
     }
+
+    /**
+     * Some GPU architectures have a text based encoding.
+     */
+    protected final void emitString(String x) {
+        codeBuffer.emitString(x);
+    }
+
+    // XXX for pretty-printing
+    protected final void emitString0(String x) {
+        codeBuffer.emitString0(x);
+    }
+
+    /**
+     * This is used by the TargetMethodAssembler to convert a {@link StackSlot} to an
+     * {@link AbstractAddress}.
+     */
+    public abstract AbstractAddress makeAddress(Register base, int displacement);
+
+    /**
+     * Returns a target specific placeholder address that can be used for code patching.
+     */
+    public abstract AbstractAddress getPlaceholder();
 }
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java	Thu Mar 21 14:11:13 2013 +0100
@@ -37,10 +37,6 @@
         data = new byte[AsmOptions.InitialCodeBufferSize];
     }
 
-    public void reset() {
-        position = 0;
-    }
-
     public int position() {
         return position;
     }
@@ -106,6 +102,27 @@
         position = emitLong(b, position);
     }
 
+    private static final String NEWLINE = System.getProperty("line.separator");
+
+    public void emitString(String s) {
+        position = emitString("\t", position);  // XXX REMOVE ME pretty-printing
+        position = emitString(s, position);
+        position = emitString(NEWLINE, position);
+    }
+
+    // XXX for pretty-printing
+    public void emitString0(String s) {
+        emitBytes(s.getBytes(), 0, s.length());
+    }
+
+    public int emitBytes(byte[] arr, int pos) {
+        final int len = arr.length;
+        final int newPos = pos + len;
+        ensureSize(newPos);
+        System.arraycopy(arr, 0, data, pos, len);
+        return newPos;
+    }
+
     public int emitByte(int b, int pos) {
         assert NumUtil.isUByte(b);
         int newPos = pos + 1;
@@ -120,6 +137,10 @@
 
     public abstract int emitLong(long b, int pos);
 
+    public int emitString(String s, int pos) {
+        return emitBytes(s.getBytes(), pos);
+    }
+
     public int getByte(int pos) {
         return data[pos] & 0xff;
     }
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/Bytecodes.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/Bytecodes.java	Thu Mar 21 14:11:13 2013 +0100
@@ -226,7 +226,7 @@
     public static final int INVOKESPECIAL        = 183; // 0xB7
     public static final int INVOKESTATIC         = 184; // 0xB8
     public static final int INVOKEINTERFACE      = 185; // 0xB9
-    public static final int XXXUNUSEDXXX         = 186; // 0xBA
+    public static final int INVOKEDYNAMIC        = 186; // 0xBA
     public static final int NEW                  = 187; // 0xBB
     public static final int NEWARRAY             = 188; // 0xBC
     public static final int ANEWARRAY            = 189; // 0xBD
@@ -552,7 +552,7 @@
         def(INVOKESPECIAL       , "invokespecial"   , "bjj"  , 5, TRAP | INVOKE);
         def(INVOKESTATIC        , "invokestatic"    , "bjj"  , 5, TRAP | INVOKE);
         def(INVOKEINTERFACE     , "invokeinterface" , "bjja_", 7, TRAP | INVOKE);
-        def(XXXUNUSEDXXX        , "xxxunusedxxx"    , ""     , 0);
+        def(INVOKEDYNAMIC       , "invokedynamic"   , "bjjjj", 7, TRAP | INVOKE);
         def(NEW                 , "new"             , "bii"  , 6, TRAP);
         def(NEWARRAY            , "newarray"        , "bc"   , 6, TRAP);
         def(ANEWARRAY           , "anewarray"       , "bii"  , 6, TRAP);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64AllocatorTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.amd64.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.backend.*;
+
+public class AMD64AllocatorTest extends AllocatorTest {
+
+    @Test
+    public void test1() {
+        test("test1snippet", 3, 1, 0);
+    }
+
+    public static long test1snippet(long x) {
+        return x + 5;
+    }
+
+    @Test
+    public void test2() {
+        test("test2snippet", 3, 0, 0);
+    }
+
+    public static long test2snippet(long x) {
+        return x * 5;
+    }
+
+    @Ignore
+    @Test
+    public void test3() {
+        test("test3snippet", 4, 1, 0);
+    }
+
+    public static long test3snippet(long x) {
+        return x / 3 + x % 3;
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.amd64;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.RuntimeCallTarget.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
-import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.phases.*;
-
-public class AMD64DeoptimizationStub extends AMD64Code {
-
-    public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, void.class);
-    public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", true, void.class, Object.class);
-
-    public final Label label = new Label();
-    public final LIRFrameState info;
-    public final DeoptimizationAction action;
-    public final DeoptimizationReason reason;
-    public final Object deoptInfo;
-
-    public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) {
-        this.action = action;
-        this.reason = reason;
-        this.info = info;
-        this.deoptInfo = deoptInfo;
-    }
-
-    private static ArrayList<Object> keepAlive = new ArrayList<>();
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        Register scratch = tasm.frameMap.registerConfig.getScratchRegister();
-
-        masm.bind(label);
-        if (GraalOptions.CreateDeoptInfo && deoptInfo != null) {
-            masm.nop();
-            keepAlive.add(deoptInfo.toString());
-            AMD64Move.move(tasm, masm, scratch.asValue(), Constant.forObject(deoptInfo));
-            AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(SET_DEOPT_INFO), info);
-        }
-
-        masm.movl(scratch, tasm.runtime.encodeDeoptActionAndReason(action, reason));
-        AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(DEOPTIMIZE), info);
-        AMD64Call.shouldNotReachHere(tasm, masm);
-    }
-
-    @Override
-    public String description() {
-        return "deopt stub[reason=" + reason + ", action=" + action + "]";
-    }
-}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,8 +25,8 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*;
+import static com.oracle.graal.lir.amd64.AMD64BitManipulationOp.IntrinsicOpcode.*;
 import static com.oracle.graal.lir.amd64.AMD64Compare.*;
-import static com.oracle.graal.lir.amd64.AMD64BitManipulationOp.IntrinsicOpcode.*;
 import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.*;
 
 import com.oracle.graal.amd64.*;
@@ -34,21 +34,22 @@
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
-import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivOp;
-import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Reg;
-import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Stack;
-import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Reg;
-import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Stack;
-import com.oracle.graal.lir.amd64.AMD64Arithmetic.ShiftOp;
 import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
-import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryCommutative;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegConst;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegReg;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegStack;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegStackConst;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivRemOp;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary1Op;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2Op;
 import com.oracle.graal.lir.amd64.AMD64Compare.CompareOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
@@ -64,12 +65,11 @@
 import com.oracle.graal.lir.amd64.AMD64Move.MembarOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp;
-import com.oracle.graal.lir.amd64.AMD64Move.NullCheckOp;
-import com.oracle.graal.lir.amd64.AMD64Move.SpillMoveOp;
+import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.util.*;
 
@@ -91,7 +91,7 @@
 
         @Override
         public LIRInstruction createMove(Value result, Value input) {
-            return new SpillMoveOp(result, input);
+            return AMD64LIRGenerator.createMove(result, input);
         }
     }
 
@@ -137,110 +137,138 @@
     }
 
     @Override
-    public Address makeAddress(LocationNode location, ValueNode object) {
-        Value base = operand(object);
-        Value index = Value.ILLEGAL;
-        int scale = 1;
-        int displacement = location.displacement();
+    public Variable emitMove(Value input) {
+        Variable result = newVariable(input.getKind());
+        emitMove(result, input);
+        return result;
+    }
 
+    private static AMD64LIRInstruction createMove(Value dst, Value src) {
+        if (isRegister(src) || isStackSlot(dst)) {
+            return new MoveFromRegOp(dst, src);
+        } else {
+            return new MoveToRegOp(dst, src);
+        }
+    }
+
+    @Override
+    public void emitMove(Value dst, Value src) {
+        append(createMove(dst, src));
+    }
+
+    private AMD64AddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) {
+        AllocatableValue baseRegister;
+        int finalDisp = displacement;
         if (isConstant(base)) {
             if (asConstant(base).isNull()) {
-                base = Value.ILLEGAL;
+                baseRegister = AllocatableValue.UNUSED;
             } else if (asConstant(base).getKind() != Kind.Object) {
                 long newDisplacement = displacement + asConstant(base).asLong();
                 if (NumUtil.isInt(newDisplacement)) {
                     assert !runtime.needsDataPatch(asConstant(base));
-                    displacement = (int) newDisplacement;
-                    base = Value.ILLEGAL;
+                    finalDisp = (int) newDisplacement;
+                    baseRegister = AllocatableValue.UNUSED;
                 } else {
-                    Value newBase = newVariable(Kind.Long);
-                    emitMove(base, newBase);
-                    base = newBase;
+                    Variable newBase = newVariable(Kind.Long);
+                    emitMove(newBase, base);
+                    baseRegister = newBase;
                 }
+            } else {
+                baseRegister = load(base);
             }
+        } else if (base == Value.ILLEGAL) {
+            baseRegister = AllocatableValue.UNUSED;
+        } else {
+            baseRegister = asAllocatable(base);
         }
 
-        if (location instanceof IndexedLocationNode) {
-            IndexedLocationNode indexedLoc = (IndexedLocationNode) location;
-
-            index = operand(indexedLoc.index());
-            if (indexedLoc.indexScalingEnabled()) {
-                scale = target().sizeInBytes(location.getValueKind());
-            }
+        AllocatableValue indexRegister;
+        Scale scaleEnum;
+        if (index != Value.ILLEGAL && scale != 0) {
+            scaleEnum = Scale.fromInt(scale);
             if (isConstant(index)) {
-                long newDisplacement = displacement + asConstant(index).asLong() * scale;
+                long newDisplacement = finalDisp + asConstant(index).asLong() * scale;
                 // only use the constant index if the resulting displacement fits into a 32 bit
                 // offset
                 if (NumUtil.isInt(newDisplacement)) {
-                    displacement = (int) newDisplacement;
-                    index = Value.ILLEGAL;
+                    finalDisp = (int) newDisplacement;
+                    indexRegister = AllocatableValue.UNUSED;
                 } else {
                     // create a temporary variable for the index, the pointer load cannot handle a
                     // constant index
-                    Value newIndex = newVariable(Kind.Long);
-                    emitMove(index, newIndex);
-                    index = newIndex;
+                    Variable newIndex = newVariable(Kind.Long);
+                    emitMove(newIndex, index);
+                    indexRegister = newIndex;
                 }
+            } else {
+                indexRegister = asAllocatable(index);
             }
+        } else {
+            indexRegister = AllocatableValue.UNUSED;
+            scaleEnum = Scale.Times1;
         }
 
-        return new Address(location.getValueKind(), base, index, Address.Scale.fromInt(scale), displacement);
+        return new AMD64AddressValue(kind, baseRegister, indexRegister, scaleEnum, finalDisp);
     }
 
     @Override
-    public Variable emitMove(Value input) {
-        Variable result = newVariable(input.getKind());
-        emitMove(input, result);
-        return result;
-    }
-
-    @Override
-    public void emitMove(Value src, Value dst) {
-        if (isRegister(src) || isStackSlot(dst)) {
-            append(new MoveFromRegOp(dst, src));
-        } else {
-            append(new MoveToRegOp(dst, src));
-        }
-    }
-
-    @Override
-    public Variable emitLoad(Value loadAddress, boolean canTrap) {
+    public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
+        AMD64AddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale);
         Variable result = newVariable(loadAddress.getKind());
         append(new LoadOp(result, loadAddress, canTrap ? state() : null));
         return result;
     }
 
     @Override
-    public void emitStore(Value storeAddress, Value inputVal, boolean canTrap) {
-        Value input = loadForStore(inputVal, storeAddress.getKind());
-        append(new StoreOp(storeAddress, input, canTrap ? state() : null));
+    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) {
+        AMD64AddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale);
+        LIRFrameState state = canTrap ? state() : null;
+
+        if (isConstant(inputVal)) {
+            Constant c = asConstant(inputVal);
+            if (canStoreConstant(c)) {
+                append(new StoreConstantOp(storeAddress, c, state));
+                return;
+            }
+        }
+
+        Variable input = load(inputVal);
+        append(new StoreOp(storeAddress, input, state));
     }
 
     @Override
-    public Variable emitLea(Value address) {
+    public Variable emitLea(Value base, int displacement, Value index, int scale) {
         Variable result = newVariable(target().wordKind);
+        AMD64AddressValue address = prepareAddress(result.getKind(), base, displacement, index, scale);
         append(new LeaOp(result, address));
         return result;
     }
 
     @Override
-    public void emitJump(LabelRef label, LIRFrameState info) {
-        append(new JumpOp(label, info));
+    public Variable emitLea(StackSlot address) {
+        Variable result = newVariable(target().wordKind);
+        append(new StackLeaOp(result, address));
+        return result;
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
+    public void emitJump(LabelRef label) {
+        append(new JumpOp(label));
+    }
+
+    @Override
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         switch (left.getKind().getStackKind()) {
             case Int:
             case Long:
             case Object:
-                append(new BranchOp(finalCondition, label, info));
+                append(new BranchOp(finalCondition, label));
                 break;
             case Float:
             case Double:
-                append(new FloatBranchOp(finalCondition, unorderedIsTrue, label, info));
+                append(new FloatBranchOp(finalCondition, unorderedIsTrue, label));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -248,9 +276,14 @@
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) {
+    public void emitOverflowCheckBranch(LabelRef destination, boolean negated) {
+        append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, destination));
+    }
+
+    @Override
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
         emitIntegerTest(left, right);
-        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label, info));
+        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label));
     }
 
     @Override
@@ -314,7 +347,6 @@
             mirrored = false;
         }
         switch (left.getKind().getStackKind()) {
-            case Jsr:
             case Int:
                 append(new CompareOp(ICMP, left, right));
                 break;
@@ -337,42 +369,29 @@
     }
 
     @Override
-    public Variable emitNegate(Value input) {
+    public void emitNullCheck(ValueNode v) {
+        assert v.kind() == Kind.Object;
+        Variable obj = newVariable(Kind.Object);
+        emitMove(obj, operand(v));
+        append(new AMD64Move.NullCheckOp(obj, state()));
+    }
+
+    @Override
+    public Variable emitNegate(Value inputVal) {
+        AllocatableValue input = asAllocatable(inputVal);
         Variable result = newVariable(input.getKind());
         switch (input.getKind()) {
             case Int:
-                append(new Op1Stack(INEG, result, input));
+                append(new Unary1Op(INEG, result, input));
                 break;
             case Long:
-                append(new Op1Stack(LNEG, result, input));
+                append(new Unary1Op(LNEG, result, input));
                 break;
             case Float:
-                append(new Op2Reg(FXOR, result, input, Constant.forFloat(Float.intBitsToFloat(0x80000000))));
+                append(new BinaryRegConst(FXOR, result, input, Constant.forFloat(Float.intBitsToFloat(0x80000000))));
                 break;
             case Double:
-                append(new Op2Reg(DXOR, result, input, Constant.forDouble(Double.longBitsToDouble(0x8000000000000000L))));
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-        return result;
-    }
-
-    @Override
-    public Variable emitAdd(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
-            case Int:
-                append(new Op2Stack(IADD, result, a, loadNonConst(b)));
-                break;
-            case Long:
-                append(new Op2Stack(LADD, result, a, loadNonConst(b)));
-                break;
-            case Float:
-                append(new Op2Stack(FADD, result, a, loadNonConst(b)));
-                break;
-            case Double:
-                append(new Op2Stack(DADD, result, a, loadNonConst(b)));
+                append(new BinaryRegConst(DXOR, result, input, Constant.forDouble(Double.longBitsToDouble(0x8000000000000000L))));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -380,48 +399,104 @@
         return result;
     }
 
-    @Override
-    public Variable emitSub(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
-            case Int:
-                append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
+    private Variable emitBinary(AMD64Arithmetic op, boolean commutative, Value a, Value b) {
+        if (isConstant(b)) {
+            return emitBinaryConst(op, commutative, asAllocatable(a), asConstant(b));
+        } else if (commutative && isConstant(a)) {
+            return emitBinaryConst(op, commutative, asAllocatable(b), asConstant(a));
+        } else {
+            return emitBinaryVar(op, commutative, asAllocatable(a), asAllocatable(b));
+        }
+    }
+
+    private Variable emitBinaryConst(AMD64Arithmetic op, boolean commutative, AllocatableValue a, Constant b) {
+        switch (op) {
+            case IADD:
+            case LADD:
+            case ISUB:
+            case LSUB:
+            case IAND:
+            case LAND:
+            case IOR:
+            case LOR:
+            case IXOR:
+            case LXOR:
+                if (NumUtil.isInt(b.asLong())) {
+                    Variable result = newVariable(a.getKind());
+                    append(new BinaryRegConst(op, result, a, b));
+                    return result;
+                }
                 break;
-            case Long:
-                append(new Op2Stack(LSUB, result, a, loadNonConst(b)));
-                break;
-            case Float:
-                append(new Op2Stack(FSUB, result, a, loadNonConst(b)));
+
+            case IMUL:
+            case LMUL:
+                if (NumUtil.isInt(b.asLong())) {
+                    Variable result = newVariable(a.getKind());
+                    append(new BinaryRegStackConst(op, result, a, b));
+                    return result;
+                }
                 break;
-            case Double:
-                append(new Op2Stack(DSUB, result, a, loadNonConst(b)));
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
+        }
+
+        return emitBinaryVar(op, commutative, a, asAllocatable(b));
+    }
+
+    private Variable emitBinaryVar(AMD64Arithmetic op, boolean commutative, AllocatableValue a, AllocatableValue b) {
+        Variable result = newVariable(a.getKind());
+        if (commutative) {
+            append(new BinaryCommutative(op, result, a, b));
+        } else {
+            append(new BinaryRegStack(op, result, a, b));
         }
         return result;
     }
 
     @Override
-    public Variable emitMul(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+    public Variable emitAdd(Value a, Value b) {
         switch (a.getKind()) {
             case Int:
-                append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
-                break;
+                return emitBinary(IADD, true, a, b);
             case Long:
-                append(new Op2Reg(LMUL, result, a, loadNonConst(b)));
-                break;
+                return emitBinary(LADD, true, a, b);
             case Float:
-                append(new Op2Stack(FMUL, result, a, loadNonConst(b)));
-                break;
+                return emitBinary(FADD, true, a, b);
             case Double:
-                append(new Op2Stack(DMUL, result, a, loadNonConst(b)));
-                break;
+                return emitBinary(DADD, true, a, b);
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        return result;
+    }
+
+    @Override
+    public Variable emitSub(Value a, Value b) {
+        switch (a.getKind()) {
+            case Int:
+                return emitBinary(ISUB, false, a, b);
+            case Long:
+                return emitBinary(LSUB, false, a, b);
+            case Float:
+                return emitBinary(FSUB, false, a, b);
+            case Double:
+                return emitBinary(DSUB, false, a, b);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Variable emitMul(Value a, Value b) {
+        switch (a.getKind()) {
+            case Int:
+                return emitBinary(IMUL, true, a, b);
+            case Long:
+                return emitBinary(LMUL, true, a, b);
+            case Float:
+                return emitBinary(FMUL, true, a, b);
+            case Double:
+                return emitBinary(DMUL, true, a, b);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
     }
 
     @Override
@@ -451,15 +526,19 @@
         return false;
     }
 
+    private void emitDivRem(AMD64Arithmetic op, Value a, Value b) {
+        AllocatableValue rax = AMD64.rax.asValue(a.getKind());
+        emitMove(rax, a);
+        append(new DivRemOp(op, rax, asAllocatable(b), state()));
+    }
+
     public Value[] emitIntegerDivRem(Value a, Value b) {
         switch (a.getKind()) {
             case Int:
-                emitMove(a, RAX_I);
-                append(new DivRemOp(IDIVREM, RAX_I, load(b), state()));
+                emitDivRem(IDIVREM, a, b);
                 return new Value[]{emitMove(RAX_I), emitMove(RDX_I)};
             case Long:
-                emitMove(a, RAX_L);
-                append(new DivRemOp(LDIVREM, RAX_L, load(b), state()));
+                emitDivRem(LDIVREM, a, b);
                 return new Value[]{emitMove(RAX_L), emitMove(RDX_L)};
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -470,21 +549,19 @@
     public Value emitDiv(Value a, Value b) {
         switch (a.getKind()) {
             case Int:
-                emitMove(a, RAX_I);
-                append(new DivOp(IDIV, RAX_I, RAX_I, load(b), state()));
+                emitDivRem(IDIV, a, b);
                 return emitMove(RAX_I);
             case Long:
-                emitMove(a, RAX_L);
-                append(new DivOp(LDIV, RAX_L, RAX_L, load(b), state()));
+                emitDivRem(LDIV, a, b);
                 return emitMove(RAX_L);
             case Float: {
                 Variable result = newVariable(a.getKind());
-                append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
+                append(new BinaryRegStack(FDIV, result, asAllocatable(a), asAllocatable(b)));
                 return result;
             }
             case Double: {
                 Variable result = newVariable(a.getKind());
-                append(new Op2Stack(DDIV, result, a, loadNonConst(b)));
+                append(new BinaryRegStack(DDIV, result, asAllocatable(a), asAllocatable(b)));
                 return result;
             }
             default:
@@ -496,12 +573,10 @@
     public Value emitRem(Value a, Value b) {
         switch (a.getKind()) {
             case Int:
-                emitMove(a, RAX_I);
-                append(new DivOp(IREM, RDX_I, RAX_I, load(b), state()));
+                emitDivRem(IREM, a, b);
                 return emitMove(RDX_I);
             case Long:
-                emitMove(a, RAX_L);
-                append(new DivOp(LREM, RDX_L, RAX_L, load(b), state()));
+                emitDivRem(LREM, a, b);
                 return emitMove(RDX_L);
             case Float: {
                 RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_FREM);
@@ -520,12 +595,10 @@
     public Variable emitUDiv(Value a, Value b) {
         switch (a.getKind()) {
             case Int:
-                emitMove(a, RAX_I);
-                append(new DivOp(IUDIV, RAX_I, RAX_I, load(b), state()));
+                emitDivRem(IUDIV, a, b);
                 return emitMove(RAX_I);
             case Long:
-                emitMove(a, RAX_L);
-                append(new DivOp(LUDIV, RAX_L, RAX_L, load(b), state()));
+                emitDivRem(LUDIV, a, b);
                 return emitMove(RAX_L);
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -536,12 +609,10 @@
     public Variable emitURem(Value a, Value b) {
         switch (a.getKind()) {
             case Int:
-                emitMove(a, RAX_I);
-                append(new DivOp(IUREM, RDX_I, RAX_I, load(b), state()));
+                emitDivRem(IUREM, a, b);
                 return emitMove(RDX_I);
             case Long:
-                emitMove(a, RAX_L);
-                append(new DivOp(LUREM, RDX_L, RAX_L, load(b), state()));
+                emitDivRem(LUREM, a, b);
                 return emitMove(RDX_L);
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -550,107 +621,86 @@
 
     @Override
     public Variable emitAnd(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(IAND, result, a, loadNonConst(b)));
-                break;
+                return emitBinary(IAND, true, a, b);
             case Long:
-                append(new Op2Stack(LAND, result, a, loadNonConst(b)));
-                break;
+                return emitBinary(LAND, true, a, b);
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        return result;
     }
 
     @Override
     public Variable emitOr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(IOR, result, a, loadNonConst(b)));
-                break;
+                return emitBinary(IOR, true, a, b);
             case Long:
-                append(new Op2Stack(LOR, result, a, loadNonConst(b)));
-                break;
+                return emitBinary(LOR, true, a, b);
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        return result;
     }
 
     @Override
     public Variable emitXor(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new Op2Stack(IXOR, result, a, loadNonConst(b)));
-                break;
+                return emitBinary(IXOR, true, a, b);
             case Long:
-                append(new Op2Stack(LXOR, result, a, loadNonConst(b)));
-                break;
+                return emitBinary(LXOR, true, a, b);
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
+    }
+
+    private Variable emitShift(AMD64Arithmetic op, Value a, Value b) {
+        Variable result = newVariable(a.getKind());
+        AllocatableValue input = asAllocatable(a);
+        if (isConstant(b)) {
+            append(new BinaryRegConst(op, result, input, asConstant(b)));
+        } else {
+            emitMove(RCX_I, b);
+            append(new BinaryRegReg(op, result, input, RCX_I));
+        }
         return result;
     }
 
     @Override
     public Variable emitShl(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new ShiftOp(ISHL, result, a, loadShiftCount(b)));
-                break;
+                return emitShift(ISHL, a, b);
             case Long:
-                append(new ShiftOp(LSHL, result, a, loadShiftCount(b)));
-                break;
+                return emitShift(LSHL, a, b);
             default:
-                GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
-        return result;
     }
 
     @Override
     public Variable emitShr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new ShiftOp(ISHR, result, a, loadShiftCount(b)));
-                break;
+                return emitShift(ISHR, a, b);
             case Long:
-                append(new ShiftOp(LSHR, result, a, loadShiftCount(b)));
-                break;
+                return emitShift(LSHR, a, b);
             default:
-                GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
-        return result;
     }
 
     @Override
     public Variable emitUShr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
-                append(new ShiftOp(IUSHR, result, a, loadShiftCount(b)));
-                break;
+                return emitShift(IUSHR, a, b);
             case Long:
-                append(new ShiftOp(LUSHR, result, a, loadShiftCount(b)));
-                break;
+                return emitShift(LUSHR, a, b);
             default:
-                GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere();
         }
-        return result;
-    }
-
-    private Value loadShiftCount(Value value) {
-        if (isConstant(value)) {
-            return value;
-        }
-        // Non-constant shift count must be in RCX
-        emitMove(value, RCX_I);
-        return RCX_I;
     }
 
     @Override
@@ -659,67 +709,67 @@
         Variable result = newVariable(opcode.to);
         switch (opcode) {
             case I2L:
-                append(new Op1Reg(I2L, result, input));
+                append(new Unary2Op(I2L, result, input));
                 break;
             case L2I:
-                append(new Op1Stack(L2I, result, input));
+                append(new Unary1Op(L2I, result, input));
                 break;
             case I2B:
-                append(new Op1Stack(I2B, result, input));
+                append(new Unary2Op(I2B, result, input));
                 break;
             case I2C:
-                append(new Op1Stack(I2C, result, input));
+                append(new Unary1Op(I2C, result, input));
                 break;
             case I2S:
-                append(new Op1Stack(I2S, result, input));
+                append(new Unary2Op(I2S, result, input));
                 break;
             case F2D:
-                append(new Op1Reg(F2D, result, input));
+                append(new Unary2Op(F2D, result, input));
                 break;
             case D2F:
-                append(new Op1Reg(D2F, result, input));
+                append(new Unary2Op(D2F, result, input));
                 break;
             case I2F:
-                append(new Op1Reg(I2F, result, input));
+                append(new Unary2Op(I2F, result, input));
                 break;
             case I2D:
-                append(new Op1Reg(I2D, result, input));
+                append(new Unary2Op(I2D, result, input));
                 break;
             case F2I:
-                append(new Op1Reg(F2I, result, input));
+                append(new Unary2Op(F2I, result, input));
                 break;
             case D2I:
-                append(new Op1Reg(D2I, result, input));
+                append(new Unary2Op(D2I, result, input));
                 break;
             case L2F:
-                append(new Op1Reg(L2F, result, input));
+                append(new Unary2Op(L2F, result, input));
                 break;
             case L2D:
-                append(new Op1Reg(L2D, result, input));
+                append(new Unary2Op(L2D, result, input));
                 break;
             case F2L:
-                append(new Op1Reg(F2L, result, input));
+                append(new Unary2Op(F2L, result, input));
                 break;
             case D2L:
-                append(new Op1Reg(D2L, result, input));
+                append(new Unary2Op(D2L, result, input));
                 break;
             case MOV_I2F:
-                append(new Op1Reg(MOV_I2F, result, input));
+                append(new Unary2Op(MOV_I2F, result, input));
                 break;
             case MOV_L2D:
-                append(new Op1Reg(MOV_L2D, result, input));
+                append(new Unary2Op(MOV_L2D, result, input));
                 break;
             case MOV_F2I:
-                append(new Op1Reg(MOV_F2I, result, input));
+                append(new Unary2Op(MOV_F2I, result, input));
                 break;
             case MOV_D2L:
-                append(new Op1Reg(MOV_D2L, result, input));
+                append(new Unary2Op(MOV_D2L, result, input));
                 break;
             case UNSIGNED_I2L:
                 // Instructions that move or generate 32-bit register values also set the upper 32
                 // bits of the register to zero.
                 // Consequently, there is no need for a special zero-extension move.
-                emitMove(input, result);
+                emitMove(result, input);
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -728,20 +778,6 @@
     }
 
     @Override
-    public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) {
-        LIRFrameState info = state();
-        LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
-        append(new BranchOp(ConditionFlag.overflow, stubEntry, info));
-    }
-
-    @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) {
-        LIRFrameState info = state();
-        LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
-        append(new JumpOp(stubEntry, info));
-    }
-
-    @Override
     public void emitMembar(int barriers) {
         int necessaryBarriers = target.arch.requiredBarriers(barriers);
         if (target.isMP && necessaryBarriers != 0) {
@@ -750,54 +786,42 @@
     }
 
     @Override
-    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        append(new DirectCallOp(callTarget.target(), result, parameters, temps, callState));
-    }
+    protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
 
-    @Override
-    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        // The current register allocator cannot handle variables at call sites, need a fixed
-        // register.
-        Value targetAddress = AMD64.rax.asValue();
-        emitMove(operand(callTarget.computedAddress()), targetAddress);
-        append(new IndirectCallOp(callTarget.target(), result, parameters, temps, targetAddress, callState));
-    }
-
-    @Override
-    protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info) {
-        if (isConstant(targetAddress)) {
-            append(new DirectCallOp(callTarget, result, arguments, temps, info));
+        long maxOffset = callTarget.getMaxCallTargetOffset();
+        if (maxOffset != (int) maxOffset) {
+            append(new AMD64Call.DirectFarRuntimeCallOp(this, callTarget, result, arguments, temps, info));
         } else {
-            append(new IndirectCallOp(callTarget, result, arguments, temps, targetAddress, info));
+            append(new AMD64Call.DirectNearRuntimeCallOp(callTarget, result, arguments, temps, info));
         }
     }
 
     @Override
     public void emitBitCount(Variable result, Value value) {
         if (value.getKind().getStackKind() == Kind.Int) {
-            append(new AMD64BitManipulationOp(IPOPCNT, result, value));
+            append(new AMD64BitManipulationOp(IPOPCNT, result, asAllocatable(value)));
         } else {
-            append(new AMD64BitManipulationOp(LPOPCNT, result, value));
+            append(new AMD64BitManipulationOp(LPOPCNT, result, asAllocatable(value)));
         }
     }
 
     @Override
     public void emitBitScanForward(Variable result, Value value) {
-        append(new AMD64BitManipulationOp(BSF, result, value));
+        append(new AMD64BitManipulationOp(BSF, result, asAllocatable(value)));
     }
 
     @Override
     public void emitBitScanReverse(Variable result, Value value) {
         if (value.getKind().getStackKind() == Kind.Int) {
-            append(new AMD64BitManipulationOp(IBSR, result, value));
+            append(new AMD64BitManipulationOp(IBSR, result, asAllocatable(value)));
         } else {
-            append(new AMD64BitManipulationOp(LBSR, result, value));
+            append(new AMD64BitManipulationOp(LBSR, result, asAllocatable(value)));
         }
     }
 
     @Override
     public void emitMathAbs(Variable result, Variable input) {
-        append(new Op2Reg(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL))));
+        append(new BinaryRegConst(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL))));
     }
 
     @Override
@@ -861,21 +885,6 @@
     }
 
     @Override
-    protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) {
-        assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate";
-        AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info, deoptInfo);
-        lir.stubs.add(stub);
-        return LabelRef.forLabel(stub.label);
-    }
-
-    @Override
-    protected void emitNullCheckGuard(ValueNode object) {
-        Variable value = load(operand(object));
-        LIRFrameState info = state();
-        append(new NullCheckOp(value, info));
-    }
-
-    @Override
     public void visitCompareAndSwap(CompareAndSwapNode node) {
         Kind kind = node.newValue().kind();
         assert kind == node.expected().kind();
@@ -883,19 +892,19 @@
         Value expected = loadNonConst(operand(node.expected()));
         Variable newValue = load(operand(node.newValue()));
 
-        Address address;
+        AMD64AddressValue address;
         int displacement = node.displacement();
         Value index = operand(node.offset());
         if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) {
             assert !runtime.needsDataPatch(asConstant(index));
             displacement += (int) asConstant(index).asLong();
-            address = new Address(kind, load(operand(node.object())), displacement);
+            address = new AMD64AddressValue(kind, load(operand(node.object())), displacement);
         } else {
-            address = new Address(kind, load(operand(node.object())), load(index), Address.Scale.Times1, displacement);
+            address = new AMD64AddressValue(kind, load(operand(node.object())), load(index), Scale.Times1, displacement);
         }
 
         RegisterValue rax = AMD64.rax.asValue(kind);
-        emitMove(expected, rax);
+        emitMove(rax, expected);
         append(new CompareAndSwapOp(rax, address, rax, newValue));
 
         Variable result = newVariable(node.kind());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.ptx.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.ptx.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.PhasePlan.*;
+import com.oracle.graal.ptx.*;
+
+/**
+ * Test class for small Java methods compiled to PTX kernels.
+ */
+public class BasicPTXTest extends GraalCompilerTest {
+
+    @Test
+    public void testAdd() {
+        test("testAddSnippet");
+    }
+
+    public static int testAddSnippet(int a) {
+        return a + 1;
+    }
+
+    @Test
+    public void testArray() {
+        test("testArraySnippet");
+    }
+
+    public static int testArraySnippet(int[] array) {
+        return array[0];
+    }
+
+    private void test(String snippet) {
+        StructuredGraph graph = parse(snippet);
+        Debug.dump(graph, "Graph");
+        TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true);
+        PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(CodeCacheProvider.class), target);
+        PhasePlan phasePlan = new PhasePlan();
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase());
+        new PTXPhase().apply(graph);
+        CompilationResult result = GraalCompiler.compileMethod(runtime, ptxBackend, target, graph.method(), graph, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog());
+        System.out.println("result=" + result);
+    }
+
+    private static class PTXPhase extends Phase {
+
+        @Override
+        protected void run(StructuredGraph graph) {
+            System.out.println("PTX phase");
+            for (LocalNode local : graph.getNodes(LocalNode.class)) {
+                if (local.kind() == Kind.Object) {
+                    local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type()));
+                }
+            }
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.ptx;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * PTX specific backend.
+ */
+public class PTXBackend extends Backend {
+
+    public PTXBackend(CodeCacheProvider runtime, TargetDescription target) {
+        super(runtime, target);
+    }
+
+    @Override
+    public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
+        return new PTXLIRGenerator(graph, runtime(), target, frameMap, method, lir);
+    }
+
+    class HotSpotFrameContext implements FrameContext {
+
+        @Override
+        public void enter(TargetMethodAssembler tasm) {
+            Buffer codeBuffer = tasm.asm.codeBuffer;
+            codeBuffer.emitString(".version 1.4");
+            codeBuffer.emitString(".target sm_10");
+            // codeBuffer.emitString(".address_size 32"); // PTX ISA version 2.3
+        }
+
+        @Override
+        public void leave(TargetMethodAssembler tasm) {
+        }
+    }
+
+    @Override
+    public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
+        // Omit the frame if the method:
+        // - has no spill slots or other slots allocated during register allocation
+        // - has no callee-saved registers
+        // - has no incoming arguments passed on the stack
+        // - has no instructions with debug info
+        FrameMap frameMap = lirGen.frameMap;
+        AbstractAssembler masm = new PTXAssembler(target, frameMap.registerConfig);
+        HotSpotFrameContext frameContext = new HotSpotFrameContext();
+        TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult);
+        tasm.setFrameSize(frameMap.frameSize());
+        return tasm;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen) {
+        // Emit the prologue
+        final String name = method.getName();
+        Buffer codeBuffer = tasm.asm.codeBuffer;
+        codeBuffer.emitString0(".entry " + name + " (");
+        codeBuffer.emitString("");
+
+        Signature signature = method.getSignature();
+        for (int i = 0; i < signature.getParameterCount(false); i++) {
+            System.err.println(i + ": " + signature.getParameterKind(i));
+            String param = ".param .u32 param" + i;
+            codeBuffer.emitString(param);
+        }
+
+        codeBuffer.emitString0(") {");
+        codeBuffer.emitString("");
+
+        // XXX For now declare one predicate and all registers
+        codeBuffer.emitString("  .reg .pred %p;");
+        codeBuffer.emitString("  .reg .u32 %r<16>;");
+
+        // Emit code for the LIR
+        lirGen.lir.emitCode(tasm);
+
+        // Emit the epilogue
+        codeBuffer.emitString0("}");
+        codeBuffer.emitString("");
+
+        byte[] data = codeBuffer.copyData(0, codeBuffer.position());
+        System.err.println(new String(data));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.graal.compiler.ptx;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.ptx.PTXArithmetic.*;
+import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*;
+import static com.oracle.graal.lir.ptx.PTXCompare.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.JumpOp;
+import com.oracle.graal.lir.ptx.*;
+import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack;
+import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg;
+import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack;
+import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp;
+import com.oracle.graal.lir.ptx.PTXCompare.CompareOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp;
+import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp;
+import com.oracle.graal.lir.ptx.PTXMove.LoadOp;
+import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp;
+import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp;
+import com.oracle.graal.lir.ptx.PTXMove.StoreOp;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * This class implements the PTX specific portion of the LIR generator.
+ */
+public class PTXLIRGenerator extends LIRGenerator {
+
+    public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory {
+
+        @Override
+        public LIRInstruction createMove(Value result, Value input) {
+            throw new InternalError("NYI");
+        }
+    }
+
+    public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
+        super(graph, runtime, target, frameMap, method, lir);
+        lir.spillMoveFactory = new PTXSpillMoveFactory();
+    }
+
+    @Override
+    protected void emitNode(ValueNode node) {
+        if (node instanceof LIRGenLowerable) {
+            ((LIRGenLowerable) node).generate(this);
+        } else {
+            super.emitNode(node);
+        }
+    }
+
+    @Override
+    public boolean canStoreConstant(Constant c) {
+        // Operand b must be in the .reg state space.
+        return false;
+    }
+
+    @Override
+    public boolean canInlineConstant(Constant c) {
+        switch (c.getKind()) {
+            case Long:
+                return NumUtil.isInt(c.asLong()) && !runtime.needsDataPatch(c);
+            case Object:
+                return c.isNull();
+            default:
+                return true;
+        }
+    }
+
+    @Override
+    public Variable emitMove(Value input) {
+        Variable result = newVariable(input.getKind());
+        emitMove(result, input);
+        return result;
+    }
+
+    @Override
+    public void emitMove(Value dst, Value src) {
+        if (isRegister(src) || isStackSlot(dst)) {
+            append(new MoveFromRegOp(dst, src));
+        } else {
+            append(new MoveToRegOp(dst, src));
+        }
+    }
+
+    private PTXAddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) {
+        AllocatableValue baseRegister;
+        long finalDisp = displacement;
+        if (isConstant(base)) {
+            if (asConstant(base).isNull()) {
+                baseRegister = AllocatableValue.UNUSED;
+            } else if (asConstant(base).getKind() != Kind.Object) {
+                finalDisp += asConstant(base).asLong();
+                baseRegister = AllocatableValue.UNUSED;
+            } else {
+                baseRegister = load(base);
+            }
+        } else if (base == Value.ILLEGAL) {
+            baseRegister = AllocatableValue.UNUSED;
+        } else {
+            baseRegister = asAllocatable(base);
+        }
+
+        if (index != Value.ILLEGAL) {
+            if (isConstant(index)) {
+                finalDisp += asConstant(index).asLong() * scale;
+            } else {
+                Value indexRegister;
+                if (scale != 1) {
+                    indexRegister = emitMul(index, Constant.forInt(scale));
+                } else {
+                    indexRegister = index;
+                }
+
+                if (baseRegister == AllocatableValue.UNUSED) {
+                    baseRegister = asAllocatable(indexRegister);
+                } else {
+                    baseRegister = emitAdd(baseRegister, indexRegister);
+                }
+            }
+        }
+
+        return new PTXAddressValue(kind, baseRegister, finalDisp);
+    }
+
+    @Override
+    public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
+        PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale);
+        Variable result = newVariable(loadAddress.getKind());
+        append(new LoadOp(result, loadAddress, canTrap ? state() : null));
+        return result;
+    }
+
+    @Override
+    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) {
+        PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale);
+        Variable input = load(inputVal);
+        append(new StoreOp(storeAddress, input, canTrap ? state() : null));
+    }
+
+    @Override
+    public Variable emitLea(Value base, int displacement, Value index, int scale) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitLea(StackSlot address) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitJump(LabelRef label) {
+        append(new JumpOp(label));
+    }
+
+    @Override
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
+        switch (left.getKind().getStackKind()) {
+            case Int:
+                append(new CompareOp(ICMP, cond, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            case Object:
+                append(new CompareOp(ACMP, cond, left, right));
+                append(new BranchOp(cond, label));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("" + left.getKind());
+        }
+    }
+
+    @Override
+    public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitNegate(Value input) {
+        Variable result = newVariable(input.getKind());
+        switch (input.getKind()) {
+            case Int:
+                append(new Op1Stack(INEG, result, input));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitAdd(Value a, Value b) {
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(IADD, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitSub(Value a, Value b) {
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitMul(Value a, Value b) {
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    @Override
+    protected boolean peephole(ValueNode valueNode) {
+        // No peephole optimizations for now
+        return false;
+    }
+
+    @Override
+    public Value emitDiv(Value a, Value b) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Value emitRem(Value a, Value b) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitUDiv(Value a, Value b) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitURem(Value a, Value b) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitAnd(Value a, Value b) {
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new Op2Stack(IAND, result, a, loadNonConst(b)));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitOr(Value a, Value b) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitXor(Value a, Value b) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitShl(Value a, Value b) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitShr(Value a, Value b) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public Variable emitUShr(Value a, Value b) {
+        Variable result = newVariable(a.getKind());
+        switch (a.getKind()) {
+            case Int:
+                append(new ShiftOp(IUSHR, result, a, b));
+                break;
+            default:
+                GraalInternalError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
+        append(new ReturnOp(Value.ILLEGAL));
+    }
+
+    @Override
+    public void emitMembar(int barriers) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitBitCount(Variable result, Value value) {
+        if (value.getKind().getStackKind() == Kind.Int) {
+            append(new PTXBitManipulationOp(IPOPCNT, result, value));
+        } else {
+            append(new PTXBitManipulationOp(LPOPCNT, result, value));
+        }
+    }
+
+    @Override
+    public void emitBitScanForward(Variable result, Value value) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitBitScanReverse(Variable result, Value value) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitMathAbs(Variable result, Variable input) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitMathSqrt(Variable result, Variable input) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitMathLog(Variable result, Variable input, boolean base10) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitMathCos(Variable result, Variable input) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitMathSin(Variable result, Variable input) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitMathTan(Variable result, Variable input) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitByteSwap(Variable result, Value input) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    protected void emitReturn(Value input) {
+        append(new ReturnOp(input));
+    }
+
+    @Override
+    protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void visitCompareAndSwap(CompareAndSwapNode node) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void visitBreakpointNode(BreakpointNode node) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void visitExceptionObject(ExceptionObjectNode i) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void visitSafepointNode(SafepointNode i) {
+        throw new InternalError("NYI");
+    }
+
+    @Override
+    public void emitUnwind(Value operand) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitNullCheck(ValueNode v) {
+        throw new InternalError("NYI");
+    }
+}
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -31,7 +31,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.ConvertNode.Op;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 
 /**
@@ -63,13 +62,7 @@
     }
 
     @Override
-    protected void emitNullCheckGuard(ValueNode object) {
-        // SPARC: Auto-generated method stub
-
-    }
-
-    @Override
-    public void emitJump(LabelRef label, LIRFrameState info) {
+    public void emitJump(LabelRef label) {
         @SuppressWarnings("unused")
         SPARCLIRInstruction instruction = null;
         // SPARC: Auto-generated method stub
@@ -77,13 +70,19 @@
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
         // SPARC: Auto-generated method stub
 
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) {
+    public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
         // SPARC: Auto-generated method stub
 
     }
@@ -113,18 +112,12 @@
     }
 
     @Override
-    protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info) {
+    protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
         // SPARC: Auto-generated method stub
 
     }
 
     @Override
-    protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) {
-        // SPARC: Auto-generated method stub
-        return null;
-    }
-
-    @Override
     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
         // SPARC: Auto-generated method stub
 
@@ -215,31 +208,31 @@
     }
 
     @Override
-    public Address makeAddress(LocationNode location, ValueNode object) {
-        // SPARC: Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void emitMove(Value src, Value dst) {
+    public void emitMove(Value dst, Value src) {
         // SPARC: Auto-generated method stub
 
     }
 
     @Override
-    public Value emitLoad(Value loadAddress, boolean canTrap) {
+    public Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
         // SPARC: Auto-generated method stub
         return null;
     }
 
     @Override
-    public void emitStore(Value storeAddress, Value input, boolean canTrap) {
+    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, boolean canTrap) {
         // SPARC: Auto-generated method stub
 
     }
 
     @Override
-    public Value emitLea(Value address) {
+    public Value emitLea(Value base, int displacement, Value index, int scale) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Value emitLea(StackSlot address) {
         // SPARC: Auto-generated method stub
         return null;
     }
@@ -341,13 +334,7 @@
     }
 
     @Override
-    public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) {
-        // SPARC: Auto-generated method stub
-
-    }
-
-    @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) {
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
         // SPARC: Auto-generated method stub
 
     }
@@ -375,4 +362,16 @@
         // SPARC: Auto-generated method stub
 
     }
+
+    @Override
+    public void emitUnwind(Value operand) {
+        // SPARC: Auto-generated method stub
+
+    }
+
+    @Override
+    public void emitNullCheck(ValueNode v) {
+        // SPARC: Auto-generated method stub
+
+    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -126,13 +126,13 @@
                 }
 
                 Assumptions assumptions = new Assumptions(false);
-                new InliningPhase(null, runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
-                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+                new InliningPhase(runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
                 Debug.dump(graph, "Graph");
                 new BoxingEliminationPhase(runtime()).apply(graph);
                 Debug.dump(graph, "Graph");
                 new ExpandBoxingNodesPhase(pool).apply(graph);
-                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 StructuredGraph referenceGraph = parse(referenceSnippet);
                 assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -35,7 +35,7 @@
 
     private StructuredGraph getCanonicalizedGraph(String name) {
         StructuredGraph graph = parse(name);
-        new CanonicalizerPhase(null, runtime(), null).apply(graph);
+        new CanonicalizerPhase(runtime(), null).apply(graph);
         return graph;
     }
 
@@ -53,7 +53,7 @@
             assertEquals(referenceGraph, graph);
         }
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
         for (int i = 1; i < 4; i++) {
             StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i);
             assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.test;
-
-import java.lang.reflect.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.InstalledCode.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.java.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-
-/**
- * In the following tests, the usages of local variable "a" are replaced with the integer constant
- * 0. Then canonicalization is applied and it is verified that the resulting graph is equal to the
- * graph of the method that just has a "return 1" statement in it.
- */
-public class CompiledMethodTest extends GraalCompilerTest {
-
-    public static Object testMethod(Object arg1, Object arg2, Object arg3) {
-        return arg1 + " " + arg2 + " " + arg3;
-    }
-
-    Object f1;
-
-    public Object testMethodVirtual(Object arg1, Object arg2, Object arg3) {
-        return f1 + " " + arg1 + " " + arg2 + " " + arg3;
-    }
-
-    @Test
-    public void test1() {
-        Method method = getMethod("testMethod");
-        final StructuredGraph graph = parse(method);
-        new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph);
-        new DeadCodeEliminationPhase().apply(graph);
-
-        for (Node node : graph.getNodes()) {
-            if (node instanceof ConstantNode) {
-                ConstantNode constant = (ConstantNode) node;
-                if (constant.kind() == Kind.Object && " ".equals(constant.value.asObject())) {
-                    graph.replaceFloating(constant, ConstantNode.forObject("-", runtime, graph));
-                }
-            }
-        }
-
-        final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
-        InstalledCode compiledMethod = getCode(javaMethod, graph);
-        try {
-            Object result = compiledMethod.execute("1", "2", "3");
-            Assert.assertEquals("1-2-3", result);
-        } catch (MethodInvalidatedException t) {
-            Assert.fail("method invalidated");
-        }
-    }
-
-    @Test
-    public void test3() {
-        Method method = getMethod("testMethod");
-        final StructuredGraph graph = parse(method);
-        final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
-        InstalledCode compiledMethod = getCode(javaMethod, graph);
-        try {
-            Object result = compiledMethod.executeVarargs("1", "2", "3");
-            Assert.assertEquals("1 2 3", result);
-        } catch (MethodInvalidatedException t) {
-            Assert.fail("method invalidated");
-        }
-    }
-
-    @Test
-    public void test4() {
-        Method method = getMethod("testMethodVirtual");
-        final StructuredGraph graph = parse(method);
-        final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
-        InstalledCode compiledMethod = getCode(javaMethod, graph);
-        try {
-            f1 = "0";
-            Object result = compiledMethod.executeVarargs(this, "1", "2", "3");
-            Assert.assertEquals("0 1 2 3", result);
-        } catch (MethodInvalidatedException t) {
-            Assert.fail("method invalidated");
-        }
-    }
-
-    @Test
-    public void test2() throws NoSuchMethodException, SecurityException {
-        Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class);
-        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
-        StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph);
-        new CanonicalizerPhase(null, runtime, new Assumptions(false)).apply(graph);
-        new DeadCodeEliminationPhase().apply(graph);
-
-        for (Node node : graph.getNodes()) {
-            if (node instanceof ConstantNode) {
-                ConstantNode constant = (ConstantNode) node;
-                if (constant.kind() == Kind.Object && "1 ".equals(constant.value.asObject())) {
-                    graph.replaceFloating(constant, ConstantNode.forObject("1-", runtime, graph));
-                }
-            }
-        }
-
-        InstalledCode compiledMethod = getCode(javaMethod, graph);
-        final CompilableObject compilableObject = new CompilableObjectImpl(0);
-
-        Object result;
-        result = compilableObject.execute(new ObjectCompilerImpl(compiledMethod), "3");
-        Assert.assertEquals("1-3", result);
-    }
-
-    public abstract class CompilableObject {
-
-        private CompiledObject compiledObject;
-        private final int compileThreshold;
-        private int counter;
-
-        public CompilableObject(int compileThreshold) {
-            this.compileThreshold = compileThreshold;
-        }
-
-        public final Object execute(ObjectCompiler compiler, String args) {
-            if (counter++ < compileThreshold || compiler == null) {
-                return executeHelper(compiler, args);
-            } else {
-                compiledObject = compiler.compile(this);
-                return compiledObject.execute(compiler, args);
-            }
-        }
-
-        protected abstract Object executeHelper(ObjectCompiler context, String args);
-    }
-
-    private final class CompilableObjectImpl extends CompilableObject {
-
-        private CompilableObjectImpl(int compileThreshold) {
-            super(compileThreshold);
-        }
-
-        @Override
-        protected Object executeHelper(ObjectCompiler compiler, String args) {
-            return "1 " + args;
-        }
-    }
-
-    public interface CompiledObject {
-
-        Object execute(ObjectCompiler context, String args);
-    }
-
-    public interface ObjectCompiler {
-
-        CompiledObject compile(CompilableObject node);
-    }
-
-    private final class ObjectCompilerImpl implements ObjectCompiler {
-
-        private final InstalledCode compiledMethod;
-
-        private ObjectCompilerImpl(InstalledCode compiledMethod) {
-            this.compiledMethod = compiledMethod;
-        }
-
-        @Override
-        public CompiledObject compile(final CompilableObject node) {
-            return new CompiledObject() {
-
-                @Override
-                public Object execute(ObjectCompiler compiler, String args) {
-                    return compiledMethod.execute(node, compiler, args);
-                }
-            };
-        }
-    }
-}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -84,7 +84,7 @@
                 for (Invoke invoke : graph.getInvokes()) {
                     invoke.intrinsify(null);
                 }
-                new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph);
+                new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
                 StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
                 Debug.dump(referenceGraph, "Graph");
                 assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,6 +32,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
@@ -67,12 +68,12 @@
 public abstract class GraalCompilerTest extends GraalTest {
 
     protected final GraalCodeCacheProvider runtime;
-    protected final GraalCompiler graalCompiler;
+    protected final Backend backend;
 
     public GraalCompilerTest() {
         DebugEnvironment.initialize(System.out);
         this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class);
-        this.graalCompiler = Graal.getRequiredCapability(GraalCompiler.class);
+        this.backend = Graal.getRequiredCapability(Backend.class);
     }
 
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
@@ -220,7 +221,7 @@
         return method.invoke(receiver, args);
     }
 
-    static class Result {
+    protected static class Result {
 
         final Object returnValue;
         final Throwable exception;
@@ -262,7 +263,10 @@
         before();
         Object[] executeArgs = argsWithReceiver(receiver, args);
 
-        InstalledCode compiledMethod = getCode(runtime.lookupJavaMethod(method), parse(method));
+        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
+        checkArgs(javaMethod, executeArgs);
+
+        InstalledCode compiledMethod = getCode(javaMethod, parse(method));
         try {
             return new Result(compiledMethod.executeVarargs(executeArgs), null);
         } catch (Throwable e) {
@@ -272,6 +276,25 @@
         }
     }
 
+    protected void checkArgs(ResolvedJavaMethod method, Object[] args) {
+        JavaType[] sig = MetaUtil.signatureToTypes(method);
+        Assert.assertEquals(sig.length, args.length);
+        for (int i = 0; i < args.length; i++) {
+            JavaType javaType = sig[i];
+            Kind kind = javaType.getKind();
+            Object arg = args[i];
+            if (kind == Kind.Object) {
+                if (arg != null && javaType instanceof ResolvedJavaType) {
+                    ResolvedJavaType resolvedJavaType = (ResolvedJavaType) javaType;
+                    Assert.assertTrue(resolvedJavaType + " from " + runtime.lookupJavaType(arg.getClass()), resolvedJavaType.isAssignableFrom(runtime.lookupJavaType(arg.getClass())));
+                }
+            } else {
+                Assert.assertNotNull(arg);
+                Assert.assertEquals(kind.toBoxedJavaClass(), arg.getClass());
+            }
+        }
+    }
+
     /**
      * Prepends a non-null receiver argument to a given list or args.
      * 
@@ -295,18 +318,28 @@
         Method method = getMethod(name);
         Object receiver = Modifier.isStatic(method.getModifiers()) ? null : this;
 
+        test(method, receiver, args);
+    }
+
+    protected void test(Method method, Object receiver, Object... args) {
         Result expect = executeExpected(method, receiver, args);
         if (runtime == null) {
             return;
         }
+        test(method, expect, receiver, args);
+    }
+
+    protected void test(Method method, Result expect, Object receiver, Object... args) {
         Result actual = executeActual(method, receiver, args);
 
         if (expect.exception != null) {
             Assert.assertTrue("expected " + expect.exception, actual.exception != null);
             Assert.assertEquals(expect.exception.getClass(), actual.exception.getClass());
         } else {
-            // System.out.println(name + "(" + Arrays.toString(args) + "): expected=" +
-            // expect.returnValue + ", actual=" + actual.returnValue);
+            if (actual.exception != null) {
+                actual.exception.printStackTrace();
+                Assert.fail("expected " + expect.returnValue + " but got an exception");
+            }
             assertEquals(expect.returnValue, actual.returnValue);
         }
     }
@@ -342,8 +375,6 @@
             if (cached != null) {
                 if (cached.isValid()) {
                     return cached;
-                } else {
-                    // System.out.println(cached.getMethod() + " was invalidated");
                 }
 
             }
@@ -351,7 +382,7 @@
 
         final int id = compilationId++;
 
-        InstalledCode installedCode = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true), new Callable<InstalledCode>() {
+        InstalledCode installedCode = Debug.scope("Compiling", new Object[]{runtime, new DebugDumpScope(String.valueOf(id), true)}, new Callable<InstalledCode>() {
 
             public InstalledCode call() throws Exception {
                 final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed();
@@ -363,7 +394,7 @@
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                 editPhasePlan(method, graph, phasePlan);
-                CompilationResult compResult = graalCompiler.compileMethod(method, graph, null, phasePlan, OptimisticOptimizations.ALL);
+                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog());
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
                 }
@@ -378,17 +409,16 @@
     }
 
     protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) {
-        assert graalCompiler != null;
-        return Debug.scope("CodeInstall", new Object[]{graalCompiler, method}, new Callable<InstalledCode>() {
+        return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable<InstalledCode>() {
 
             @Override
             public InstalledCode call() throws Exception {
-                final CodeInfo[] info = Debug.isDumpEnabled() ? new CodeInfo[1] : null;
-                InstalledCode installedMethod = runtime.addMethod(method, compResult, info);
-                if (info != null) {
-                    Debug.dump(new Object[]{compResult, info[0]}, "After code installation");
+                InstalledCode installedCode = runtime.addMethod(method, compResult);
+                if (Debug.isDumpEnabled()) {
+                    Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
-                return installedMethod;
+
+                return installedCode;
             }
         });
     }
@@ -408,7 +438,7 @@
     protected StructuredGraph parse(Method m) {
         ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m);
         StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.ALL).apply(graph);
+        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
         return graph;
     }
 
@@ -424,7 +454,7 @@
 
     protected PhasePlan getDefaultPhasePlan() {
         PhasePlan plan = new PhasePlan();
-        plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.ALL));
+        plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL));
         return plan;
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -89,19 +89,19 @@
                 }
 
                 Assumptions assumptions = new Assumptions(false);
-                new InliningPhase(null, runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
-                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+                new InliningPhase(runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
                 new PhiStampPhase().apply(graph);
-                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
                 Debug.dump(graph, "Graph");
                 new BoxingEliminationPhase(runtime()).apply(graph);
                 Debug.dump(graph, "Graph");
                 new ExpandBoxingNodesPhase(pool).apply(graph);
-                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
-                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
-                new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph);
+                new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
                 new DeadCodeEliminationPhase().apply(referenceGraph);
 
                 assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -144,7 +144,7 @@
             n.replaceFirstInput(local, constant);
         }
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -65,8 +65,8 @@
             hints.add(invoke);
         }
         Assumptions assumptions = new Assumptions(false);
-        new InliningPhase(null, runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new InliningPhase(runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -76,8 +76,8 @@
         }
 
         Assumptions assumptions = new Assumptions(false);
-        new InliningPhase(null, runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new InliningPhase(runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -133,8 +133,8 @@
         }
 
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
         Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() {
 
             @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import static org.junit.Assert.*;
+
+import java.util.concurrent.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.schedule.*;
+
+/**
+ * In these test the FrameStates are explicitly cleared out, so that the scheduling of
+ * FloatingReadNodes depends solely on the scheduling algorithm. The FrameStates normally keep the
+ * FloatingReadNodes above a certain point, so that they (most of the time...) magically do the
+ * right thing.
+ * 
+ * The scheduling shouldn't depend on FrameStates, which is tested by this class.
+ */
+public class MemoryScheduleTest extends GraphScheduleTest {
+
+    private static enum TestMode {
+        WITH_FRAMESTATES, WITHOUT_FRAMESTATES, INLINED_WITHOUT_FRAMESTATES
+    }
+
+    public static class Container {
+
+        public int a;
+        public int b;
+        public int c;
+    }
+
+    private static final Container container = new Container();
+
+    /**
+     * In this test the read should be scheduled before the write.
+     */
+    public static int testSimpleSnippet() {
+        try {
+            return container.a;
+        } finally {
+            container.a = 15;
+        }
+    }
+
+    @Test
+    public void testSimple() {
+        for (TestMode mode : TestMode.values()) {
+            SchedulePhase schedule = getFinalSchedule("testSimpleSnippet", mode);
+            assertReadAfterWrite(schedule, false);
+        }
+    }
+
+    /**
+     * In this case the read should be scheduled in the first block.
+     */
+    public static int testSplitSnippet1(int a) {
+        try {
+            return container.a;
+        } finally {
+            if (a < 0) {
+                container.a = 15;
+            } else {
+                container.b = 15;
+            }
+        }
+    }
+
+    @Test
+    public void testSplit1() {
+        for (TestMode mode : TestMode.values()) {
+            SchedulePhase schedule = getFinalSchedule("testSplitSnippet1", mode);
+            assertReadWithinStartBlock(schedule, true);
+        }
+    }
+
+    /**
+     * Here the read should float to the end.
+     */
+    public static int testSplit2Snippet(int a) {
+        try {
+            return container.a;
+        } finally {
+            if (a < 0) {
+                container.c = 15;
+            } else {
+                container.b = 15;
+            }
+        }
+    }
+
+    @Test
+    public void testSplit2() {
+        SchedulePhase schedule = getFinalSchedule("testSplit2Snippet", TestMode.WITHOUT_FRAMESTATES);
+        assertReadWithinStartBlock(schedule, false);
+    }
+
+    /**
+     * Here the read should not float to the end.
+     */
+    public static int testLoop1Snippet(int a, int b) {
+        try {
+            return container.a;
+        } finally {
+            for (int i = 0; i < a; i++) {
+                if (b < 0) {
+                    container.b = 10;
+                } else {
+                    container.a = 15;
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testLoop1() {
+        SchedulePhase schedule = getFinalSchedule("testLoop1Snippet", TestMode.WITHOUT_FRAMESTATES);
+        assertEquals(7, schedule.getCFG().getBlocks().length);
+        assertReadWithinStartBlock(schedule, true);
+    }
+
+    /**
+     * Here the read should float to the end.
+     */
+    public static int testLoop2Snippet(int a, int b) {
+        try {
+            return container.a;
+        } finally {
+            for (int i = 0; i < a; i++) {
+                if (b < 0) {
+                    container.b = 10;
+                } else {
+                    container.c = 15;
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testLoop2() {
+        SchedulePhase schedule = getFinalSchedule("testLoop2Snippet", TestMode.WITHOUT_FRAMESTATES);
+        assertEquals(7, schedule.getCFG().getBlocks().length);
+        assertReadWithinStartBlock(schedule, false);
+    }
+
+    /**
+     * Here the read should float to the end (into the same block as the return).
+     */
+    public static int testArrayCopySnippet(Integer intValue, char[] a, char[] b, int len) {
+        System.arraycopy(a, 0, b, 0, len);
+        return intValue.intValue();
+    }
+
+    @Test
+    public void testArrayCopy() {
+        SchedulePhase schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES);
+        StructuredGraph graph = (StructuredGraph) schedule.getCFG().getStartBlock().getBeginNode().graph();
+        ReturnNode ret = graph.getNodes(ReturnNode.class).first();
+        assertTrue(ret.result() instanceof FloatingReadNode);
+        assertEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result()));
+    }
+
+    private void assertReadAfterWrite(SchedulePhase schedule, boolean readAfterWrite) {
+        boolean writeEncountered = false;
+        assertEquals(1, schedule.getCFG().getBlocks().length);
+        for (Node node : schedule.getBlockToNodesMap().get(schedule.getCFG().getStartBlock())) {
+            if (node instanceof WriteNode) {
+                writeEncountered = true;
+            } else if (node instanceof FloatingReadNode) {
+                assertEquals(readAfterWrite, writeEncountered);
+            }
+        }
+    }
+
+    private void assertReadWithinStartBlock(SchedulePhase schedule, boolean withinStartBlock) {
+        boolean readEncountered = false;
+        for (Node node : schedule.getBlockToNodesMap().get(schedule.getCFG().getStartBlock())) {
+            if (node instanceof FloatingReadNode) {
+                readEncountered = true;
+            }
+        }
+        assertEquals(withinStartBlock, readEncountered);
+    }
+
+    private SchedulePhase getFinalSchedule(final String snippet, final TestMode mode) {
+        return Debug.scope("FloatingReadTest", new DebugDumpScope(snippet), new Callable<SchedulePhase>() {
+
+            @Override
+            public SchedulePhase call() throws Exception {
+                StructuredGraph graph = parse(snippet);
+                if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
+                    Assumptions assumptions = new Assumptions(false);
+                    new InliningPhase(runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+                }
+                new LoweringPhase(null, runtime(), new Assumptions(false)).apply(graph);
+                if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
+                    for (Node node : graph.getNodes()) {
+                        if (node instanceof StateSplit) {
+                            FrameState stateAfter = ((StateSplit) node).stateAfter();
+                            if (stateAfter != null) {
+                                ((StateSplit) node).setStateAfter(null);
+                                GraphUtil.killWithUnusedFloatingInputs(stateAfter);
+                            }
+                        }
+                    }
+                }
+                new FloatingReadPhase().apply(graph);
+
+                new RemoveValueProxyPhase().apply(graph);
+
+                SchedulePhase schedule = new SchedulePhase();
+                schedule.apply(graph);
+                return schedule;
+            }
+        });
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -54,7 +54,7 @@
         return 1;
     }
 
-    @Test(expected = AssertionError.class)
+    @Test
     public void test1() {
         test("test1Snippet");
     }
@@ -93,8 +93,8 @@
             hints.add(invoke);
         }
         Assumptions assumptions = new Assumptions(false);
-        new InliningPhase(null, runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new InliningPhase(runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -244,9 +244,9 @@
     private <T extends Node & Node.IterableNodeType> void test(String test, String ref) {
         StructuredGraph testGraph = parse(test);
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(testGraph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(testGraph);
         StructuredGraph refGraph = parse(ref);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(refGraph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(refGraph);
         assertEquals(testGraph, refGraph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -165,11 +165,10 @@
         // No debug scope to reduce console noise for @Test(expected = ...) tests
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
-        // TypeSystemTest.outputGraph(graph);
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -98,7 +98,7 @@
 
     private void testZeroReturn(String methodName) {
         StructuredGraph graph = parse(methodName);
-        new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         assertConstantReturn(graph, 0);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -89,7 +89,7 @@
         // No debug scope to reduce console noise for @Test(expected = ...) tests
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph);
+        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -186,13 +186,13 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
         // a second canonicalizer is needed to process nested MaterializeNodes
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph);
         assertEquals(referenceGraph, graph);
     }
 
@@ -242,9 +242,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+        new CanonicalizerPhase(runtime(), assumptions).apply(graph);
         Debug.dump(graph, "Graph");
         Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext());
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test.backend;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+import com.oracle.graal.lir.StandardOp.MoveOp;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.phases.*;
+
+public class AllocatorTest extends GraalCompilerTest {
+
+    protected void test(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) {
+        final StructuredGraph graph = parse(snippet);
+        Debug.scope("AllocatorTest", new Object[]{graph, graph.method(), runtime}, new Runnable() {
+
+            @Override
+            public void run() {
+                final RegisterStats stats = getRegisterStats(graph);
+
+                Debug.scope("Assertions", stats.lir, new Runnable() {
+
+                    @Override
+                    public void run() {
+                        Assert.assertEquals("register count", expectedRegisters, stats.registers.size());
+                        Assert.assertEquals("reg-reg moves", expectedRegRegMoves, stats.regRegMoves);
+                        Assert.assertEquals("spill moves", expectedSpillMoves, stats.spillMoves);
+                    }
+                });
+            }
+        });
+    }
+
+    private class RegisterStats {
+
+        public final LIR lir;
+        public HashSet<Register> registers = new HashSet<>();
+        public int regRegMoves;
+        public int spillMoves;
+
+        public RegisterStats(LIR lir) {
+            this.lir = lir;
+
+            for (Block block : lir.codeEmittingOrder()) {
+                for (LIRInstruction instr : lir.lir(block)) {
+                    collectStats(instr);
+                }
+            }
+        }
+
+        private void collectStats(final LIRInstruction instr) {
+            instr.forEachOutput(new ValueProcedure() {
+
+                @Override
+                public Value doValue(Value value) {
+                    if (ValueUtil.isRegister(value)) {
+                        final Register reg = ValueUtil.asRegister(value);
+                        registers.add(reg);
+                    }
+                    return value;
+                }
+            });
+
+            if (instr instanceof MoveOp) {
+                MoveOp move = (MoveOp) instr;
+                Value def = move.getResult();
+                Value use = move.getInput();
+                if (ValueUtil.isRegister(def)) {
+                    if (ValueUtil.isRegister(use) && ValueUtil.asRegister(def) != ValueUtil.asRegister(use)) {
+                        regRegMoves++;
+                    }
+                } else if (ValueUtil.isStackSlot(def)) {
+                    spillMoves++;
+                }
+            }
+        }
+    }
+
+    private RegisterStats getRegisterStats(final StructuredGraph graph) {
+        final PhasePlan phasePlan = getDefaultPhasePlan();
+        final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions);
+
+        final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
+
+            @Override
+            public LIR call() {
+                return GraalCompiler.emitHIR(runtime, backend.target, graph, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog());
+            }
+        });
+
+        return Debug.scope("BackEnd", lir, new Callable<RegisterStats>() {
+
+            @Override
+            public RegisterStats call() {
+                GraalCompiler.emitLIR(backend, backend.target, lir, graph, graph.method());
+                return new RegisterStats(lir);
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test.deopt;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.InstalledCode.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.test.*;
+
+/**
+ * In the following tests, the usages of local variable "a" are replaced with the integer constant
+ * 0. Then canonicalization is applied and it is verified that the resulting graph is equal to the
+ * graph of the method that just has a "return 1" statement in it.
+ */
+public class CompiledMethodTest extends GraalCompilerTest {
+
+    public static Object testMethod(Object arg1, Object arg2, Object arg3) {
+        return arg1 + " " + arg2 + " " + arg3;
+    }
+
+    Object f1;
+
+    public Object testMethodVirtual(Object arg1, Object arg2, Object arg3) {
+        return f1 + " " + arg1 + " " + arg2 + " " + arg3;
+    }
+
+    @LongTest
+    public void test1() {
+        Method method = getMethod("testMethod");
+        final StructuredGraph graph = parse(method);
+        new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph);
+        new DeadCodeEliminationPhase().apply(graph);
+
+        for (Node node : graph.getNodes()) {
+            if (node instanceof ConstantNode) {
+                ConstantNode constant = (ConstantNode) node;
+                if (constant.kind() == Kind.Object && " ".equals(constant.value.asObject())) {
+                    graph.replaceFloating(constant, ConstantNode.forObject("-", runtime, graph));
+                }
+            }
+        }
+
+        final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
+        InstalledCode compiledMethod = getCode(javaMethod, graph);
+        try {
+            Object result = compiledMethod.execute("1", "2", "3");
+            Assert.assertEquals("1-2-3", result);
+        } catch (MethodInvalidatedException t) {
+            Assert.fail("method invalidated");
+        }
+    }
+
+    @LongTest
+    public void test3() {
+        Method method = getMethod("testMethod");
+        final StructuredGraph graph = parse(method);
+        final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
+        InstalledCode compiledMethod = getCode(javaMethod, graph);
+        try {
+            Object result = compiledMethod.executeVarargs("1", "2", "3");
+            Assert.assertEquals("1 2 3", result);
+        } catch (MethodInvalidatedException t) {
+            Assert.fail("method invalidated");
+        }
+    }
+
+    @LongTest
+    public void test4() {
+        Method method = getMethod("testMethodVirtual");
+        final StructuredGraph graph = parse(method);
+        final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
+        InstalledCode compiledMethod = getCode(javaMethod, graph);
+        try {
+            f1 = "0";
+            Object result = compiledMethod.executeVarargs(this, "1", "2", "3");
+            Assert.assertEquals("0 1 2 3", result);
+        } catch (MethodInvalidatedException t) {
+            Assert.fail("method invalidated");
+        }
+    }
+
+    @LongTest
+    public void test2() throws NoSuchMethodException, SecurityException {
+        Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class);
+        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
+        StructuredGraph graph = new StructuredGraph(javaMethod);
+        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.NONE).apply(graph);
+        new CanonicalizerPhase(runtime, new Assumptions(false)).apply(graph);
+        new DeadCodeEliminationPhase().apply(graph);
+
+        for (Node node : graph.getNodes()) {
+            if (node instanceof ConstantNode) {
+                ConstantNode constant = (ConstantNode) node;
+                if (constant.kind() == Kind.Object && "1 ".equals(constant.value.asObject())) {
+                    graph.replaceFloating(constant, ConstantNode.forObject("1-", runtime, graph));
+                }
+            }
+        }
+
+        InstalledCode compiledMethod = getCode(javaMethod, graph);
+        final CompilableObject compilableObject = new CompilableObjectImpl(0);
+
+        Object result;
+        result = compilableObject.execute(new ObjectCompilerImpl(compiledMethod), "3");
+        Assert.assertEquals("1-3", result);
+    }
+
+    public abstract class CompilableObject {
+
+        private CompiledObject compiledObject;
+        private final int compileThreshold;
+        private int counter;
+
+        public CompilableObject(int compileThreshold) {
+            this.compileThreshold = compileThreshold;
+        }
+
+        public final Object execute(ObjectCompiler compiler, String args) {
+            if (counter++ < compileThreshold || compiler == null) {
+                return executeHelper(compiler, args);
+            } else {
+                compiledObject = compiler.compile(this);
+                return compiledObject.execute(compiler, args);
+            }
+        }
+
+        protected abstract Object executeHelper(ObjectCompiler context, String args);
+    }
+
+    private final class CompilableObjectImpl extends CompilableObject {
+
+        private CompilableObjectImpl(int compileThreshold) {
+            super(compileThreshold);
+        }
+
+        @Override
+        protected Object executeHelper(ObjectCompiler compiler, String args) {
+            return "1 " + args;
+        }
+    }
+
+    public interface CompiledObject {
+
+        Object execute(ObjectCompiler context, String args);
+    }
+
+    public interface ObjectCompiler {
+
+        CompiledObject compile(CompilableObject node);
+    }
+
+    private final class ObjectCompilerImpl implements ObjectCompiler {
+
+        private final InstalledCode compiledMethod;
+
+        private ObjectCompilerImpl(InstalledCode compiledMethod) {
+            this.compiledMethod = compiledMethod;
+        }
+
+        @Override
+        public CompiledObject compile(final CompilableObject node) {
+            return new CompiledObject() {
+
+                @Override
+                public Object execute(ObjectCompiler compiler, String args) {
+                    return compiledMethod.execute(node, compiler, args);
+                }
+            };
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test.deopt;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.InstalledCode.MethodInvalidatedException;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * In the following tests, we try to deoptimize out of synchronized methods.
+ */
+public class SynchronizedMethodDeoptimizationTest extends GraalCompilerTest {
+
+    public static final int N = 15000;
+
+    public static synchronized Object testMethodSynchronized(Object o) {
+        if (o == null) {
+            return null;
+        }
+        return o;
+    }
+
+    @Test
+    public void test1() {
+        Method method = getMethod("testMethodSynchronized");
+        String testString = "test";
+        for (int i = 0; i < N; ++i) {
+            Assert.assertEquals(testString, testMethodSynchronized(testString));
+        }
+        final StructuredGraph graph = parseProfiled(method);
+        final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
+        InstalledCode compiledMethod = getCode(javaMethod, graph);
+        try {
+            Object result = compiledMethod.executeVarargs(testString);
+            Assert.assertEquals(testString, result);
+        } catch (MethodInvalidatedException t) {
+            Assert.fail("method invalidated");
+        }
+
+        try {
+            Object result = compiledMethod.executeVarargs(new Object[]{null});
+            Assert.assertEquals(null, result);
+            Assert.assertFalse(compiledMethod.isValid());
+        } catch (MethodInvalidatedException t) {
+            Assert.fail("method invalidated");
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -205,9 +205,9 @@
             }
 
             Assumptions assumptions = new Assumptions(false);
-            new InliningPhase(null, runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+            new InliningPhase(runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
-            new PartialEscapeAnalysisPhase(null, runtime(), assumptions, iterativeEscapeAnalysis).apply(graph);
+            new PartialEscapeAnalysisPhase(runtime(), assumptions, iterativeEscapeAnalysis).apply(graph);
             Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
             ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
             if (expectedConstantResult != null) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -150,14 +150,14 @@
                 n.node().setProbability(100000);
             }
             Assumptions assumptions = new Assumptions(false);
-            new InliningPhase(null, runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+            new InliningPhase(runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
-            new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
-            new PartialEscapeAnalysisPhase(null, runtime(), assumptions, false).apply(graph);
+            new CanonicalizerPhase(runtime(), assumptions).apply(graph);
+            new PartialEscapeAnalysisPhase(runtime(), assumptions, false).apply(graph);
 
             new CullFrameStatesPhase().apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
-            new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+            new CanonicalizerPhase(runtime(), assumptions).apply(graph);
             return graph;
         } catch (AssertionFailedError t) {
             throw new RuntimeException(t.getMessage() + "\n" + getCanonicalGraphString(graph), t);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -136,9 +136,9 @@
                 Assumptions assumptions = new Assumptions(true);
                 new ComputeProbabilityPhase().apply(graph);
                 Debug.dump(graph, "Graph");
-                new InliningPhase(null, runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                new InliningPhase(runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 Debug.dump(graph, "Graph");
-                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 return graph;
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Mar 21 14:11:13 2013 +0100
@@ -47,55 +47,38 @@
 
 public class GraalCompiler {
 
-    /**
-     * The target that this compiler has been configured for.
-     */
-    public final TargetDescription target;
-
-    /**
-     * The runtime that this compiler has been configured for.
-     */
-    public final GraalCodeCacheProvider runtime;
-
-    /**
-     * The backend that this compiler has been configured for.
-     */
-    public final Backend backend;
-
-    public GraalCompiler(GraalCodeCacheProvider runtime, TargetDescription target, Backend backend) {
-        this.runtime = runtime;
-        this.target = target;
-        this.backend = backend;
-    }
-
-    public CompilationResult compileMethod(final ResolvedJavaMethod method, final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) {
+    public static CompilationResult compileMethod(final GraalCodeCacheProvider runtime, final Backend backend, final TargetDescription target, final ResolvedJavaMethod method,
+                    final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) {
         assert (method.getModifiers() & Modifier.NATIVE) == 0 : "compiling native methods is not supported";
 
-        return Debug.scope("GraalCompiler", new Object[]{graph, method, this}, new Callable<CompilationResult>() {
+        final CompilationResult compilationResult = new CompilationResult();
+        Debug.scope("GraalCompiler", new Object[]{graph, method, runtime}, new Runnable() {
 
-            public CompilationResult call() {
+            public void run() {
                 final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions);
                 final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
 
                     public LIR call() {
-                        return emitHIR(graph, assumptions, cache, plan, optimisticOpts);
+                        return emitHIR(runtime, target, graph, assumptions, cache, plan, optimisticOpts, speculationLog);
                     }
                 });
-                final FrameMap frameMap = Debug.scope("BackEnd", lir, new Callable<FrameMap>() {
+                final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable<LIRGenerator>() {
 
-                    public FrameMap call() {
-                        return emitLIR(lir, graph, method);
+                    public LIRGenerator call() {
+                        return emitLIR(backend, target, lir, graph, method);
                     }
                 });
-                return Debug.scope("CodeGen", frameMap, new Callable<CompilationResult>() {
+                Debug.scope("CodeGen", lirGen, new Runnable() {
 
-                    public CompilationResult call() {
-                        return emitCode(getLeafGraphIdArray(graph), assumptions, method, lir, frameMap);
+                    public void run() {
+                        emitCode(backend, getLeafGraphIdArray(graph), assumptions, method, lirGen, compilationResult);
                     }
 
                 });
             }
         });
+
+        return compilationResult;
     }
 
     private static long[] getLeafGraphIdArray(StructuredGraph graph) {
@@ -110,8 +93,17 @@
 
     /**
      * Builds the graph, optimizes it.
+     * 
+     * @param runtime
+     * 
+     * @param target
      */
-    public LIR emitHIR(StructuredGraph graph, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+    public static LIR emitHIR(GraalCodeCacheProvider runtime, TargetDescription target, StructuredGraph graph, Assumptions assumptions, GraphCache cache, PhasePlan plan,
+                    OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) {
+
+        if (speculationLog != null) {
+            speculationLog.snapshot();
+        }
 
         if (graph.start().next() == null) {
             plan.runPhases(PhasePosition.AFTER_PARSING, graph);
@@ -125,16 +117,16 @@
         }
 
         if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+            new CanonicalizerPhase(runtime, assumptions).apply(graph);
         }
 
         if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) {
-            new InliningPhase(target, runtime, null, assumptions, cache, plan, optimisticOpts).apply(graph);
+            new InliningPhase(runtime, null, assumptions, cache, plan, optimisticOpts).apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
 
-            if (GraalOptions.CheckCastElimination && GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
-                new IterativeConditionalEliminationPhase(target, runtime, assumptions).apply(graph);
+            if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
+                new CanonicalizerPhase(runtime, assumptions).apply(graph);
+                new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph);
             }
         }
 
@@ -145,19 +137,23 @@
         if (GraalOptions.FullUnroll) {
             new LoopFullUnrollPhase(runtime, assumptions).apply(graph);
             if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+                new CanonicalizerPhase(runtime, assumptions).apply(graph);
             }
         }
 
         if (GraalOptions.OptTailDuplication) {
             new TailDuplicationPhase().apply(graph);
             if (GraalOptions.OptCanonicalizer) {
-                new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+                new CanonicalizerPhase(runtime, assumptions).apply(graph);
             }
         }
 
         if (GraalOptions.PartialEscapeAnalysis && !plan.isPhaseDisabled(PartialEscapeAnalysisPhase.class)) {
-            new PartialEscapeAnalysisPhase(target, runtime, assumptions, true).apply(graph);
+            new PartialEscapeAnalysisPhase(runtime, assumptions, true).apply(graph);
+        }
+
+        if (GraalOptions.OptConvertDeoptsToGuards) {
+            new ConvertDeoptimizeToGuardPhase().apply(graph);
         }
 
         new LockEliminationPhase().apply(graph);
@@ -169,7 +165,7 @@
         new RemoveValueProxyPhase().apply(graph);
 
         if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+            new CanonicalizerPhase(runtime, assumptions).apply(graph);
         }
 
         new LoweringPhase(target, runtime, assumptions).apply(graph);
@@ -181,7 +177,7 @@
         if (GraalOptions.OptFloatingReads) {
             int mark = graph.getMark();
             new FloatingReadPhase().apply(graph);
-            new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph);
+            new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph);
             if (GraalOptions.OptReadElimination) {
                 new ReadEliminationPhase().apply(graph);
             }
@@ -189,15 +185,15 @@
         new RemoveValueProxyPhase().apply(graph);
 
         if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+            new CanonicalizerPhase(runtime, assumptions).apply(graph);
         }
 
         if (GraalOptions.OptEliminatePartiallyRedundantGuards) {
             new EliminatePartiallyRedundantGuardsPhase(false, true).apply(graph);
         }
 
-        if (GraalOptions.CheckCastElimination && GraalOptions.OptCanonicalizer) {
-            new IterativeConditionalEliminationPhase(target, runtime, assumptions).apply(graph);
+        if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) {
+            new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph);
         }
 
         if (GraalOptions.OptEliminatePartiallyRedundantGuards) {
@@ -208,10 +204,10 @@
 
         plan.runPhases(PhasePosition.LOW_LEVEL, graph);
 
+        new GuardLoweringPhase(target).apply(graph);
+
         // Add safepoints to loops
-        if (GraalOptions.GenLoopSafepoints) {
-            new LoopSafepointInsertionPhase().apply(graph);
-        }
+        new SafepointInsertionPhase().apply(graph);
 
         final SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
@@ -231,7 +227,7 @@
                 List<Block> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
                 List<Block> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
 
-                LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder);
+                LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder, speculationLog);
                 Debug.dump(lir, "After linear scan order");
                 return lir;
 
@@ -240,11 +236,11 @@
 
     }
 
-    public FrameMap emitLIR(final LIR lir, StructuredGraph graph, final ResolvedJavaMethod method) {
-        final FrameMap frameMap = backend.newFrameMap(runtime.lookupRegisterConfig(method));
-        final LIRGenerator lirGenerator = backend.newLIRGenerator(graph, frameMap, method, lir);
+    public static LIRGenerator emitLIR(Backend backend, final TargetDescription target, final LIR lir, StructuredGraph graph, final ResolvedJavaMethod method) {
+        final FrameMap frameMap = backend.newFrameMap();
+        final LIRGenerator lirGen = backend.newLIRGenerator(graph, frameMap, method, lir);
 
-        Debug.scope("LIRGen", lirGenerator, new Runnable() {
+        Debug.scope("LIRGen", lirGen, new Runnable() {
 
             public void run() {
                 for (Block b : lir.linearScanOrder()) {
@@ -261,23 +257,25 @@
                             emitBlock(pred);
                         }
                     }
-                    lirGenerator.doBlock(b);
+                    lirGen.doBlock(b);
                 }
             }
         });
 
+        lirGen.beforeRegisterAllocation();
+
         Debug.scope("Allocator", new Runnable() {
 
             public void run() {
-                new LinearScan(target, method, lir, lirGenerator, frameMap).allocate();
+                new LinearScan(target, method, lir, lirGen, frameMap).allocate();
             }
         });
-        return frameMap;
+        return lirGen;
     }
 
-    public CompilationResult emitCode(long[] leafGraphIds, Assumptions assumptions, ResolvedJavaMethod method, LIR lir, FrameMap frameMap) {
-        TargetMethodAssembler tasm = backend.newAssembler(frameMap, lir);
-        backend.emitCode(tasm, method, lir);
+    public static void emitCode(Backend backend, long[] leafGraphIds, Assumptions assumptions, ResolvedJavaMethod method, LIRGenerator lirGen, CompilationResult compilationResult) {
+        TargetMethodAssembler tasm = backend.newAssembler(lirGen, compilationResult);
+        backend.emitCode(tasm, method, lirGen);
         CompilationResult result = tasm.finishTargetMethod(method, false);
         if (!assumptions.isEmpty()) {
             result.setAssumptions(assumptions);
@@ -285,6 +283,5 @@
         result.setLeafGraphIds(leafGraphIds);
 
         Debug.dump(result, "After code generation");
-        return result;
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Thu Mar 21 14:11:13 2013 +0100
@@ -417,8 +417,8 @@
     public final int operandNumber;
 
     /**
-     * The {@linkplain RegisterValue register}, {@linkplain StackSlot spill slot} or
-     * {@linkplain Address address} assigned to this interval.
+     * The {@linkplain RegisterValue register} or {@linkplain StackSlot spill slot} assigned to this
+     * interval.
      */
     private Value location;
 
@@ -515,8 +515,8 @@
     }
 
     /**
-     * Gets the {@linkplain RegisterValue register}, {@linkplain StackSlot spill slot} or
-     * {@linkplain Address address} assigned to this interval.
+     * Gets the {@linkplain RegisterValue register} or {@linkplain StackSlot spill slot} assigned to
+     * this interval.
      */
     public Value location() {
         return location;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Thu Mar 21 14:11:13 2013 +0100
@@ -282,7 +282,6 @@
      * @return the created interval
      */
     Interval createInterval(Value operand) {
-        assert isProcessed(operand);
         assert isLegal(operand);
         int operandNumber = operandNumber(operand);
         Interval interval = new Interval(operand, operandNumber);
@@ -347,6 +346,15 @@
         return intervals[operandNumber];
     }
 
+    Interval getOrCreateInterval(Value operand) {
+        Interval ret = intervalFor(operand);
+        if (ret == null) {
+            return createInterval(operand);
+        } else {
+            return ret;
+        }
+    }
+
     /**
      * Gets the highest instruction id allocated by this object.
      */
@@ -968,11 +976,7 @@
             TTY.println(" use %s from %d to %d (%s)", operand, from, to, registerPriority.name());
         }
 
-        Interval interval = intervalFor(operand);
-        if (interval == null) {
-            interval = createInterval(operand);
-        }
-
+        Interval interval = getOrCreateInterval(operand);
         if (kind != Kind.Illegal) {
             interval.setKind(kind);
         }
@@ -990,11 +994,8 @@
         if (GraalOptions.TraceLinearScanLevel >= 2) {
             TTY.println(" temp %s tempPos %d (%s)", operand, tempPos, RegisterPriority.MustHaveRegister.name());
         }
-        Interval interval = intervalFor(operand);
-        if (interval == null) {
-            interval = createInterval(operand);
-        }
 
+        Interval interval = getOrCreateInterval(operand);
         if (kind != Kind.Illegal) {
             interval.setKind(kind);
         }
@@ -1014,42 +1015,26 @@
         if (GraalOptions.TraceLinearScanLevel >= 2) {
             TTY.println(" def %s defPos %d (%s)", operand, defPos, registerPriority.name());
         }
-        Interval interval = intervalFor(operand);
-        if (interval != null) {
 
-            if (kind != Kind.Illegal) {
-                interval.setKind(kind);
-            }
+        Interval interval = getOrCreateInterval(operand);
+        if (kind != Kind.Illegal) {
+            interval.setKind(kind);
+        }
 
-            Range r = interval.first();
-            if (r.from <= defPos) {
-                // Update the starting point (when a range is first created for a use, its
-                // start is the beginning of the current block until a def is encountered.)
-                r.from = defPos;
-                interval.addUsePos(defPos, registerPriority);
-
-            } else {
-                // Dead value - make vacuous interval
-                // also add register priority for dead intervals
-                interval.addRange(defPos, defPos + 1);
-                interval.addUsePos(defPos, registerPriority);
-                if (GraalOptions.TraceLinearScanLevel >= 2) {
-                    TTY.println("Warning: def of operand %s at %d occurs without use", operand, defPos);
-                }
-            }
+        Range r = interval.first();
+        if (r.from <= defPos) {
+            // Update the starting point (when a range is first created for a use, its
+            // start is the beginning of the current block until a def is encountered.)
+            r.from = defPos;
+            interval.addUsePos(defPos, registerPriority);
 
         } else {
             // Dead value - make vacuous interval
             // also add register priority for dead intervals
-            interval = createInterval(operand);
-            if (kind != Kind.Illegal) {
-                interval.setKind(kind);
-            }
-
             interval.addRange(defPos, defPos + 1);
             interval.addUsePos(defPos, registerPriority);
             if (GraalOptions.TraceLinearScanLevel >= 2) {
-                TTY.println("Warning: dead value %s at %d in live intervals", operand, defPos);
+                TTY.println("Warning: def of operand %s at %d occurs without use", operand, defPos);
             }
         }
 
@@ -1066,8 +1051,7 @@
     static RegisterPriority registerPriorityOfOutputOperand(LIRInstruction op) {
         if (op instanceof MoveOp) {
             MoveOp move = (MoveOp) op;
-            if (isStackSlot(move.getInput()) && move.getInput().getKind() != Kind.Object) {
-                // method argument (condition must be equal to handleMethodArguments)
+            if (optimizeMethodArgument(move.getInput())) {
                 return RegisterPriority.None;
             }
         }
@@ -1088,6 +1072,14 @@
         return RegisterPriority.MustHaveRegister;
     }
 
+    private static boolean optimizeMethodArgument(Value value) {
+        /*
+         * Object method arguments that are passed on the stack are currently not optimized because
+         * this requires that the runtime visits method arguments during stack walking.
+         */
+        return isStackSlot(value) && asStackSlot(value).isInCallerFrame() && value.getKind() != Kind.Object;
+    }
+
     /**
      * Optimizes moves related to incoming stack based arguments. The interval for the destination
      * of such moves is assigned the stack slot (which is in the caller's frame) as its spill slot.
@@ -1095,8 +1087,8 @@
     void handleMethodArguments(LIRInstruction op) {
         if (op instanceof MoveOp) {
             MoveOp move = (MoveOp) op;
-            if (isStackSlot(move.getInput()) && move.getInput().getKind() != Kind.Object) {
-                StackSlot slot = (StackSlot) move.getInput();
+            if (optimizeMethodArgument(move.getInput())) {
+                StackSlot slot = asStackSlot(move.getInput());
                 if (GraalOptions.DetailedAsserts) {
                     assert op.id() > 0 : "invalid id";
                     assert blockForId(op.id()).getPredecessorCount() == 0 : "move from stack must be in first block";
@@ -1114,7 +1106,7 @@
         }
     }
 
-    void addRegisterHint(final LIRInstruction op, final Value targetValue, OperandMode mode, EnumSet<OperandFlag> flags) {
+    void addRegisterHint(final LIRInstruction op, final Value targetValue, OperandMode mode, EnumSet<OperandFlag> flags, final boolean hintAtDef) {
         if (flags.contains(OperandFlag.HINT) && isVariableOrRegister(targetValue)) {
 
             op.forEachRegisterHint(targetValue, mode, new ValueProcedure() {
@@ -1122,15 +1114,20 @@
                 @Override
                 protected Value doValue(Value registerHint) {
                     if (isVariableOrRegister(registerHint)) {
-                        Interval from = intervalFor(registerHint);
-                        Interval to = intervalFor(targetValue);
-                        if (from != null && to != null) {
+                        Interval from = getOrCreateInterval(registerHint);
+                        Interval to = getOrCreateInterval(targetValue);
+
+                        // hints always point from def to use
+                        if (hintAtDef) {
                             to.setLocationHint(from);
-                            if (GraalOptions.TraceLinearScanLevel >= 4) {
-                                TTY.println("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber);
-                            }
-                            return registerHint;
+                        } else {
+                            from.setLocationHint(to);
                         }
+
+                        if (GraalOptions.TraceLinearScanLevel >= 4) {
+                            TTY.println("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber);
+                        }
+                        return registerHint;
                     }
                     return null;
                 }
@@ -1201,7 +1198,7 @@
                     public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                         if (isVariableOrRegister(operand)) {
                             addDef(operand, opId, registerPriorityOfOutputOperand(op), operand.getKind().getStackKind());
-                            addRegisterHint(op, operand, mode, flags);
+                            addRegisterHint(op, operand, mode, flags, true);
                         }
                         return operand;
                     }
@@ -1212,7 +1209,7 @@
                     public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                         if (isVariableOrRegister(operand)) {
                             addTemp(operand, opId, RegisterPriority.MustHaveRegister, operand.getKind().getStackKind());
-                            addRegisterHint(op, operand, mode, flags);
+                            addRegisterHint(op, operand, mode, flags, false);
                         }
                         return operand;
                     }
@@ -1224,7 +1221,7 @@
                         if (isVariableOrRegister(operand)) {
                             RegisterPriority p = registerPriorityOfInputOperand(flags);
                             addUse(operand, blockFrom, opId + 1, p, operand.getKind().getStackKind());
-                            addRegisterHint(op, operand, mode, flags);
+                            addRegisterHint(op, operand, mode, flags, false);
                         }
                         return operand;
                     }
@@ -1236,7 +1233,7 @@
                         if (isVariableOrRegister(operand)) {
                             RegisterPriority p = registerPriorityOfInputOperand(flags);
                             addUse(operand, blockFrom, opId, p, operand.getKind().getStackKind());
-                            addRegisterHint(op, operand, mode, flags);
+                            addRegisterHint(op, operand, mode, flags, false);
                         }
                         return operand;
                     }
@@ -1960,12 +1957,6 @@
                 throw new GraalInternalError("");
             }
 
-            if (!isProcessed(i1.location())) {
-                TTY.println("Can not have an Interval for an ignored register " + i1.location());
-                TTY.println(i1.logString(this));
-                throw new GraalInternalError("");
-            }
-
             if (i1.first() == Range.EndMarker) {
                 TTY.println("Interval %d has no Range", i1.operandNumber);
                 TTY.println(i1.logString(this));
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Thu Mar 21 14:11:13 2013 +0100
@@ -45,7 +45,7 @@
     private HashMap<VirtualObjectNode, VirtualObject> virtualObjects = new HashMap<>();
     private IdentityHashMap<VirtualObjectNode, EscapeObjectState> objectStates = new IdentityHashMap<>();
 
-    public LIRFrameState build(FrameState topState, List<StackSlot> lockData, LabelRef exceptionEdge) {
+    public LIRFrameState build(FrameState topState, List<StackSlot> lockData, short reason, LabelRef exceptionEdge) {
         assert virtualObjects.size() == 0;
         assert objectStates.size() == 0;
 
@@ -103,7 +103,7 @@
         }
         objectStates.clear();
 
-        return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge);
+        return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason);
     }
 
     private BytecodeFrame computeFrameForState(FrameState state, List<StackSlot> lockDataSlots) {
@@ -135,7 +135,7 @@
                 throw new BailoutException("unbalanced monitors: found monitor for unknown frame (%d != %d) at %s", lockDataSlots.size(), numLocks, state);
             }
         }
-        assert state.bci >= 0 || state.bci == FrameState.BEFORE_BCI;
+        assert state.bci >= 0 || state.bci == FrameState.BEFORE_BCI : "bci == " + state.bci;
         return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks);
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -54,17 +54,18 @@
  */
 public abstract class LIRGenerator extends LIRGeneratorTool {
 
+    public final FrameMap frameMap;
+    public final NodeMap<Value> nodeOperands;
+    public final LIR lir;
+
     protected final StructuredGraph graph;
     protected final CodeCacheProvider runtime;
     protected final TargetDescription target;
     protected final ResolvedJavaMethod method;
-    protected final FrameMap frameMap;
-    public final NodeMap<Value> nodeOperands;
 
-    protected final LIR lir;
     private final DebugInfoBuilder debugInfoBuilder;
 
-    private Block currentBlock;
+    protected Block currentBlock;
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
     private FrameState lastState;
@@ -90,6 +91,16 @@
      */
     private final ArrayList<StackSlot> lockDataSlots;
 
+    /**
+     * Checks whether the supplied constant can be used without loading it into a register for store
+     * operations, i.e., on the right hand side of a memory access.
+     * 
+     * @param c The constant to check.
+     * @return True if the constant can be used directly, false if the constant needs to be in a
+     *         register.
+     */
+    public abstract boolean canStoreConstant(Constant c);
+
     public LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
         this.graph = graph;
         this.runtime = runtime;
@@ -151,7 +162,6 @@
     public Variable newVariable(Kind kind) {
         Kind stackKind = kind.getStackKind();
         switch (stackKind) {
-            case Jsr:
             case Int:
             case Long:
             case Object:
@@ -184,6 +194,14 @@
     @Override
     public abstract Variable emitMove(Value input);
 
+    public AllocatableValue asAllocatable(Value value) {
+        if (isAllocatableValue(value)) {
+            return asAllocatableValue(value);
+        } else {
+            return emitMove(value);
+        }
+    }
+
     public Variable load(Value value) {
         if (!isVariable(value)) {
             return emitMove(value);
@@ -198,18 +216,6 @@
         return value;
     }
 
-    public Value loadForStore(Value value, Kind storeKind) {
-        if (isConstant(value) && canStoreConstant((Constant) value)) {
-            return value;
-        }
-        if (storeKind == Kind.Byte || storeKind == Kind.Boolean) {
-            Variable tempVar = new Variable(value.getKind(), lir.nextVariable(), Register.RegisterFlag.Byte);
-            emitMove(value, tempVar);
-            return tempVar;
-        }
-        return load(value);
-    }
-
     protected LabelRef getLIRBlock(FixedNode b) {
         Block result = lir.cfg.blockFor(b);
         int suxIndex = currentBlock.getSuccessors().indexOf(result);
@@ -226,19 +232,23 @@
     }
 
     public LIRFrameState state() {
+        return state(null);
+    }
+
+    public LIRFrameState state(DeoptimizationReason reason) {
         assert lastState != null || needOnlyOopMaps() : "must have state before instruction";
-        return stateFor(lastState);
+        return stateFor(lastState, reason);
     }
 
-    public LIRFrameState stateFor(FrameState state) {
-        return stateFor(state, null);
+    public LIRFrameState stateFor(FrameState state, DeoptimizationReason reason) {
+        return stateForWithExceptionEdge(state, reason, null);
     }
 
-    public LIRFrameState stateFor(FrameState state, LabelRef exceptionEdge) {
+    public LIRFrameState stateForWithExceptionEdge(FrameState state, DeoptimizationReason reason, LabelRef exceptionEdge) {
         if (needOnlyOopMaps()) {
-            return new LIRFrameState(null, null, null);
+            return new LIRFrameState(null, null, null, (short) -1);
         }
-        return debugInfoBuilder.build(state, lockDataSlots.subList(0, currentLockCount), exceptionEdge);
+        return debugInfoBuilder.build(state, lockDataSlots.subList(0, currentLockCount), lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge);
     }
 
     /**
@@ -340,28 +350,6 @@
         List<ScheduledNode> nodes = lir.nodesFor(block);
         for (int i = 0; i < nodes.size(); i++) {
             Node instr = nodes.get(i);
-
-            if (GraalOptions.OptImplicitNullChecks) {
-                Node nextInstr = null;
-                if (i < nodes.size() - 1) {
-                    nextInstr = nodes.get(i + 1);
-                }
-
-                if (instr instanceof GuardNode) {
-                    GuardNode guardNode = (GuardNode) instr;
-                    if (guardNode.condition() instanceof IsNullNode && guardNode.negated()) {
-                        IsNullNode isNullNode = (IsNullNode) guardNode.condition();
-                        if (nextInstr instanceof Access) {
-                            Access access = (Access) nextInstr;
-                            if (isNullNode.object() == access.object() && canBeNullCheck(access.location())) {
-                                // TTY.println("implicit null check");
-                                access.setNullCheck(true);
-                                continue;
-                            }
-                        }
-                    }
-                }
-            }
             if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
                 TTY.println("LIRGen for " + instr);
             }
@@ -402,7 +390,7 @@
             NodeClassIterable successors = block.getEndNode().successors();
             assert successors.isNotEmpty() : "should have at least one successor : " + block.getEndNode();
 
-            emitJump(getLIRBlock((FixedNode) successors.first()), null);
+            emitJump(getLIRBlock((FixedNode) successors.first()));
         }
 
         if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
@@ -461,10 +449,6 @@
         ((LIRLowerable) node).generate(this);
     }
 
-    private boolean canBeNullCheck(LocationNode location) {
-        return !(location instanceof IndexedLocationNode) && location.displacement() < this.target().implicitNullCheckLimit;
-    }
-
     protected CallingConvention createCallingConvention() {
         return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), MetaUtil.signatureToTypes(method), target, false);
     }
@@ -483,7 +467,7 @@
             }
         }
 
-        append(new ParametersOp(params));
+        emitIncomingValues(params);
 
         for (LocalNode local : graph.getNodes(LocalNode.class)) {
             Value param = params[local.index()];
@@ -492,6 +476,10 @@
         }
     }
 
+    public void emitIncomingValues(Value[] params) {
+        append(new ParametersOp(params));
+    }
+
     /**
      * Increases the number of currently locked monitors and makes sure that a lock data slot is
      * available for the new lock.
@@ -527,7 +515,7 @@
         Value operand = Value.ILLEGAL;
         if (x.result() != null) {
             operand = resultOperandFor(x.result().kind());
-            emitMove(operand(x.result()), operand);
+            emitMove(operand, operand(x.result()));
         }
         emitReturn(operand);
     }
@@ -558,12 +546,12 @@
         for (PhiNode phi : merge.phis()) {
             if (phi.type() == PhiType.Value) {
                 ValueNode curVal = phi.valueAt(pred);
-                resolver.move(operand(curVal), operandForPhi(phi));
+                resolver.move(operandForPhi(phi), operand(curVal));
             }
         }
         resolver.dispose();
 
-        append(new JumpOp(getLIRBlock(merge), null));
+        append(new JumpOp(getLIRBlock(merge)));
     }
 
     private Value operandForPhi(PhiNode phi) {
@@ -581,82 +569,46 @@
 
     @Override
     public void emitIf(IfNode x) {
-        emitBranch(x.condition(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()), null);
+        emitBranch(x.condition(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()));
     }
 
-    @Override
-    public void emitGuardCheck(LogicNode comp, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
-        if (comp instanceof IsNullNode && negated) {
-            emitNullCheckGuard(((IsNullNode) comp).object());
-        } else if (comp instanceof LogicConstantNode && ((LogicConstantNode) comp).getValue() != negated) {
-            // True constant, nothing to emit.
-            // False constants are handled within emitBranch.
-        } else {
-            // Fall back to a normal branch.
-            LIRFrameState info = state();
-            LabelRef stubEntry = createDeoptStub(action, deoptReason, info, comp);
-            if (negated) {
-                emitBranch(comp, stubEntry, null, info);
-            } else {
-                emitBranch(comp, null, stubEntry, info);
-            }
-        }
-    }
-
-    protected abstract void emitNullCheckGuard(ValueNode object);
-
-    public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
+    public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor) {
         if (node instanceof IsNullNode) {
-            emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, info);
+            emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor);
         } else if (node instanceof CompareNode) {
-            emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, info);
+            emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor);
         } else if (node instanceof LogicConstantNode) {
-            emitConstantBranch(((LogicConstantNode) node).getValue(), trueSuccessor, falseSuccessor, info);
+            emitConstantBranch(((LogicConstantNode) node).getValue(), trueSuccessor, falseSuccessor);
         } else if (node instanceof IntegerTestNode) {
-            emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, info);
+            emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor);
         } else {
             throw GraalInternalError.unimplemented(node.toString());
         }
     }
 
-    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
-        if (falseSuccessor != null) {
-            emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info);
-            if (trueSuccessor != null) {
-                emitJump(trueSuccessor, null);
-            }
-        } else {
-            emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, info);
-        }
+    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+        emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor);
+        emitJump(trueSuccessor);
+    }
+
+    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
+        emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock);
+        emitJump(trueSuccessorBlock);
     }
 
-    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
-        if (falseSuccessorBlock != null) {
-            emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info);
-            if (trueSuccessorBlock != null) {
-                emitJump(trueSuccessorBlock, null);
-            }
-        } else {
-            emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessorBlock, info);
-        }
+    public void emitOverflowCheckBranch(LabelRef noOverflowBlock, LabelRef overflowBlock) {
+        emitOverflowCheckBranch(overflowBlock, false);
+        emitJump(noOverflowBlock);
     }
 
-    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
-        if (falseSuccessorBlock != null) {
-            emitIntegerTestBranch(operand(test.x()), operand(test.y()), true, falseSuccessorBlock, info);
-            if (trueSuccessorBlock != null) {
-                emitJump(trueSuccessorBlock, null);
-            }
-        } else {
-            emitIntegerTestBranch(operand(test.x()), operand(test.y()), false, trueSuccessorBlock, info);
-        }
+    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
+        emitIntegerTestBranch(operand(test.x()), operand(test.y()), true, falseSuccessorBlock);
+        emitJump(trueSuccessorBlock);
     }
 
-    public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
+    public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
         LabelRef block = value ? trueSuccessorBlock : falseSuccessorBlock;
-        if (block != null) {
-            emitJump(block, info);
-        }
+        emitJump(block);
     }
 
     @Override
@@ -683,11 +635,13 @@
         }
     }
 
-    public abstract void emitJump(LabelRef label, LIRFrameState info);
+    public abstract void emitJump(LabelRef label);
+
+    public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label);
 
-    public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info);
+    public abstract void emitOverflowCheckBranch(LabelRef label, boolean negated);
 
-    public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info);
+    public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label);
 
     public abstract Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
 
@@ -703,7 +657,7 @@
 
         LIRFrameState callState = null;
         if (x.stateAfter() != null) {
-            callState = stateFor(x.stateDuring(), x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null);
+            callState = stateForWithExceptionEdge(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null);
         }
 
         Value result = cc.getReturn();
@@ -725,9 +679,9 @@
 
     protected abstract void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState);
 
-    protected abstract void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info);
+    protected abstract void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info);
 
-    private static Value toStackKind(Value value) {
+    protected static Value toStackKind(Value value) {
         if (value.getKind().getStackKind() != value.getKind()) {
             // We only have stack-kinds in the LIR, so convert the operand kind for values from the
             // calling convention.
@@ -749,7 +703,7 @@
         for (ValueNode arg : arguments) {
             if (arg != null) {
                 Value operand = toStackKind(cc.getArgument(j));
-                emitMove(operand(arg), operand);
+                emitMove(operand, operand(arg));
                 result[j] = operand;
                 j++;
             } else {
@@ -759,8 +713,6 @@
         return result;
     }
 
-    protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo);
-
     @Override
     public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args) {
         LIRFrameState info = canTrap ? state() : null;
@@ -772,10 +724,10 @@
         for (int i = 0; i < args.length; i++) {
             Value arg = args[i];
             Value loc = cc.getArgument(i);
-            emitMove(arg, loc);
+            emitMove(loc, arg);
             argLocations[i] = loc;
         }
-        emitCall(callTarget, cc.getReturn(), argLocations, cc.getTemporaries(), Constant.forLong(0), info);
+        emitCall(callTarget, cc.getReturn(), argLocations, cc.getTemporaries(), info);
 
         if (isLegal(cc.getReturn())) {
             return emitMove(cc.getReturn());
@@ -805,12 +757,12 @@
             if ((stateAfter.stackSize() > 0 && stateAfter.stackAt(stateAfter.stackSize() - 1) == x) || (stateAfter.stackSize() > 1 && stateAfter.stackAt(stateAfter.stackSize() - 2) == x)) {
                 stateBeforeReturn = stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), x.kind());
             }
-            info = stateFor(stateBeforeReturn);
+            info = stateFor(stateBeforeReturn, null);
         } else {
             info = state();
         }
 
-        emitCall(call, resultOperand, args, cc.getTemporaries(), Constant.forLong(0), info);
+        emitCall(call, resultOperand, args, cc.getTemporaries(), info);
 
         if (isLegal(resultOperand)) {
             setResult(x, emitMove(resultOperand));
@@ -829,7 +781,7 @@
     public void emitSwitch(SwitchNode x) {
         int keyCount = x.keyCount();
         if (keyCount == 0) {
-            emitJump(getLIRBlock(x.defaultSuccessor()), null);
+            emitJump(getLIRBlock(x.defaultSuccessor()));
         } else {
             Variable value = load(operand(x.value()));
             LabelRef defaultTarget = x.defaultSuccessor() == null ? null : getLIRBlock(x.defaultSuccessor());
@@ -841,7 +793,7 @@
                 long valueRange = x.keyAt(keyCount - 1).asLong() - x.keyAt(0).asLong() + 1;
                 int switchRangeCount = switchRangeCount(x);
                 if (switchRangeCount == 0) {
-                    emitJump(getLIRBlock(x.defaultSuccessor()), null);
+                    emitJump(getLIRBlock(x.defaultSuccessor()));
                 } else if (switchRangeCount >= GraalOptions.MinimumJumpTableSize && keyCount / (double) valueRange >= GraalOptions.MinTableSwitchDensity) {
                     int minValue = x.keyAt(0).asInt();
                     assert valueRange < Integer.MAX_VALUE;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Thu Mar 21 14:11:13 2013 +0100
@@ -131,7 +131,7 @@
             PhiResolverNode node = variableOperands.get(i);
             if (!node.visited) {
                 loop = null;
-                move(null, node);
+                move(node, null);
                 node.startNode = true;
                 assert isIllegal(temp) : "moveTempTo() call missing";
             }
@@ -141,12 +141,12 @@
         for (int i = otherOperands.size() - 1; i >= 0; i--) {
             PhiResolverNode node = otherOperands.get(i);
             for (int j = node.destinations.size() - 1; j >= 0; j--) {
-                emitMove(node.operand, node.destinations.get(j).operand);
+                emitMove(node.destinations.get(j).operand, node.operand);
             }
         }
     }
 
-    public void move(Value src, Value dest) {
+    public void move(Value dest, Value src) {
         assert isVariable(dest) : "destination must be virtual";
         // tty.print("move "); src.print(); tty.print(" to "); dest.print(); tty.cr();
         assert isLegal(src) : "source for phi move is illegal";
@@ -184,24 +184,24 @@
         return createNode(opr, false);
     }
 
-    private void emitMove(Value src, Value dest) {
+    private void emitMove(Value dest, Value src) {
         assert isLegal(src);
         assert isLegal(dest);
-        gen.emitMove(src, dest);
+        gen.emitMove(dest, src);
     }
 
     // Traverse assignment graph in depth first order and generate moves in post order
     // ie. two assignments: b := c, a := b start with node c:
-    // Call graph: move(NULL, c) -> move(c, b) -> move(b, a)
+    // Call graph: move(c, NULL) -> move(b, c) -> move(a, b)
     // Generates moves in this order: move b to a and move c to b
     // ie. cycle a := b, b := a start with node a
-    // Call graph: move(NULL, a) -> move(a, b) -> move(b, a)
+    // Call graph: move(a, NULL) -> move(b, a) -> move(a, b)
     // Generates moves in this order: move b to temp, move a to b, move temp to a
-    private void move(PhiResolverNode src, PhiResolverNode dest) {
+    private void move(PhiResolverNode dest, PhiResolverNode src) {
         if (!dest.visited) {
             dest.visited = true;
             for (int i = dest.destinations.size() - 1; i >= 0; i--) {
-                move(dest, dest.destinations.get(i));
+                move(dest.destinations.get(i), dest);
             }
         } else if (!dest.startNode) {
             // cycle in graph detected
@@ -216,7 +216,7 @@
                 moveTempTo(dest.operand);
                 dest.assigned = true;
             } else if (src != null) {
-                emitMove(src.operand, dest.operand);
+                emitMove(dest.operand, src.operand);
                 dest.assigned = true;
             }
         }
@@ -224,14 +224,14 @@
 
     private void moveTempTo(Value dest) {
         assert isLegal(temp);
-        emitMove(temp, dest);
+        emitMove(dest, temp);
         temp = ILLEGAL;
     }
 
     private void moveToTemp(Value src) {
         assert isIllegal(temp);
         temp = gen.newVariable(src.getKind());
-        emitMove(src, temp);
+        emitMove(temp, src);
     }
 
     private PhiResolverNode sourceNode(Value opr) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,7 +28,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 
 /**
  * The {@code Backend} class represents a compiler backend for Graal.
@@ -47,46 +46,19 @@
         return runtime;
     }
 
-    public FrameMap newFrameMap(RegisterConfig registerConfig) {
-        return new FrameMap(runtime, target, registerConfig);
+    public FrameMap newFrameMap() {
+        return new FrameMap(runtime, target, runtime.lookupRegisterConfig());
     }
 
     public abstract LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir);
 
-    public abstract TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir);
-
-    /**
-     * Emits code to do stack overflow checking.
-     * 
-     * @param afterFrameInit specifies if the stack pointer has already been adjusted to allocate
-     *            the current frame
-     */
-    protected static void emitStackOverflowCheck(TargetMethodAssembler tasm, boolean afterFrameInit) {
-        if (GraalOptions.StackShadowPages > 0) {
-            int frameSize = tasm.frameMap.frameSize();
-            if (frameSize > 0) {
-                int lastFramePage = frameSize / tasm.target.pageSize;
-                // emit multiple stack bangs for methods with frames larger than a page
-                for (int i = 0; i <= lastFramePage; i++) {
-                    int disp = (i + GraalOptions.StackShadowPages) * tasm.target.pageSize;
-                    if (afterFrameInit) {
-                        disp -= frameSize;
-                    }
-                    tasm.blockComment("[stack overflow check]");
-                    tasm.asm.bangStack(disp);
-                }
-            }
-        }
-    }
+    public abstract TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult);
 
     /**
      * Emits the code for a given method. This includes any architecture/runtime specific
      * prefix/suffix. A prefix typically contains the code for setting up the frame, spilling
      * callee-save registers, stack overflow checking, handling multiple entry points etc. A suffix
      * may contain out-of-line stubs and method end guard instructions.
-     * 
-     * @param method the method associated with {@code lir}
-     * @param lir the LIR of {@code method}
      */
-    public abstract void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir);
+    public abstract void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen);
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Thu Mar 21 14:11:13 2013 +0100
@@ -324,10 +324,8 @@
         };
     }
 
-    private static class PlaceHolderNode extends Node {
-    }
-
-    private static final PlaceHolderNode PLACE_HOLDER = new PlaceHolderNode();
+    private static final Node PLACE_HOLDER = new Node() {
+    };
 
     private class TypedNodeIterator<T extends IterableNodeType> implements Iterator<T> {
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java	Thu Mar 21 14:11:13 2013 +0100
@@ -72,6 +72,10 @@
         assert !isNew(node) : "this node was added to the graph after creating the node map : " + node;
     }
 
+    public void clear() {
+        Arrays.fill(values, null);
+    }
+
     public Iterable<Entry<Node, T>> entries() {
         return new Iterable<Entry<Node, T>>() {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64.test;
+
+import static com.oracle.graal.amd64.AMD64.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.compiler.test.*;
+
+/**
+ * Ensures that frame omission works in cases where it is expected to.
+ */
+public class AMD64HotSpotFrameOmissionTest extends GraalCompilerTest {
+
+    interface CodeGenerator {
+
+        void generateCode(AMD64Assembler asm);
+    }
+
+    public static void test1snippet() {
+        return;
+    }
+
+    @Test
+    public void test1() {
+        testHelper("test1snippet", new CodeGenerator() {
+
+            @Override
+            public void generateCode(AMD64Assembler asm) {
+                asm.ret(0);
+            }
+        });
+    }
+
+    public static int test2snippet(int x) {
+        return x + 5;
+    }
+
+    @Test
+    public void test2() {
+        testHelper("test2snippet", new CodeGenerator() {
+
+            @Override
+            public void generateCode(AMD64Assembler asm) {
+                asm.addl(rsi, 5);
+                asm.movl(rax, rsi);
+                asm.ret(0);
+            }
+        });
+    }
+
+    public static long test3snippet(long x) {
+        return 1 + x;
+    }
+
+    @Test
+    public void test3() {
+        testHelper("test3snippet", new CodeGenerator() {
+
+            @Override
+            public void generateCode(AMD64Assembler asm) {
+                asm.addq(rsi, 1);
+                asm.movq(rax, rsi);
+                asm.ret(0);
+            }
+        });
+    }
+
+    private void testHelper(String name, CodeGenerator gen) {
+        Method method = getMethod(name);
+        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
+        InstalledCode installedCode = getCode(javaMethod, parse(method));
+
+        CodeCacheProvider codeCache = Graal.getRequiredCapability(CodeCacheProvider.class);
+        TargetDescription target = codeCache.getTarget();
+        RegisterConfig registerConfig = codeCache.lookupRegisterConfig();
+        AMD64Assembler asm = new AMD64Assembler(target, registerConfig);
+
+        gen.generateCode(asm);
+        byte[] expectedCode = asm.codeBuffer.close(true);
+
+        // Only compare up to expectedCode.length bytes to ignore
+        // padding instructions adding during code installation
+        byte[] actualCode = Arrays.copyOf(installedCode.getCode(), expectedCode.length);
+
+        Assert.assertArrayEquals(expectedCode, actualCode);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+
+@Opcode("DEOPT")
+final class AMD64DeoptimizeOp extends AMD64LIRInstruction {
+
+    public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, void.class);
+
+    private DeoptimizationAction action;
+    private DeoptimizationReason reason;
+    @State private LIRFrameState info;
+
+    AMD64DeoptimizeOp(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) {
+        this.action = action;
+        this.reason = reason;
+        this.info = info;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        HotSpotGraalRuntime runtime = HotSpotGraalRuntime.getInstance();
+        Register thread = runtime.getRuntime().threadRegister();
+        masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason));
+        AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(DEOPTIMIZE), null, false, info);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.amd64;
-
-import static com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind.*;
-
-import com.oracle.graal.amd64.*;
-import com.oracle.graal.api.code.CompilationResult.Mark;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.hotspot.bridge.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
-import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
-
-/**
- * A direct call that complies with the conventions for such calls in HotSpot. In particular, for
- * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call.
- * This instruction (which moves 0L in RAX) is patched by the C++ Graal code to replace the 0L
- * constant with Universe::non_oop_word(), a special sentinel used for the initial value of the
- * Klass in an inline cache.
- * <p>
- * For non-inline cache calls (i.e., INVOKESTATIC and INVOKESPECIAL), a static call stub is emitted.
- * Initially, these calls go to the global static call resolution stub (i.e.,
- * SharedRuntime::get_resolve_static_call_stub()). Resolution will link the call to a compiled
- * version of the callee if available otherwise to the interpreter. The interpreter expects to find
- * the Method* for the callee in RBX. To achieve this, the static call is linked to a static call
- * stub which initializes RBX and jumps to the interpreter. This pattern is shown below:
- * 
- * <pre>
- *       call L1
- *       nop
- * 
- *       ...
- * 
- *   L1: mov rbx [Method*]
- *       jmp [interpreter entry point]
- * </pre>
- */
-@Opcode("CALL_DIRECT")
-final class AMD64DirectCallOp extends DirectCallOp {
-
-    /**
-     * The mark emitted at the position of the direct call instruction. This is only recorded for
-     * calls that have an associated static call stub (i.e.,
-     * {@code invokeKind == Static || invokeKind == Special}).
-     */
-    Mark callsiteMark;
-
-    private final InvokeKind invokeKind;
-
-    AMD64DirectCallOp(Object target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, LIR lir) {
-        super(target, result, parameters, temps, state);
-        this.invokeKind = invokeKind;
-
-        if (invokeKind == Static || invokeKind == Special) {
-            lir.stubs.add(new AMD64Code() {
-
-                public String description() {
-                    return "static call stub for Invoke" + AMD64DirectCallOp.this.invokeKind;
-                }
-
-                @Override
-                public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-                    assert callsiteMark != null : "static call site has not yet been emitted";
-                    tasm.recordMark(Marks.MARK_STATIC_CALL_STUB, callsiteMark);
-                    masm.movq(AMD64.rbx, 0L);
-                    int pos = masm.codeBuffer.position();
-                    // Create a jump-to-self as expected by CompiledStaticCall::set_to_interpreted()
-                    // in compiledIC.cpp
-                    masm.jmp(pos, true);
-                }
-            });
-        }
-
-    }
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        if (invokeKind == Static || invokeKind == Special) {
-            tasm.recordMark(invokeKind == Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL);
-        } else {
-            assert invokeKind == Virtual || invokeKind == Interface;
-            // The mark for an invocation that uses an inline cache must be placed at the
-            // instruction
-            // that loads the Klass from the inline cache so that the C++ code can find it
-            // and replace the inline 0L value with Universe::non_oop_word()
-            tasm.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE);
-            AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Long), Constant.LONG_0);
-        }
-
-        emitAlignmentForDirectCall(tasm, masm);
-
-        if (invokeKind == Static || invokeKind == Special) {
-            callsiteMark = tasm.recordMark(null);
-        }
-
-        AMD64Call.directCall(tasm, masm, callTarget, state);
-    }
-}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,25 +29,23 @@
 
 import java.lang.reflect.*;
 
+import sun.misc.*;
+
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.compiler.amd64.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 
 /**
@@ -55,110 +53,43 @@
  */
 public class AMD64HotSpotBackend extends HotSpotBackend {
 
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    public static final Descriptor EXCEPTION_HANDLER = new Descriptor("exceptionHandler", true, void.class);
+    public static final Descriptor DEOPT_HANDLER = new Descriptor("deoptHandler", true, void.class);
+    public static final Descriptor IC_MISS_HANDLER = new Descriptor("icMissHandler", true, void.class);
+
     public AMD64HotSpotBackend(HotSpotRuntime runtime, TargetDescription target) {
         super(runtime, target);
     }
 
     @Override
     public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-        return new HotSpotAMD64LIRGenerator(graph, runtime(), target, frameMap, method, lir);
+        return new AMD64HotSpotLIRGenerator(graph, runtime(), target, frameMap, method, lir);
     }
 
-    static final class HotSpotAMD64LIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator {
-
-        private HotSpotRuntime runtime() {
-            return (HotSpotRuntime) runtime;
-        }
-
-        private HotSpotAMD64LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-            super(graph, runtime, target, frameMap, method, lir);
-        }
-
-        @Override
-        protected boolean needOnlyOopMaps() {
-            // Stubs only need oop maps
-            return runtime().asStub(method) != null;
-        }
-
-        @Override
-        protected CallingConvention createCallingConvention() {
-            Stub stub = runtime().asStub(method);
-            if (stub != null) {
-                return stub.getLinkage().getCallingConvention();
-            }
-
-            if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) {
-                return super.createCallingConvention();
-            } else {
-                return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), new JavaType[]{runtime.lookupJavaType(long.class)}, target, false);
-            }
-        }
-
-        @Override
-        public void visitSafepointNode(SafepointNode i) {
-            LIRFrameState info = state();
-            append(new AMD64SafepointOp(info, runtime().config));
-        }
-
-        @Override
-        public void visitExceptionObject(ExceptionObjectNode x) {
-            HotSpotVMConfig config = runtime().config;
-            RegisterValue thread = runtime().threadRegister().asValue();
-            Address exceptionAddress = new Address(Kind.Object, thread, config.threadExceptionOopOffset);
-            Address pcAddress = new Address(Kind.Long, thread, config.threadExceptionPcOffset);
-            Value exception = emitLoad(exceptionAddress, false);
-            emitStore(exceptionAddress, Constant.NULL_OBJECT, false);
-            emitStore(pcAddress, Constant.LONG_0, false);
-            setResult(x, exception);
-        }
+    /**
+     * Emits code to do stack overflow checking.
+     * 
+     * @param afterFrameInit specifies if the stack pointer has already been adjusted to allocate
+     *            the current frame
+     */
+    protected static void emitStackOverflowCheck(TargetMethodAssembler tasm, boolean afterFrameInit) {
+        if (GraalOptions.StackShadowPages > 0) {
 
-        @SuppressWarnings("hiding")
-        @Override
-        public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
-            Kind kind = x.newValue().kind();
-            assert kind == x.expectedValue().kind();
-
-            Value expected = loadNonConst(operand(x.expectedValue()));
-            Variable newVal = load(operand(x.newValue()));
-
-            int disp = 0;
-            Address address;
-            Value index = operand(x.offset());
-            if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) {
-                assert !runtime.needsDataPatch(asConstant(index));
-                disp += (int) ValueUtil.asConstant(index).asLong();
-                address = new Address(kind, load(operand(x.object())), disp);
-            } else {
-                address = new Address(kind, load(operand(x.object())), load(index), Address.Scale.Times1, disp);
+            AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
+            int frameSize = tasm.frameMap.frameSize();
+            if (frameSize > 0) {
+                int lastFramePage = frameSize / unsafe.pageSize();
+                // emit multiple stack bangs for methods with frames larger than a page
+                for (int i = 0; i <= lastFramePage; i++) {
+                    int disp = (i + GraalOptions.StackShadowPages) * unsafe.pageSize();
+                    if (afterFrameInit) {
+                        disp -= frameSize;
+                    }
+                    tasm.blockComment("[stack overflow check]");
+                    asm.movq(new AMD64Address(rsp, -disp), AMD64.rax);
+                }
             }
-
-            RegisterValue rax = AMD64.rax.asValue(kind);
-            emitMove(expected, rax);
-            append(new CompareAndSwapOp(rax, address, rax, newVal));
-
-            Variable result = newVariable(x.kind());
-            emitMove(rax, result);
-            setResult(x, result);
-        }
-
-        @Override
-        public void emitTailcall(Value[] args, Value address) {
-            append(new AMD64TailcallOp(args, address));
-
-        }
-
-        @Override
-        protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-            append(new AMD64DirectCallOp(callTarget.target(), result, parameters, temps, callState, ((HotSpotDirectCallTargetNode) callTarget).invokeKind(), lir));
-        }
-
-        @Override
-        protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-            Value metaspaceMethod = AMD64.rbx.asValue();
-            emitMove(operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()), metaspaceMethod);
-            Value targetAddress = AMD64.rax.asValue();
-            emitMove(operand(callTarget.computedAddress()), targetAddress);
-            append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
         }
     }
 
@@ -171,13 +102,11 @@
 
             AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
             emitStackOverflowCheck(tasm, false);
-            asm.push(rbp);
-            asm.movq(rbp, rsp);
-            asm.decrementq(rsp, frameSize - 8); // account for the push of RBP above
+            asm.decrementq(rsp, frameSize);
             if (GraalOptions.ZapStackOnMethodEntry) {
                 final int intSize = 4;
                 for (int i = 0; i < frameSize / intSize; ++i) {
-                    asm.movl(new Address(Kind.Int, rsp.asValue(), i * intSize), 0xC1C1C1C1);
+                    asm.movl(new AMD64Address(rsp, i * intSize), 0xC1C1C1C1);
                 }
             }
             CalleeSaveLayout csl = frameMap.registerConfig.getCalleeSaveLayout();
@@ -193,61 +122,43 @@
             int frameSize = tasm.frameMap.frameSize();
             AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
             CalleeSaveLayout csl = tasm.frameMap.registerConfig.getCalleeSaveLayout();
-            RegisterConfig regConfig = tasm.frameMap.registerConfig;
 
             if (csl != null && csl.size != 0) {
-                tasm.targetMethod.setRegisterRestoreEpilogueOffset(asm.codeBuffer.position());
+                tasm.compilationResult.setRegisterRestoreEpilogueOffset(asm.codeBuffer.position());
                 // saved all registers, restore all registers
                 int frameToCSA = tasm.frameMap.offsetToCalleeSaveArea();
                 asm.restore(csl, frameToCSA);
             }
 
-            asm.incrementq(rsp, frameSize - 8); // account for the pop of RBP below
-            asm.pop(rbp);
-
-            if (GraalOptions.GenSafepoints) {
-                HotSpotVMConfig config = runtime().config;
-
-                // If at the return point, then the frame has already been popped
-                // so deoptimization cannot be performed here. The HotSpot runtime
-                // detects this case - see the definition of frame::should_be_deoptimized()
-
-                Register scratch = regConfig.getScratchRegister();
-                int offset = SafepointPollOffset % target.pageSize;
-                if (config.isPollingPageFar) {
-                    asm.movq(scratch, config.safepointPollingAddress + offset);
-                    tasm.recordMark(Marks.MARK_POLL_RETURN_FAR);
-                    asm.movq(scratch, new Address(tasm.target.wordKind, scratch.asValue()));
-                } else {
-                    tasm.recordMark(Marks.MARK_POLL_RETURN_NEAR);
-                    // The C++ code transforms the polling page offset into an RIP displacement
-                    // to the real address at that offset in the polling page.
-                    asm.movq(scratch, new Address(tasm.target.wordKind, rip.asValue(), offset));
-                }
-            }
+            asm.incrementq(rsp, frameSize);
         }
     }
 
     @Override
-    public TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir) {
+    public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
         // Omit the frame if the method:
         // - has no spill slots or other slots allocated during register allocation
         // - has no callee-saved registers
         // - has no incoming arguments passed on the stack
         // - has no instructions with debug info
-        boolean omitFrame = GraalOptions.CanOmitFrame && frameMap.frameSize() == frameMap.initialFrameSize && frameMap.registerConfig.getCalleeSaveLayout().registers.length == 0 &&
-                        !lir.hasArgInCallerFrame() && !lir.hasDebugInfo();
+        AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen;
+        FrameMap frameMap = gen.frameMap;
+        LIR lir = gen.lir;
+        boolean omitFrame = CanOmitFrame && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
 
         AbstractAssembler masm = new AMD64MacroAssembler(target, frameMap.registerConfig);
         HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext();
-        TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, lir.stubs);
+        TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult);
         tasm.setFrameSize(frameMap.frameSize());
-        tasm.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea());
+        StackSlot deoptimizationRescueSlot = gen.deoptimizationRescueSlot;
+        if (deoptimizationRescueSlot != null) {
+            tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
+        }
         return tasm;
     }
 
     @Override
-    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir) {
+    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen) {
         AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
         FrameMap frameMap = tasm.frameMap;
         RegisterConfig regConfig = frameMap.registerConfig;
@@ -263,10 +174,10 @@
             Register inlineCacheKlass = rax; // see definition of IC_Klass in
                                              // c1_LIRAssembler_x86.cpp
             Register receiver = asRegister(cc.getArgument(0));
-            Address src = new Address(target.wordKind, receiver.asValue(), config.hubOffset);
+            AMD64Address src = new AMD64Address(receiver, config.hubOffset);
 
             asm.cmpq(inlineCacheKlass, src);
-            asm.jcc(ConditionFlag.notEqual, unverifiedStub);
+            asm.jcc(ConditionFlag.NotEqual, unverifiedStub);
         }
 
         asm.align(config.codeEntryAlignment);
@@ -274,31 +185,23 @@
         tasm.recordMark(Marks.MARK_VERIFIED_ENTRY);
 
         // Emit code for the LIR
-        lir.emitCode(tasm);
+        lirGen.lir.emitCode(tasm);
 
         boolean frameOmitted = tasm.frameContext == null;
         if (!frameOmitted) {
             tasm.recordMark(Marks.MARK_EXCEPTION_HANDLER_ENTRY);
-            AMD64Call.directCall(tasm, asm, config.handleExceptionStub, null);
-            AMD64Call.shouldNotReachHere(tasm, asm);
-
+            AMD64Call.directCall(tasm, asm, runtime().lookupRuntimeCall(EXCEPTION_HANDLER), null, false, null);
             tasm.recordMark(Marks.MARK_DEOPT_HANDLER_ENTRY);
-            AMD64Call.directCall(tasm, asm, config.handleDeoptStub, null);
-            AMD64Call.shouldNotReachHere(tasm, asm);
+            AMD64Call.directCall(tasm, asm, runtime().lookupRuntimeCall(DEOPT_HANDLER), null, false, null);
         } else {
             // No need to emit the stubs for entries back into the method since
             // it has no calls that can cause such "return" entries
-            assert !frameMap.accessesCallerFrame();
+            assert !frameMap.accessesCallerFrame() : method;
         }
 
         if (unverifiedStub != null) {
             asm.bind(unverifiedStub);
-            AMD64Call.directJmp(tasm, asm, config.inlineCacheMissStub);
+            AMD64Call.directJmp(tasm, asm, runtime().lookupRuntimeCall(IC_MISS_HANDLER));
         }
-
-        for (int i = 0; i < GraalOptions.MethodEndBreakpointGuards; ++i) {
-            asm.int3();
-        }
-
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+
+/**
+ * Superclass for operations that use the value of RBP saved in a method's prologue.
+ */
+abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction {
+
+    /**
+     * The type of location (i.e., stack or register) in which RBP is saved is not known until
+     * initial LIR generation is finished. Until then, we use a placeholder variable so that LIR
+     * verification is successful.
+     */
+    private static final Variable PLACEHOLDER = new Variable(Kind.Long, Integer.MAX_VALUE, Register.RegisterFlag.CPU);
+
+    @Use({REG, STACK}) protected AllocatableValue savedRbp = PLACEHOLDER;
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java	Thu Mar 21 14:11:13 2013 +0100
@@ -47,11 +47,9 @@
 
     @Override
     protected TargetDescription createTarget() {
-        final int wordSize = 8;
         final int stackFrameAlignment = 16;
-        final int stackBias = 0;
         final int implicitNullCheckLimit = 4096;
-        return new TargetDescription(new AMD64(), true, stackFrameAlignment, stackBias, implicitNullCheckLimit, config.vmPageSize, wordSize, true, true);
+        return new TargetDescription(new AMD64(), true, stackFrameAlignment, implicitNullCheckLimit, true);
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.api.code.CallingConvention.Type.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.amd64.AMD64HotSpotUnwindOp.*;
+
+import java.util.*;
+
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.amd64.AMD64Address.*;
+import com.oracle.graal.compiler.amd64.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64Move.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.*;
+
+/**
+ * LIR generator specialized for AMD64 HotSpot.
+ */
+final class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator {
+
+    private HotSpotRuntime runtime() {
+        return (HotSpotRuntime) runtime;
+    }
+
+    AMD64HotSpotLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
+        super(graph, runtime, target, frameMap, method, lir);
+    }
+
+    /**
+     * The slot reserved for storing the original return address when a frame is marked for
+     * deoptimization. The return address slot in the callee is overwritten with the address of a
+     * deoptimization stub.
+     */
+    StackSlot deoptimizationRescueSlot;
+
+    /**
+     * The position at which the instruction for saving RBP should be inserted.
+     */
+    Block saveRbpBlock;
+    int saveRbpIndex;
+
+    /**
+     * The slot reserved for saving RBP.
+     */
+    StackSlot rbpSlot;
+
+    /**
+     * List of epilogue operations that need to restore RBP.
+     */
+    List<AMD64HotSpotEpilogueOp> epilogueOps = new ArrayList<>(2);
+
+    @Override
+    protected void emitPrologue() {
+
+        CallingConvention incomingArguments = createCallingConvention();
+
+        RegisterValue rbpParam = rbp.asValue(Kind.Long);
+        Value[] params = new Value[incomingArguments.getArgumentCount() + 1];
+        for (int i = 0; i < params.length - 1; i++) {
+            params[i] = toStackKind(incomingArguments.getArgument(i));
+            if (isStackSlot(params[i])) {
+                StackSlot slot = ValueUtil.asStackSlot(params[i]);
+                if (slot.isInCallerFrame() && !lir.hasArgInCallerFrame()) {
+                    lir.setHasArgInCallerFrame();
+                }
+            }
+        }
+        params[params.length - 1] = rbpParam;
+
+        ParametersOp paramsOp = new ParametersOp(params);
+        append(paramsOp);
+        saveRbpBlock = currentBlock;
+        saveRbpIndex = lir.lir(saveRbpBlock).size();
+        append(paramsOp); // placeholder
+        rbpSlot = frameMap.allocateSpillSlot(Kind.Long);
+        assert rbpSlot.getRawOffset() == -16 : rbpSlot.getRawOffset();
+
+        for (LocalNode local : graph.getNodes(LocalNode.class)) {
+            Value param = params[local.index()];
+            assert param.getKind() == local.kind().getStackKind();
+            setResult(local, emitMove(param));
+        }
+    }
+
+    @Override
+    protected void emitReturn(Value input) {
+        AMD64HotSpotReturnOp op = new AMD64HotSpotReturnOp(input);
+        epilogueOps.add(op);
+        append(op);
+    }
+
+    @Override
+    protected boolean needOnlyOopMaps() {
+        // Stubs only need oop maps
+        return runtime().asStub(method) != null;
+    }
+
+    @Override
+    protected CallingConvention createCallingConvention() {
+        Stub stub = runtime().asStub(method);
+        if (stub != null) {
+            return stub.getLinkage().getCallingConvention();
+        }
+
+        if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) {
+            return super.createCallingConvention();
+        } else {
+            return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), new JavaType[]{runtime.lookupJavaType(long.class)}, target, false);
+        }
+    }
+
+    @Override
+    public void visitSafepointNode(SafepointNode i) {
+        LIRFrameState info = state();
+        append(new AMD64SafepointOp(info, runtime().config, this));
+    }
+
+    @Override
+    public void visitExceptionObject(ExceptionObjectNode x) {
+        HotSpotVMConfig config = runtime().config;
+        RegisterValue thread = runtime().threadRegister().asValue();
+        Value exception = emitLoad(Kind.Object, thread, config.threadExceptionOopOffset, Value.ILLEGAL, 0, false);
+        emitStore(Kind.Object, thread, config.threadExceptionOopOffset, Value.ILLEGAL, 0, Constant.NULL_OBJECT, false);
+        emitStore(Kind.Long, thread, config.threadExceptionPcOffset, Value.ILLEGAL, 0, Constant.LONG_0, false);
+        setResult(x, exception);
+    }
+
+    @SuppressWarnings("hiding")
+    @Override
+    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
+        Kind kind = x.newValue().kind();
+        assert kind == x.expectedValue().kind();
+
+        Value expected = loadNonConst(operand(x.expectedValue()));
+        Variable newVal = load(operand(x.newValue()));
+
+        int disp = 0;
+        AMD64AddressValue address;
+        Value index = operand(x.offset());
+        if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) {
+            assert !runtime.needsDataPatch(asConstant(index));
+            disp += (int) ValueUtil.asConstant(index).asLong();
+            address = new AMD64AddressValue(kind, load(operand(x.object())), disp);
+        } else {
+            address = new AMD64AddressValue(kind, load(operand(x.object())), load(index), Scale.Times1, disp);
+        }
+
+        RegisterValue rax = AMD64.rax.asValue(kind);
+        emitMove(rax, expected);
+        append(new CompareAndSwapOp(rax, address, rax, newVal));
+
+        Variable result = newVariable(x.kind());
+        emitMove(result, rax);
+        setResult(x, result);
+    }
+
+    @Override
+    public void emitTailcall(Value[] args, Value address) {
+        append(new AMD64TailcallOp(args, address));
+
+    }
+
+    @Override
+    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
+        if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
+            append(new AMD64HotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
+        } else {
+            assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
+            HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
+            Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
+            append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
+        }
+    }
+
+    @Override
+    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        Value metaspaceMethod = AMD64.rbx.asValue();
+        emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
+        Value targetAddress = AMD64.rax.asValue();
+        emitMove(targetAddress, operand(callTarget.computedAddress()));
+        append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
+    }
+
+    @Override
+    public void emitUnwind(Value exception) {
+        RegisterValue exceptionParameter = EXCEPTION.asValue();
+        emitMove(exceptionParameter, exception);
+        AMD64HotSpotUnwindOp op = new AMD64HotSpotUnwindOp(exceptionParameter);
+        epilogueOps.add(op);
+        append(op);
+    }
+
+    @Override
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
+        append(new AMD64DeoptimizeOp(action, reason, state()));
+    }
+
+    @Override
+    public void beforeRegisterAllocation() {
+        assert rbpSlot != null;
+        RegisterValue rbpParam = rbp.asValue(Kind.Long);
+        AllocatableValue savedRbp;
+        LIRInstruction saveRbp;
+        if (lir.hasDebugInfo()) {
+            savedRbp = rbpSlot;
+            deoptimizationRescueSlot = frameMap.allocateSpillSlot(Kind.Long);
+        } else {
+            frameMap.freeSpillSlot(rbpSlot);
+            savedRbp = newVariable(Kind.Long);
+        }
+
+        for (AMD64HotSpotEpilogueOp op : epilogueOps) {
+            op.savedRbp = savedRbp;
+        }
+
+        saveRbp = new MoveFromRegOp(savedRbp, rbpParam);
+        lir.lir(saveRbpBlock).set(saveRbpIndex, saveRbp);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Thu Mar 21 14:11:13 2013 +0100
@@ -33,16 +33,12 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.phases.*;
 
 // @formatter:off
 public class AMD64HotSpotRegisterConfig implements RegisterConfig {
 
-    // be careful - the contents of this array are duplicated in graal_CodeInstaller.cpp
-    private final Register[] allocatable = {
-        rax, rbx, rcx, rdx, rsi, rdi, r8, r9, /* r10, */r11, r12, r13, r14, /*r15*/
-        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
-        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
-    };
+    private final Register[] allocatable = initAllocatable();
 
     private final EnumMap<RegisterFlag, Register[]> categorized = Register.categorize(allocatable);
 
@@ -69,6 +65,34 @@
 
     private final CalleeSaveLayout csl;
 
+    private static Register findRegister(String name, Register[] all) {
+        for (Register reg : all) {
+            if (reg.name.equals(name)) {
+                return reg;
+            }
+        }
+        throw new IllegalArgumentException("register " + name + " is not allocatable");
+    }
+
+    private static Register[] initAllocatable() {
+        Register[] allocatable = {
+                        rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9,  r10, r11, r12, r13, r14, /*r15, */
+                        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+                        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+                    };
+
+        if (GraalOptions.RegisterPressure != null) {
+            String[] names = GraalOptions.RegisterPressure.split(",");
+            Register[] regs = new Register[names.length];
+            for (int i = 0; i < names.length; i++) {
+                regs[i] = findRegister(names[i], allocatable);
+            }
+            return regs;
+        }
+
+        return allocatable;
+    }
+
     public AMD64HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) {
         if (config.windowsOs) {
             javaGeneralParameterRegisters = new Register[] {rdx, r8, r9, rdi, rsi, rcx};
@@ -87,12 +111,7 @@
             };
             csl = new CalleeSaveLayout(0, -1, 8, regs);
         } else {
-            // We reserve space for saving RBP but don't explicitly specify
-            // it as a callee save register since we explicitly do the saving
-            // with push and pop in HotSpotFrameContext
-            final int size = 8;
-            final Register[] regs = {};
-            csl = new CalleeSaveLayout(0, size, 8, regs);
+            csl = null;
         }
 
         attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters);
@@ -191,11 +210,6 @@
     }
 
     @Override
-    public Register getScratchRegister() {
-        return r10;
-    }
-
-    @Override
     public Register getFrameRegister() {
         return rsp;
     }
@@ -209,8 +223,7 @@
         String res = String.format(
              "Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" +
              "CallerSave:  " + Arrays.toString(getCallerSaveRegisters()) + "%n" +
-             "CalleeSave:  " + getCalleeSaveLayout() + "%n" +
-             "Scratch:     " + getScratchRegister() + "%n");
+             "CalleeSave:  " + getCalleeSaveLayout() + "%n");
         return res;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Performs an unwind to throw an exception.
+ */
+@Opcode("RETURN")
+final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp {
+
+    @Use({REG, ILLEGAL}) protected Value value;
+
+    AMD64HotSpotReturnOp(Value value) {
+        this.value = value;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        if (isStackSlot(savedRbp)) {
+            // Restoring RBP from the stack must be done before the frame is removed
+            masm.movq(rbp, (AMD64Address) tasm.asAddress(savedRbp));
+        } else {
+            Register framePointer = asRegister(savedRbp);
+            if (framePointer != rbp) {
+                masm.movq(rbp, framePointer);
+            }
+        }
+        if (tasm.frameContext != null) {
+            tasm.frameContext.leave(tasm);
+        }
+        masm.ret(0);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,8 +23,9 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.amd64.AMD64.*;
-import static com.oracle.graal.compiler.amd64.AMD64DeoptimizationStub.*;
 import static com.oracle.graal.compiler.amd64.AMD64LIRGenerator.*;
+import static com.oracle.graal.hotspot.amd64.AMD64DeoptimizeOp.*;
+import static com.oracle.graal.hotspot.amd64.AMD64HotSpotUnwindOp.*;
 import static com.oracle.graal.hotspot.nodes.IdentityHashCodeStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
@@ -42,12 +43,17 @@
 import static com.oracle.graal.hotspot.snippets.AESCryptSubstitutions.EncryptBlockStubCall.*;
 import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*;
 import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*;
-import static com.oracle.graal.lir.amd64.AMD64Call.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.snippets.*;
+import com.oracle.graal.snippets.amd64.*;
 
 public class AMD64HotSpotRuntime extends HotSpotRuntime {
 
@@ -57,20 +63,15 @@
         Kind word = graalRuntime.getTarget().wordKind;
 
         // @formatter:off
+        addRuntimeCall(UNWIND_EXCEPTION, config.unwindExceptionStub,
+               /*           temps */ null,
+               /*             ret */ ret(Kind.Void),
+               /* arg0: exception */ rax.asValue(Kind.Object));
 
         addRuntimeCall(DEOPTIMIZE, config.deoptimizeStub,
                 /*           temps */ null,
                 /*             ret */ ret(Kind.Void));
 
-        addRuntimeCall(SET_DEOPT_INFO, config.setDeoptInfoStub,
-                /*           temps */ null,
-                /*             ret */ ret(Kind.Void),
-                /* arg0:      info */ scratch(Kind.Object));
-
-        addRuntimeCall(DEBUG, config.debugStub,
-                /*           temps */ null,
-                /*             ret */ ret(Kind.Void));
-
         addRuntimeCall(ARITHMETIC_FREM, config.arithmeticFremStub,
                 /*           temps */ null,
                 /*             ret */ ret(Kind.Float),
@@ -189,10 +190,39 @@
                 /* arg3:      r */                         word,
               /* arg4: inLength */                         Kind.Int));
 
+        addRuntimeCall(AMD64HotSpotBackend.EXCEPTION_HANDLER, config.handleExceptionStub,
+                /*        temps */ null,
+                /*          ret */ ret(Kind.Void));
+
+        addRuntimeCall(AMD64HotSpotBackend.DEOPT_HANDLER, config.handleDeoptStub,
+                /*        temps */ null,
+                /*          ret */ ret(Kind.Void));
+
+        addRuntimeCall(AMD64HotSpotBackend.IC_MISS_HANDLER, config.inlineCacheMissStub,
+                /*        temps */ null,
+                /*          ret */ ret(Kind.Void));
         // @formatter:on
 
     }
 
+    private AMD64ConvertSnippets.Templates convertSnippets;
+
+    @Override
+    public void installSnippets(Backend backend, SnippetInstaller installer, Assumptions assumptions) {
+        installer.installSnippets(AMD64ConvertSnippets.class);
+        convertSnippets = new AMD64ConvertSnippets.Templates(this, assumptions, graalRuntime.getTarget());
+        super.installSnippets(backend, installer, assumptions);
+    }
+
+    @Override
+    public void lower(Node n, LoweringTool tool) {
+        if (n instanceof ConvertNode) {
+            convertSnippets.lower((ConvertNode) n, tool);
+        } else {
+            super.lower(n, tool);
+        }
+    }
+
     @Override
     public Register threadRegister() {
         return r15;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Performs an unwind to throw an exception.
+ */
+@Opcode("UNWIND")
+final class AMD64HotSpotUnwindOp extends AMD64HotSpotEpilogueOp {
+
+    public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", true, void.class, Object.class);
+
+    /**
+     * Unwind stub expects the exception in RAX.
+     */
+    public static final Register EXCEPTION = AMD64.rax;
+
+    @Use({REG}) protected AllocatableValue exception;
+
+    AMD64HotSpotUnwindOp(AllocatableValue exception) {
+        this.exception = exception;
+        assert asRegister(exception) == EXCEPTION;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        // Copy the saved RBP value into the slot just below the return address
+        // so that the stub can pick it up from there.
+        AMD64Address rbpSlot;
+        int rbpSlotOffset = tasm.frameMap.frameSize() - 8;
+        if (isStackSlot(savedRbp)) {
+            rbpSlot = (AMD64Address) tasm.asAddress(savedRbp);
+            assert rbpSlot.getDisplacement() == rbpSlotOffset;
+        } else {
+            rbpSlot = new AMD64Address(rsp, rbpSlotOffset);
+            masm.movq(rbpSlot, asRegister(savedRbp));
+        }
+
+        // Pass the address of the RBP slot in RBP itself
+        masm.leaq(rbp, rbpSlot);
+        AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(UNWIND_EXCEPTION), AMD64.r10, false, null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+
+/**
+ * A direct call that complies with the conventions for such calls in HotSpot. In particular, for
+ * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call.
+ * This instruction (which moves 0L in RAX) is patched by the C++ Graal code to replace the 0L
+ * constant with Universe::non_oop_word(), a special sentinel used for the initial value of the
+ * Klass in an inline cache. It puts the called method into rbx before calling.
+ */
+@Opcode("CALL_DIRECT")
+final class AMD64HotspotDirectStaticCallOp extends DirectCallOp {
+
+    private final Constant metaspaceMethod;
+    private final InvokeKind invokeKind;
+
+    AMD64HotspotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, Constant metaspaceMethod) {
+        super(target, result, parameters, temps, state);
+        assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
+        this.metaspaceMethod = metaspaceMethod;
+        this.invokeKind = invokeKind;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        // The mark for an invocation that uses an inline cache must be placed at the
+        // instruction
+        // that loads the Klass from the inline cache so that the C++ code can find it
+        // and replace the inline 0L value with Universe::non_oop_word()
+        AMD64Move.move(tasm, masm, AMD64.rbx.asValue(Kind.Long), metaspaceMethod);
+        tasm.recordMark(invokeKind == InvokeKind.Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL);
+        AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Long), Constant.LONG_0);
+        super.emitCode(tasm, masm);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind.*;
+
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+
+/**
+ * A direct call that complies with the conventions for such calls in HotSpot. In particular, for
+ * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call.
+ * This instruction (which moves 0L in RAX) is patched by the C++ Graal code to replace the 0L
+ * constant with Universe::non_oop_word(), a special sentinel used for the initial value of the
+ * Klass in an inline cache.
+ */
+@Opcode("CALL_DIRECT")
+final class AMD64HotspotDirectVirtualCallOp extends DirectCallOp {
+
+    private final InvokeKind invokeKind;
+
+    AMD64HotspotDirectVirtualCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) {
+        super(target, result, parameters, temps, state);
+        this.invokeKind = invokeKind;
+        assert invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        // The mark for an invocation that uses an inline cache must be placed at the
+        // instruction
+        // that loads the Klass from the inline cache so that the C++ code can find it
+        // and replace the inline 0L value with Universe::non_oop_word()
+        tasm.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE);
+        AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Long), Constant.LONG_0);
+        super.emitCode(tasm, masm);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -52,14 +52,14 @@
 
     @Use({REG}) protected Value metaspaceMethod;
 
-    AMD64IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) {
+    AMD64IndirectCallOp(InvokeTarget targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) {
         super(targetMethod, result, parameters, temps, targetAddress, state);
         this.metaspaceMethod = metaspaceMethod;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        tasm.recordMark(Marks.MARK_INLINE_INVOKEVIRTUAL);
+        tasm.recordMark(Marks.MARK_INLINE_INVOKE);
         Register callReg = asRegister(targetAddress);
         assert callReg != METHOD;
         AMD64Call.indirectCall(tasm, masm, callReg, callTarget, state);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.phases.GraalOptions.*;
+import sun.misc.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
@@ -33,6 +34,7 @@
 import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.spi.*;
 
 /**
  * Emits a safepoint poll.
@@ -40,31 +42,35 @@
 @Opcode("SAFEPOINT")
 public class AMD64SafepointOp extends AMD64LIRInstruction {
 
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
     @State protected LIRFrameState state;
+    @Temp({OperandFlag.REG}) private AllocatableValue temp;
 
     private final HotSpotVMConfig config;
 
-    public AMD64SafepointOp(LIRFrameState state, HotSpotVMConfig config) {
+    public AMD64SafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) {
         this.state = state;
         this.config = config;
+        temp = tool.newVariable(tool.target().wordKind);
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm) {
-        Register scratch = tasm.frameMap.registerConfig.getScratchRegister();
         int pos = asm.codeBuffer.position();
-        int offset = SafepointPollOffset % tasm.target.pageSize;
+        int offset = SafepointPollOffset % unsafe.pageSize();
+        RegisterValue scratch = (RegisterValue) temp;
         if (config.isPollingPageFar) {
-            asm.movq(scratch, config.safepointPollingAddress + offset);
+            asm.movq(scratch.getRegister(), config.safepointPollingAddress + offset);
             tasm.recordMark(Marks.MARK_POLL_FAR);
             tasm.recordSafepoint(pos, state);
-            asm.movq(scratch, new Address(tasm.target.wordKind, scratch.asValue()));
+            asm.movq(scratch.getRegister(), new AMD64Address(scratch.getRegister()));
         } else {
             tasm.recordMark(Marks.MARK_POLL_NEAR);
             tasm.recordSafepoint(pos, state);
             // The C++ code transforms the polling page offset into an RIP displacement
             // to the real address at that offset in the polling page.
-            asm.movq(scratch, new Address(tasm.target.wordKind, rip.asValue(), offset));
+            asm.movq(scratch.getRegister(), new AMD64Address(rip, offset));
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/CompilationServer.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/CompilationServer.java	Thu Mar 21 14:11:13 2013 +0100
@@ -93,7 +93,6 @@
 
                 // return the initialized compiler to the client
                 HotSpotGraalRuntime compiler = initializeServer(toVM);
-                compiler.getCompiler();
                 streams.getInvocation().sendResult(compiler);
 
                 for (ConnectionObserver observer : observers) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Mar 21 14:11:13 2013 +0100
@@ -47,13 +47,13 @@
     }
 
     @Override
-    public TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir) {
+    public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
         // SPARC: Create assembler.
         return null;
     }
 
     @Override
-    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir) {
+    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen) {
         // SPARC: Emit code
     }
 }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -51,9 +51,8 @@
                     if (node instanceof Invoke) {
                         Invoke invoke = (Invoke) node;
                         Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode);
-                        DirectCallTargetNode directCall = (DirectCallTargetNode) invoke.callTarget();
-                        Assert.assertTrue(directCall.target() instanceof JavaMethod);
-                        JavaMethod callee = (JavaMethod) directCall.target();
+                        AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget();
+                        JavaMethod callee = directCall.target();
                         Assert.assertTrue(callee.getName().equals("<init>"));
                         Assert.assertTrue(runtime.lookupJavaType(ArrayIndexOutOfBoundsException.class).equals(callee.getDeclaringClass()) ||
                                         runtime.lookupJavaType(NullPointerException.class).equals(callee.getDeclaringClass()));
@@ -64,8 +63,8 @@
                 for (Node node : graph.getNodes()) {
                     if (node instanceof Invoke) {
                         Invoke invoke = (Invoke) node;
-                        DirectCallTargetNode directCall = (DirectCallTargetNode) invoke.callTarget();
-                        JavaMethod callee = (JavaMethod) directCall.target();
+                        AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget();
+                        JavaMethod callee = directCall.target();
                         if (callee.getDeclaringClass().equals(runtime.lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) {
                             found = true;
                         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.graph.*;
@@ -143,10 +144,10 @@
                         } else {
                             // Compiling an intrinsic graph - must clone the graph
                             graph = graph.copy();
-                            // System.out.println("compiling intrinsic " + method);
                         }
                         InlinedBytecodes.add(method.getCodeSize());
-                        return graalRuntime.getCompiler().compileMethod(method, graph, graalRuntime.getCache(), plan, optimisticOpts);
+                        return GraalCompiler.compileMethod(graalRuntime.getRuntime(), graalRuntime.getBackend(), graalRuntime.getTarget(), method, graph, graalRuntime.getCache(), plan,
+                                        optimisticOpts, method.getSpeculationLog());
                     }
                 });
             } finally {
@@ -176,15 +177,14 @@
         stats.finish(method);
     }
 
-    private void installMethod(final CompilationResult tm) {
-        Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getCompiler(), method}, new Runnable() {
+    private void installMethod(final CompilationResult compResult) {
+        Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getRuntime(), method}, new Runnable() {
 
             @Override
             public void run() {
-                final CodeInfo[] info = Debug.isDumpEnabled() ? new CodeInfo[1] : null;
-                graalRuntime.getRuntime().installMethod(method, entryBCI, tm, info);
-                if (info != null) {
-                    Debug.dump(new Object[]{tm, info[0]}, "After code installation");
+                HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, entryBCI, compResult);
+                if (Debug.isDumpEnabled()) {
+                    Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
             }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,7 +30,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -109,13 +109,13 @@
     protected/* final */VMToCompiler vmToCompiler;
 
     protected final HotSpotRuntime runtime;
-    protected final GraalCompiler compiler;
     protected final TargetDescription target;
 
     private HotSpotRuntimeInterpreterInterface runtimeInterpreterInterface;
     private volatile HotSpotGraphCache cache;
 
     protected final HotSpotVMConfig config;
+    private final HotSpotBackend backend;
 
     protected HotSpotGraalRuntime() {
         CompilerToVM toVM = new CompilerToVMImpl();
@@ -139,9 +139,8 @@
 
         runtime = createRuntime();
 
-        HotSpotBackend backend = createBackend();
+        backend = createBackend();
         GraalOptions.StackShadowPages = config.stackShadowPages;
-        compiler = new GraalCompiler(getRuntime(), getTarget(), backend);
         if (GraalOptions.CacheGraphs) {
             cache = new HotSpotGraphCache();
         }
@@ -176,10 +175,6 @@
         return target;
     }
 
-    public GraalCompiler getCompiler() {
-        return compiler;
-    }
-
     public HotSpotGraphCache getCache() {
         return cache;
     }
@@ -211,8 +206,6 @@
                     break;
                 case Int:
                     return impl.typeInt;
-                case Jsr:
-                    break;
                 case Long:
                     return impl.typeLong;
                 case Object:
@@ -264,9 +257,16 @@
         if (clazz == DisassemblerProvider.class || clazz == BytecodeDisassemblerProvider.class) {
             return (T) getRuntime();
         }
-        if (clazz == GraalCompiler.class) {
-            return (T) getCompiler();
+        if (clazz == HotSpotRuntime.class) {
+            return (T) runtime;
+        }
+        if (clazz == Backend.class) {
+            return (T) getBackend();
         }
         return null;
     }
+
+    public HotSpotBackend getBackend() {
+        return backend;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,7 +30,7 @@
 /**
  * The details required to link a HotSpot runtime or stub call.
  */
-public class HotSpotRuntimeCallTarget implements RuntimeCallTarget {
+public class HotSpotRuntimeCallTarget implements RuntimeCallTarget, InvokeTarget {
 
     /**
      * The descriptor of the stub. This is for informational purposes only.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSnippetInstaller.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSnippetInstaller.java	Thu Mar 21 14:11:13 2013 +0100
@@ -42,7 +42,7 @@
     }
 
     @Override
-    protected void installMethodSubstitution(Method originalMethod, Method substituteMethod) {
+    protected void installMethodSubstitution(Member originalMethod, Method substituteMethod) {
         if (substituteMethod.getDeclaringClass() == IntegerSubstitutions.class || substituteMethod.getDeclaringClass() == LongSubstitutions.class) {
             if (substituteMethod.getName().equals("bitCount")) {
                 if (!config.usePopCountInstruction) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Mar 21 14:11:13 2013 +0100
@@ -45,7 +45,6 @@
     public boolean useG1GC;
 
     // offsets, ...
-    public int vmPageSize;
     public int stackShadowPages;
 
     /**
@@ -171,6 +170,11 @@
     public int uninitializedIdentityHashCodeValue;
 
     /**
+     * Offset of the pending deoptimization field.
+     */
+    public int pendingDeoptimizationOffset;
+
+    /**
      * Mark word right shift to get identity hash code.
      */
     public int identityHashCodeShift;
@@ -316,8 +320,6 @@
     public int typeProfileWidth;
 
     // runtime stubs
-    public long debugStub;
-    public long instanceofStub;
     public long newInstanceStub;
     public long newArrayStub;
     public long newMultiArrayStub;
@@ -335,7 +337,6 @@
     public long unwindExceptionStub;
     public long osrMigrationEndStub;
     public long registerFinalizerStub;
-    public long setDeoptInfoStub;
     public long createNullPointerExceptionStub;
     public long createOutOfBoundsExceptionStub;
     public long javaTimeMillisStub;
@@ -376,7 +377,6 @@
     public int deoptActionMakeNotCompilable;
 
     public void check() {
-        assert vmPageSize >= 16;
         assert codeEntryAlignment > 0;
         assert stackShadowPages > 0;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,6 +25,7 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -148,11 +149,9 @@
      * @param compResult the result of a compilation
      * @param code if not null, then the code is installed as the non-default compiled code for the
      *            associated method and the details of the installation are written to this object
-     * @param info additional information about the installation are written to this object if it is
-     *            not null
      * @return the outcome of the installation as a {@link CodeInstallResult}.
      */
-    CodeInstallResult installCode(HotSpotCompilationResult compResult, HotSpotInstalledCode code, HotSpotCodeInfo info);
+    CodeInstallResult installCode(HotSpotCompilationResult compResult, HotSpotInstalledCode code, SpeculationLog cache);
 
     void initializeConfiguration(HotSpotVMConfig config);
 
@@ -189,9 +188,14 @@
 
     long getMaxCallTargetOffset(long stub);
 
-    String disassembleNative(byte[] code, long address);
+    String disassembleNMethod(long nmethod);
 
-    String disassembleNMethod(long nmethod);
+    /**
+     * Gets a copy of the machine code for an nmethod.
+     * 
+     * @return the machine code for {@code nmethod} if it is valid, null otherwise
+     */
+    byte[] getCode(long nmethod);
 
     StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
@@ -203,8 +207,6 @@
 
     long[] getDeoptedLeafGraphIds();
 
-    String decodePC(long pc);
-
     long[] getLineNumberTable(HotSpotResolvedJavaMethod method);
 
     Local[] getLocalVariableTable(HotSpotResolvedJavaMethod method);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,6 +25,7 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -34,11 +35,11 @@
  */
 public class CompilerToVMImpl implements CompilerToVM {
 
-    private native int installCode0(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info);
+    private native int installCode0(HotSpotCompilationResult comp, HotSpotInstalledCode code, boolean[] triggeredDeoptimizations);
 
     @Override
-    public CodeInstallResult installCode(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info) {
-        return CodeInstallResult.values()[installCode0(comp, code, info)];
+    public CodeInstallResult installCode(HotSpotCompilationResult comp, HotSpotInstalledCode code, SpeculationLog speculationLog) {
+        return CodeInstallResult.values()[installCode0(comp, code, (speculationLog == null) ? null : speculationLog.getRawMap())];
     }
 
     @Override
@@ -123,10 +124,10 @@
     public native long getMaxCallTargetOffset(long stub);
 
     @Override
-    public native String disassembleNative(byte[] code, long address);
+    public native String disassembleNMethod(long nmethod);
 
     @Override
-    public native String disassembleNMethod(long nmethod);
+    public native byte[] getCode(long nmethod);
 
     @Override
     public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
@@ -144,9 +145,6 @@
     public native long[] getDeoptedLeafGraphIds();
 
     @Override
-    public native String decodePC(long pc);
-
-    @Override
     public native long[] getLineNumberTable(HotSpotResolvedJavaMethod method);
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/Marks.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/Marks.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,24 +29,18 @@
  */
 public interface Marks {
 
-    // @formatter:off
-    // These constants need to correspond to those of the same name in graalCodeInstaller.hpp
-    Integer MARK_VERIFIED_ENTRY            = 0x0001;
-    Integer MARK_UNVERIFIED_ENTRY          = 0x0002;
-    Integer MARK_OSR_ENTRY                 = 0x0003;
-    Integer MARK_UNWIND_ENTRY              = 0x0004;
-    Integer MARK_EXCEPTION_HANDLER_ENTRY   = 0x0005;
-    Integer MARK_DEOPT_HANDLER_ENTRY       = 0x0006;
-    Integer MARK_STATIC_CALL_STUB          = 0x1000;
-    Integer MARK_INVOKEINTERFACE           = 0x2001;
-    Integer MARK_INVOKESTATIC              = 0x2002;
-    Integer MARK_INVOKESPECIAL             = 0x2003;
-    Integer MARK_INVOKEVIRTUAL             = 0x2004;
-    Integer MARK_INLINE_INVOKEVIRTUAL      = 0x2005;
-    Integer MARK_IMPLICIT_NULL             = 0x3000;
-    Integer MARK_POLL_NEAR                 = 0x3001;
-    Integer MARK_POLL_RETURN_NEAR          = 0x3002;
-    Integer MARK_POLL_FAR                  = 0x3003;
-    Integer MARK_POLL_RETURN_FAR           = 0x3004;
-
+    int MARK_VERIFIED_ENTRY = 1;
+    int MARK_UNVERIFIED_ENTRY = 2;
+    int MARK_OSR_ENTRY = 3;
+    int MARK_EXCEPTION_HANDLER_ENTRY = 4;
+    int MARK_DEOPT_HANDLER_ENTRY = 5;
+    int MARK_INVOKEINTERFACE = 6;
+    int MARK_INVOKEVIRTUAL = 7;
+    int MARK_INVOKESTATIC = 8;
+    int MARK_INVOKESPECIAL = 9;
+    int MARK_INLINE_INVOKE = 10;
+    int MARK_POLL_NEAR = 11;
+    int MARK_POLL_RETURN_NEAR = 12;
+    int MARK_POLL_FAR = 13;
+    int MARK_POLL_RETURN_FAR = 14;
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Mar 21 14:11:13 2013 +0100
@@ -36,7 +36,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.hotspot.*;
@@ -143,10 +142,9 @@
         }
 
         // Install intrinsics.
-        GraalCompiler compiler = graalRuntime.getCompiler();
-        final HotSpotRuntime runtime = (HotSpotRuntime) compiler.runtime;
+        final HotSpotRuntime runtime = graalRuntime.getCapability(HotSpotRuntime.class);
         if (GraalOptions.Intrinsify) {
-            Debug.scope("InstallSnippets", new Object[]{new DebugDumpScope("InstallSnippets"), compiler}, new Runnable() {
+            Debug.scope("InstallSnippets", new Object[]{new DebugDumpScope("InstallSnippets")}, new Runnable() {
 
                 @Override
                 public void run() {
@@ -155,7 +153,7 @@
                     Assumptions assumptions = new Assumptions(false);
                     SnippetInstaller installer = new HotSpotSnippetInstaller(runtime, assumptions, runtime.getGraalRuntime().getTarget());
                     GraalIntrinsics.installIntrinsics(installer);
-                    runtime.installSnippets(installer, assumptions);
+                    runtime.installSnippets(graalRuntime.getBackend(), installer, assumptions);
                 }
             });
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeInfo.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.meta;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.*;
-
-/**
- * Implementation of {@link CodeInfo} for HotSpot.
- */
-public class HotSpotCodeInfo extends CompilerObject implements CodeInfo {
-
-    private static final long serialVersionUID = -6766490427732498354L;
-
-    private long start;
-    private byte[] code;
-    public final CompilationResult targetMethod;
-    private HotSpotResolvedJavaMethod method;
-
-    public HotSpotCodeInfo(CompilationResult targetMethod, HotSpotResolvedJavaMethod method) {
-        assert targetMethod != null;
-        this.method = method;
-        this.targetMethod = targetMethod;
-    }
-
-    @Override
-    public long getStart() {
-        return start;
-    }
-
-    @Override
-    public byte[] getCode() {
-        return code;
-    }
-
-    @Override
-    public String toString() {
-        int size = code == null ? 0 : code.length;
-        return "installed code @[" + Long.toHexString(start) + "-" + Long.toHexString(start + size) + "]";
-
-    }
-
-    @Override
-    public ResolvedJavaMethod getMethod() {
-        return method;
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -38,10 +38,17 @@
     private static final long serialVersionUID = 156632908220561612L;
 
     private final HotSpotResolvedJavaMethod method;
+    private final boolean isDefault;
     long nmethod;
+    long start;
 
-    public HotSpotInstalledCode(HotSpotResolvedJavaMethod method) {
+    public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, boolean isDefault) {
         this.method = method;
+        this.isDefault = isDefault;
+    }
+
+    public boolean isDefault() {
+        return isDefault;
     }
 
     @Override
@@ -87,4 +94,14 @@
         assert checkArgs(args);
         return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(method.metaspaceMethod, nmethod, args);
     }
+
+    @Override
+    public long getStart() {
+        return isValid() ? start : 0;
+    }
+
+    @Override
+    public byte[] getCode() {
+        return HotSpotGraalRuntime.getInstance().getCompilerToVM().getCode(nmethod);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,6 +30,7 @@
 import java.util.*;
 import java.util.concurrent.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.ExceptionSeen;
 import com.oracle.graal.bytecode.*;
@@ -58,8 +59,8 @@
     private HotSpotMethodData methodData;
     private byte[] code;
     private int compilationComplexity;
-
     private CompilationTask currentTask;
+    private SpeculationLog speculationLog;
 
     HotSpotResolvedJavaMethod(HotSpotResolvedObjectType holder, long metaspaceMethod) {
         this.metaspaceMethod = metaspaceMethod;
@@ -72,6 +73,13 @@
         return holder;
     }
 
+    /**
+     * Gets the address of the C++ Method object for this method.
+     */
+    public Constant getMetaspaceMethodConstant() {
+        return Constant.forIntegerKind(HotSpotGraalRuntime.getInstance().getTarget().wordKind, metaspaceMethod, this);
+    }
+
     @Override
     public int getModifiers() {
         HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig();
@@ -86,6 +94,9 @@
 
     @Override
     public byte[] getCode() {
+        if (codeSize == 0) {
+            return null;
+        }
         if (code == null) {
             code = HotSpotGraalRuntime.getInstance().getCompilerToVM().initializeBytecode(metaspaceMethod, new byte[codeSize]);
             assert code.length == codeSize : "expected: " + codeSize + ", actual: " + code.length;
@@ -335,4 +346,10 @@
         return currentTask;
     }
 
+    public SpeculationLog getSpeculationLog() {
+        if (speculationLog == null) {
+            speculationLog = new SpeculationLog();
+        }
+        return speculationLog;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.net.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -497,4 +498,26 @@
         }
         return null;
     }
+
+    @Override
+    public URL getClassFilePath() {
+        Class<?> cls = mirror();
+        return cls.getResource(MetaUtil.getSimpleName(cls, true).replace('.', '$') + ".class");
+    }
+
+    @Override
+    public boolean isLocal() {
+        return mirror().isLocalClass();
+    }
+
+    @Override
+    public boolean isMember() {
+        return mirror().isMemberClass();
+    }
+
+    @Override
+    public ResolvedJavaType getEnclosingType() {
+        final Class<?> encl = mirror().getEnclosingClass();
+        return encl == null ? null : fromClass(encl);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.net.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
@@ -189,4 +190,24 @@
     public Class<?> mirror() {
         return javaMirror;
     }
+
+    @Override
+    public URL getClassFilePath() {
+        return null;
+    }
+
+    @Override
+    public boolean isLocal() {
+        return false;
+    }
+
+    @Override
+    public boolean isMember() {
+        return false;
+    }
+
+    @Override
+    public ResolvedJavaType getEnclosingType() {
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,7 +32,6 @@
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.snippets.SystemSubstitutions.*;
 import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
-import static com.oracle.graal.nodes.UnwindNode.*;
 import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
 import static com.oracle.graal.snippets.Log.*;
 import static com.oracle.graal.snippets.MathSubstitutionsX86.*;
@@ -51,6 +50,7 @@
 import com.oracle.graal.api.code.Register.RegisterFlag;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
@@ -196,10 +196,6 @@
         return result;
     }
 
-    protected Value scratch(Kind kind) {
-        return globalStubRegConfig.getScratchRegister().asValue(kind);
-    }
-
     public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) {
         this.config = config;
         this.graalRuntime = graalRuntime;
@@ -208,11 +204,6 @@
 
         // @formatter:off
 
-        addRuntimeCall(UNWIND_EXCEPTION, config.unwindExceptionStub,
-                        /*           temps */ null,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0: exception */ javaCallingConvention(Kind.Object));
-
         addRuntimeCall(OnStackReplacementPhase.OSR_MIGRATION_END, config.osrMigrationEndStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Void),
@@ -328,7 +319,7 @@
 
     protected abstract RegisterConfig createRegisterConfig(boolean globalStubConfig);
 
-    public void installSnippets(SnippetInstaller installer, Assumptions assumptions) {
+    public void installSnippets(Backend backend, SnippetInstaller installer, Assumptions assumptions) {
         if (GraalOptions.IntrinsifyObjectMethods) {
             installer.installSubstitutions(ObjectSubstitutions.class);
         }
@@ -372,9 +363,8 @@
 
         newInstanceStub = new NewInstanceStub(this, assumptions, graalRuntime.getTarget());
         newArrayStub = new NewArrayStub(this, assumptions, graalRuntime.getTarget());
-        newInstanceStub.install(graalRuntime.getCompiler());
-        newArrayStub.install(graalRuntime.getCompiler());
-
+        newInstanceStub.install(backend);
+        newArrayStub.install(backend);
     }
 
     public HotSpotGraalRuntime getGraalRuntime() {
@@ -392,16 +382,17 @@
     public abstract Register stackPointerRegister();
 
     @Override
-    public String disassemble(CodeInfo info, CompilationResult tm) {
-        byte[] code = info.getCode();
+    public String disassemble(CompilationResult compResult, InstalledCode installedCode) {
+        byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode();
+        long start = installedCode == null ? 0L : installedCode.getStart();
         TargetDescription target = graalRuntime.getTarget();
-        HexCodeFile hcf = new HexCodeFile(code, info.getStart(), target.arch.getName(), target.wordSize * 8);
-        if (tm != null) {
-            HexCodeFile.addAnnotations(hcf, tm.getAnnotations());
-            addExceptionHandlersComment(tm, hcf);
+        HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8);
+        if (compResult != null) {
+            HexCodeFile.addAnnotations(hcf, compResult.getAnnotations());
+            addExceptionHandlersComment(compResult, hcf);
             Register fp = regConfig.getFrameRegister();
             RefMapFormatter slotFormatter = new RefMapFormatter(target.arch, target.wordSize, fp, 0);
-            for (Safepoint safepoint : tm.getSafepoints()) {
+            for (Safepoint safepoint : compResult.getSafepoints()) {
                 if (safepoint instanceof Call) {
                     Call call = (Call) safepoint;
                     if (call.debugInfo != null) {
@@ -415,10 +406,10 @@
                     addOperandComment(hcf, safepoint.pcOffset, "{safepoint}");
                 }
             }
-            for (DataPatch site : tm.getDataReferences()) {
+            for (DataPatch site : compResult.getDataReferences()) {
                 hcf.addOperandComment(site.pcOffset, "{" + site.constant + "}");
             }
-            for (Mark mark : tm.getMarks()) {
+            for (Mark mark : compResult.getMarks()) {
                 hcf.addComment(mark.pcOffset, getMarkName(mark));
             }
         }
@@ -507,7 +498,7 @@
     }
 
     @Override
-    public RegisterConfig lookupRegisterConfig(ResolvedJavaMethod method) {
+    public RegisterConfig lookupRegisterConfig() {
         return regConfig;
     }
 
@@ -576,6 +567,9 @@
                             graph.addAfterFixed(metaspaceMethod, compiledEntry);
                         }
                     }
+                } else if (callTarget.invokeKind() == InvokeKind.Special || callTarget.invokeKind() == InvokeKind.Static) {
+                    loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall,
+                                    callTarget.invokeKind()));
                 }
 
                 if (loweredCallTarget == null) {
@@ -642,7 +636,7 @@
             // Separate out GC barrier semantics
             CompareAndSwapNode cas = (CompareAndSwapNode) n;
             ValueNode expected = cas.expected();
-            LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, false);
+            LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
             if (expected.kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) {
                 ResolvedJavaType type = cas.object().objectStamp().type();
                 if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) {
@@ -721,7 +715,7 @@
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
             assert load.kind() != Kind.Illegal;
-            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, false);
+            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1);
             ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp()));
             // An unsafe read must not floating outside its block as may float above an explicit
             // null check on its object.
@@ -729,7 +723,7 @@
             graph.replaceFixedWithFixed(load, memoryRead);
         } else if (n instanceof UnsafeStoreNode) {
             UnsafeStoreNode store = (UnsafeStoreNode) n;
-            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, false);
+            IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
             ValueNode object = store.object();
             WriteNode write = graph.add(new WriteNode(object, store.value(), location));
             write.setStateAfter(store.stateAfter());
@@ -808,14 +802,17 @@
         } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) {
             // Nothing to do for division nodes. The HotSpot signal handler catches divisions by
             // zero and the MIN_VALUE / -1 cases.
+        } else if (n instanceof UnwindNode || n instanceof ExceptionObjectNode) {
+            // Nothing to do, using direct LIR lowering for these nodes.
         } else {
             assert false : "Node implementing Lowerable not handled: " + n;
             throw GraalInternalError.shouldNotReachHere();
         }
     }
 
-    private static IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) {
-        return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, true);
+    private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) {
+        int scale = this.graalRuntime.getTarget().sizeInBytes(elementKind);
+        return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale);
     }
 
     private SafeReadNode safeReadArrayLength(ValueNode array) {
@@ -839,13 +836,6 @@
         return HotSpotResolvedObjectType.fromClass(clazz);
     }
 
-    public Object lookupCallTarget(Object callTarget) {
-        if (callTarget instanceof HotSpotRuntimeCallTarget) {
-            return ((HotSpotRuntimeCallTarget) callTarget).getAddress();
-        }
-        return callTarget;
-    }
-
     /**
      * Gets the stub corresponding to a given method.
      * 
@@ -881,26 +871,17 @@
         return graalRuntime.getCompilerToVM().getJavaField(reflectionField);
     }
 
-    private static HotSpotCodeInfo makeInfo(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) {
-        HotSpotCodeInfo hsInfo = null;
-        if (info != null && info.length > 0) {
-            hsInfo = new HotSpotCodeInfo(compResult, (HotSpotResolvedJavaMethod) method);
-            info[0] = hsInfo;
-        }
-        return hsInfo;
-    }
-
-    public void installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult, CodeInfo[] info) {
-        HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info);
-        graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), null, hsInfo);
+    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult) {
+        HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, true);
+        graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), installedCode, method.getSpeculationLog());
+        return installedCode;
     }
 
     @Override
-    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) {
-        HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info);
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) {
         HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
-        HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod);
-        CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(hotspotMethod, -1, compResult), code, hsInfo);
+        HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, false);
+        CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(hotspotMethod, -1, compResult), code, null);
         if (result != CodeInstallResult.OK) {
             return null;
         }
@@ -968,7 +949,7 @@
     }
 
     public boolean needsDataPatch(Constant constant) {
-        return constant.getPrimitiveAnnotation() instanceof HotSpotResolvedObjectType;
+        return constant.getPrimitiveAnnotation() != null;
     }
 
     /**
@@ -1021,7 +1002,7 @@
             long nmethod = ((HotSpotInstalledCode) code).nmethod;
             return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod);
         }
-        return "";
+        return null;
     }
 
     public String disassemble(ResolvedJavaMethod method) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -52,6 +52,11 @@
     }
 
     @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
+    @Override
     public void generate(LIRGenerator gen) {
         gen.lock();
         StackSlot lockData = gen.peekLock();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java	Thu Mar 21 14:11:13 2013 +0100
@@ -42,7 +42,7 @@
     public void generate(LIRGeneratorTool gen) {
         HotSpotGraalRuntime runtime = HotSpotGraalRuntime.getInstance();
         Register thread = runtime.getRuntime().threadRegister();
-        gen.setResult(this, gen.emitLoad(new Address(Kind.Object, thread.asValue(gen.target().wordKind), runtime.getConfig().threadObjectOffset), false));
+        gen.setResult(this, gen.emitLoad(Kind.Object, thread.asValue(gen.target().wordKind), runtime.getConfig().threadObjectOffset, Value.ILLEGAL, 0, false));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,8 +32,8 @@
 
 /**
  * A special purpose store node that differs from {@link CompareAndSwapNode} in that it is not a
- * {@link StateSplit} and it {@linkplain #compareAndSwap(Object, long, Word, Word) returns} either
- * the expected value or the compared against value instead of a boolean.
+ * {@link StateSplit} and it {@linkplain #compareAndSwap(Object, long, Word, Word, Object)} returns
+ * either the expected value or the compared against value instead of a boolean.
  */
 public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRGenLowerable, MemoryCheckpoint {
 
@@ -42,17 +42,15 @@
     @Input private ValueNode expectedValue;
     @Input private ValueNode newValue;
 
-    public DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue) {
+    private final Object locationIdentity;
+
+    public DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, Object locationIdentity) {
         super(expected.stamp());
         this.object = object;
         this.offset = offset;
         this.expectedValue = expected;
         this.newValue = newValue;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        ((HotSpotLIRGenerator) gen).visitDirectCompareAndSwap(this);
+        this.locationIdentity = locationIdentity;
     }
 
     public ValueNode object() {
@@ -71,6 +69,16 @@
         return newValue;
     }
 
+    @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{locationIdentity};
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        ((HotSpotLIRGenerator) gen).visitDirectCompareAndSwap(this);
+    }
+
     /**
      * Compares an expected value with the actual value in a location denoted by an object and a
      * given offset. Iff they are same, {@code newValue} is placed into the location and the
@@ -84,5 +92,5 @@
      * @return either {@code expectedValue} or the actual value
      */
     @NodeIntrinsic
-    public static native Word compareAndSwap(Object object, long offset, Word expectedValue, Word newValue);
+    public static native Word compareAndSwap(Object object, long offset, Word expectedValue, Word newValue, @ConstantNodeParameter Object locationIdentity);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -44,6 +44,11 @@
     }
 
     @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
+    @Override
     public void generate(LIRGenerator gen) {
         gen.unlock();
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -47,7 +47,7 @@
     @Override
     public void generate(LIRGeneratorTool gen) {
         Value obj = gen.newVariable(gen.target().wordKind);
-        gen.emitMove(gen.operand(object), obj);
+        gen.emitMove(obj, gen.operand(object));
         gen.setResult(this, obj);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -34,7 +34,7 @@
 
     private final InvokeKind invokeKind;
 
-    public HotSpotDirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, Type callType, InvokeKind invokeKind) {
+    public HotSpotDirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) {
         super(arguments, returnStamp, signature, target, callType);
         this.invokeKind = invokeKind;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -33,7 +33,8 @@
 
     @Input private ValueNode metaspaceMethod;
 
-    public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, Type callType) {
+    public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target,
+                    Type callType) {
         super(computedAddress, arguments, returnStamp, signature, target, callType);
         this.metaspaceMethod = metaspaceMethod;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.nodes;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * Access the value of a specific register.
- */
-@NodeInfo(nameTemplate = "Register %{p#register}")
-public final class RegisterNode extends FixedWithNextNode implements LIRLowerable {
-
-    private final Register register;
-
-    public RegisterNode(Register register, Kind kind) {
-        super(StampFactory.forKind(kind));
-        this.register = register;
-    }
-
-    public RegisterNode(Register register) {
-        super(StampFactory.object());
-        this.register = register;
-    }
-
-    @Override
-    public void generate(LIRGeneratorTool generator) {
-        Value result;
-        if (generator.attributes(register).isAllocatable()) {
-            // The register allocator would prefer us not to tie up an allocatable
-            // register for the complete lifetime of this node.
-            result = generator.newVariable(kind());
-            generator.emitMove(register.asValue(kind()), result);
-        } else {
-            result = register.asValue(kind());
-        }
-        generator.setResult(this, result);
-    }
-
-    @Override
-    public String toString(Verbosity verbosity) {
-        if (verbosity == Verbosity.Name) {
-            return super.toString(Verbosity.Name) + "%" + register;
-        } else {
-            return super.toString(verbosity);
-        }
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -69,7 +69,7 @@
             parameters.add(frameState.localAt(slot));
         }
         Value[] args = gen.visitInvokeArguments(cc, parameters);
-        Value entry = gen.emitLoad(new Address(Kind.Long, gen.operand(target), config.nmethodEntryOffset), false);
+        Value entry = gen.emitLoad(Kind.Long, gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0, false);
         HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen;
         hsgen.emitTailcall(args, entry);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.nodes.*;
@@ -46,6 +45,6 @@
         } else {
             base = gen.emitAdd(base, Constant.forLong(config.cardtableStartAddress));
         }
-        gen.emitStore(new Address(Kind.Boolean, base, displacement), Constant.FALSE, false);
+        gen.emitStore(Kind.Boolean, base, displacement, Value.ILLEGAL, 0, Constant.FALSE, false);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,14 +26,16 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.*;
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.java.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
@@ -43,6 +45,27 @@
 
     public static final Descriptor OSR_MIGRATION_END = new Descriptor("OSR_migration_end", true, void.class, long.class);
 
+    public class OSREntryProxyNode extends FloatingNode implements LIRLowerable {
+
+        @Input private ValueNode object;
+        @Input(notDataflow = true) private final RuntimeCallNode anchor;
+
+        public OSREntryProxyNode(ValueNode object, RuntimeCallNode anchor) {
+            super(object.stamp());
+            this.object = object;
+            this.anchor = anchor;
+        }
+
+        public RuntimeCallNode getAnchor() {
+            return anchor;
+        }
+
+        @Override
+        public void generate(LIRGeneratorTool generator) {
+            generator.setResult(this, generator.operand(object));
+        }
+    }
+
     @Override
     protected void run(StructuredGraph graph) {
         if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) {
@@ -81,7 +104,7 @@
 
             LoopTransformations.peel(osrLoop);
             for (Node usage : osr.usages().snapshot()) {
-                ValueProxyNode proxy = (ValueProxyNode) usage;
+                ProxyNode proxy = (ProxyNode) usage;
                 proxy.replaceAndDelete(proxy.value());
             }
             FixedNode next = osr.next();
@@ -108,15 +131,17 @@
         start.setStateAfter(null);
         GraphUtil.killWithUnusedFloatingInputs(oldStartState);
 
+        // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block)
         int localsOffset = (graph.method().getMaxLocals() - 1) * 8;
         for (int i = 0; i < osrState.localsSize(); i++) {
             ValueNode value = osrState.localAt(i);
             if (value != null) {
-                ValueProxyNode proxy = (ValueProxyNode) value;
-                int size = (value.kind() == Kind.Long || value.kind() == Kind.Double) ? 2 : 1;
+                ProxyNode proxy = (ProxyNode) value;
+                int size = FrameStateBuilder.stackSlots(value.kind());
                 int offset = localsOffset - (i + size - 1) * 8;
                 UnsafeLoadNode load = graph.add(new UnsafeLoadNode(buffer, offset, ConstantNode.forInt(0, graph), value.kind()));
-                proxy.replaceAndDelete(load);
+                OSREntryProxyNode newProxy = graph.add(new OSREntryProxyNode(load, migrationEnd));
+                proxy.replaceAndDelete(newProxy);
                 graph.addBeforeFixed(migrationEnd, load);
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java	Thu Mar 21 14:11:13 2013 +0100
@@ -41,7 +41,7 @@
 /**
  * Substitutions for {@code com.sun.crypto.provider.AESCrypt} methods.
  */
-@ClassSubstitution(className = "com.sun.crypto.provider.AESCrypt")
+@ClassSubstitution(className = "com.sun.crypto.provider.AESCrypt", optional = true)
 public class AESCryptSubstitutions {
 
     static final long kOffset;
@@ -70,7 +70,7 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) {
-        Word kAddr = Word.fromObject(rcvr).readWord(Word.unsigned(kOffset)).add(arrayBaseOffset(Kind.Byte));
+        Word kAddr = Word.fromObject(rcvr).readWord(Word.unsigned(kOffset), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
         if (encrypt) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopyNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopyNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.snippets.nodes.*;
 
@@ -59,21 +60,19 @@
         return arguments.get(4);
     }
 
-    private ResolvedJavaMethod selectSnippet(LoweringTool tool) {
+    private StructuredGraph selectSnippet(LoweringTool tool) {
         ResolvedJavaType srcType = getSource().objectStamp().type();
         ResolvedJavaType destType = getDestination().objectStamp().type();
 
-        if (srcType != null && srcType.isArray() && destType != null && destType.isArray()) {
-            Kind componentKind = srcType.getComponentType().getKind();
-            if (componentKind != Kind.Object) {
-                if (srcType.getComponentType() == destType.getComponentType()) {
-                    return tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind));
-                }
-            } else if (destType.getComponentType().isAssignableFrom(srcType.getComponentType()) && getDestination().objectStamp().isExactType()) {
-                return tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(Kind.Object));
-            }
+        if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) {
+            return null;
         }
-        return null;
+        if (!destType.getComponentType().isAssignableFrom(srcType.getComponentType()) || !getDestination().objectStamp().isExactType()) {
+            return null;
+        }
+        Kind componentKind = srcType.getComponentType().getKind();
+        ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind));
+        return (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class);
     }
 
     private static void unrollFixedLengthLoop(StructuredGraph snippetGraph, int length, LoweringTool tool) {
@@ -83,32 +82,48 @@
         }
         // the canonicalization before loop unrolling is needed to propagate the length into
         // additions, etc.
-        new CanonicalizerPhase(tool.getTarget(), tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
+        new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
         new LoopFullUnrollPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
-        new CanonicalizerPhase(tool.getTarget(), tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
+        new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph);
+    }
+
+    private static void replaceSnippetInvokes(StructuredGraph snippetGraph, ResolvedJavaMethod targetMethod, int bci) {
+        for (InvokeNode invoke : snippetGraph.getNodes(InvokeNode.class)) {
+            if (invoke.methodCallTarget().targetMethod() != targetMethod) {
+                throw new GraalInternalError("unexpected invoke in arraycopy snippet");
+            }
+            if (invoke.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI) {
+                InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.methodCallTarget(), bci));
+                newInvoke.setStateAfter(snippetGraph.add(new FrameState(FrameState.AFTER_BCI)));
+                snippetGraph.replaceFixedWithFixed(invoke, newInvoke);
+            } else {
+                assert invoke.stateAfter().bci == FrameState.AFTER_BCI : invoke;
+            }
+        }
     }
 
     @Override
-    public void lower(LoweringTool tool) {
-        ResolvedJavaMethod snippetMethod = selectSnippet(tool);
-        if (snippetMethod == null) {
-            snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.increaseGenericCallCounterMethod);
-            // we will call the generic method. the generic snippet will only increase the counter,
-            // not call the actual method. therefore we create a second invoke here.
-            ((StructuredGraph) graph()).addAfterFixed(this, createInvoke());
-        }
-        if (Debug.isLogEnabled()) {
-            Debug.log("%s > Intrinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType());
+    protected StructuredGraph getSnippetGraph(LoweringTool tool) {
+        if (!GraalOptions.IntrinsifyArrayCopy) {
+            return null;
         }
 
-        StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class);
-        assert snippetGraph != null : "ArrayCopySnippets should be installed";
-        if (getLength().isConstant()) {
-            snippetGraph = snippetGraph.copy();
-            unrollFixedLengthLoop(snippetGraph, getLength().asConstant().asInt(), tool);
+        StructuredGraph snippetGraph = selectSnippet(tool);
+        if (snippetGraph == null) {
+            ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.genericArraycopySnippet);
+            snippetGraph = ((StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class)).copy();
+            assert snippetGraph != null : "ArrayCopySnippets should be installed";
+
+            replaceSnippetInvokes(snippetGraph, getTargetMethod(), getBci());
+        } else {
+            assert snippetGraph != null : "ArrayCopySnippets should be installed";
+
+            if (getLength().isConstant()) {
+                snippetGraph = snippetGraph.copy();
+                unrollFixedLengthLoop(snippetGraph, getLength().asConstant().asInt(), tool);
+            }
         }
-        InvokeNode invoke = replaceWithInvoke();
-        InliningUtil.inline(invoke, snippetGraph, false);
+        return snippetGraph;
     }
 
     private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.snippets;
 
-import static com.oracle.graal.api.code.DeoptimizationAction.*;
-import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
 import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
 
@@ -33,24 +31,21 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
-import com.oracle.graal.snippets.Snippet.Fold;
 import com.oracle.graal.snippets.nodes.*;
+import com.oracle.graal.word.*;
 
 @SuppressWarnings("unused")
 public class ArrayCopySnippets implements SnippetsInterface {
 
     private static final EnumMap<Kind, Method> arraycopyMethods = new EnumMap<>(Kind.class);
-    public static final Method increaseGenericCallCounterMethod;
+    public static final Method genericArraycopySnippet;
 
     private static void addArraycopySnippetMethod(Kind kind, Class<?> arrayClass) throws NoSuchMethodException {
         arraycopyMethods.put(kind, ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class));
@@ -67,7 +62,7 @@
             addArraycopySnippetMethod(Kind.Float, float[].class);
             addArraycopySnippetMethod(Kind.Double, double[].class);
             addArraycopySnippetMethod(Kind.Object, Object[].class);
-            increaseGenericCallCounterMethod = ArrayCopySnippets.class.getDeclaredMethod("increaseGenericCallCounter", Object.class, int.class, Object.class, int.class, int.class);
+            genericArraycopySnippet = ArrayCopySnippets.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
         } catch (SecurityException | NoSuchMethodException e) {
             throw new GraalInternalError(e);
         }
@@ -81,7 +76,9 @@
     private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
 
     public static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter("baseKind") Kind baseKind) {
-        checkInputs(src, srcPos, dest, destPos, length);
+        checkNonNull(src);
+        checkNonNull(dest);
+        checkLimits(src, srcPos, dest, destPos, length);
         int header = arrayBaseOffset(baseKind);
         int elementSize = arrayIndexScale(baseKind);
         long byteLength = (long) length * elementSize;
@@ -109,17 +106,24 @@
         }
     }
 
-    public static void checkInputs(Object src, int srcPos, Object dest, int destPos, int length) {
-        if (src == null) {
+    public static void checkNonNull(Object obj) {
+        if (obj == null) {
             probability(DEOPT_PATH_PROBABILITY);
             checkNPECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
-        if (dest == null) {
+    }
+
+    public static int checkArrayType(Word hub) {
+        int layoutHelper = readLayoutHelper(hub);
+        if (layoutHelper >= 0) {
             probability(DEOPT_PATH_PROBABILITY);
-            checkNPECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
+        return layoutHelper;
+    }
+
+    public static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) {
         if (srcPos < 0) {
             probability(DEOPT_PATH_PROBABILITY);
             checkAIOOBECounter.inc();
@@ -187,7 +191,9 @@
     @Snippet
     public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
         longCounter.inc();
-        checkInputs(src, srcPos, dest, destPos, length);
+        checkNonNull(src);
+        checkNonNull(dest);
+        checkLimits(src, srcPos, dest, destPos, length);
         Kind baseKind = Kind.Long;
         int header = arrayBaseOffset(baseKind);
         long byteLength = (long) length * arrayIndexScale(baseKind);
@@ -209,7 +215,9 @@
     @Snippet
     public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
         doubleCounter.inc();
-        checkInputs(src, srcPos, dest, destPos, length);
+        checkNonNull(src);
+        checkNonNull(dest);
+        checkLimits(src, srcPos, dest, destPos, length);
         Kind baseKind = Kind.Double;
         int header = arrayBaseOffset(baseKind);
         long byteLength = (long) length * arrayIndexScale(baseKind);
@@ -232,7 +240,9 @@
     @Snippet
     public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
         objectCounter.inc();
-        checkInputs(src, srcPos, dest, destPos, length);
+        checkNonNull(src);
+        checkNonNull(dest);
+        checkLimits(src, srcPos, dest, destPos, length);
         final int scale = arrayIndexScale(Kind.Object);
         int header = arrayBaseOffset(Kind.Object);
         if (src == dest && srcPos < destPos) { // bad aliased case
@@ -262,12 +272,67 @@
     }
 
     @Snippet
-    public static void increaseGenericCallCounter(Object src, int srcPos, Object dest, int destPos, int length) {
-        if (GraalOptions.SnippetCounters) {
-            if (src.getClass().getComponentType().isPrimitive()) {
-                genericPrimitiveCallCounter.inc();
-            } else {
-                genericObjectCallCounter.inc();
+    public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
+
+        // loading the hubs also checks for nullness
+        Word srcHub = loadHub(src);
+        Word destHub = loadHub(dest);
+
+        int layoutHelper = checkArrayType(srcHub);
+        if (srcHub.equal(destHub) && src != dest) {
+            probability(FAST_PATH_PROBABILITY);
+
+            checkLimits(src, srcPos, dest, destPos, length);
+
+            arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper);
+        } else {
+            genericObjectCallCounter.inc();
+            System.arraycopy(src, srcPos, dest, destPos, length);
+        }
+    }
+
+    public static void arraycopyInnerloop(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper) {
+        int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
+        int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
+
+        Word memory = (Word) Word.fromObject(src);
+
+        Word srcOffset = (Word) Word.fromObject(src).add(headerSize).add(srcPos << log2ElementSize);
+        Word destOffset = (Word) Word.fromObject(dest).add(headerSize).add(destPos << log2ElementSize);
+        Word destStart = destOffset;
+        long sizeInBytes = ((long) length) << log2ElementSize;
+        Word destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize));
+
+        int nonVectorBytes = (int) (sizeInBytes % VECTOR_SIZE);
+        Word destNonVectorEnd = destStart.add(nonVectorBytes);
+
+        while (destOffset.belowThan(destNonVectorEnd)) {
+            destOffset.writeByte(0, srcOffset.readByte(0, UNKNOWN_LOCATION), ANY_LOCATION);
+            destOffset = destOffset.add(1);
+            srcOffset = srcOffset.add(1);
+        }
+        while (destOffset.belowThan(destEnd)) {
+            destOffset.writeWord(0, srcOffset.readWord(0, UNKNOWN_LOCATION), ANY_LOCATION);
+            destOffset = destOffset.add(wordSize());
+            srcOffset = srcOffset.add(wordSize());
+        }
+
+        if ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) != 0) {
+            genericPrimitiveCallCounter.inc();
+
+        } else {
+            probability(LIKELY_PROBABILITY);
+            genericObjectExactCallCounter.inc();
+
+            if (length > 0) {
+                int cardShift = cardTableShift();
+                long cardStart = cardTableStart();
+                Word destCardOffset = destStart.unsignedShiftRight(cardShift).add(Word.unsigned(cardStart));
+                Word destCardEnd = destEnd.subtract(1).unsignedShiftRight(cardShift).add(Word.unsigned(cardStart));
+                while (destCardOffset.belowOrEqual(destCardEnd)) {
+                    DirectStoreNode.store(destCardOffset.rawValue(), false, Kind.Boolean);
+                    destCardOffset = destCardOffset.add(1);
+                }
             }
         }
     }
@@ -287,7 +352,8 @@
     private static final SnippetCounter objectCounter = new SnippetCounter(counters, "Object[]", "arraycopy for Object[] arrays");
     private static final SnippetCounter floatCounter = new SnippetCounter(counters, "float[]", "arraycopy for float[] arrays");
     private static final SnippetCounter doubleCounter = new SnippetCounter(counters, "double[]", "arraycopy for double[] arrays");
-    private static final SnippetCounter genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "call to the generic, native arraycopy method");
+    private static final SnippetCounter genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "generic arraycopy snippet for primitive arrays");
+    private static final SnippetCounter genericObjectExactCallCounter = new SnippetCounter(counters, "genericObjectExact", "generic arraycopy snippet for special object arrays");
     private static final SnippetCounter genericObjectCallCounter = new SnippetCounter(counters, "genericObject", "call to the generic, native arraycopy method");
 
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Thu Mar 21 14:11:13 2013 +0100
@@ -108,7 +108,7 @@
             isNull.inc();
         } else {
             Word objectHub = loadHub(object);
-            if (objectHub.readWord(superCheckOffset).notEqual(hub)) {
+            if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) {
                 probability(DEOPT_PATH_PROBABILITY);
                 displayMiss.inc();
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java	Thu Mar 21 14:11:13 2013 +0100
@@ -42,7 +42,7 @@
 /**
  * Substitutions for {@code com.sun.crypto.provider.CipherBlockChaining} methods.
  */
-@ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining")
+@ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining", optional = true)
 public class CipherBlockChainingSubstitutions {
 
     private static final long embeddedCipherOffset;
@@ -66,7 +66,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset));
+        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), UNKNOWN_LOCATION);
         if (getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, true);
         } else {
@@ -75,8 +75,8 @@
     }
 
     private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
-        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset)).add(arrayBaseOffset(Kind.Byte));
-        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset)).add(arrayBaseOffset(Kind.Byte));
+        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte));
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
         if (encrypt) {
@@ -89,7 +89,7 @@
 
     @MethodSubstitution(isStatic = false)
     static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
-        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset));
+        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), UNKNOWN_LOCATION);
         if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
             crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, false);
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java	Thu Mar 21 14:11:13 2013 +0100
@@ -45,7 +45,7 @@
             // Class for primitive type
             return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
         } else {
-            return klass.readInt(klassModifierFlagsOffset());
+            return klass.readInt(klassModifierFlagsOffset(), FINAL_LOCATION);
         }
     }
 
@@ -55,7 +55,7 @@
         if (klass.equal(0)) {
             return false;
         } else {
-            int accessFlags = klass.readInt(klassAccessFlagsOffset());
+            int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION);
             return (accessFlags & Modifier.INTERFACE) != 0;
         }
     }
@@ -66,8 +66,7 @@
         if (klass.equal(0)) {
             return false;
         } else {
-            int layoutHelper = klass.readInt(klassLayoutHelperOffset());
-            return (layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0;
+            return (readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0;
         }
     }
 
@@ -81,17 +80,16 @@
     public static Class<?> getSuperclass(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass.notEqual(0)) {
-            int accessFlags = klass.readInt(klassAccessFlagsOffset());
+            int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION);
             if ((accessFlags & Modifier.INTERFACE) == 0) {
-                int layoutHelper = klass.readInt(klassLayoutHelperOffset());
-                if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
+                if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) {
                     return Object.class;
                 } else {
-                    Word superKlass = klass.readWord(klassSuperKlassOffset());
+                    Word superKlass = klass.readWord(klassSuperKlassOffset(), FINAL_LOCATION);
                     if (superKlass.equal(0)) {
                         return null;
                     } else {
-                        return unsafeCast(superKlass.readObject(classMirrorOffset()), Class.class, true, true);
+                        return unsafeCast(superKlass.readObject(classMirrorOffset(), FINAL_LOCATION), Class.class, true, true);
                     }
                 }
             }
@@ -103,9 +101,8 @@
     public static Class<?> getComponentType(final Class<?> thisObj) {
         Word klass = loadWordFromObject(thisObj, klassOffset());
         if (klass.notEqual(0)) {
-            int layoutHelper = klass.readInt(klassLayoutHelperOffset());
-            if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
-                return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset()), Class.class, true, true);
+            if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) {
+                return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), FINAL_LOCATION), Class.class, true, true);
             }
         }
         return null;
@@ -113,6 +110,6 @@
 
     @MethodSubstitution(isStatic = false)
     public static boolean isInstance(final Class<?> thisObj, Object obj) {
-        return !thisObj.isPrimitive() && ConditionalNode.materializeIsInstance(thisObj, obj);
+        return !isPrimitive(thisObj) && ConditionalNode.materializeIsInstance(thisObj, obj);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.snippets;
 
 import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
+import sun.misc.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -33,6 +34,7 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.snippets.Snippet.Fold;
+import com.oracle.graal.snippets.nodes.*;
 import com.oracle.graal.word.*;
 
 //JaCoCo Exclude
@@ -42,6 +44,10 @@
  */
 public class HotSpotSnippetUtils {
 
+    public static final Object ANY_LOCATION = LocationNode.ANY_LOCATION;
+    public static final Object UNKNOWN_LOCATION = LocationNode.UNKNOWN_LOCATION;
+    public static final Object FINAL_LOCATION = LocationNode.FINAL_LOCATION;
+
     public static HotSpotVMConfig config() {
         return HotSpotGraalRuntime.getInstance().getConfig();
     }
@@ -56,16 +62,49 @@
         return config().verifyOops;
     }
 
+    public static final Object TLAB_TOP_LOCATION = LocationNode.createLocation("TlabTop");
+
     @Fold
     public static int threadTlabTopOffset() {
         return config().threadTlabTopOffset;
     }
 
+    public static final Object TLAB_END_LOCATION = LocationNode.createLocation("TlabEnd");
+
     @Fold
-    public static int threadTlabEndOffset() {
+    private static int threadTlabEndOffset() {
         return config().threadTlabEndOffset;
     }
 
+    public static final Object TLAB_START_LOCATION = LocationNode.createLocation("TlabStart");
+
+    @Fold
+    private static int threadTlabStartOffset() {
+        return config().threadTlabStartOffset;
+    }
+
+    public static Word readTlabTop(Word thread) {
+        return thread.readWord(threadTlabTopOffset(), TLAB_TOP_LOCATION);
+    }
+
+    public static Word readTlabEnd(Word thread) {
+        return thread.readWord(threadTlabEndOffset(), TLAB_END_LOCATION);
+    }
+
+    public static Word readTlabStart(Word thread) {
+        return thread.readWord(threadTlabStartOffset(), TLAB_START_LOCATION);
+    }
+
+    public static void writeTlabTop(Word thread, Word top) {
+        thread.writeWord(threadTlabTopOffset(), top, TLAB_TOP_LOCATION);
+    }
+
+    public static void initializeTlab(Word thread, Word start, Word end) {
+        thread.writeWord(threadTlabStartOffset(), start, TLAB_START_LOCATION);
+        thread.writeWord(threadTlabTopOffset(), start, TLAB_TOP_LOCATION);
+        thread.writeWord(threadTlabEndOffset(), end, TLAB_END_LOCATION);
+    }
+
     @Fold
     public static int threadObjectOffset() {
         return config().threadObjectOffset;
@@ -103,9 +142,11 @@
 
     @Fold
     public static int pageSize() {
-        return HotSpotGraalRuntime.getInstance().getTarget().pageSize;
+        return Unsafe.getUnsafe().pageSize();
     }
 
+    public static final Object PROTOTYPE_MARK_WORD_LOCATION = LocationNode.createLocation("PrototypeMarkWord");
+
     @Fold
     public static int prototypeMarkWordOffset() {
         return config().prototypeMarkWordOffset;
@@ -122,10 +163,14 @@
     }
 
     @Fold
-    public static int klassLayoutHelperOffset() {
+    private static int klassLayoutHelperOffset() {
         return config().klassLayoutHelperOffset;
     }
 
+    public static int readLayoutHelper(Word hub) {
+        return hub.readInt(klassLayoutHelperOffset(), FINAL_LOCATION);
+    }
+
     @Fold
     public static int arrayKlassLayoutHelperIdentifier() {
         return config().arrayKlassLayoutHelperIdentifier;
@@ -141,11 +186,25 @@
         return config().klassSuperKlassOffset;
     }
 
+    public static final Object MARK_WORD_LOCATION = LocationNode.createLocation("MarkWord");
+
     @Fold
     public static int markOffset() {
         return config().markOffset;
     }
 
+    public static final Object HUB_LOCATION = LocationNode.createLocation("Hub");
+
+    @Fold
+    private static int hubOffset() {
+        return config().hubOffset;
+    }
+
+    public static void initializeObjectHeader(Word memory, Word markWord, Word hub) {
+        memory.writeWord(markOffset(), markWord, MARK_WORD_LOCATION);
+        memory.writeWord(hubOffset(), hub, HUB_LOCATION);
+    }
+
     @Fold
     public static int unlockedMask() {
         return config().unlockedMask;
@@ -192,11 +251,6 @@
     }
 
     @Fold
-    public static int hubOffset() {
-        return config().hubOffset;
-    }
-
-    @Fold
     public static int metaspaceArrayLengthOffset() {
         return config().metaspaceArrayLengthOffset;
     }
@@ -266,16 +320,22 @@
         return config().superCheckOffsetOffset;
     }
 
+    public static final Object SECONDARY_SUPER_CACHE_LOCATION = LocationNode.createLocation("SecondarySuperCache");
+
     @Fold
     public static int secondarySuperCacheOffset() {
         return config().secondarySuperCacheOffset;
     }
 
+    public static final Object SECONDARY_SUPERS_LOCATION = LocationNode.createLocation("SecondarySupers");
+
     @Fold
     public static int secondarySupersOffset() {
         return config().secondarySupersOffset;
     }
 
+    public static final Object DISPLACED_MARK_WORD_LOCATION = LocationNode.createLocation("DisplacedMarkWord");
+
     @Fold
     public static int lockDisplacedMarkOffset() {
         return config().basicLockDisplacedHeaderOffset;
@@ -319,22 +379,22 @@
      * Gets the value of the stack pointer register as a Word.
      */
     public static Word stackPointer() {
-        return HotSpotSnippetUtils.registerAsWord(stackPointerRegister());
+        return HotSpotSnippetUtils.registerAsWord(stackPointerRegister(), true, false);
     }
 
     /**
      * Gets the value of the thread register as a Word.
      */
     public static Word thread() {
-        return HotSpotSnippetUtils.registerAsWord(threadRegister());
+        return HotSpotSnippetUtils.registerAsWord(threadRegister(), true, false);
     }
 
     public static Word loadWordFromObject(Object object, int offset) {
         return loadWordFromObjectIntrinsic(object, 0, offset, wordKind());
     }
 
-    @NodeIntrinsic(value = RegisterNode.class, setStampFromReturnType = true)
-    public static native Word registerAsWord(@ConstantNodeParameter Register register);
+    @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true)
+    public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming);
 
     @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
     private static native Word loadWordFromObjectIntrinsic(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind);
@@ -347,12 +407,19 @@
         return CodeUtil.log2(wordSize());
     }
 
+    public static final Object CLASS_STATE_LOCATION = LocationNode.createLocation("ClassState");
+
     @Fold
     public static int klassStateOffset() {
         return config().klassStateOffset;
     }
 
     @Fold
+    public static int klassStateFullyInitialized() {
+        return config().klassStateFullyInitialized;
+    }
+
+    @Fold
     public static int klassModifierFlagsOffset() {
         return config().klassModifierFlagsOffset;
     }
@@ -372,22 +439,21 @@
         return config().klassInstanceSizeOffset;
     }
 
+    public static final Object HEAP_TOP_LOCATION = LocationNode.createLocation("HeapTop");
+
     @Fold
     public static long heapTopAddress() {
         return config().heapTopAddress;
     }
 
+    public static final Object HEAP_END_LOCATION = LocationNode.createLocation("HeapEnd");
+
     @Fold
     public static long heapEndAddress() {
         return config().heapEndAddress;
     }
 
     @Fold
-    public static int threadTlabStartOffset() {
-        return config().threadTlabStartOffset;
-    }
-
-    @Fold
     public static long tlabIntArrayMarkWord() {
         return config().tlabIntArrayMarkWord;
     }
@@ -402,36 +468,43 @@
         return config().tlabAlignmentReserve;
     }
 
+    public static final Object TLAB_SIZE_LOCATION = LocationNode.createLocation("TlabSize");
+
     @Fold
     public static int threadTlabSizeOffset() {
         return config().threadTlabSizeOffset;
     }
 
+    public static final Object TLAB_THREAD_ALLOCATED_BYTES_LOCATION = LocationNode.createLocation("TlabThreadAllocatedBytes");
+
     @Fold
     public static int threadAllocatedBytesOffset() {
         return config().threadAllocatedBytesOffset;
     }
 
-    @Fold
-    public static int klassStateFullyInitialized() {
-        return config().klassStateFullyInitialized;
-    }
+    public static final Object TLAB_REFILL_WASTE_LIMIT_LOCATION = LocationNode.createLocation("RefillWasteLimit");
 
     @Fold
     public static int tlabRefillWasteLimitOffset() {
         return config().tlabRefillWasteLimitOffset;
     }
 
+    public static final Object TLAB_NOF_REFILLS_LOCATION = LocationNode.createLocation("TlabNOfRefills");
+
     @Fold
     public static int tlabNumberOfRefillsOffset() {
         return config().tlabNumberOfRefillsOffset;
     }
 
+    public static final Object TLAB_FAST_REFILL_WASTE_LOCATION = LocationNode.createLocation("TlabFastRefillWaste");
+
     @Fold
     public static int tlabFastRefillWasteOffset() {
         return config().tlabFastRefillWasteOffset;
     }
 
+    public static final Object TLAB_SLOW_ALLOCATIONS_LOCATION = LocationNode.createLocation("TlabSlowAllocations");
+
     @Fold
     public static int tlabSlowAllocationsOffset() {
         return config().tlabSlowAllocationsOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Thu Mar 21 14:11:13 2013 +0100
@@ -99,7 +99,7 @@
             return falseValue;
         }
         Word objectHub = loadHub(object);
-        if (objectHub.readWord(superCheckOffset).notEqual(hub)) {
+        if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) {
             probability(NOT_LIKELY_PROBABILITY);
             displayMiss.inc();
             return falseValue;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Thu Mar 21 14:11:13 2013 +0100
@@ -40,6 +40,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
@@ -109,7 +110,7 @@
                 // The bias pattern is present in the object's mark word. Need to check
                 // whether the bias owner and the epoch are both still current.
                 Word hub = loadHub(object);
-                final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
+                final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
                 final Word thread = thread();
                 final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace());
                 trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord);
@@ -154,7 +155,7 @@
                         Word biasedMark = unbiasedMark.or(thread);
                         trace(trace, "     unbiasedMark: 0x%016lx\n", unbiasedMark);
                         trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
-                        if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark).equal(unbiasedMark)) {
+                        if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark)) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:acquired}", object);
                             return;
@@ -175,7 +176,7 @@
                         // the bias from one thread to another directly in this situation.
                         Word biasedMark = prototypeMarkWord.or(thread);
                         trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
-                        if (compareAndSwap(object, markOffset(), mark, biasedMark).equal(mark)) {
+                        if (compareAndSwap(object, markOffset(), mark, biasedMark, MARK_WORD_LOCATION).equal(mark)) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:transfer}", object);
                             return;
@@ -197,7 +198,7 @@
                     // that another thread raced us for the privilege of revoking the
                     // bias of this particular object, so it's okay to continue in the
                     // normal locking code.
-                    Word result = compareAndSwap(object, markOffset(), mark, prototypeMarkWord);
+                    Word result = compareAndSwap(object, markOffset(), mark, prototypeMarkWord, MARK_WORD_LOCATION);
 
                     // Fall through to the normal CAS-based lock, because no matter what
                     // the result of the above CAS, some thread must have succeeded in
@@ -215,11 +216,11 @@
         trace(trace, "     unlockedMark: 0x%016lx\n", unlockedMark);
 
         // Copy this unlocked mark word into the lock slot on the stack
-        lock.writeWord(lockDisplacedMarkOffset(), unlockedMark);
+        lock.writeWord(lockDisplacedMarkOffset(), unlockedMark, DISPLACED_MARK_WORD_LOCATION);
 
         // Test if the object's mark word is unlocked, and if so, store the
         // (address of) the lock slot into the object's mark word.
-        Word currentMark = compareAndSwap(object, markOffset(), unlockedMark, lock);
+        Word currentMark = compareAndSwap(object, markOffset(), unlockedMark, lock, MARK_WORD_LOCATION);
         if (currentMark.notEqual(unlockedMark)) {
             trace(trace, "      currentMark: 0x%016lx\n", currentMark);
             // The mark word in the object header was not the same.
@@ -247,7 +248,7 @@
                 return;
             } else {
                 // Recursively locked => write 0 to the lock slot
-                lock.writeWord(lockDisplacedMarkOffset(), Word.zero());
+                lock.writeWord(lockDisplacedMarkOffset(), Word.zero(), DISPLACED_MARK_WORD_LOCATION);
                 traceObject(trace, "+lock{recursive}", object);
             }
         } else {
@@ -302,7 +303,7 @@
         final Word lock = CurrentLockNode.currentLock();
 
         // Load displaced mark
-        final Word displacedMark = lock.readWord(lockDisplacedMarkOffset());
+        final Word displacedMark = lock.readWord(lockDisplacedMarkOffset(), DISPLACED_MARK_WORD_LOCATION);
         trace(trace, "    displacedMark: 0x%016lx\n", displacedMark);
 
         if (displacedMark.equal(0)) {
@@ -313,7 +314,7 @@
             // Test if object's mark word is pointing to the displaced mark word, and if so, restore
             // the displaced mark in the object - if the object's mark word is not pointing to
             // the displaced mark word, do unlocking via runtime call.
-            if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark).notEqual(lock)) {
+            if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock)) {
                 // The object's mark word was not pointing to the displaced header,
                 // we do unlocking via runtime call.
                 probability(DEOPT_PATH_PROBABILITY);
@@ -365,35 +366,37 @@
      */
     private static final boolean ENABLE_BREAKPOINT = false;
 
+    private static final Object MONITOR_COUNTER_LOCATION = LocationNode.createLocation("MonitorCounter");
+
     @NodeIntrinsic(BreakpointNode.class)
     static native void bkpt(Object object, Word mark, Word tmp, Word value);
 
     private static void incCounter() {
         if (CHECK_BALANCED_MONITORS) {
             final Word counter = MonitorCounterNode.counter();
-            final int count = counter.readInt(0);
-            counter.writeInt(0, count + 1);
+            final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION);
+            counter.writeInt(0, count + 1, MONITOR_COUNTER_LOCATION);
         }
     }
 
     private static void decCounter() {
         if (CHECK_BALANCED_MONITORS) {
             final Word counter = MonitorCounterNode.counter();
-            final int count = counter.readInt(0);
-            counter.writeInt(0, count - 1);
+            final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION);
+            counter.writeInt(0, count - 1, MONITOR_COUNTER_LOCATION);
         }
     }
 
     @Snippet
     private static void initCounter() {
         final Word counter = MonitorCounterNode.counter();
-        counter.writeInt(0, 0);
+        counter.writeInt(0, 0, MONITOR_COUNTER_LOCATION);
     }
 
     @Snippet
     private static void checkCounter(String errMsg) {
         final Word counter = MonitorCounterNode.counter();
-        final int count = counter.readInt(0);
+        final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION);
         if (count != 0) {
             vmError(errMsg, count);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Thu Mar 21 14:11:13 2013 +0100
@@ -62,13 +62,13 @@
     @Snippet
     public static Word allocate(@Parameter("size") int size) {
         Word thread = thread();
-        Word top = thread.readWord(threadTlabTopOffset());
-        Word end = thread.readWord(threadTlabEndOffset());
+        Word top = readTlabTop(thread);
+        Word end = readTlabEnd(thread);
         Word newTop = top.add(size);
         // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code)
         if (newTop.belowOrEqual(end)) {
             probability(FAST_PATH_PROBABILITY);
-            thread.writeWord(threadTlabTopOffset(), newTop);
+            writeTlabTop(thread, newTop);
             return top;
         }
         return Word.zero();
@@ -178,7 +178,7 @@
         Word dims = DimensionsNode.allocaDimsArray(rank);
         ExplodeLoopNode.explodeLoop();
         for (int i = 0; i < rank; i++) {
-            dims.writeInt(i * 4, dimensions[i]);
+            dims.writeInt(i * 4, dimensions[i], ANY_LOCATION);
         }
         return NewMultiArrayStubCall.call(hub, rank, dims);
     }
@@ -194,20 +194,19 @@
      * Formats some allocated memory with an object header zeroes out the rest.
      */
     private static void formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents) {
-        Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset()) : compileTimePrototypeMarkWord;
-        memory.writeWord(markOffset(), prototypeMarkWord);
-        memory.writeWord(hubOffset(), hub);
+        Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord;
+        initializeObjectHeader(memory, prototypeMarkWord, hub);
         if (fillContents) {
             if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) {
                 new_seqInit.inc();
                 explodeLoop();
                 for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
-                    memory.writeWord(offset, Word.zero());
+                    memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                 }
             } else {
                 new_loopInit.inc();
                 for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
-                    memory.writeWord(offset, Word.zero());
+                    memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                 }
             }
         }
@@ -217,13 +216,12 @@
      * Formats some allocated memory with an object header zeroes out the rest.
      */
     public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) {
-        memory.writeWord(markOffset(), prototypeMarkWord);
-        memory.writeInt(arrayLengthOffset(), length);
+        memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION);
         // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null
-        memory.writeWord(hubOffset(), hub);
+        initializeObjectHeader(memory, prototypeMarkWord, hub);
         if (fillContents) {
             for (int offset = headerSize; offset < allocationSize; offset += wordSize()) {
-                memory.writeWord(offset, Word.zero());
+                memory.writeWord(offset, Word.zero(), ANY_LOCATION);
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
@@ -34,7 +33,6 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
 import com.oracle.graal.snippets.nodes.*;
 
 public class ObjectCloneNode extends MacroNode implements VirtualizableAllocation, ArrayLengthProvider {
@@ -52,33 +50,30 @@
         return arguments.get(0);
     }
 
-    private Method selectSnippetMethod(LoweringTool tool) {
-        ResolvedJavaType type = getObject().objectStamp().type();
-        if (type.isArray()) {
-            return ObjectCloneSnippets.arrayCloneMethod;
-        } else if (type.isAssignableFrom(tool.getRuntime().lookupJavaType(Object[].class))) {
-            // arrays are assignable to Object, Cloneable and Serializable
-            return ObjectCloneSnippets.genericCloneMethod;
-        } else {
-            return ObjectCloneSnippets.instanceCloneMethod;
-        }
-    }
-
     @Override
-    public void lower(LoweringTool tool) {
+    protected StructuredGraph getSnippetGraph(LoweringTool tool) {
         if (!GraalOptions.IntrinsifyObjectClone) {
-            super.lower(tool);
-            return;
-        }
-        ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(selectSnippetMethod(tool));
-        if (Debug.isLogEnabled()) {
-            Debug.log("%s > Intrinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType());
+            return null;
         }
 
+        ResolvedJavaType type = getObject().objectStamp().type();
+        Method method;
+        /*
+         * The first condition tests if the parameter is an array, the second condition tests if the
+         * parameter can be an array. Otherwise, the parameter is known to be a non-array object.
+         */
+        if (type.isArray()) {
+            method = ObjectCloneSnippets.arrayCloneMethod;
+        } else if (type == null || type.isAssignableFrom(tool.getRuntime().lookupJavaType(Object[].class))) {
+            method = ObjectCloneSnippets.genericCloneMethod;
+        } else {
+            method = ObjectCloneSnippets.instanceCloneMethod;
+        }
+        ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(method);
         StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class);
+
         assert snippetGraph != null : "ObjectCloneSnippets should be installed";
-        InvokeNode invoke = replaceWithInvoke();
-        InliningUtil.inline(invoke, snippetGraph, false);
+        return snippetGraph;
     }
 
     private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) {
@@ -86,7 +81,7 @@
     }
 
     private static ResolvedJavaType getConcreteType(ObjectStamp stamp, Assumptions assumptions) {
-        if (stamp.isExactType()) {
+        if (stamp.isExactType() || stamp.type() == null) {
             return stamp.type();
         } else {
             ResolvedJavaType type = stamp.type().findUniqueConcreteSubtype();
@@ -121,14 +116,15 @@
             ResolvedJavaType type = getConcreteType(obj.objectStamp(), tool.getAssumptions());
             if (isCloneableType(type, tool.getMetaAccessProvider())) {
                 if (!type.isArray()) {
-                    ResolvedJavaField[] fields = type.getInstanceFields(true);
+                    VirtualInstanceNode newVirtual = new VirtualInstanceNode(type);
+                    ResolvedJavaField[] fields = newVirtual.getFields();
+
                     ValueNode[] state = new ValueNode[fields.length];
                     final LoadFieldNode[] loads = new LoadFieldNode[fields.length];
                     for (int i = 0; i < fields.length; i++) {
                         state[i] = loads[i] = graph().add(new LoadFieldNode(obj, fields[i]));
                     }
 
-                    VirtualObjectNode newVirtual = new VirtualInstanceNode(type, fields);
                     final StructuredGraph structuredGraph = (StructuredGraph) graph();
                     tool.customAction(new Runnable() {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneSnippets.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneSnippets.java	Thu Mar 21 14:11:13 2013 +0100
@@ -53,12 +53,12 @@
     private static Object instanceClone(Object src, Word hub, int layoutHelper) {
         int instanceSize = layoutHelper;
         Pointer memory = NewObjectSnippets.allocate(instanceSize);
-        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
+        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
         Object result = NewObjectSnippets.initializeObject((Word) memory, hub, prototypeMarkWord, instanceSize, false, false);
 
         memory = Word.fromObject(result);
         for (int offset = 2 * wordSize(); offset < instanceSize; offset += wordSize()) {
-            memory.writeWord(offset, Word.fromObject(src).readWord(offset));
+            memory.writeWord(offset, Word.fromObject(src).readWord(offset, UNKNOWN_LOCATION), ANY_LOCATION);
         }
 
         return result;
@@ -71,12 +71,12 @@
         int sizeInBytes = NewObjectSnippets.computeArrayAllocationSize(arrayLength, wordSize(), headerSize, log2ElementSize);
 
         Pointer memory = NewObjectSnippets.allocate(sizeInBytes);
-        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
+        Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
         Object result = NewObjectSnippets.initializeArray((Word) memory, hub, arrayLength, sizeInBytes, prototypeMarkWord, headerSize, false, false);
 
         memory = Word.fromObject(result);
         for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) {
-            memory.writeWord(offset, Word.fromObject(src).readWord(offset));
+            memory.writeWord(offset, Word.fromObject(src).readWord(offset, UNKNOWN_LOCATION), ANY_LOCATION);
         }
         return result;
     }
@@ -94,14 +94,14 @@
     public static Object instanceClone(Object src) {
         instanceCloneCounter.inc();
         Word hub = getAndCheckHub(src);
-        return instanceClone(src, hub, hub.readInt(layoutHelperOffset()));
+        return instanceClone(src, hub, hub.readInt(layoutHelperOffset(), FINAL_LOCATION));
     }
 
     @Snippet
     public static Object arrayClone(Object src) {
         arrayCloneCounter.inc();
         Word hub = getAndCheckHub(src);
-        int layoutHelper = hub.readInt(layoutHelperOffset());
+        int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
         return arrayClone(src, hub, layoutHelper);
     }
 
@@ -109,7 +109,7 @@
     public static Object genericClone(Object src) {
         genericCloneCounter.inc();
         Word hub = getAndCheckHub(src);
-        int layoutHelper = hub.readInt(layoutHelperOffset());
+        int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
         if (layoutHelper < 0) {
             probability(LIKELY_PROBABILITY);
             genericArrayCloneCounter.inc();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,8 +25,10 @@
 import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
 import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.snippets.*;
-import com.oracle.graal.snippets.ClassSubstitution.*;
+import com.oracle.graal.snippets.ClassSubstitution.MacroSubstitution;
+import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
 import com.oracle.graal.word.*;
 
 /**
@@ -38,7 +40,7 @@
     @MethodSubstitution(isStatic = false)
     public static Class<?> getClass(final Object thisObj) {
         Word hub = loadHub(thisObj);
-        return unsafeCast(hub.readFinalObject(Word.signed(classMirrorOffset())), Class.class, true, true);
+        return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationNode.FINAL_LOCATION), Class.class, true, true);
     }
 
     @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSubstitutions.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSubstitutions.java	Thu Mar 21 14:11:13 2013 +0100
@@ -43,10 +43,10 @@
     @MethodSubstitution(isStatic = false)
     private static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) {
         Word rawThread = HotSpotCurrentRawThreadNode.get();
-        Thread thread = (Thread) rawThread.readObject(threadObjectOffset());
+        Thread thread = (Thread) rawThread.readObject(threadObjectOffset(), FINAL_LOCATION);
         if (thisObject == thread) {
-            Word osThread = rawThread.readWord(osThreadOffset());
-            boolean interrupted = osThread.readInt(osThreadInterruptedOffset()) != 0;
+            Word osThread = rawThread.readWord(osThreadOffset(), FINAL_LOCATION);
+            boolean interrupted = osThread.readInt(osThreadInterruptedOffset(), UNKNOWN_LOCATION) != 0;
             if (!interrupted || !clearInterrupted) {
                 return interrupted;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.word.*;
@@ -39,9 +40,11 @@
  */
 public class TypeCheckSnippetUtils {
 
+    public static final Object TYPE_DISPLAY_LOCATION = LocationNode.createLocation("TypeDisplay");
+
     static boolean checkSecondarySubType(Word t, Word s) {
         // if (S.cache == T) return true
-        if (s.readWord(secondarySuperCacheOffset()).equal(t)) {
+        if (s.readWord(secondarySuperCacheOffset(), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) {
             cacheHit.inc();
             return true;
         }
@@ -51,11 +54,11 @@
 
     static boolean checkUnknownSubType(Word t, Word s) {
         // int off = T.offset
-        int superCheckOffset = t.readInt(superCheckOffsetOffset());
+        int superCheckOffset = t.readInt(superCheckOffsetOffset(), FINAL_LOCATION);
         boolean primary = superCheckOffset != secondarySuperCacheOffset();
 
         // if (T = S[off]) return true
-        if (s.readWord(superCheckOffset).equal(t)) {
+        if (s.readWord(superCheckOffset, TYPE_DISPLAY_LOCATION).equal(t)) {
             if (primary) {
                 cacheHit.inc();
             } else {
@@ -81,12 +84,12 @@
         }
 
         // if (S.scan_s_s_array(T)) { S.cache = T; return true; }
-        Word secondarySupers = s.readWord(secondarySupersOffset());
-        int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
+        Word secondarySupers = s.readWord(secondarySupersOffset(), SECONDARY_SUPERS_LOCATION);
+        int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), FINAL_LOCATION);
         for (int i = 0; i < length; i++) {
-            if (t.equal(loadWordElement(secondarySupers, i))) {
+            if (t.equal(loadSecondarySupersElement(secondarySupers, i))) {
                 probability(NOT_LIKELY_PROBABILITY);
-                s.writeWord(secondarySuperCacheOffset(), t);
+                s.writeWord(secondarySuperCacheOffset(), t, SECONDARY_SUPER_CACHE_LOCATION);
                 secondariesHit.inc();
                 return true;
             }
@@ -103,8 +106,8 @@
         return hintHubs;
     }
 
-    static Word loadWordElement(Word metaspaceArray, int index) {
-        return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize());
+    static Word loadSecondarySupersElement(Word metaspaceArray, int index) {
+        return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), FINAL_LOCATION);
     }
 
     private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("TypeCheck") : null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Thu Mar 21 14:11:13 2013 +0100
@@ -67,7 +67,7 @@
      */
     @Snippet
     private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) {
-        int layoutHelper = hub.readInt(layoutHelperOffset());
+        int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
         int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java	Thu Mar 21 14:11:13 2013 +0100
@@ -67,16 +67,15 @@
      */
     @Snippet
     private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) {
-        int sizeInBytes = hub.readInt(klassInstanceSizeOffset());
+        int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION);
         if (!forceSlowPath() && inlineContiguousAllocationSupported()) {
-            if (hub.readInt(klassStateOffset()) == klassStateFullyInitialized()) {
+            if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) {
                 Word memory = refillAllocate(intArrayHub, sizeInBytes, log);
                 if (memory.notEqual(0)) {
-                    Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
-                    memory.writeWord(markOffset(), prototypeMarkWord);
-                    memory.writeWord(hubOffset(), hub);
+                    Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
+                    initializeObjectHeader(memory, prototypeMarkWord, hub);
                     for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) {
-                        memory.writeWord(offset, Word.zero());
+                        memory.writeWord(offset, Word.zero(), ANY_LOCATION);
                     }
                     return verifyOop(memory.toObject());
                 }
@@ -105,8 +104,8 @@
         int alignmentReserveInBytes = tlabAlignmentReserveInHeapWords() * wordSize();
 
         Word thread = thread();
-        Word top = thread.readWord(threadTlabTopOffset());
-        Word end = thread.readWord(threadTlabEndOffset());
+        Word top = readTlabTop(thread);
+        Word end = readTlabEnd(thread);
 
         // calculate amount of free space
         Word tlabFreeSpaceInBytes = end.subtract(top);
@@ -120,16 +119,16 @@
 
         // Retain TLAB and allocate object in shared space if
         // the amount free in the TLAB is too large to discard.
-        Word refillWasteLimit = thread.readWord(tlabRefillWasteLimitOffset());
+        Word refillWasteLimit = thread.readWord(tlabRefillWasteLimitOffset(), TLAB_REFILL_WASTE_LIMIT_LOCATION);
         if (tlabFreeSpaceInWords.belowOrEqual(refillWasteLimit)) {
             if (tlabStats()) {
                 // increment number of refills
-                thread.writeInt(tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset()) + 1);
-                log(log, "thread: %p -- number_of_refills %d\n", thread, thread.readInt(tlabNumberOfRefillsOffset()));
+                thread.writeInt(tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset(), TLAB_NOF_REFILLS_LOCATION) + 1, TLAB_NOF_REFILLS_LOCATION);
+                log(log, "thread: %p -- number_of_refills %d\n", thread, thread.readInt(tlabNumberOfRefillsOffset(), TLAB_NOF_REFILLS_LOCATION));
                 // accumulate wastage
-                Word wastage = thread.readWord(tlabFastRefillWasteOffset()).add(tlabFreeSpaceInWords);
+                Word wastage = thread.readWord(tlabFastRefillWasteOffset(), TLAB_FAST_REFILL_WASTE_LOCATION).add(tlabFreeSpaceInWords);
                 log(log, "thread: %p -- accumulated wastage %d\n", thread, wastage);
-                thread.writeWord(tlabFastRefillWasteOffset(), wastage);
+                thread.writeWord(tlabFastRefillWasteOffset(), wastage, TLAB_FAST_REFILL_WASTE_LOCATION);
             }
 
             // if TLAB is currently allocated (top or end != null) then
@@ -142,22 +141,19 @@
                 int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts;
                 NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false);
 
-                Word allocated = thread.readWord(threadAllocatedBytesOffset());
-                allocated = allocated.add(top.subtract(thread.readWord(threadTlabStartOffset())));
-                thread.writeWord(threadAllocatedBytesOffset(), allocated);
+                Word allocated = thread.readWord(threadAllocatedBytesOffset(), TLAB_THREAD_ALLOCATED_BYTES_LOCATION);
+                allocated = allocated.add(top.subtract(readTlabStart(thread)));
+                thread.writeWord(threadAllocatedBytesOffset(), allocated, TLAB_THREAD_ALLOCATED_BYTES_LOCATION);
             }
 
             // refill the TLAB with an eden allocation
-            Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset());
+            Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset(), TLAB_SIZE_LOCATION);
             Word tlabRefillSizeInBytes = tlabRefillSizeInWords.multiply(wordSize());
             // allocate new TLAB, address returned in top
             top = edenAllocate(tlabRefillSizeInBytes, log);
             if (top.notEqual(0)) {
-                thread.writeWord(threadTlabStartOffset(), top);
-                thread.writeWord(threadTlabTopOffset(), top);
-
                 end = top.add(tlabRefillSizeInBytes.subtract(alignmentReserveInBytes));
-                thread.writeWord(threadTlabEndOffset(), end);
+                initializeTlab(thread, top, end);
 
                 return allocate(sizeInBytes);
             } else {
@@ -166,11 +162,11 @@
         } else {
             // Retain TLAB
             Word newRefillWasteLimit = refillWasteLimit.add(tlabRefillWasteIncrement());
-            thread.writeWord(tlabRefillWasteLimitOffset(), newRefillWasteLimit);
+            thread.writeWord(tlabRefillWasteLimitOffset(), newRefillWasteLimit, TLAB_REFILL_WASTE_LIMIT_LOCATION);
             log(log, "refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit);
 
             if (tlabStats()) {
-                thread.writeInt(tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset()) + 1);
+                thread.writeInt(tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset(), TLAB_SLOW_ALLOCATIONS_LOCATION) + 1, TLAB_SLOW_ALLOCATIONS_LOCATION);
             }
 
             return edenAllocate(Word.unsigned(sizeInBytes), log);
@@ -189,18 +185,18 @@
         Word heapEndAddress = Word.unsigned(heapEndAddress());
 
         while (true) {
-            Word heapTop = heapTopAddress.readWord(0);
+            Word heapTop = heapTopAddress.readWord(0, HEAP_TOP_LOCATION);
             Word newHeapTop = heapTop.add(sizeInBytes);
             if (newHeapTop.belowOrEqual(heapTop)) {
                 return Word.zero();
             }
 
-            Word heapEnd = heapEndAddress.readWord(0);
+            Word heapEnd = heapEndAddress.readWord(0, HEAP_END_LOCATION);
             if (newHeapTop.aboveThan(heapEnd)) {
                 return Word.zero();
             }
 
-            if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop).equal(heapTop)) {
+            if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop, HEAP_TOP_LOCATION).equal(heapTop)) {
                 return heapTop;
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Thu Mar 21 14:11:13 2013 +0100
@@ -31,6 +31,7 @@
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
@@ -69,8 +70,8 @@
     protected InstalledCode stubCode;
 
     /**
-     * Creates a new stub container. The new stub still needs to be
-     * {@linkplain #install(GraalCompiler) installed}.
+     * Creates a new stub container. The new stub still needs to be {@linkplain #install(Backend)
+     * installed}.
      * 
      * @param descriptor linkage details for a call to the stub
      */
@@ -106,7 +107,7 @@
      * Compiles the code for this stub, installs it and initializes the address used for calls to
      * it.
      */
-    public void install(GraalCompiler compiler) {
+    public void install(Backend backend) {
         StructuredGraph graph = (StructuredGraph) stubMethod.getCompilerStorage().get(Graph.class);
 
         Key key = new Key(stubMethod);
@@ -117,24 +118,24 @@
         PhasePlan phasePlan = new PhasePlan();
         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-        final CompilationResult compResult = compiler.compileMethod(stubMethod, graph, null, phasePlan, OptimisticOptimizations.ALL);
+        final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, OptimisticOptimizations.ALL,
+                        new SpeculationLog());
 
-        final CodeInfo[] info = new CodeInfo[1];
-        stubCode = Debug.scope("CodeInstall", new Object[]{compiler, stubMethod}, new Callable<InstalledCode>() {
+        stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), stubMethod}, new Callable<InstalledCode>() {
 
             @Override
             public InstalledCode call() {
-                InstalledCode installedCode = runtime().addMethod(stubMethod, compResult, info);
+                InstalledCode installedCode = runtime().addMethod(stubMethod, compResult);
                 assert installedCode != null : "error installing stub " + stubMethod;
                 if (Debug.isDumpEnabled()) {
-                    Debug.dump(new Object[]{compResult, info[0]}, "After code installation");
+                    Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
                 }
                 return installedCode;
             }
         });
 
         assert stubCode != null : "error installing stub " + stubMethod;
-        linkage.setAddress(info[0].getStart());
+        linkage.setAddress(stubCode.getStart());
     }
 
     /**
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Mar 21 14:11:13 2013 +0100
@@ -345,7 +345,8 @@
                 case INVOKEINTERFACE:
                 case INVOKESPECIAL:
                 case INVOKESTATIC:
-                case INVOKEVIRTUAL: {
+                case INVOKEVIRTUAL:
+                case INVOKEDYNAMIC: {
                     current = null;
                     addSuccessor(bci, makeBlock(stream.nextBCI()));
                     ExceptionDispatchBlock handler = handleExceptions(bci);
@@ -757,7 +758,7 @@
                 if (blockChanged) {
                     block.localsLiveIn.clear();
                     block.localsLiveIn.or(block.localsLiveOut);
-                    block.localsLiveIn.xor(block.localsLiveKill);
+                    block.localsLiveIn.andNot(block.localsLiveKill);
                     block.localsLiveIn.or(block.localsLiveGen);
                     Debug.log("  end   B%d  [%d, %d]  in: %s  out: %s  gen: %s  kill: %s", block.blockID, block.startBci, block.endBci, block.localsLiveIn, block.localsLiveOut, block.localsLiveGen,
                                     block.localsLiveKill);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Thu Mar 21 14:11:13 2013 +0100
@@ -203,16 +203,16 @@
     }
 
     private void propagateDelete(FloatingNode node) {
-        assert node instanceof PhiNode || node instanceof ValueProxyNode;
+        assert node instanceof PhiNode || node instanceof ProxyNode;
         if (node.isDeleted()) {
             return;
         }
         // Collect all phi functions that use this phi so that we can delete them recursively (after
         // we delete ourselves to avoid circles).
-        List<FloatingNode> propagateUsages = node.usages().filter(FloatingNode.class).filter(isA(PhiNode.class).or(ValueProxyNode.class)).snapshot();
+        List<FloatingNode> propagateUsages = node.usages().filter(FloatingNode.class).filter(isA(PhiNode.class).or(ProxyNode.class)).snapshot();
 
         // Remove the phi function from all FrameStates where it is used and then delete it.
-        assert node.usages().filter(isNotA(FrameState.class).nor(PhiNode.class).nor(ValueProxyNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states";
+        assert node.usages().filter(isNotA(FrameState.class).nor(PhiNode.class).nor(ProxyNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states";
         node.replaceAtUsages(null);
         node.safeDelete();
 
@@ -235,21 +235,21 @@
             ValueNode value = localAt(i);
             if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) {
                 Debug.log(" inserting proxy for %s", value);
-                storeLocal(i, graph.unique(new ValueProxyNode(value, loopExit, PhiType.Value)));
+                storeLocal(i, graph.unique(new ProxyNode(value, loopExit, PhiType.Value)));
             }
         }
         for (int i = 0; i < stackSize(); i++) {
             ValueNode value = stackAt(i);
             if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) {
                 Debug.log(" inserting proxy for %s", value);
-                storeStack(i, graph.unique(new ValueProxyNode(value, loopExit, PhiType.Value)));
+                storeStack(i, graph.unique(new ProxyNode(value, loopExit, PhiType.Value)));
             }
         }
         for (int i = 0; i < locks.length; i++) {
             ValueNode value = locks[i];
             if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) {
                 Debug.log(" inserting proxy for %s", value);
-                locks[i] = graph.unique(new ValueProxyNode(value, loopExit, PhiType.Value));
+                locks[i] = graph.unique(new ProxyNode(value, loopExit, PhiType.Value));
             }
         }
     }
@@ -259,21 +259,21 @@
             ValueNode value = localAt(i);
             if (value != null) {
                 Debug.log(" inserting proxy for %s", value);
-                storeLocal(i, graph.unique(new ValueProxyNode(value, begin, PhiType.Value)));
+                storeLocal(i, graph.unique(new ProxyNode(value, begin, PhiType.Value)));
             }
         }
         for (int i = 0; i < stackSize(); i++) {
             ValueNode value = stackAt(i);
             if (value != null) {
                 Debug.log(" inserting proxy for %s", value);
-                storeStack(i, graph.unique(new ValueProxyNode(value, begin, PhiType.Value)));
+                storeStack(i, graph.unique(new ProxyNode(value, begin, PhiType.Value)));
             }
         }
         for (int i = 0; i < locks.length; i++) {
             ValueNode value = locks[i];
             if (value != null) {
                 Debug.log(" inserting proxy for %s", value);
-                locks[i] = graph.unique(new ValueProxyNode(value, begin, PhiType.Value));
+                locks[i] = graph.unique(new ProxyNode(value, begin, PhiType.Value));
             }
         }
     }
@@ -292,7 +292,7 @@
     public void cleanupDeletedPhis() {
         for (int i = 0; i < localsSize(); i++) {
             if (localAt(i) != null && localAt(i).isDeleted()) {
-                assert localAt(i) instanceof PhiNode || localAt(i) instanceof ValueProxyNode : "Only phi and value proxies can be deleted during parsing: " + localAt(i);
+                assert localAt(i) instanceof PhiNode || localAt(i) instanceof ProxyNode : "Only phi and value proxies can be deleted during parsing: " + localAt(i);
                 storeLocal(i, null);
             }
         }
@@ -479,15 +479,6 @@
     }
 
     /**
-     * Pushes a value onto the stack and checks that it is a JSR return address.
-     * 
-     * @param x the instruction to push onto the stack
-     */
-    public void jpush(ValueNode x) {
-        xpush(assertJsr(x));
-    }
-
-    /**
      * Pushes a value onto the stack and checks that it is a long.
      * 
      * @param x the instruction to push onto the stack
@@ -566,15 +557,6 @@
     }
 
     /**
-     * Pops a value off of the stack and checks that it is a JSR return address.
-     * 
-     * @return x the instruction popped off the stack
-     */
-    public ValueNode jpop() {
-        return assertJsr(xpop());
-    }
-
-    /**
      * Pops a value off of the stack and checks that it is a long.
      * 
      * @return x the instruction popped off the stack
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,21 +23,16 @@
 package com.oracle.graal.java;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.phases.*;
 
 public class GraphBuilderConfiguration {
 
-    public static enum ResolvePolicy {
-        Default, EagerForSnippets, Eager,
-    }
-
-    private final ResolvePolicy resolving;
-    private final PhasePlan plan;
+    private final boolean eagerResolving;
+    private final boolean omitAllExceptionEdges;
     private ResolvedJavaType[] skippedExceptionTypes;
 
-    public GraphBuilderConfiguration(ResolvePolicy resolving, PhasePlan plan) {
-        this.resolving = resolving;
-        this.plan = plan;
+    protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges) {
+        this.eagerResolving = eagerResolving;
+        this.omitAllExceptionEdges = omitAllExceptionEdges;
     }
 
     public void setSkippedExceptionTypes(ResolvedJavaType[] skippedExceptionTypes) {
@@ -48,31 +43,32 @@
         return skippedExceptionTypes;
     }
 
-    public boolean eagerResolvingForSnippets() {
-        return (resolving == ResolvePolicy.EagerForSnippets || resolving == ResolvePolicy.Eager);
+    public boolean eagerResolving() {
+        return eagerResolving;
     }
 
-    public boolean eagerResolving() {
-        return (resolving == ResolvePolicy.Eager);
-    }
-
-    public PhasePlan plan() {
-        return plan;
+    public boolean omitAllExceptionEdges() {
+        return omitAllExceptionEdges;
     }
 
     public static GraphBuilderConfiguration getDefault() {
-        return getDefault(null);
+        return new GraphBuilderConfiguration(false, false);
     }
 
-    public static GraphBuilderConfiguration getDefault(PhasePlan plan) {
-        return new GraphBuilderConfiguration(ResolvePolicy.Default, plan);
+    public static GraphBuilderConfiguration getEagerDefault() {
+        return new GraphBuilderConfiguration(true, false);
     }
 
     public static GraphBuilderConfiguration getSnippetDefault() {
-        return getSnippetDefault(null);
+        return new GraphBuilderConfiguration(true, true);
     }
 
-    public static GraphBuilderConfiguration getSnippetDefault(PhasePlan plan) {
-        return new GraphBuilderConfiguration(ResolvePolicy.EagerForSnippets, plan);
+    /**
+     * Returns {@code true} if it is an error for a class/field/method resolution to fail.
+     * The default is the same result as returned by {@link #eagerResolving()}.
+     * However, it may be overridden to allow failure even when {@link #eagerResolving} is {@code true}.
+     */
+    public boolean unresolvedIsError() {
+        return eagerResolving;
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.java;
 
+import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.bytecode.Bytecodes.*;
 import static java.lang.reflect.Modifier.*;
 
@@ -52,7 +54,7 @@
 /**
  * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
  */
-public final class GraphBuilderPhase extends Phase {
+public class GraphBuilderPhase extends Phase {
 
     public static final class RuntimeCalls {
 
@@ -72,7 +74,7 @@
      */
     public static final int TRACELEVEL_STATE = 2;
 
-    private StructuredGraph currentGraph;
+    protected StructuredGraph currentGraph;
 
     private final MetaAccessProvider runtime;
     private ConstantPool constantPool;
@@ -82,7 +84,7 @@
 
     private BytecodeStream stream;           // the bytecode stream
 
-    private FrameStateBuilder frameState;          // the current execution state
+    protected FrameStateBuilder frameState;          // the current execution state
     private Block currentBlock;
 
     private ValueNode methodSynchronizedObject;
@@ -114,6 +116,20 @@
 
     private Block[] loopHeaders;
 
+    /**
+     * Gets the current frame state being processed by this builder.
+     */
+    protected FrameStateBuilder getCurrentFrameState() {
+        return frameState;
+    }
+
+    /**
+     * Gets the graph being processed by this builder.
+     */
+    protected StructuredGraph getGraph() {
+        return currentGraph;
+    }
+
     public GraphBuilderPhase(MetaAccessProvider runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
         this.graphBuilderConfig = graphBuilderConfig;
         this.optimisticOpts = optimisticOpts;
@@ -182,11 +198,12 @@
         currentBlock = blockMap.startBlock;
         blockMap.startBlock.entryState = frameState;
         if (blockMap.startBlock.isLoopHeader) {
-            // TODO(lstadler,gduboscq) createTarget might not be safe at this position, since it
-            // expects currentBlock,
-            // etc. to be set up correctly. A better solution to this problem of start blocks that
-            // are loop headers
-            // would be to create a dummy block in BciBlockMapping.
+            /*
+             * TODO(lstadler,gduboscq) createTarget might not be safe at this position, since it
+             * expects currentBlock, etc. to be set up correctly. A better solution to this problem
+             * of start blocks that are loop headers would be to create a dummy block in
+             * BciBlockMapping.
+             */
             appendGoto(createTarget(blockMap.startBlock, frameState));
         } else {
             blockMap.startBlock.firstInstruction = lastInstr;
@@ -260,6 +277,99 @@
         return handler.catchTypeCPI() == 0;
     }
 
+    /**
+     * @param type the unresolved type of the constant
+     */
+    protected void handleUnresolvedLoadConstant(JavaType type) {
+        append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)));
+        frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph)));
+    }
+
+    /**
+     * @param type the unresolved type of the type check
+     * @param object the object value whose type is being checked against {@code type}
+     */
+    protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) {
+        append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), Unresolved, InvalidateRecompile)));
+        frameState.apush(appendConstant(Constant.NULL_OBJECT));
+    }
+
+    /**
+     * @param type the unresolved type of the type check
+     * @param object the object value whose type is being checked against {@code type}
+     */
+    protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) {
+        BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode());
+        DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved));
+        IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1));
+        append(ifNode);
+        lastInstr = successor;
+        frameState.ipush(appendConstant(Constant.INT_0));
+    }
+
+    /**
+     * @param type the type being instantiated
+     */
+    protected void handleUnresolvedNewInstance(JavaType type) {
+        append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)));
+        frameState.apush(appendConstant(Constant.NULL_OBJECT));
+    }
+
+    /**
+     * @param type the type of the array being instantiated
+     * @param length the length of the array
+     */
+    protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) {
+        append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)));
+        frameState.apush(appendConstant(Constant.NULL_OBJECT));
+    }
+
+    /**
+     * @param type the type being instantiated
+     * @param dims the dimensions for the multi-array
+     */
+    protected void handleUnresolvedNewMultiArray(JavaType type, ValueNode[] dims) {
+        append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)));
+        frameState.apush(appendConstant(Constant.NULL_OBJECT));
+    }
+
+    /**
+     * @param field the unresolved field
+     * @param receiver the object containing the field or {@code null} if {@code field} is static
+     */
+    protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) {
+        Kind kind = field.getKind();
+        append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)));
+        frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
+    }
+
+    /**
+     * @param field the unresolved field
+     * @param value the value being stored to the field
+     * @param receiver the object containing the field or {@code null} if {@code field} is static
+     */
+    protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) {
+        append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)));
+    }
+
+    /**
+     * @param representation
+     * @param type
+     */
+    protected void handleUnresolvedExceptionType(Representation representation, JavaType type) {
+        append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)));
+    }
+
+    protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) {
+        boolean withReceiver = invokeKind != InvokeKind.Static;
+        append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)));
+        frameState.popArguments(javaMethod.getSignature().getParameterSlots(withReceiver), javaMethod.getSignature().getParameterCount(withReceiver));
+        Kind kind = javaMethod.getSignature().getReturnKind();
+        if (kind != Kind.Void) {
+            frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
+        }
+    }
+
     private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) {
         assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci";
         Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci));
@@ -306,8 +416,7 @@
             if (type instanceof ResolvedJavaType) {
                 frameState.push(Kind.Object, append(ConstantNode.forConstant(((ResolvedJavaType) type).getEncoding(Representation.JavaClass), runtime, currentGraph)));
             } else {
-                append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-                frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph)));
+                handleUnresolvedLoadConstant(type);
             }
         } else if (con instanceof Constant) {
             Constant constant = (Constant) con;
@@ -626,8 +735,7 @@
 
     private void genThrow() {
         ValueNode exception = frameState.apop();
-        FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile,
-                        true));
+        FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true));
         append(node);
         append(handleException(exception, bci()));
     }
@@ -635,21 +743,21 @@
     private JavaType lookupType(int cpi, int bytecode) {
         eagerResolvingForSnippets(cpi, bytecode);
         JavaType result = constantPool.lookupType(cpi, bytecode);
-        assert !graphBuilderConfig.eagerResolvingForSnippets() || result instanceof ResolvedJavaType;
+        assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType;
         return result;
     }
 
     private JavaMethod lookupMethod(int cpi, int opcode) {
         eagerResolvingForSnippets(cpi, opcode);
         JavaMethod result = constantPool.lookupMethod(cpi, opcode);
-        assert !graphBuilderConfig.eagerResolvingForSnippets() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result;
+        assert !graphBuilderConfig.unresolvedIsError() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result;
         return result;
     }
 
     private JavaField lookupField(int cpi, int opcode) {
         eagerResolvingForSnippets(cpi, opcode);
         JavaField result = constantPool.lookupField(cpi, opcode);
-        assert !graphBuilderConfig.eagerResolvingForSnippets() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
+        assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
         return result;
     }
 
@@ -660,14 +768,8 @@
         return result;
     }
 
-    // private void eagerResolving(int cpi, int bytecode) {
-    // if (graphBuilderConfig.eagerResolving()) {
-    // constantPool.loadReferencedType(cpi, bytecode);
-    // }
-    // }
-
     private void eagerResolvingForSnippets(int cpi, int bytecode) {
-        if (graphBuilderConfig.eagerResolvingForSnippets()) {
+        if (graphBuilderConfig.eagerResolving()) {
             constantPool.loadReferencedType(cpi, bytecode);
         }
     }
@@ -688,16 +790,13 @@
     private void genCheckCast() {
         int cpi = stream().readCPI();
         JavaType type = lookupType(cpi, CHECKCAST);
-        boolean initialized = type instanceof ResolvedJavaType;
-        if (initialized) {
-            ValueNode object = frameState.apop();
+        ValueNode object = frameState.apop();
+        if (type instanceof ResolvedJavaType) {
             CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) type, object, getProfileForTypeCheck((ResolvedJavaType) type)));
             append(checkCast);
             frameState.apush(checkCast);
         } else {
-            ValueNode object = frameState.apop();
-            append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), DeoptimizationReason.Unresolved, DeoptimizationAction.InvalidateRecompile)));
-            frameState.apush(appendConstant(Constant.NULL_OBJECT));
+            handleUnresolvedCheckCast(type, object);
         }
     }
 
@@ -711,12 +810,7 @@
             ConditionalNode conditional = currentGraph.unique(new ConditionalNode(currentGraph.unique(instanceOfNode), ConstantNode.forInt(1, currentGraph), ConstantNode.forInt(0, currentGraph)));
             frameState.ipush(append(conditional));
         } else {
-            BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode());
-            DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved));
-            IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1));
-            append(ifNode);
-            lastInstr = successor;
-            frameState.ipush(appendConstant(Constant.INT_0));
+            handleUnresolvedInstanceOf(type, object);
         }
     }
 
@@ -726,8 +820,7 @@
             NewInstanceNode n = currentGraph.add(new NewInstanceNode((ResolvedJavaType) type, true, false));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-            frameState.apush(appendConstant(Constant.NULL_OBJECT));
+            handleUnresolvedNewInstance(type);
         }
     }
 
@@ -777,8 +870,7 @@
             NewArrayNode n = currentGraph.add(new NewArrayNode((ResolvedJavaType) type, length, true, false));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-            frameState.apush(appendConstant(Constant.NULL_OBJECT));
+            handleUnresolvedNewObjectArray(type, length);
         }
 
     }
@@ -794,8 +886,7 @@
             FixedWithNextNode n = currentGraph.add(new NewMultiArrayNode((ResolvedJavaType) type, dims));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-            frameState.apush(appendConstant(Constant.NULL_OBJECT));
+            handleUnresolvedNewMultiArray(type, dims);
         }
     }
 
@@ -808,8 +899,7 @@
             LoadFieldNode load = currentGraph.add(new LoadFieldNode(receiver, (ResolvedJavaField) field));
             appendOptimizedLoadField(kind, load);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-            frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
+            handleUnresolvedLoadField(field, receiver);
         }
     }
 
@@ -872,9 +962,9 @@
         }
     }
 
-    private void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) {
+    protected void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) {
         assert receiver != null;
-        if (!GraalOptions.AllowExplicitExceptionChecks || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE)) {
+        if (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE) {
             return;
         }
 
@@ -895,7 +985,7 @@
             StoreFieldNode store = currentGraph.add(new StoreFieldNode(receiver, (ResolvedJavaField) field, value));
             appendOptimizedStoreField(store);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+            handleUnresolvedStoreField(field, value, receiver);
         }
     }
 
@@ -910,8 +1000,7 @@
                 appendOptimizedLoadField(kind, load);
             }
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-            frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
+            handleUnresolvedLoadField(field, null);
         }
     }
 
@@ -921,15 +1010,15 @@
             StoreFieldNode store = currentGraph.add(new StoreFieldNode(null, (ResolvedJavaField) field, value));
             appendOptimizedStoreField(store);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+            handleUnresolvedStoreField(field, value, null);
         }
     }
 
-    private ConstantNode genTypeOrDeopt(Representation representation, JavaType holder, boolean initialized) {
+    private ConstantNode genTypeOrDeopt(Representation representation, JavaType type, boolean initialized) {
         if (initialized) {
-            return appendConstant(((ResolvedJavaType) holder).getEncoding(representation));
+            return appendConstant(((ResolvedJavaType) type).getEncoding(representation));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
+            handleUnresolvedExceptionType(representation, type);
             return null;
         }
     }
@@ -949,13 +1038,13 @@
             ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target;
             ResolvedJavaType holder = resolvedTarget.getDeclaringClass();
             if (!holder.isInitialized() && GraalOptions.ResolveClassBeforeStaticInvoke) {
-                genInvokeDeopt(target, false);
+                handleUnresolvedInvoke(target, InvokeKind.Static);
             } else {
                 ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterSlots(false), resolvedTarget.getSignature().getParameterCount(false));
                 appendInvoke(InvokeKind.Static, resolvedTarget, args);
             }
         } else {
-            genInvokeDeopt(target, false);
+            handleUnresolvedInvoke(target, InvokeKind.Static);
         }
     }
 
@@ -964,7 +1053,7 @@
             ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
             genInvokeIndirect(InvokeKind.Interface, (ResolvedJavaMethod) target, args);
         } else {
-            genInvokeDeopt(target, true);
+            handleUnresolvedInvoke(target, InvokeKind.Interface);
         }
     }
 
@@ -973,7 +1062,7 @@
             ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
             genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
         } else {
-            genInvokeDeopt(target, true);
+            handleUnresolvedInvoke(target, InvokeKind.Virtual);
         }
 
     }
@@ -985,16 +1074,7 @@
             ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true));
             invokeDirect((ResolvedJavaMethod) target, args);
         } else {
-            genInvokeDeopt(target, true);
-        }
-    }
-
-    private void genInvokeDeopt(JavaMethod unresolvedTarget, boolean withReceiver) {
-        append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)));
-        frameState.popArguments(unresolvedTarget.getSignature().getParameterSlots(withReceiver), unresolvedTarget.getSignature().getParameterCount(withReceiver));
-        Kind kind = unresolvedTarget.getSignature().getReturnKind();
-        if (kind != Kind.Void) {
-            frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
+            handleUnresolvedInvoke(target, InvokeKind.Special);
         }
     }
 
@@ -1030,21 +1110,20 @@
     private void appendInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) {
         Kind resultType = targetMethod.getSignature().getReturnKind();
         if (GraalOptions.DeoptALot) {
-            DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint));
-            deoptimize.setMessage(targetMethod.getName());
+            DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint));
             append(deoptimize);
             frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph));
             return;
         }
 
         JavaType returnType = targetMethod.getSignature().getReturnType(method.getDeclaringClass());
-        if (graphBuilderConfig.eagerResolvingForSnippets()) {
+        if (graphBuilderConfig.eagerResolving()) {
             returnType = returnType.resolve(targetMethod.getDeclaringClass());
         }
         MethodCallTargetNode callTarget = currentGraph.add(new MethodCallTargetNode(invokeKind, targetMethod, args, returnType));
         // be conservative if information was not recorded (could result in endless recompiles
         // otherwise)
-        if (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE) {
+        if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE)) {
             ValueNode result = appendWithBCI(currentGraph.add(new InvokeNode(callTarget, bci())));
             frameState.pushReturn(resultType, result);
 
@@ -1103,7 +1182,7 @@
         if (successor.jsrScope.nextReturnAddress() != stream().nextBCI()) {
             throw new JsrNotSupportedBailout("unstructured control flow (internal limitation)");
         }
-        frameState.push(Kind.Jsr, ConstantNode.forJsr(stream().nextBCI(), currentGraph));
+        frameState.push(Kind.Int, ConstantNode.forInt(stream().nextBCI(), currentGraph));
         appendGoto(createTarget(successor, frameState));
     }
 
@@ -1112,8 +1191,7 @@
         ValueNode local = frameState.loadLocal(localIndex);
         JsrScope scope = currentBlock.jsrScope;
         int retAddress = scope.nextReturnAddress();
-        append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IntegerEqualsNode(local, ConstantNode.forJsr(retAddress, currentGraph))), DeoptimizationReason.JavaSubroutineMismatch,
-                        DeoptimizationAction.InvalidateReprofile)));
+        append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IntegerEqualsNode(local, ConstantNode.forInt(retAddress, currentGraph))), JavaSubroutineMismatch, InvalidateReprofile)));
         if (!successor.jsrScope.equals(scope.pop())) {
             throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
         }
@@ -1219,7 +1297,7 @@
         }
     }
 
-    private ConstantNode appendConstant(Constant constant) {
+    protected ConstantNode appendConstant(Constant constant) {
         assert constant != null;
         return ConstantNode.forConstant(constant, runtime, currentGraph);
     }
@@ -1230,7 +1308,7 @@
         return fixed;
     }
 
-    private ValueNode append(FixedWithNextNode x) {
+    protected ValueNode append(FixedWithNextNode x) {
         return appendWithBCI(x);
     }
 
@@ -1238,7 +1316,7 @@
         return v;
     }
 
-    private ValueNode appendWithBCI(FixedWithNextNode x) {
+    protected ValueNode appendWithBCI(FixedWithNextNode x) {
         assert x.predecessor() == null : "instruction should not have been appended yet";
         assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
         lastInstr.setNext(x);
@@ -1313,7 +1391,7 @@
     private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) {
         assert probability >= 0 && probability <= 1.01 : probability;
         if (isNeverExecutedCode(probability)) {
-            return currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode));
+            return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
         } else {
             assert block != null;
             return createTarget(block, stateAfter);
@@ -1474,8 +1552,11 @@
 
     private void createUnwind() {
         assert frameState.stackSize() == 1 : frameState;
+        ValueNode exception = frameState.apop();
+        FixedGuardNode guard = currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true));
+        append(guard);
         synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI);
-        UnwindNode unwindNode = currentGraph.add(new UnwindNode(frameState.apop()));
+        UnwindNode unwindNode = currentGraph.add(new UnwindNode(exception));
         append(unwindNode);
     }
 
@@ -1487,9 +1568,8 @@
         ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind);
         assert frameState.stackSize() == 0;
 
-        // TODO (gdub) remove this when FloatingRead can handle this case
         if (Modifier.isSynchronized(method.getModifiers())) {
-            append(currentGraph.add(new ValueAnchorNode(x)));
+            append(currentGraph.add(new ValueAnchorNode(true, x)));
             assert !frameState.rethrowException();
         }
 
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -48,6 +48,10 @@
      */
     Object[] argsToBind;
 
+    public JTTTest() {
+        Assert.assertNotNull(runtime);
+    }
+
     @Override
     protected StructuredGraph parse(Method m) {
         StructuredGraph graph = super.parse(m);
@@ -89,10 +93,14 @@
     }
 
     protected void runTest(String name, Object... args) {
-        // System.out.println(getClass().getSimpleName() + "." + name);
-        super.test(name, args);
+        Method method = getMethod(name);
+        Object receiver = Modifier.isStatic(method.getModifiers()) ? null : this;
+
+        Result expect = executeExpected(method, receiver, args);
+
+        test(method, expect, receiver, args);
         this.argsToBind = args;
-        super.test(name, args);
+        test(method, expect, receiver, args);
         this.argsToBind = null;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_d2l03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.graal.jtt.bytecode;
+
+import com.oracle.graal.jtt.*;
+import org.junit.*;
+
+/*
+ */
+public class BC_d2l03 extends JTTTest {
+
+    public static long test(double divider) {
+        return (long) (((long) divider) * divider);
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test", 34.5D);
+    }
+
+}
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NPE_07.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NPE_07.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,12 +23,11 @@
 
 package com.oracle.graal.jtt.except;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
-
 public class Catch_NPE_07 extends JTTTest {
 
     @SuppressWarnings("serial")
@@ -62,12 +61,12 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.except;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -49,17 +49,17 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 3);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.except;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -56,17 +56,17 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized05.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized05.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,29 +29,11 @@
 
 public class Except_Synchronized05 extends JTTTest {
 
-    Object field;
-
-    public static int test(int arg) {
-        Except_Synchronized05 obj = new Except_Synchronized05();
-        int a = obj.bar(arg) != null ? 1 : 0;
-        int b = obj.baz(arg) != null ? 1 : 0;
-        return a + b;
-    }
+    static class Foo {
 
-    public synchronized Object bar(int arg) {
-        try {
-            String f = foo1(arg);
-            if (f == null) {
-                field = new Object();
-            }
-        } catch (NullPointerException e) {
-            // do nothing
-        }
-        return field;
-    }
+        Object field;
 
-    public Object baz(int arg) {
-        synchronized (this) {
+        public synchronized Object bar(int arg) {
             try {
                 String f = foo1(arg);
                 if (f == null) {
@@ -62,14 +44,36 @@
             }
             return field;
         }
+
+        public Object baz(int arg) {
+            synchronized (this) {
+                try {
+                    String f = foo1(arg);
+                    if (f == null) {
+                        field = new Object();
+                    }
+                } catch (NullPointerException e) {
+                    // do nothing
+                }
+                return field;
+            }
+        }
+
+        @SuppressWarnings("static-method")
+        private String foo1(int arg) {
+            if (arg == 0) {
+                throw null;
+            }
+            return null;
+        }
+
     }
 
-    @SuppressWarnings("static-method")
-    private String foo1(int arg) {
-        if (arg == 0) {
-            throw null;
-        }
-        return null;
+    public static int test(int arg) {
+        Foo obj = new Foo();
+        int a = obj.bar(arg) != null ? 1 : 0;
+        int b = obj.baz(arg) != null ? 1 : 0;
+        return a + b;
     }
 
     @Test
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_InNested.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_InNested.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.except;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Throw_InNested extends JTTTest {
 
@@ -48,12 +48,12 @@
         return i;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.except;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Throw_Synchronized01 extends JTTTest {
 
@@ -38,12 +38,12 @@
         throw new Exception();
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.except;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Throw_Synchronized02 extends JTTTest {
 
@@ -36,12 +36,12 @@
         throw new Exception();
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.except;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Throw_Synchronized03 extends JTTTest {
 
@@ -41,12 +41,12 @@
         throw new Exception();
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_allocate01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_allocate01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.hotpath;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -37,27 +37,27 @@
         return sum;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 80);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,8 +23,8 @@
 // Checkstyle: stop
 package com.oracle.graal.jtt.hotpath;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -55,12 +55,12 @@
         return (int) (b + c + s + i + l + f + d);
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 40);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1000);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java	Thu Mar 21 14:11:13 2013 +0100
@@ -372,7 +372,7 @@
 
     /*
      * private int mul(int a, int b) throws ArithmeticException { long p; // Large enough to catch 16-bit multiply //
-     * without hitting sign bit. if (a != 0) { if(b != 0) { p = (long) a * b; b = (int) p & 0xFFFF; // Lower 16 bits. a
+     * without hitting sign bit. if (a != 0) { if (b != 0) { p = (long) a * b; b = (int) p & 0xFFFF; // Lower 16 bits. a
      * = (int) p >>> 16; // Upper 16 bits.
      *
      * return (b - a + (b < a ? 1 : 0) & 0xFFFF); } else return ((1 - a) & 0xFFFF); // If b = 0, then same as // 0x10001
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_invoke01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_invoke01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 package com.oracle.graal.jtt.hotpath;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -104,12 +104,12 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 40);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 80);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_life.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_life.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,8 +25,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -107,7 +107,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_nest02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_nest02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,8 +23,8 @@
 // Checkstyle: stop
 package com.oracle.graal.jtt.hotpath;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -48,7 +48,7 @@
         return sum;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 15);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6196102.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6196102.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.jtt.hotspot;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /**
- * @test
+ * @LongTest
  * @bug 6196102
  * @summary Integer seems to be greater than Integer.MAX_VALUE
  * 
@@ -48,7 +48,7 @@
         return "ok";
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6850611.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6850611.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.hotspot;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 //@formatter:off
 
@@ -50,7 +50,7 @@
         return 95;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/EnumMap02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/EnumMap02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -43,17 +43,17 @@
         A, B, C
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.io.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -56,7 +56,7 @@
         System.out.println(test(10000));
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 10000);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 import sun.misc.*;
 
@@ -55,7 +55,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/ClassLoader_loadClass01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/ClassLoader_loadClass01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.net.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -43,22 +43,22 @@
         return null;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_Literal01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_Literal01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public final class Class_Literal01 extends JTTTest {
 
@@ -45,27 +45,27 @@
         return null;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_asSubclass01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_asSubclass01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public final class Class_asSubclass01 extends JTTTest {
 
@@ -53,27 +53,27 @@
         return i;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public final class Class_cast01 extends JTTTest {
 
@@ -57,27 +57,27 @@
         return i;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public final class Class_forName01 extends JTTTest {
 
@@ -45,27 +45,27 @@
         return null;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public final class Class_forName02 extends JTTTest {
 
@@ -51,27 +51,27 @@
         return null;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.net.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -56,32 +56,32 @@
         return null;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName04.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName04.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -48,32 +48,32 @@
         return null;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName05.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName05.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.net.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -41,17 +41,17 @@
         return null;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getInterfaces01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getInterfaces01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,12 +22,11 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
-
 public final class Class_getInterfaces01 extends JTTTest {
 
     public static String test(int i) {
@@ -82,27 +81,27 @@
 
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public final class Object_getClass01 extends JTTTest {
 
@@ -49,27 +49,27 @@
         return null;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Object_toString01 extends JTTTest {
 
@@ -47,17 +47,17 @@
         return string;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -33,17 +33,17 @@
         return ("id" + i).intern() == ("id" + i).intern();
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.lang;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -33,17 +33,17 @@
         return ("id" + i).intern().equals("id" + i);
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.loop;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class LoopParseLong extends JTTTest {
 
@@ -79,7 +79,7 @@
         return negative ? result : -result;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", "7", 10);
         runTest("test", "-100", 10);
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopSwitch01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopSwitch01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.loop;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -58,7 +58,7 @@
         return "" + ('a' + count);
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigObjectParams02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigObjectParams02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.micro;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -33,7 +33,7 @@
         return p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/Matrix01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/Matrix01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.micro;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -155,32 +155,32 @@
         ((Matrix[]) array)[val % array.length] = new Matrix(number);
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/ReferenceMap01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/ReferenceMap01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.micro;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -57,7 +57,7 @@
         return Integer.valueOf(foo(new String[]{"asdf"}));
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.micro;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -58,7 +58,7 @@
         Object c = b;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -117,22 +117,22 @@
         return c2 ? 1 : 0;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 10);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 20);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 40);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_FlowSensitive05.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_FlowSensitive05.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.optimize;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -40,7 +40,7 @@
         return (String) arg;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", (Object) null);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.optimize;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  * Tests value numbering of instanceof operations.
@@ -76,17 +76,17 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -37,22 +37,22 @@
         return Class_getField01.class.getField(input).getName();
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", "test");
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", "field");
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", "field2");
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", "field3");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -42,27 +42,27 @@
         public String field4;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", "test");
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", "field");
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", "field2");
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", "field3");
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", "field4");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -39,17 +39,17 @@
         field = args[0];
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", "test");
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", "main");
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", "xx");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -52,37 +52,37 @@
         field = args[0];
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @Test
+    @LongTest
     public void run6() throws Throwable {
         runTest("test", 6);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_newInstance03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_newInstance03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Class_newInstance03 extends JTTTest {
 
@@ -45,27 +45,27 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -59,47 +59,47 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @Test
+    @LongTest
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @Test
+    @LongTest
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @Test
+    @LongTest
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -61,47 +61,47 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @Test
+    @LongTest
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @Test
+    @LongTest
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @Test
+    @LongTest
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -89,47 +89,47 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @Test
+    @LongTest
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @Test
+    @LongTest
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @Test
+    @LongTest
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -61,47 +61,47 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @Test
+    @LongTest
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @Test
+    @LongTest
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @Test
+    @LongTest
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_getType01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_getType01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -59,47 +59,47 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @Test
+    @LongTest
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @Test
+    @LongTest
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @Test
+    @LongTest
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -67,47 +67,47 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @Test
+    @LongTest
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @Test
+    @LongTest
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @Test
+    @LongTest
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -69,47 +69,47 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @Test
+    @LongTest
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @Test
+    @LongTest
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @Test
+    @LongTest
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -69,47 +69,47 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
 
-    @Test
+    @LongTest
     public void run6() throws Throwable {
         runTest("test", 6);
     }
 
-    @Test
+    @LongTest
     public void run7() throws Throwable {
         runTest("test", 7);
     }
 
-    @Test
+    @LongTest
     public void run8() throws Throwable {
         runTest("test", 8);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -56,27 +56,27 @@
         return arg.length;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -44,12 +44,12 @@
         field = args[0];
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", "test1");
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", "test2");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -48,12 +48,12 @@
         field = args[0];
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", "test1");
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", "test2");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getParameterTypes01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getParameterTypes01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -51,22 +51,22 @@
     public void method3(int arg1, Object arg2) {
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getReturnType01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getReturnType01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.reflect;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -51,22 +51,22 @@
     public void method3() {
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public final class Monitor_contended01 extends JTTTest implements Runnable {
 
@@ -71,7 +71,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Monitor_notowner01 extends JTTTest {
 
@@ -62,7 +62,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Object_wait01 extends JTTTest implements Runnable {
 
@@ -57,22 +57,22 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 15);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Object_wait02 extends JTTTest implements Runnable {
 
@@ -57,17 +57,17 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Object_wait03 extends JTTTest implements Runnable {
 
@@ -63,17 +63,17 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Object_wait04 extends JTTTest implements Runnable {
 
@@ -67,32 +67,32 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
 
-    @Test
+    @LongTest
     public void run5() throws Throwable {
         runTest("test", 5);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/ThreadLocal03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/ThreadLocal03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -59,22 +59,22 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_getState02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_getState02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public final class Thread_getState02 extends JTTTest {
 
@@ -33,7 +33,7 @@
         return new Thread().getState() == Thread.State.NEW;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,8 +26,8 @@
 
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 //Test all, mainly monitors
 public class Thread_isInterrupted02 extends JTTTest {
@@ -85,12 +85,12 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0, 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1, 500);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -68,7 +68,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -66,7 +66,7 @@
 
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 /*
  */
@@ -66,7 +66,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Thread_join01 extends JTTTest implements Runnable {
 
@@ -43,7 +43,7 @@
         cont = false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -27,8 +27,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Thread_join02 extends JTTTest implements Runnable {
 
@@ -50,7 +50,7 @@
         cont = false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java	Thu Mar 21 14:11:13 2013 +0100
@@ -27,8 +27,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Thread_join03 extends JTTTest implements Runnable {
 
@@ -47,7 +47,7 @@
         cont = false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test");
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public final class Thread_new01 extends JTTTest {
 
@@ -45,27 +45,27 @@
         return false;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public class Thread_new02 extends JTTTest implements Runnable {
 
@@ -51,27 +51,27 @@
         // do nothing.
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 0);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 1);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 2);
     }
 
-    @Test
+    @LongTest
     public void run3() throws Throwable {
         runTest("test", 3);
     }
 
-    @Test
+    @LongTest
     public void run4() throws Throwable {
         runTest("test", 4);
     }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,8 @@
  */
 package com.oracle.graal.jtt.threads;
 
+import com.oracle.graal.test.*;
 import com.oracle.graal.jtt.*;
-import org.junit.*;
 
 public final class Thread_sleep01 extends JTTTest {
 
@@ -35,17 +35,17 @@
         return System.currentTimeMillis() - before >= i;
     }
 
-    @Test
+    @LongTest
     public void run0() throws Throwable {
         runTest("test", 10);
     }
 
-    @Test
+    @LongTest
     public void run1() throws Throwable {
         runTest("test", 20);
     }
 
-    @Test
+    @LongTest
     public void run2() throws Throwable {
         runTest("test", 100);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.asm.amd64.AMD64Address.Scale;
+import com.oracle.graal.lir.*;
+
+public class AMD64AddressValue extends CompositeValue {
+
+    private static final long serialVersionUID = -4444600052487578694L;
+
+    @Component({REG, UNUSED}) protected AllocatableValue base;
+    @Component({REG, UNUSED}) protected AllocatableValue index;
+    protected final Scale scale;
+    protected final int displacement;
+
+    public AMD64AddressValue(Kind kind, AllocatableValue base, int displacement) {
+        this(kind, base, AllocatableValue.UNUSED, Scale.Times1, displacement);
+    }
+
+    public AMD64AddressValue(Kind kind, AllocatableValue base, AllocatableValue index, Scale scale, int displacement) {
+        super(kind);
+        this.base = base;
+        this.index = index;
+        this.scale = scale;
+        this.displacement = displacement;
+    }
+
+    private static Register toRegister(AllocatableValue value) {
+        if (value == AllocatableValue.UNUSED) {
+            return Register.None;
+        } else {
+            RegisterValue reg = (RegisterValue) value;
+            return reg.getRegister();
+        }
+    }
+
+    public AMD64Address toAddress() {
+        return new AMD64Address(toRegister(base), toRegister(index), scale, displacement);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append(getKind().getJavaName()).append("[");
+        String sep = "";
+        if (isLegal(base)) {
+            s.append(base);
+            sep = " + ";
+        }
+        if (isLegal(index)) {
+            s.append(sep).append(index).append(" * ").append(scale.value);
+            sep = " + ";
+        }
+        if (displacement < 0) {
+            s.append(" - ").append(-displacement);
+        } else if (displacement > 0) {
+            s.append(sep).append(displacement);
+        }
+        s.append("]");
+        return s.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof AMD64AddressValue) {
+            AMD64AddressValue addr = (AMD64AddressValue) obj;
+            return getKind() == addr.getKind() && displacement == addr.displacement && base.equals(addr.base) && scale == addr.scale && index.equals(addr.index);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return base.hashCode() ^ index.hashCode() ^ (displacement << 4) ^ (scale.value << 8) ^ (getKind().ordinal() << 12);
+    }
+}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,10 +26,9 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.asm.amd64.AMD64Assembler.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
@@ -43,17 +42,25 @@
     INEG, LNEG,
     I2L, L2I, I2B, I2C, I2S,
     F2D, D2F,
-    I2F, I2D, F2I, D2I,
-    L2F, L2D, F2L, D2L,
-    MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L;
+    I2F, I2D,
+    L2F, L2D,
+    MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L,
 
+    /*
+     * Converts a float/double to an int/long. The result of the conversion does not comply with Java semantics
+     * when the input is a NaN, infinity or the conversion result is greater than Integer.MAX_VALUE/Long.MAX_VALUE.
+     */
+    F2I, D2I, F2L, D2L;
 
-    public static class Op1Reg extends AMD64LIRInstruction {
+    /**
+     * Unary operation with separate source and destination operand. 
+     */
+    public static class Unary2Op extends AMD64LIRInstruction {
         @Opcode private final AMD64Arithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG}) protected Value x;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
 
-        public Op1Reg(AMD64Arithmetic opcode, Value result, Value x) {
+        public Unary2Op(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) {
             this.opcode = opcode;
             this.result = result;
             this.x = x;
@@ -65,12 +72,15 @@
         }
     }
 
-    public static class Op1Stack extends AMD64LIRInstruction {
+    /**
+     * Unary operation with single operand for source and destination. 
+     */
+    public static class Unary1Op extends AMD64LIRInstruction {
         @Opcode private final AMD64Arithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
 
-        public Op1Stack(AMD64Arithmetic opcode, Value result, Value x) {
+        public Unary1Op(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) {
             this.opcode = opcode;
             this.result = result;
             this.x = x;
@@ -83,13 +93,17 @@
         }
     }
 
-    public static class Op2Stack extends AMD64LIRInstruction {
+    /**
+     * Binary operation with two operands. The first source operand is combined with the destination.
+     * The second source operand may be a stack slot. 
+     */
+    public static class BinaryRegStack extends AMD64LIRInstruction {
         @Opcode private final AMD64Arithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
-        @Alive({REG, STACK, CONST}) protected Value y;
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
+        @Alive({REG, STACK}) protected AllocatableValue y;
 
-        public Op2Stack(AMD64Arithmetic opcode, Value result, Value x, Value y) {
+        public BinaryRegStack(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) {
             this.opcode = opcode;
             this.result = result;
             this.x = x;
@@ -110,13 +124,17 @@
         }
     }
 
-    public static class Op2Reg extends AMD64LIRInstruction {
+    /**
+     * Binary operation with two operands. The first source operand is combined with the destination.
+     * The second source operand must be a register. 
+     */
+    public static class BinaryRegReg extends AMD64LIRInstruction {
         @Opcode private final AMD64Arithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
-        @Alive({REG, CONST}) protected Value y;
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
+        @Alive({REG}) protected AllocatableValue y;
 
-        public Op2Reg(AMD64Arithmetic opcode, Value result, Value x, Value y) {
+        public BinaryRegReg(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) {
             this.opcode = opcode;
             this.result = result;
             this.x = x;
@@ -137,13 +155,45 @@
         }
     }
 
-    public static class Op2RegCommutative extends AMD64LIRInstruction {
+    /**
+     * Binary operation with single source/destination operand and one constant.
+     */
+    public static class BinaryRegConst extends AMD64LIRInstruction {
         @Opcode private final AMD64Arithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
-        @Use({REG, CONST}) protected Value y;
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
+        protected Constant y;
+
+        public BinaryRegConst(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            AMD64Move.move(tasm, masm, result, x);
+            emit(tasm, masm, opcode, result, y, null);
+        }
 
-        public Op2RegCommutative(AMD64Arithmetic opcode, Value result, Value x, Value y) {
+        @Override
+        public void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    /**
+     * Commutative binary operation with two operands. One of the operands is combined with the result.
+     */
+    public static class BinaryCommutative extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
+        @Use({REG, STACK}) protected AllocatableValue y;
+
+        public BinaryCommutative(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) {
             this.opcode = opcode;
             this.result = result;
             this.x = x;
@@ -167,13 +217,16 @@
         }
     }
 
-    public static class ShiftOp extends AMD64LIRInstruction {
+    /**
+     * Binary operation with separate source and destination and one constant operand.
+     */
+    public static class BinaryRegStackConst extends AMD64LIRInstruction {
         @Opcode private final AMD64Arithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
-        @Alive({REG, CONST}) protected Value y;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue x;
+        protected Constant y;
 
-        public ShiftOp(AMD64Arithmetic opcode, Value result, Value x, Value y) {
+        public BinaryRegStackConst(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y) {
             this.opcode = opcode;
             this.result = result;
             this.x = x;
@@ -189,22 +242,19 @@
         @Override
         public void verify() {
             super.verify();
-            assert isConstant(y) || asRegister(y) == AMD64.rcx;
-            assert differentRegisters(result, y) || sameRegister(x, y);
-            verifyKind(opcode, result, x, x);
-            assert y.getKind().getStackKind() == Kind.Int;
+            verifyKind(opcode, result, x, y);
         }
     }
 
     public static class DivRemOp extends AMD64LIRInstruction {
         @Opcode private final AMD64Arithmetic opcode;
-        @Def protected Value divResult;
-        @Def protected Value remResult;
-        @Use protected Value x;
-        @Alive protected Value y;
+        @Def protected AllocatableValue divResult;
+        @Def protected AllocatableValue remResult;
+        @Use protected AllocatableValue x;
+        @Alive protected AllocatableValue y;
         @State protected LIRFrameState state;
 
-        public DivRemOp(AMD64Arithmetic opcode, Value x, Value y, LIRFrameState state) {
+        public DivRemOp(AMD64Arithmetic opcode, AllocatableValue x, AllocatableValue y, LIRFrameState state) {
             this.opcode = opcode;
             this.divResult = AMD64.rax.asValue(x.getKind());
             this.remResult = AMD64.rdx.asValue(x.getKind());
@@ -229,49 +279,14 @@
         }
     }
 
-    public static class DivOp extends AMD64LIRInstruction {
-        @Opcode private final AMD64Arithmetic opcode;
-        @Def protected Value result;
-        @Use protected Value x;
-        @Alive protected Value y;
-        @Temp protected Value temp;
-        @State protected LIRFrameState state;
-
-        public DivOp(AMD64Arithmetic opcode, Value result, Value x, Value y, LIRFrameState state) {
-            this.opcode = opcode;
-            this.result = result;
-            this.x = x;
-            this.y = y;
-            this.temp = asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.getKind()) : AMD64.rax.asValue(result.getKind());
-            this.state = state;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            emit(tasm, masm, opcode, result, y, state);
-        }
-
-        @Override
-        protected void verify() {
-            super.verify();
-            // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx
-            assert asRegister(x) == AMD64.rax;
-            assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue());
-            assert (name().endsWith("DIV") && asRegister(result) == AMD64.rax) || (name().endsWith("REM") && asRegister(result) == AMD64.rdx);
-            verifyKind(opcode, result, x, y);
-        }
-    }
-
 
     @SuppressWarnings("unused")
-    protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, Value result) {
+    protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, AllocatableValue result) {
         switch (opcode) {
             case INEG: masm.negl(asIntReg(result)); break;
             case LNEG: masm.negq(asLongReg(result)); break;
             case L2I:  masm.andl(asIntReg(result), 0xFFFFFFFF); break;
-            case I2B:  masm.signExtendByte(asIntReg(result)); break;
             case I2C:  masm.andl(asIntReg(result), 0xFFFF); break;
-            case I2S:  masm.signExtendShort(asIntReg(result)); break;
             default:   throw GraalInternalError.shouldNotReachHere();
         }
     }
@@ -286,9 +301,9 @@
                 case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break;
                 case IOR:  masm.orl(asIntReg(dst),   asIntReg(src)); break;
                 case IXOR: masm.xorl(asIntReg(dst),  asIntReg(src)); break;
-                case ISHL: masm.shll(asIntReg(dst)); break;
-                case ISHR: masm.sarl(asIntReg(dst)); break;
-                case IUSHR:masm.shrl(asIntReg(dst)); break;
+                case ISHL: assert asIntReg(src) == AMD64.rcx; masm.shll(asIntReg(dst)); break;
+                case ISHR: assert asIntReg(src) == AMD64.rcx; masm.sarl(asIntReg(dst)); break;
+                case IUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrl(asIntReg(dst)); break;
 
                 case LADD: masm.addq(asLongReg(dst),  asLongReg(src)); break;
                 case LSUB: masm.subq(asLongReg(dst),  asLongReg(src)); break;
@@ -296,9 +311,9 @@
                 case LAND: masm.andq(asLongReg(dst),  asLongReg(src)); break;
                 case LOR:  masm.orq(asLongReg(dst),   asLongReg(src)); break;
                 case LXOR: masm.xorq(asLongReg(dst),  asLongReg(src)); break;
-                case LSHL: masm.shlq(asLongReg(dst)); break;
-                case LSHR: masm.sarq(asLongReg(dst)); break;
-                case LUSHR:masm.shrq(asLongReg(dst)); break;
+                case LSHL: assert asIntReg(src) == AMD64.rcx; masm.shlq(asLongReg(dst)); break;
+                case LSHR: assert asIntReg(src) == AMD64.rcx; masm.sarq(asLongReg(dst)); break;
+                case LUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrq(asLongReg(dst)); break;
 
                 case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break;
                 case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break;
@@ -316,6 +331,8 @@
                 case DOR:  masm.orpd(asDoubleReg(dst),  asDoubleReg(src)); break;
                 case DXOR: masm.xorpd(asDoubleReg(dst), asDoubleReg(src)); break;
 
+                case I2B: masm.movsxb(asIntReg(dst), asIntReg(src)); break;
+                case I2S: masm.movsxw(asIntReg(dst), asIntReg(src)); break;
                 case I2L: masm.movslq(asLongReg(dst), asIntReg(src)); break;
                 case F2D: masm.cvtss2sd(asDoubleReg(dst), asFloatReg(src)); break;
                 case D2F: masm.cvtsd2ss(asFloatReg(dst), asDoubleReg(src)); break;
@@ -325,19 +342,15 @@
                 case L2D: masm.cvtsi2sdq(asDoubleReg(dst), asLongReg(src)); break;
                 case F2I:
                     masm.cvttss2sil(asIntReg(dst), asFloatReg(src));
-                    emitConvertFixup(tasm, masm, dst, src);
                     break;
                 case D2I:
                     masm.cvttsd2sil(asIntReg(dst), asDoubleReg(src));
-                    emitConvertFixup(tasm, masm, dst, src);
                     break;
                 case F2L:
                     masm.cvttss2siq(asLongReg(dst), asFloatReg(src));
-                    emitConvertFixup(tasm, masm, dst, src);
                     break;
                 case D2L:
                     masm.cvttsd2siq(asLongReg(dst), asDoubleReg(src));
-                    emitConvertFixup(tasm, masm, dst, src);
                     break;
                 case MOV_I2F: masm.movdl(asFloatReg(dst), asIntReg(src)); break;
                 case MOV_L2D: masm.movdq(asDoubleReg(dst), asLongReg(src)); break;
@@ -400,46 +413,75 @@
                 case LSHR: masm.sarq(asLongReg(dst), tasm.asIntConst(src) & 63); break;
                 case LUSHR:masm.shrq(asLongReg(dst), tasm.asIntConst(src) & 63); break;
 
-                case FADD: masm.addss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
-                case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
-                case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
-                case FAND: masm.andps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break;
-                case FOR:  masm.orps(asFloatReg(dst),  tasm.asFloatConstRef(src, 16)); break;
-                case FXOR: masm.xorps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break;
-                case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatConstRef(src)); break;
+                case FADD: masm.addss(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src)); break;
+                case FSUB: masm.subss(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src)); break;
+                case FMUL: masm.mulss(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src)); break;
+                case FAND: masm.andps(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src, 16)); break;
+                case FOR:  masm.orps(asFloatReg(dst),  (AMD64Address) tasm.asFloatConstRef(src, 16)); break;
+                case FXOR: masm.xorps(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src, 16)); break;
+                case FDIV: masm.divss(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src)); break;
 
-                case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
-                case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
-                case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
-                case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break;
-                case DAND: masm.andpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break;
-                case DOR:  masm.orpd(asDoubleReg(dst),  tasm.asDoubleConstRef(src, 16)); break;
-                case DXOR: masm.xorpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break;
+                case DADD: masm.addsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src)); break;
+                case DSUB: masm.subsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src)); break;
+                case DMUL: masm.mulsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src)); break;
+                case DDIV: masm.divsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src)); break;
+                case DAND: masm.andpd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src, 16)); break;
+                case DOR:  masm.orpd(asDoubleReg(dst),  (AMD64Address) tasm.asDoubleConstRef(src, 16)); break;
+                case DXOR: masm.xorpd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src, 16)); break;
                 default:   throw GraalInternalError.shouldNotReachHere();
             }
         } else {
             switch (opcode) {
-                case IADD: masm.addl(asIntReg(dst), tasm.asIntAddr(src)); break;
-                case ISUB: masm.subl(asIntReg(dst), tasm.asIntAddr(src)); break;
-                case IAND: masm.andl(asIntReg(dst), tasm.asIntAddr(src)); break;
-                case IOR:  masm.orl(asIntReg(dst),  tasm.asIntAddr(src)); break;
-                case IXOR: masm.xorl(asIntReg(dst), tasm.asIntAddr(src)); break;
+                case IADD: masm.addl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case ISUB: masm.subl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case IAND: masm.andl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case IMUL: masm.imull(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case IOR:  masm.orl(asIntReg(dst),  (AMD64Address) tasm.asIntAddr(src)); break;
+                case IXOR: masm.xorl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+
+                case LADD: masm.addq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+                case LSUB: masm.subq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+                case LMUL: masm.imulq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+                case LAND: masm.andq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+                case LOR:  masm.orq(asLongReg(dst),  (AMD64Address) tasm.asLongAddr(src)); break;
+                case LXOR: masm.xorq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+
+                case FADD: masm.addss(asFloatReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break;
+                case FSUB: masm.subss(asFloatReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break;
+                case FMUL: masm.mulss(asFloatReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break;
+                case FDIV: masm.divss(asFloatReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break;
+
+                case DADD: masm.addsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
+                case DSUB: masm.subsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
+                case DMUL: masm.mulsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
+                case DDIV: masm.divsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
 
-                case LADD: masm.addq(asLongReg(dst), tasm.asLongAddr(src)); break;
-                case LSUB: masm.subq(asLongReg(dst), tasm.asLongAddr(src)); break;
-                case LAND: masm.andq(asLongReg(dst), tasm.asLongAddr(src)); break;
-                case LOR:  masm.orq(asLongReg(dst),  tasm.asLongAddr(src)); break;
-                case LXOR: masm.xorq(asLongReg(dst), tasm.asLongAddr(src)); break;
+                case I2B: masm.movsxb(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case I2S: masm.movsxw(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case I2L: masm.movslq(asLongReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case F2D: masm.cvtss2sd(asDoubleReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break;
+                case D2F: masm.cvtsd2ss(asFloatReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
+                case I2F: masm.cvtsi2ssl(asFloatReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case I2D: masm.cvtsi2sdl(asDoubleReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case L2F: masm.cvtsi2ssq(asFloatReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+                case L2D: masm.cvtsi2sdq(asDoubleReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+                case F2I:
+                    masm.cvttss2sil(asIntReg(dst), (AMD64Address) tasm.asFloatAddr(src));
+                    break;
+                case D2I:
+                    masm.cvttsd2sil(asIntReg(dst), (AMD64Address) tasm.asDoubleAddr(src));
+                    break;
+                case F2L:
+                    masm.cvttss2siq(asLongReg(dst), (AMD64Address) tasm.asFloatAddr(src));
+                    break;
+                case D2L:
+                    masm.cvttsd2siq(asLongReg(dst), (AMD64Address) tasm.asDoubleAddr(src));
+                    break;
+                case MOV_I2F: masm.movss(asFloatReg(dst), (AMD64Address) tasm.asIntAddr(src)); break;
+                case MOV_L2D: masm.movsd(asDoubleReg(dst), (AMD64Address) tasm.asLongAddr(src)); break;
+                case MOV_F2I: masm.movl(asIntReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break;
+                case MOV_D2L: masm.movq(asLongReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break;
 
-                case FADD: masm.addss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
-                case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
-                case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
-                case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatAddr(src)); break;
-
-                case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
-                case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
-                case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
-                case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break;
                 default:   throw GraalInternalError.shouldNotReachHere();
             }
         }
@@ -450,67 +492,11 @@
         }
     }
 
-    private static void emitConvertFixup(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value x) {
-        ConvertSlowPath slowPath = new ConvertSlowPath(result, x);
-        tasm.stubs.add(slowPath);
-        switch (result.getKind()) {
-            case Int:  masm.cmpl(asIntReg(result),  Integer.MIN_VALUE); break;
-            case Long: masm.cmpq(asLongReg(result), tasm.asLongConstRef(Constant.forLong(java.lang.Long.MIN_VALUE))); break;
-            default:   throw GraalInternalError.shouldNotReachHere();
-        }
-        masm.jcc(ConditionFlag.equal, slowPath.start);
-        masm.bind(slowPath.continuation);
-    }
-
-    private static class ConvertSlowPath extends AMD64Code {
-        public final Label start = new Label();
-        public final Label continuation = new Label();
-        private final Value result;
-        private final Value x;
-
-        public ConvertSlowPath(Value result, Value x) {
-            this.result = result;
-            this.x = x;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.bind(start);
-            switch (x.getKind()) {
-                case Float:  masm.ucomiss(asFloatReg(x),  tasm.asFloatConstRef(Constant.FLOAT_0)); break;
-                case Double: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(Constant.DOUBLE_0)); break;
-                default:     throw GraalInternalError.shouldNotReachHere();
-            }
-            Label nan = new Label();
-            masm.jcc(ConditionFlag.parity, nan);
-            masm.jcc(ConditionFlag.below, continuation);
-
-            // input is > 0 -> return maxInt
-            // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff
-            switch (result.getKind()) {
-                case Int:  masm.decrementl(asIntReg(result),  1); break;
-                case Long: masm.decrementq(asLongReg(result), 1); break;
-                default:   throw GraalInternalError.shouldNotReachHere();
-            }
-            masm.jmp(continuation);
-
-            // input is NaN -> return 0
-            masm.bind(nan);
-            masm.xorptr(asRegister(result), asRegister(result));
-            masm.jmp(continuation);
-        }
-
-        @Override
-        public String description() {
-            return "convert " + x + " to " + result;
-        }
-    }
-
-
     private static void verifyKind(AMD64Arithmetic opcode, Value result, Value x, Value y) {
         assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int)
             || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
             || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
-            || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
+            || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double)
+            || (opcode.name().matches(".U?SH.") && result.getKind() == x.getKind() && y.getKind() == Kind.Int && (isConstant(y) || asRegister(y) == AMD64.rcx));
     }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,7 +23,6 @@
 package com.oracle.graal.lir.amd64;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -34,10 +33,10 @@
     }
 
     @Opcode private final IntrinsicOpcode opcode;
-    @Def protected Value result;
-    @Use({OperandFlag.REG, OperandFlag.ADDR}) protected Value input;
+    @Def protected AllocatableValue result;
+    @Use({OperandFlag.REG, OperandFlag.STACK}) protected AllocatableValue input;
 
-    public AMD64BitManipulationOp(IntrinsicOpcode opcode, Value result, Value input) {
+    public AMD64BitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input) {
         this.opcode = opcode;
         this.result = result;
         this.input = input;
@@ -46,8 +45,8 @@
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
         Register dst = ValueUtil.asIntReg(result);
-        if (ValueUtil.isAddress(input)) {
-            Address src = ValueUtil.asAddress(input);
+        if (ValueUtil.isRegister(input)) {
+            Register src = ValueUtil.asRegister(input);
             switch (opcode) {
                 case IPOPCNT:
                     masm.popcntl(dst, src);
@@ -66,7 +65,7 @@
                     break;
             }
         } else {
-            Register src = ValueUtil.asRegister(input);
+            AMD64Address src = (AMD64Address) tasm.asAddress(input);
             switch (opcode) {
                 case IPOPCNT:
                     masm.popcntl(dst, src);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,17 +26,15 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.spi.*;
 
 public class AMD64Call {
 
-    public static final Descriptor DEBUG = new Descriptor("debug", false, void.class);
-
     @Opcode("CALL_DIRECT")
     public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
 
@@ -45,9 +43,9 @@
         @Temp protected Value[] temps;
         @State protected LIRFrameState state;
 
-        protected final Object callTarget;
+        protected final ResolvedJavaMethod callTarget;
 
-        public DirectCallOp(Object callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+        public DirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
             this.callTarget = callTarget;
             this.result = result;
             this.parameters = parameters;
@@ -58,15 +56,59 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            emitAlignmentForDirectCall(tasm, masm);
-            directCall(tasm, masm, callTarget, state);
+            directCall(tasm, masm, callTarget, null, true, state);
+        }
+    }
+
+    @Opcode("CALL_NEAR_RUNTIME")
+    public static class DirectNearRuntimeCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+
+        @Def({REG, ILLEGAL}) protected Value result;
+        @Use({REG, STACK}) protected Value[] parameters;
+        @Temp protected Value[] temps;
+        @State protected LIRFrameState state;
+
+        protected final RuntimeCallTarget callTarget;
+
+        public DirectNearRuntimeCallOp(RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            this.callTarget = callTarget;
+            this.result = result;
+            this.parameters = parameters;
+            this.state = state;
+            this.temps = temps;
+            assert temps != null;
         }
 
-        protected void emitAlignmentForDirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            // make sure that the displacement word of the call ends up word aligned
-            int offset = masm.codeBuffer.position();
-            offset += tasm.target.arch.getMachineCodeCallDisplacementOffset();
-            masm.nop(tasm.target.wordSize - offset % tasm.target.wordSize);
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            directCall(tasm, masm, callTarget, null, false, state);
+        }
+    }
+
+    @Opcode("CALL_FAR_RUNTIME")
+    public static class DirectFarRuntimeCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+
+        @Def({REG, ILLEGAL}) protected Value result;
+        @Use({REG, STACK}) protected Value[] parameters;
+        @Temp protected Value[] temps;
+        @State protected LIRFrameState state;
+        @Temp({REG}) protected AllocatableValue callTemp;
+
+        protected final RuntimeCallTarget callTarget;
+
+        public DirectFarRuntimeCallOp(LIRGeneratorTool gen, RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            this.callTarget = callTarget;
+            this.result = result;
+            this.parameters = parameters;
+            this.state = state;
+            this.temps = temps;
+            assert temps != null;
+            callTemp = gen.newVariable(Kind.Long);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            directCall(tasm, masm, callTarget, ((RegisterValue) callTemp).getRegister(), false, state);
         }
     }
 
@@ -79,9 +121,9 @@
         @Temp protected Value[] temps;
         @State protected LIRFrameState state;
 
-        protected final Object callTarget;
+        protected final InvokeTarget callTarget;
 
-        public IndirectCallOp(Object callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) {
+        public IndirectCallOp(InvokeTarget callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) {
             this.callTarget = callTarget;
             this.result = result;
             this.parameters = parameters;
@@ -103,53 +145,49 @@
         }
     }
 
-    public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object callTarget, LIRFrameState info) {
+    public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, InvokeTarget callTarget, Register scratch, boolean align, LIRFrameState info) {
+        if (align) {
+            emitAlignmentForDirectCall(tasm, masm);
+        }
         int before = masm.codeBuffer.position();
-        if (callTarget instanceof RuntimeCallTarget) {
-            long maxOffset = ((RuntimeCallTarget) callTarget).getMaxCallTargetOffset();
-            if (maxOffset != (int) maxOffset) {
-                // offset might not fit a 32-bit immediate, generate an
-                // indirect call with a 64-bit immediate
-                Register scratch = tasm.frameMap.registerConfig.getScratchRegister();
-                masm.movq(scratch, 0L);
-                masm.call(scratch);
-            } else {
-                masm.call();
-            }
-
+        if (scratch != null) {
+            // offset might not fit a 32-bit immediate, generate an
+            // indirect call with a 64-bit immediate
+            masm.movq(scratch, 0L);
+            masm.call(scratch);
         } else {
             masm.call();
         }
         int after = masm.codeBuffer.position();
-        tasm.recordDirectCall(before, after, tasm.runtime.lookupCallTarget(callTarget), info);
+        tasm.recordDirectCall(before, after, callTarget, info);
         tasm.recordExceptionHandlers(after, info);
         masm.ensureUniquePC();
     }
 
-    public static void directJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target) {
+    protected static void emitAlignmentForDirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        // make sure that the displacement word of the call ends up word aligned
+        int offset = masm.codeBuffer.position();
+        offset += tasm.target.arch.getMachineCodeCallDisplacementOffset();
+        int modulus = tasm.target.wordSize;
+        if (offset % modulus != 0) {
+            masm.nop(modulus - offset % modulus);
+        }
+    }
+
+    public static void directJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, InvokeTarget target) {
         int before = masm.codeBuffer.position();
         masm.jmp(0, true);
         int after = masm.codeBuffer.position();
-        tasm.recordDirectCall(before, after, tasm.runtime.lookupCallTarget(target), null);
+        tasm.recordDirectCall(before, after, target, null);
         masm.ensureUniquePC();
     }
 
-    public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, Object callTarget, LIRFrameState info) {
+    public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) {
         int before = masm.codeBuffer.position();
         masm.call(dst);
         int after = masm.codeBuffer.position();
-        tasm.recordIndirectCall(before, after, tasm.runtime.lookupCallTarget(callTarget), info);
+        tasm.recordIndirectCall(before, after, callTarget, info);
         tasm.recordExceptionHandlers(after, info);
         masm.ensureUniquePC();
     }
-
-    public static void shouldNotReachHere(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        boolean assertions = false;
-        assert (assertions = true) == true;
-
-        if (assertions) {
-            directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(DEBUG), null);
-            masm.hlt();
-        }
-    }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Code.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.lir.amd64;
-
-import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.asm.*;
-
-/**
- * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
- */
-public abstract class AMD64Code implements LIR.Code {
-
-    @Override
-    public final void emitCode(TargetMethodAssembler tasm) {
-        emitCode(tasm, (AMD64MacroAssembler) tasm.asm);
-    }
-
-    public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm);
-}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Thu Mar 21 14:11:13 2013 +0100
@@ -54,7 +54,6 @@
         protected void verify() {
             super.verify();
             assert (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int)
-                || (name().startsWith("I") && x.getKind() == Kind.Jsr && y.getKind() == Kind.Jsr)
                 || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
                 || (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object)
                 || (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
@@ -82,17 +81,17 @@
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons");
                     }
-                case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(y)); break;
-                case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(y)); break;
+                case FCMP: masm.ucomiss(asFloatReg(x), (AMD64Address) tasm.asFloatConstRef(y)); break;
+                case DCMP: masm.ucomisd(asDoubleReg(x), (AMD64Address) tasm.asDoubleConstRef(y)); break;
                 default:   throw GraalInternalError.shouldNotReachHere();
             }
         } else {
             switch (opcode) {
-                case ICMP: masm.cmpl(asIntReg(x), tasm.asIntAddr(y)); break;
-                case LCMP: masm.cmpq(asLongReg(x), tasm.asLongAddr(y)); break;
-                case ACMP: masm.cmpptr(asObjectReg(x), tasm.asObjectAddr(y)); break;
-                case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatAddr(y)); break;
-                case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleAddr(y)); break;
+                case ICMP: masm.cmpl(asIntReg(x), (AMD64Address) tasm.asIntAddr(y)); break;
+                case LCMP: masm.cmpq(asLongReg(x), (AMD64Address) tasm.asLongAddr(y)); break;
+                case ACMP: masm.cmpptr(asObjectReg(x), (AMD64Address) tasm.asObjectAddr(y)); break;
+                case FCMP: masm.ucomiss(asFloatReg(x), (AMD64Address) tasm.asFloatAddr(y)); break;
+                case DCMP: masm.ucomisd(asDoubleReg(x), (AMD64Address) tasm.asDoubleAddr(y)); break;
                 default:  throw GraalInternalError.shouldNotReachHere();
             }
         }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,13 +26,13 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.CompilationResult.JumpTable;
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.Address.Scale;
-import com.oracle.graal.api.code.CompilationResult.JumpTable;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.Opcode;
@@ -63,16 +63,14 @@
     public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp {
         protected ConditionFlag condition;
         protected LabelRef destination;
-        @State protected LIRFrameState state;
 
-        public BranchOp(Condition condition, LabelRef destination, LIRFrameState info) {
-            this(intCond(condition), destination, info);
+        public BranchOp(Condition condition, LabelRef destination) {
+            this(intCond(condition), destination);
         }
 
-        public BranchOp(ConditionFlag condition, LabelRef destination, LIRFrameState state) {
+        public BranchOp(ConditionFlag condition, LabelRef destination) {
             this.condition = condition;
             this.destination = destination;
-            this.state = state;
         }
 
         @Override
@@ -96,8 +94,8 @@
     public static class FloatBranchOp extends BranchOp {
         protected boolean unorderedIsTrue;
 
-        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRFrameState info) {
-            super(floatCond(condition), destination, info);
+        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination) {
+            super(floatCond(condition), destination);
             this.unorderedIsTrue = unorderedIsTrue;
         }
 
@@ -162,13 +160,13 @@
                     long lc = keyConstants[i].asLong();
                     assert NumUtil.isInt(lc);
                     masm.cmpl(intKey, (int) lc);
-                    masm.jcc(ConditionFlag.equal, keyTargets[i].label());
+                    masm.jcc(ConditionFlag.Equal, keyTargets[i].label());
                 }
             } else if (key.getKind() == Kind.Long) {
                 Register longKey = asLongReg(key);
                 for (int i = 0; i < keyConstants.length; i++) {
-                    masm.cmpq(longKey, tasm.asLongConstRef(keyConstants[i]));
-                    masm.jcc(ConditionFlag.equal, keyTargets[i].label());
+                    masm.cmpq(longKey, (AMD64Address) tasm.asLongConstRef(keyConstants[i]));
+                    masm.jcc(ConditionFlag.Equal, keyTargets[i].label());
                 }
             } else if (key.getKind() == Kind.Object) {
                 Register intKey = asObjectReg(key);
@@ -176,7 +174,7 @@
                 for (int i = 0; i < keyConstants.length; i++) {
                     AMD64Move.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]);
                     masm.cmpptr(intKey, temp);
-                    masm.jcc(ConditionFlag.equal, keyTargets[i].label());
+                    masm.jcc(ConditionFlag.Equal, keyTargets[i].label());
                 }
             } else {
                 throw new GraalInternalError("sequential switch only supported for int, long and object");
@@ -226,15 +224,15 @@
                 int highKey = highKeys[i];
                 if (lowKey == highKey) {
                     masm.cmpl(asIntReg(key), lowKey);
-                    masm.jcc(ConditionFlag.equal, keyTargets[i].label());
+                    masm.jcc(ConditionFlag.Equal, keyTargets[i].label());
                     skipLowCheck = false;
                 } else {
                     if (!skipLowCheck || (prevHighKey + 1) != lowKey) {
                         masm.cmpl(asIntReg(key), lowKey);
-                        masm.jcc(ConditionFlag.less, actualDefaultTarget);
+                        masm.jcc(ConditionFlag.Less, actualDefaultTarget);
                     }
                     masm.cmpl(asIntReg(key), highKey);
-                    masm.jcc(ConditionFlag.lessEqual, keyTargets[i].label());
+                    masm.jcc(ConditionFlag.LessEqual, keyTargets[i].label());
                     skipLowCheck = true;
                 }
                 prevHighKey = highKey;
@@ -333,16 +331,16 @@
 
         // Jump to default target if index is not within the jump table
         if (defaultTarget != null) {
-            masm.jcc(ConditionFlag.above, defaultTarget.label());
+            masm.jcc(ConditionFlag.Above, defaultTarget.label());
         }
 
         // Set scratch to address of jump table
         int leaPos = buf.position();
-        masm.leaq(scratch, new Address(tasm.target.wordKind, AMD64.rip.asValue(), 0));
+        masm.leaq(scratch, new AMD64Address(AMD64.rip, 0));
         int afterLea = buf.position();
 
         // Load jump table entry into scratch and jump to it
-        masm.movslq(value, new Address(Kind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0));
+        masm.movslq(value, new AMD64Address(scratch, value, Scale.Times4, 0));
         masm.addq(scratch, value);
         masm.jmp(scratch);
 
@@ -354,7 +352,7 @@
         // Patch LEA instruction above now that we know the position of the jump table
         int jumpTablePos = buf.position();
         buf.setPosition(leaPos);
-        masm.leaq(scratch, new Address(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea));
+        masm.leaq(scratch, new AMD64Address(AMD64.rip, jumpTablePos - afterLea));
         buf.setPosition(jumpTablePos);
 
         // Emit jump table entries
@@ -374,15 +372,15 @@
         }
 
         JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4);
-        tasm.targetMethod.addAnnotation(jt);
+        tasm.compilationResult.addAnnotation(jt);
     }
 
     private static void floatJcc(AMD64MacroAssembler masm, ConditionFlag condition, boolean unorderedIsTrue, Label label) {
         Label endLabel = new Label();
         if (unorderedIsTrue && !trueOnUnordered(condition)) {
-            masm.jcc(ConditionFlag.parity, label);
+            masm.jcc(ConditionFlag.Parity, label);
         } else if (!unorderedIsTrue && trueOnUnordered(condition)) {
-            masm.jcc(ConditionFlag.parity, endLabel);
+            masm.jccb(ConditionFlag.Parity, endLabel);
         }
         masm.jcc(condition, label);
         masm.bind(endLabel);
@@ -397,9 +395,9 @@
 
         if (isFloat) {
             if (unorderedIsTrue && !trueOnUnordered(condition)) {
-                cmove(tasm, masm, result, ConditionFlag.parity, trueValue);
+                cmove(tasm, masm, result, ConditionFlag.Parity, trueValue);
             } else if (!unorderedIsTrue && trueOnUnordered(condition)) {
-                cmove(tasm, masm, result, ConditionFlag.parity, falseValue);
+                cmove(tasm, masm, result, ConditionFlag.Parity, falseValue);
             }
         }
     }
@@ -413,9 +411,10 @@
                 default:   throw GraalInternalError.shouldNotReachHere();
             }
         } else {
+            AMD64Address addr = (AMD64Address) tasm.asAddress(other);
             switch (other.getKind()) {
-                case Int:  masm.cmovl(cond, asRegister(result), tasm.asAddress(other)); break;
-                case Long: masm.cmovq(cond, asRegister(result), tasm.asAddress(other)); break;
+                case Int:  masm.cmovl(cond, asRegister(result), addr); break;
+                case Long: masm.cmovq(cond, asRegister(result), addr); break;
                 default:   throw GraalInternalError.shouldNotReachHere();
             }
         }
@@ -423,45 +422,45 @@
 
     private static ConditionFlag intCond(Condition cond) {
         switch (cond) {
-            case EQ: return ConditionFlag.equal;
-            case NE: return ConditionFlag.notEqual;
-            case LT: return ConditionFlag.less;
-            case LE: return ConditionFlag.lessEqual;
-            case GE: return ConditionFlag.greaterEqual;
-            case GT: return ConditionFlag.greater;
-            case BE: return ConditionFlag.belowEqual;
-            case AE: return ConditionFlag.aboveEqual;
-            case AT: return ConditionFlag.above;
-            case BT: return ConditionFlag.below;
+            case EQ: return ConditionFlag.Equal;
+            case NE: return ConditionFlag.NotEqual;
+            case LT: return ConditionFlag.Less;
+            case LE: return ConditionFlag.LessEqual;
+            case GE: return ConditionFlag.GreaterEqual;
+            case GT: return ConditionFlag.Greater;
+            case BE: return ConditionFlag.BelowEqual;
+            case AE: return ConditionFlag.AboveEqual;
+            case AT: return ConditionFlag.Above;
+            case BT: return ConditionFlag.Below;
             default: throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     private static ConditionFlag floatCond(Condition cond) {
         switch (cond) {
-            case EQ: return ConditionFlag.equal;
-            case NE: return ConditionFlag.notEqual;
-            case LT: return ConditionFlag.below;
-            case LE: return ConditionFlag.belowEqual;
-            case GE: return ConditionFlag.aboveEqual;
-            case GT: return ConditionFlag.above;
+            case EQ: return ConditionFlag.Equal;
+            case NE: return ConditionFlag.NotEqual;
+            case LT: return ConditionFlag.Below;
+            case LE: return ConditionFlag.BelowEqual;
+            case GE: return ConditionFlag.AboveEqual;
+            case GT: return ConditionFlag.Above;
             default: throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     private static boolean trueOnUnordered(ConditionFlag condition) {
         switch(condition) {
-            case aboveEqual:
-            case notEqual:
-            case above:
-            case less:
-            case overflow:
+            case AboveEqual:
+            case NotEqual:
+            case Above:
+            case Less:
+            case Overflow:
                 return false;
-            case equal:
-            case belowEqual:
-            case below:
-            case greaterEqual:
-            case noOverflow:
+            case Equal:
+            case BelowEqual:
+            case Below:
+            case GreaterEqual:
+            case NoOverflow:
                 return true;
             default:
                 throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
 import static java.lang.Double.*;
 import static java.lang.Float.*;
 
@@ -38,37 +39,11 @@
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
 
-// @formatter:off
 public class AMD64Move {
 
     @Opcode("MOVE")
-    public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp {
-        @Def({REG, STACK}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value input;
-
-        public SpillMoveOp(Value result, Value input) {
-            this.result = result;
-            this.input = input;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            move(tasm, masm, getResult(), getInput());
-        }
+    public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp {
 
-        @Override
-        public Value getInput() {
-            return input;
-        }
-        @Override
-        public Value getResult() {
-            return result;
-        }
-    }
-
-
-    @Opcode("MOVE")
-    public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp {
         @Def({REG, HINT}) protected Value result;
         @Use({REG, STACK, CONST}) protected Value input;
 
@@ -86,15 +61,16 @@
         public Value getInput() {
             return input;
         }
+
         @Override
         public Value getResult() {
             return result;
         }
     }
 
-
     @Opcode("MOVE")
     public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp {
+
         @Def({REG, STACK}) protected Value result;
         @Use({REG, CONST, HINT}) protected Value input;
 
@@ -112,66 +88,201 @@
         public Value getInput() {
             return input;
         }
+
         @Override
         public Value getResult() {
             return result;
         }
     }
 
+    public abstract static class MemOp extends AMD64LIRInstruction {
 
-    public static class LoadOp extends AMD64LIRInstruction {
-        @Def({REG}) protected Value result;
-        @Use({ADDR}) protected Value address;
+        @Use({COMPOSITE}) protected AMD64AddressValue address;
         @State protected LIRFrameState state;
 
-        public LoadOp(Value result, Value address, LIRFrameState state) {
-            this.result = result;
+        public MemOp(AMD64AddressValue address, LIRFrameState state) {
             this.address = address;
             this.state = state;
         }
 
+        protected abstract void emitMemAccess(AMD64MacroAssembler masm);
+
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            load(tasm, masm, result, (Address) address, state);
+            if (state != null) {
+                tasm.recordImplicitException(masm.codeBuffer.position(), state);
+            }
+            emitMemAccess(masm);
+        }
+    }
+
+    public static class LoadOp extends MemOp {
+
+        @Def({REG}) protected AllocatableValue result;
+
+        public LoadOp(AllocatableValue result, AMD64AddressValue address, LIRFrameState state) {
+            super(address, state);
+            this.result = result;
+        }
+
+        @Override
+        public void emitMemAccess(AMD64MacroAssembler masm) {
+            switch (address.getKind()) {
+                case Boolean:
+                case Byte:
+                    masm.movsxb(asRegister(result), address.toAddress());
+                    break;
+                case Char:
+                    masm.movzxl(asRegister(result), address.toAddress());
+                    break;
+                case Short:
+                    masm.movswl(asRegister(result), address.toAddress());
+                    break;
+                case Int:
+                    masm.movslq(asRegister(result), address.toAddress());
+                    break;
+                case Long:
+                    masm.movq(asRegister(result), address.toAddress());
+                    break;
+                case Float:
+                    masm.movflt(asFloatReg(result), address.toAddress());
+                    break;
+                case Double:
+                    masm.movdbl(asDoubleReg(result), address.toAddress());
+                    break;
+                case Object:
+                    masm.movq(asRegister(result), address.toAddress());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
         }
     }
 
+    public static class StoreOp extends MemOp {
 
-    public static class StoreOp extends AMD64LIRInstruction {
-        @Use({ADDR}) protected Value address;
-        @Use({REG, CONST}) protected Value input;
-        @State protected LIRFrameState state;
+        @Use({REG}) protected AllocatableValue input;
 
-        public StoreOp(Value address, Value input, LIRFrameState state) {
-            this.address = address;
+        public StoreOp(AMD64AddressValue address, AllocatableValue input, LIRFrameState state) {
+            super(address, state);
             this.input = input;
-            this.state = state;
         }
 
         @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            store(tasm, masm, (Address) address, input, state);
+        public void emitMemAccess(AMD64MacroAssembler masm) {
+            assert isRegister(input);
+            switch (address.getKind()) {
+                case Boolean:
+                case Byte:
+                    masm.movb(address.toAddress(), asRegister(input));
+                    break;
+                case Char:
+                case Short:
+                    masm.movw(address.toAddress(), asRegister(input));
+                    break;
+                case Int:
+                    masm.movl(address.toAddress(), asRegister(input));
+                    break;
+                case Long:
+                    masm.movq(address.toAddress(), asRegister(input));
+                    break;
+                case Float:
+                    masm.movflt(address.toAddress(), asFloatReg(input));
+                    break;
+                case Double:
+                    masm.movsd(address.toAddress(), asDoubleReg(input));
+                    break;
+                case Object:
+                    masm.movq(address.toAddress(), asRegister(input));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
         }
     }
 
+    public static class StoreConstantOp extends MemOp {
+
+        protected final Constant input;
+
+        public StoreConstantOp(AMD64AddressValue address, Constant input, LIRFrameState state) {
+            super(address, state);
+            this.input = input;
+        }
+
+        @Override
+        public void emitMemAccess(AMD64MacroAssembler masm) {
+            switch (address.getKind()) {
+                case Boolean:
+                case Byte:
+                    masm.movb(address.toAddress(), input.asInt() & 0xFF);
+                    break;
+                case Char:
+                case Short:
+                    masm.movw(address.toAddress(), input.asInt() & 0xFFFF);
+                    break;
+                case Int:
+                    masm.movl(address.toAddress(), input.asInt());
+                    break;
+                case Long:
+                    if (NumUtil.isInt(input.asLong())) {
+                        masm.movslq(address.toAddress(), (int) input.asLong());
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
+                    }
+                    break;
+                case Float:
+                    masm.movl(address.toAddress(), floatToRawIntBits(input.asFloat()));
+                    break;
+                case Double:
+                    throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
+                case Object:
+                    if (input.isNull()) {
+                        masm.movptr(address.toAddress(), 0);
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
+                    }
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
 
     public static class LeaOp extends AMD64LIRInstruction {
-        @Def({REG}) protected Value result;
-        @Use({ADDR, STACK, UNINITIALIZED}) protected Value address;
 
-        public LeaOp(Value result, Value address) {
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE, UNINITIALIZED}) protected AMD64AddressValue address;
+
+        public LeaOp(AllocatableValue result, AMD64AddressValue address) {
             this.result = result;
             this.address = address;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.leaq(asLongReg(result), tasm.asAddress(address));
+            masm.leaq(asLongReg(result), address.toAddress());
         }
     }
 
+    public static class StackLeaOp extends AMD64LIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({STACK, UNINITIALIZED}) protected StackSlot slot;
+
+        public StackLeaOp(AllocatableValue result, StackSlot slot) {
+            this.result = result;
+            this.slot = slot;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            masm.leaq(asLongReg(result), (AMD64Address) tasm.asAddress(slot));
+        }
+    }
 
     public static class MembarOp extends AMD64LIRInstruction {
+
         private final int barriers;
 
         public MembarOp(final int barriers) {
@@ -184,9 +295,9 @@
         }
     }
 
+    public static class NullCheckOp extends AMD64LIRInstruction {
 
-    public static class NullCheckOp extends AMD64LIRInstruction {
-        @Use protected Value input;
+        @Use({REG}) protected AllocatableValue input;
         @State protected LIRFrameState state;
 
         public NullCheckOp(Variable input, LIRFrameState state) {
@@ -201,15 +312,15 @@
         }
     }
 
-
     @Opcode("CAS")
     public static class CompareAndSwapOp extends AMD64LIRInstruction {
-        @Def protected Value result;
-        @Use({ADDR}) protected Value address;
-        @Use protected Value cmpValue;
-        @Use protected Value newValue;
 
-        public CompareAndSwapOp(Value result, Address address, Value cmpValue, Value newValue) {
+        @Def protected AllocatableValue result;
+        @Use({COMPOSITE}) protected AMD64AddressValue address;
+        @Use protected AllocatableValue cmpValue;
+        @Use protected AllocatableValue newValue;
+
+        public CompareAndSwapOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
             this.result = result;
             this.address = address;
             this.cmpValue = cmpValue;
@@ -218,11 +329,10 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            compareAndSwap(tasm, masm, result, (Address) address, cmpValue, newValue);
+            compareAndSwap(tasm, masm, result, address, cmpValue, newValue);
         }
     }
 
-
     public static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value input) {
         if (isRegister(input)) {
             if (isRegister(result)) {
@@ -256,46 +366,80 @@
             return;
         }
         switch (input.getKind()) {
-            case Jsr:
-            case Int:    masm.movl(asRegister(result),    asRegister(input)); break;
-            case Long:   masm.movq(asRegister(result),    asRegister(input)); break;
-            case Float:  masm.movflt(asFloatReg(result),  asFloatReg(input)); break;
-            case Double: masm.movdbl(asDoubleReg(result), asDoubleReg(input)); break;
-            case Object: masm.movq(asRegister(result),    asRegister(input)); break;
-            default:     throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind());
+            case Int:
+                masm.movl(asRegister(result), asRegister(input));
+                break;
+            case Long:
+                masm.movq(asRegister(result), asRegister(input));
+                break;
+            case Float:
+                masm.movflt(asFloatReg(result), asFloatReg(input));
+                break;
+            case Double:
+                masm.movdbl(asDoubleReg(result), asDoubleReg(input));
+                break;
+            case Object:
+                masm.movq(asRegister(result), asRegister(input));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind());
         }
     }
 
     private static void reg2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value input) {
+        AMD64Address dest = (AMD64Address) tasm.asAddress(result);
         switch (input.getKind()) {
-            case Jsr:
-            case Int:    masm.movl(tasm.asAddress(result),   asRegister(input)); break;
-            case Long:   masm.movq(tasm.asAddress(result),   asRegister(input)); break;
-            case Float:  masm.movflt(tasm.asAddress(result), asFloatReg(input)); break;
-            case Double: masm.movsd(tasm.asAddress(result),  asDoubleReg(input)); break;
-            case Object: masm.movq(tasm.asAddress(result),   asRegister(input)); break;
-            default:     throw GraalInternalError.shouldNotReachHere();
+            case Int:
+                masm.movl(dest, asRegister(input));
+                break;
+            case Long:
+                masm.movq(dest, asRegister(input));
+                break;
+            case Float:
+                masm.movflt(dest, asFloatReg(input));
+                break;
+            case Double:
+                masm.movsd(dest, asDoubleReg(input));
+                break;
+            case Object:
+                masm.movq(dest, asRegister(input));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     private static void stack2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value input) {
+        AMD64Address src = (AMD64Address) tasm.asAddress(input);
         switch (input.getKind()) {
-            case Jsr:
-            case Int:    masm.movl(asRegister(result),    tasm.asAddress(input)); break;
-            case Long:   masm.movq(asRegister(result),    tasm.asAddress(input)); break;
-            case Float:  masm.movflt(asFloatReg(result),  tasm.asAddress(input)); break;
-            case Double: masm.movdbl(asDoubleReg(result), tasm.asAddress(input)); break;
-            case Object: masm.movq(asRegister(result),    tasm.asAddress(input)); break;
-            default:     throw GraalInternalError.shouldNotReachHere();
+            case Int:
+                masm.movl(asRegister(result), src);
+                break;
+            case Long:
+                masm.movq(asRegister(result), src);
+                break;
+            case Float:
+                masm.movflt(asFloatReg(result), src);
+                break;
+            case Double:
+                masm.movdbl(asDoubleReg(result), src);
+                break;
+            case Object:
+                masm.movq(asRegister(result), src);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     private static void const2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Constant input) {
-        // Note: we use the kind of the input operand (and not the kind of the result operand) because they don't match
-        // in all cases. For example, an object constant can be loaded to a long register when unsafe casts occurred (e.g.,
-        // for a write barrier where arithmetic operations are then performed on the pointer).
+        /*
+         * Note: we use the kind of the input operand (and not the kind of the result operand)
+         * because they don't match in all cases. For example, an object constant can be loaded to a
+         * long register when unsafe casts occurred (e.g., for a write barrier where arithmetic
+         * operations are then performed on the pointer).
+         */
         switch (input.getKind().getStackKind()) {
-            case Jsr:
             case Int:
                 if (tasm.runtime.needsDataPatch(input)) {
                     tasm.recordDataReferenceInCode(input, 0, true);
@@ -321,7 +465,7 @@
                     assert !tasm.runtime.needsDataPatch(input);
                     masm.xorps(asFloatReg(result), asFloatReg(result));
                 } else {
-                    masm.movflt(asFloatReg(result), tasm.asFloatConstRef(input));
+                    masm.movflt(asFloatReg(result), (AMD64Address) tasm.asFloatConstRef(input));
                 }
                 break;
             case Double:
@@ -330,7 +474,7 @@
                     assert !tasm.runtime.needsDataPatch(input);
                     masm.xorpd(asDoubleReg(result), asDoubleReg(result));
                 } else {
-                    masm.movdbl(asDoubleReg(result), tasm.asDoubleConstRef(input));
+                    masm.movdbl(asDoubleReg(result), (AMD64Address) tasm.asDoubleConstRef(input));
                 }
                 break;
             case Object:
@@ -343,7 +487,7 @@
                     tasm.recordDataReferenceInCode(input, 0, true);
                     masm.movq(asRegister(result), 0xDEADDEADDEADDEADL);
                 } else {
-                    masm.movq(asRegister(result), tasm.recordDataReferenceInCode(input, 0, false));
+                    masm.movq(asRegister(result), (AMD64Address) tasm.recordDataReferenceInCode(input, 0, false));
                 }
                 break;
             default:
@@ -353,15 +497,23 @@
 
     private static void const2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Constant input) {
         assert !tasm.runtime.needsDataPatch(input);
+        AMD64Address dest = (AMD64Address) tasm.asAddress(result);
         switch (input.getKind().getStackKind()) {
-            case Jsr:
-            case Int:    masm.movl(tasm.asAddress(result), input.asInt()); break;
-            case Long:   masm.movlong(tasm.asAddress(result), input.asLong()); break;
-            case Float:  masm.movl(tasm.asAddress(result), floatToRawIntBits(input.asFloat())); break;
-            case Double: masm.movlong(tasm.asAddress(result), doubleToRawLongBits(input.asDouble())); break;
+            case Int:
+                masm.movl(dest, input.asInt());
+                break;
+            case Long:
+                masm.movlong(dest, input.asLong());
+                break;
+            case Float:
+                masm.movl(dest, floatToRawIntBits(input.asFloat()));
+                break;
+            case Double:
+                masm.movlong(dest, doubleToRawLongBits(input.asDouble()));
+                break;
             case Object:
                 if (input.isNull()) {
-                    masm.movlong(tasm.asAddress(result), 0L);
+                    masm.movlong(dest, 0L);
                 } else {
                     throw GraalInternalError.shouldNotReachHere("Non-null object constants must be in register");
                 }
@@ -371,88 +523,22 @@
         }
     }
 
-
-    public static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Address loadAddr, LIRFrameState info) {
-        if (info != null) {
-            tasm.recordImplicitException(masm.codeBuffer.position(), info);
-        }
-        switch (loadAddr.getKind()) {
-            case Boolean:
-            case Byte:   masm.movsxb(asRegister(result),  loadAddr); break;
-            case Char:   masm.movzxl(asRegister(result),  loadAddr); break;
-            case Short:  masm.movswl(asRegister(result),  loadAddr); break;
-            case Int:    masm.movslq(asRegister(result),  loadAddr); break;
-            case Long:   masm.movq(asRegister(result),    loadAddr); break;
-            case Float:  masm.movflt(asFloatReg(result),  loadAddr); break;
-            case Double: masm.movdbl(asDoubleReg(result), loadAddr); break;
-            case Object: masm.movq(asRegister(result),    loadAddr); break;
-            default:     throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    public static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Address storeAddr, Value input, LIRFrameState info) {
-        if (info != null) {
-            tasm.recordImplicitException(masm.codeBuffer.position(), info);
-        }
-
-        if (isRegister(input)) {
-            switch (storeAddr.getKind()) {
-                case Boolean:
-                case Byte:   masm.movb(storeAddr,   asRegister(input)); break;
-                case Char:
-                case Short:  masm.movw(storeAddr,   asRegister(input)); break;
-                case Int:    masm.movl(storeAddr,   asRegister(input)); break;
-                case Long:   masm.movq(storeAddr,   asRegister(input)); break;
-                case Float:  masm.movflt(storeAddr, asFloatReg(input)); break;
-                case Double: masm.movsd(storeAddr,  asDoubleReg(input)); break;
-                case Object: masm.movq(storeAddr,   asRegister(input)); break;
-                default:     throw GraalInternalError.shouldNotReachHere();
-            }
-        } else if (isConstant(input)) {
-            Constant c = (Constant) input;
-            switch (storeAddr.getKind()) {
-                case Boolean:
-                case Byte:   masm.movb(storeAddr, c.asInt() & 0xFF); break;
-                case Char:
-                case Short:  masm.movw(storeAddr, c.asInt() & 0xFFFF); break;
-                case Jsr:
-                case Int:    masm.movl(storeAddr, c.asInt()); break;
-                case Long:
-                    if (NumUtil.isInt(c.asLong())) {
-                        masm.movslq(storeAddr, (int) c.asLong());
-                    } else {
-                        throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
-                    }
-                    break;
-                case Float:  masm.movl(storeAddr, floatToRawIntBits(c.asFloat())); break;
-                case Double: throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
-                case Object:
-                    if (c.isNull()) {
-                        masm.movptr(storeAddr, 0);
-                    } else {
-                        throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory");
-                    }
-                    break;
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
-
-        } else {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Address address, Value cmpValue, Value newValue) {
+    protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
         assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax;
 
         if (tasm.target.isMP) {
             masm.lock();
         }
         switch (cmpValue.getKind()) {
-            case Int:    masm.cmpxchgl(asRegister(newValue), address); break;
+            case Int:
+                masm.cmpxchgl(asRegister(newValue), address.toAddress());
+                break;
             case Long:
-            case Object: masm.cmpxchgq(asRegister(newValue), address); break;
-            default:     throw GraalInternalError.shouldNotReachHere();
+            case Object:
+                masm.cmpxchgq(asRegister(newValue), address.toAddress());
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -77,10 +77,10 @@
         } else {
             switch (x.getKind()) {
                 case Int:
-                    masm.testl(asIntReg(x), tasm.asIntAddr(y));
+                    masm.testl(asIntReg(x), (AMD64Address) tasm.asIntAddr(y));
                     break;
                 case Long:
-                    masm.testq(asLongReg(x), tasm.asLongAddr(y));
+                    masm.testq(asLongReg(x), (AMD64Address) tasm.asLongAddr(y));
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.ptx;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.lir.*;
+
+/**
+ * Represents an address in target machine memory, specified via some combination of a base register
+ * and a displacement.
+ */
+public final class PTXAddressValue extends CompositeValue {
+
+    private static final long serialVersionUID = 1802222435353022623L;
+
+    @Component({REG, UNUSED}) private AllocatableValue base;
+    private final long displacement;
+
+    /**
+     * Creates an {@link PTXAddressValue} with given base register and no displacement.
+     * 
+     * @param kind the kind of the value being addressed
+     * @param base the base register
+     */
+    public PTXAddressValue(Kind kind, AllocatableValue base) {
+        this(kind, base, 0);
+    }
+
+    /**
+     * Creates an {@link PTXAddressValue} with given base register and a displacement. This is the
+     * most general constructor.
+     * 
+     * @param kind the kind of the value being addressed
+     * @param base the base register
+     * @param displacement the displacement
+     */
+    public PTXAddressValue(Kind kind, AllocatableValue base, long displacement) {
+        super(kind);
+        this.base = base;
+        this.displacement = displacement;
+
+        assert !isStackSlot(base);
+    }
+
+    public PTXAddress toAddress() {
+        Register baseReg = base == AllocatableValue.UNUSED ? Register.None : asRegister(base);
+        return new PTXAddress(baseReg, displacement);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append(getKind().getJavaName()).append("[");
+        String sep = "";
+        if (isLegal(base)) {
+            s.append(base);
+            sep = " + ";
+        }
+        if (displacement < 0) {
+            s.append(" - ").append(-displacement);
+        } else if (displacement > 0) {
+            s.append(sep).append(displacement);
+        }
+        s.append("]");
+        return s.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof PTXAddressValue) {
+            PTXAddressValue addr = (PTXAddressValue) obj;
+            return getKind() == addr.getKind() && displacement == addr.displacement && base.equals(addr.base);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return base.hashCode() ^ ((int) displacement << 4) ^ (getKind().ordinal() << 12);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.ptx;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+// @formatter:off
+public enum PTXArithmetic {
+    IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
+    LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
+    FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR,
+    DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR,
+    INEG, LNEG,
+    I2L, L2I, I2B, I2C, I2S,
+    F2D, D2F,
+    I2F, I2D, F2I, D2I,
+    L2F, L2D, F2L, D2L,
+    MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L;
+
+
+    public static class Op1Reg extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG}) protected Value x;
+
+        public Op1Reg(PTXArithmetic opcode, Value result, Value x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            emit(tasm, masm, opcode, result, x, null);
+        }
+    }
+
+    public static class Op1Stack extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+
+        public Op1Stack(PTXArithmetic opcode, Value result, Value x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            emit(tasm, masm, opcode, result, x, null);
+        }
+    }
+
+    public static class Op2Stack extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Alive({REG, STACK, CONST}) protected Value y;
+
+        public Op2Stack(PTXArithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            emit(tasm, masm, opcode, result, x, y, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    public static class Op2Reg extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Alive({REG, CONST}) protected Value y;
+
+        public Op2Reg(PTXArithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            emit(tasm, masm, opcode, result, x, y, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    public static class Op2RegCommutative extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Use({REG, CONST}) protected Value y;
+
+        public Op2RegCommutative(PTXArithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            if (sameRegister(result, y)) {
+                emit(tasm, masm, opcode, result, x, null);
+            } else {
+                PTXMove.move(tasm, masm, result, x);
+                emit(tasm, masm, opcode, result, y, null);
+            }
+        }
+
+        @Override
+        protected void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    public static class ShiftOp extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Alive({REG, CONST}) protected Value y;
+
+        public ShiftOp(PTXArithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            emit(tasm, masm, opcode, result, x, y, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, x);
+            assert y.getKind().getStackKind() == Kind.Int;
+        }
+    }
+
+    public static class DivOp extends PTXLIRInstruction {
+        @Opcode private final PTXArithmetic opcode;
+        @Def protected Value result;
+        @Use protected Value x;
+        @Alive protected Value y;
+        @State protected LIRFrameState state;
+
+        public DivOp(PTXArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            emit(tasm, masm, opcode, result, y, state);
+        }
+
+        @Override
+        protected void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+
+    @SuppressWarnings("unused")
+    protected static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value result) {
+        switch (opcode) {
+            default:   throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src, LIRFrameState info) {
+        int exceptionOffset = -1;
+        if (isRegister(src)) {
+            Register a = asIntReg(src);
+            Register d = asIntReg(dst);
+            switch (opcode) {
+                case INEG: masm.neg_s32(d, a); break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(src)) {
+            switch (opcode) {
+                case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break;
+                case IAND: masm.and_b32(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break;
+                default:   throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            switch (opcode) {
+                default:   throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        if (info != null) {
+            assert exceptionOffset != -1;
+            tasm.recordImplicitException(exceptionOffset, info);
+        }
+    }
+
+    public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) {
+        int exceptionOffset = -1;
+        if (isConstant(src1)) {
+            int      a = tasm.asIntConst(src1);
+            Register b = asIntReg(src2);
+            Register d = asIntReg(dst);
+            switch (opcode) {
+            case ISUB:  masm.sub_s32(d, a, b); break;
+            case IAND:  masm.and_b32(d, b, a); break;
+            default:    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(src2)) {
+            Register a = asIntReg(src1);
+            int      b = tasm.asIntConst(src2);
+            Register d = asIntReg(dst);
+            switch (opcode) {
+            case IADD:  masm.add_s32(d, a, b); break;
+            case IAND:  masm.and_b32(d, a, b); break;
+            case IUSHR: masm.shr_u32(d, a, b); break;
+            default:    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            Register a = asIntReg(src1);
+            Register b = asIntReg(src2);
+            Register d = asIntReg(dst);
+            switch (opcode) {
+            case IADD:  masm.add_s32(d, a, b); break;
+            case ISUB:  masm.sub_s32(d, a, b); break;
+            case IMUL:  masm.mul_s32(d, a, b); break;
+            default:    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        if (info != null) {
+            assert exceptionOffset != -1;
+            tasm.recordImplicitException(exceptionOffset, info);
+        }
+    }
+
+    private static void verifyKind(PTXArithmetic opcode, Value result, Value x, Value y) {
+        assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int)
+            || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
+            || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
+            || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.ptx;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.asm.*;
+
+public class PTXBitManipulationOp extends PTXLIRInstruction {
+
+    public enum IntrinsicOpcode {
+        IPOPCNT, LPOPCNT, IBSR, LBSR, BSF;
+    }
+
+    @Opcode private final IntrinsicOpcode opcode;
+    @Def protected Value result;
+    @Use({OperandFlag.REG}) protected Value input;
+
+    public PTXBitManipulationOp(IntrinsicOpcode opcode, Value result, Value input) {
+        this.opcode = opcode;
+        this.result = result;
+        this.input = input;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+        Register dst = ValueUtil.asIntReg(result);
+        Register src = ValueUtil.asRegister(input);
+        switch (opcode) {
+            case IPOPCNT:
+                masm.popc_b32(dst, src);
+                break;
+            case LPOPCNT:
+                masm.popc_b64(dst, src);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.ptx;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.calc.*;
+
+public enum PTXCompare {
+    ICMP, LCMP, ACMP, FCMP, DCMP;
+
+    public static class CompareOp extends PTXLIRInstruction {
+
+        @Opcode private final PTXCompare opcode;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Use({REG, STACK, CONST}) protected Value y;
+        private final Condition condition;
+
+        public CompareOp(PTXCompare opcode, Condition condition, Value x, Value y) {
+            this.opcode = opcode;
+            this.condition = condition;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            emit(tasm, masm, opcode, condition, x, y);
+        }
+
+        @Override
+        protected void verify() {
+            super.verify();
+            assert (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long) ||
+                            (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object) ||
+                            (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
+        }
+    }
+
+    public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXCompare opcode, Condition condition, Value x, Value y) {
+        if (isConstant(x)) {
+            int a = tasm.asIntConst(x);
+            Register b = asIntReg(y);
+            switch (opcode) {
+                case ICMP:
+                    emitCompareConstReg(masm, condition, a, b);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(y)) {
+            Register a = asIntReg(x);
+            int b = tasm.asIntConst(y);
+            switch (opcode) {
+                case ICMP:
+                    emitCompareRegConst(masm, condition, a, b);
+                    break;
+                case ACMP:
+                    if (((Constant) y).isNull()) {
+                        switch (condition) {
+                            case EQ:
+                                masm.setp_eq_s32(a, b);
+                                break;
+                            case NE:
+                                masm.setp_ne_s32(a, b);
+                                break;
+                            default:
+                                throw GraalInternalError.shouldNotReachHere();
+                        }
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons");
+                    }
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            Register a = asIntReg(x);
+            Register b = asIntReg(y);
+            switch (opcode) {
+                case ICMP:
+                    emitCompareRegReg(masm, condition, a, b);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static void emitCompareConstReg(PTXAssembler masm, Condition condition, int a, Register b) {
+        switch (condition) {
+            case EQ:
+                masm.setp_eq_s32(a, b);
+                break;
+            case NE:
+                masm.setp_ne_s32(a, b);
+                break;
+            case LT:
+                masm.setp_lt_s32(a, b);
+                break;
+            case LE:
+                masm.setp_le_s32(a, b);
+                break;
+            case GT:
+                masm.setp_gt_s32(a, b);
+                break;
+            case GE:
+                masm.setp_ge_s32(a, b);
+                break;
+            case AT:
+                masm.setp_gt_u32(a, b);
+                break;
+            case AE:
+                masm.setp_ge_u32(a, b);
+                break;
+            case BT:
+                masm.setp_lt_u32(a, b);
+                break;
+            case BE:
+                masm.setp_le_u32(a, b);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void emitCompareRegConst(PTXAssembler masm, Condition condition, Register a, int b) {
+        switch (condition) {
+            case EQ:
+                masm.setp_eq_s32(a, b);
+                break;
+            case NE:
+                masm.setp_ne_s32(a, b);
+                break;
+            case LT:
+                masm.setp_lt_s32(a, b);
+                break;
+            case LE:
+                masm.setp_le_s32(a, b);
+                break;
+            case GT:
+                masm.setp_gt_s32(a, b);
+                break;
+            case GE:
+                masm.setp_ge_s32(a, b);
+                break;
+            case AT:
+                masm.setp_gt_u32(a, b);
+                break;
+            case AE:
+                masm.setp_ge_u32(a, b);
+                break;
+            case BT:
+                masm.setp_lt_u32(a, b);
+                break;
+            case BE:
+                masm.setp_le_u32(a, b);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void emitCompareRegReg(PTXAssembler masm, Condition condition, Register a, Register b) {
+        switch (condition) {
+            case EQ:
+                masm.setp_eq_s32(a, b);
+                break;
+            case NE:
+                masm.setp_ne_s32(a, b);
+                break;
+            case LT:
+                masm.setp_lt_s32(a, b);
+                break;
+            case LE:
+                masm.setp_le_s32(a, b);
+                break;
+            case GT:
+                masm.setp_gt_s32(a, b);
+                break;
+            case GE:
+                masm.setp_ge_s32(a, b);
+                break;
+            case AT:
+                masm.setp_gt_u32(a, b);
+                break;
+            case AE:
+                masm.setp_ge_u32(a, b);
+                break;
+            case BT:
+                masm.setp_lt_u32(a, b);
+                break;
+            case BE:
+                masm.setp_le_u32(a, b);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.ptx;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.calc.*;
+
+public class PTXControlFlow {
+
+    public static class ReturnOp extends PTXLIRInstruction {
+
+        @Use({REG, ILLEGAL}) protected Value x;
+
+        public ReturnOp(Value x) {
+            this.x = x;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            if (tasm.frameContext != null) {
+                tasm.frameContext.leave(tasm);
+            }
+            masm.exit();
+        }
+    }
+
+    public static class BranchOp extends PTXLIRInstruction implements StandardOp.BranchOp {
+
+        protected Condition condition;
+        protected LabelRef destination;
+
+        public BranchOp(Condition condition, LabelRef destination) {
+            this.condition = condition;
+            this.destination = destination;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            masm.at();
+            Label l = destination.label();
+            l.addPatchAt(tasm.asm.codeBuffer.position());
+            String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET;
+            masm.bra(target);
+        }
+
+        @Override
+        public LabelRef destination() {
+            return destination;
+        }
+
+        @Override
+        public void negate(LabelRef newDestination) {
+            destination = newDestination;
+            condition = condition.negate();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXLIRInstruction.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.ptx;
+
+import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Convenience class to provide PTXAssembler for the {@link #emitCode} method.
+ */
+public abstract class PTXLIRInstruction extends LIRInstruction {
+
+    @Override
+    public final void emitCode(TargetMethodAssembler tasm) {
+        emitCode(tasm, (PTXAssembler) tasm.asm);
+    }
+
+    public abstract void emitCode(TargetMethodAssembler tasm, PTXAssembler masm);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.ptx;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.StandardOp.MoveOp;
+import com.oracle.graal.lir.asm.*;
+
+public class PTXMove {
+
+    @Opcode("MOVE")
+    public static class SpillMoveOp extends PTXLIRInstruction implements MoveOp {
+
+        @Def({REG, STACK}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value input;
+
+        public SpillMoveOp(Value result, Value input) {
+            this.result = result;
+            this.input = input;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            move(tasm, masm, getResult(), getInput());
+        }
+
+        @Override
+        public Value getInput() {
+            return input;
+        }
+
+        @Override
+        public Value getResult() {
+            return result;
+        }
+    }
+
+    @Opcode("MOVE")
+    public static class MoveToRegOp extends PTXLIRInstruction implements MoveOp {
+
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value input;
+
+        public MoveToRegOp(Value result, Value input) {
+            this.result = result;
+            this.input = input;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            move(tasm, masm, getResult(), getInput());
+        }
+
+        @Override
+        public Value getInput() {
+            return input;
+        }
+
+        @Override
+        public Value getResult() {
+            return result;
+        }
+    }
+
+    @Opcode("MOVE")
+    public static class MoveFromRegOp extends PTXLIRInstruction implements MoveOp {
+
+        @Def({REG, STACK}) protected Value result;
+        @Use({REG, CONST, HINT}) protected Value input;
+
+        public MoveFromRegOp(Value result, Value input) {
+            this.result = result;
+            this.input = input;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            move(tasm, masm, getResult(), getInput());
+        }
+
+        @Override
+        public Value getInput() {
+            return input;
+        }
+
+        @Override
+        public Value getResult() {
+            return result;
+        }
+    }
+
+    public static class LoadOp extends PTXLIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE}) protected PTXAddressValue address;
+        @State protected LIRFrameState state;
+
+        public LoadOp(AllocatableValue result, PTXAddressValue address, LIRFrameState state) {
+            this.result = result;
+            this.address = address;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            PTXAddress addr = address.toAddress();
+            switch (address.getKind()) {
+                case Int:
+                    masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Object:
+                    masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    public static class StoreOp extends PTXLIRInstruction {
+
+        @Use({COMPOSITE}) protected PTXAddressValue address;
+        @Use({REG}) protected AllocatableValue input;
+        @State protected LIRFrameState state;
+
+        public StoreOp(PTXAddressValue address, AllocatableValue input, LIRFrameState state) {
+            this.address = address;
+            this.input = input;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            assert isRegister(input);
+            PTXAddress addr = address.toAddress();
+            switch (address.getKind()) {
+                case Int:
+                    masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    public static class LeaOp extends PTXLIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE, UNINITIALIZED}) protected PTXAddressValue address;
+
+        public LeaOp(AllocatableValue result, PTXAddressValue address) {
+            this.result = result;
+            this.address = address;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            throw new InternalError("NYI");
+        }
+    }
+
+    public static class StackLeaOp extends PTXLIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({STACK, UNINITIALIZED}) protected StackSlot slot;
+
+        public StackLeaOp(AllocatableValue result, StackSlot slot) {
+            this.result = result;
+            this.slot = slot;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            throw new InternalError("NYI");
+        }
+    }
+
+    @Opcode("CAS")
+    public static class CompareAndSwapOp extends PTXLIRInstruction {
+
+        @Def protected AllocatableValue result;
+        @Use({COMPOSITE}) protected PTXAddressValue address;
+        @Use protected AllocatableValue cmpValue;
+        @Use protected AllocatableValue newValue;
+
+        public CompareAndSwapOp(AllocatableValue result, PTXAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+            this.result = result;
+            this.address = address;
+            this.cmpValue = cmpValue;
+            this.newValue = newValue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
+            compareAndSwap(tasm, masm, result, address, cmpValue, newValue);
+        }
+    }
+
+    public static void move(TargetMethodAssembler tasm, PTXAssembler masm, Value result, Value input) {
+        if (isRegister(input)) {
+            if (isRegister(result)) {
+                reg2reg(masm, result, input);
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(input)) {
+            if (isRegister(result)) {
+                const2reg(tasm, masm, result, (Constant) input);
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private static void reg2reg(PTXAssembler masm, Value result, Value input) {
+        if (asRegister(input).equals(asRegister(result))) {
+            return;
+        }
+        switch (input.getKind()) {
+            case Int:
+                masm.mov_s32(asRegister(result), asRegister(input));
+                break;
+            case Object:
+                masm.mov_u64(asRegister(result), asRegister(input));
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind());
+        }
+    }
+
+    private static void const2reg(TargetMethodAssembler tasm, PTXAssembler masm, Value result, Constant input) {
+        switch (input.getKind().getStackKind()) {
+            case Int:
+                if (tasm.runtime.needsDataPatch(input)) {
+                    tasm.recordDataReferenceInCode(input, 0, true);
+                }
+                masm.mov_s32(asRegister(result), input.asInt());
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    @SuppressWarnings("unused")
+    protected static void compareAndSwap(TargetMethodAssembler tasm, PTXAssembler masm, AllocatableValue result, PTXAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+        throw new InternalError("NYI");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+import java.lang.annotation.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+
+/**
+ * Base class to represent values that need to be stored in more than one register.
+ */
+public abstract class CompositeValue extends Value {
+
+    private static final long serialVersionUID = -169180052684126180L;
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface Component {
+
+        OperandFlag[] value() default OperandFlag.REG;
+    }
+
+    private final CompositeValueClass valueClass;
+
+    public CompositeValue(Kind kind) {
+        super(kind);
+        valueClass = CompositeValueClass.get(getClass());
+    }
+
+    public final void forEachComponent(OperandMode mode, ValueProcedure proc) {
+        valueClass.forEachComponent(this, mode, proc);
+    }
+
+    @Override
+    public String toString() {
+        return valueClass.toString(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+
+public class CompositeValueClass extends LIRIntrospection {
+
+    public static final CompositeValueClass get(Class<? extends CompositeValue> c) {
+        CompositeValueClass clazz = (CompositeValueClass) allClasses.get(c);
+        if (clazz != null) {
+            return clazz;
+        }
+
+        // We can have a race of multiple threads creating the LIRInstructionClass at the same time.
+        // However, only one will be put into the map, and this is the one returned by all threads.
+        clazz = new CompositeValueClass(c);
+        CompositeValueClass oldClazz = (CompositeValueClass) allClasses.putIfAbsent(c, clazz);
+        if (oldClazz != null) {
+            return oldClazz;
+        } else {
+            return clazz;
+        }
+    }
+
+    private final int directComponentCount;
+    private final long[] componentOffsets;
+    private final EnumSet<OperandFlag>[] componentFlags;
+
+    @SuppressWarnings("unchecked")
+    public CompositeValueClass(Class<? extends CompositeValue> clazz) {
+        super(clazz);
+
+        ValueFieldScanner scanner = new ValueFieldScanner(new DefaultCalcOffset());
+        scanner.scan(clazz);
+
+        OperandModeAnnotation mode = scanner.valueAnnotations.get(CompositeValue.Component.class);
+        directComponentCount = mode.scalarOffsets.size();
+        componentOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets);
+        componentFlags = arrayUsingSortedOffsets(mode.flags, componentOffsets, new EnumSet[componentOffsets.length]);
+
+        dataOffsets = sortedLongCopy(scanner.dataOffsets);
+
+        fieldNames = scanner.fieldNames;
+        fieldTypes = scanner.fieldTypes;
+    }
+
+    @Override
+    protected void rescanFieldOffsets(CalcOffset calc) {
+        ValueFieldScanner scanner = new ValueFieldScanner(calc);
+        scanner.scan(clazz);
+
+        OperandModeAnnotation mode = scanner.valueAnnotations.get(CompositeValue.Component.class);
+        copyInto(componentOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
+
+        copyInto(dataOffsets, sortedLongCopy(scanner.dataOffsets));
+
+        fieldNames.clear();
+        fieldNames.putAll(scanner.fieldNames);
+        fieldTypes.clear();
+        fieldTypes.putAll(scanner.fieldTypes);
+    }
+
+    private static class ValueFieldScanner extends FieldScanner {
+
+        public ValueFieldScanner(CalcOffset calc) {
+            super(calc);
+
+            valueAnnotations.put(CompositeValue.Component.class, new OperandModeAnnotation());
+        }
+
+        @Override
+        protected void scan(Class<?> clazz) {
+            super.scan(clazz);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> getFlags(Field field) {
+            EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class);
+            if (field.isAnnotationPresent(CompositeValue.Component.class)) {
+                result.addAll(Arrays.asList(field.getAnnotation(CompositeValue.Component.class).value()));
+            } else {
+                GraalInternalError.shouldNotReachHere();
+            }
+            return result;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" component[");
+        for (int i = 0; i < componentOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(componentOffsets[i]);
+        }
+        str.append("] data[");
+        for (int i = 0; i < dataOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(dataOffsets[i]);
+        }
+        str.append("]");
+        return str.toString();
+    }
+
+    public final void forEachComponent(CompositeValue obj, OperandMode mode, ValueProcedure proc) {
+        forEach(obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
+    }
+
+    public String toString(CompositeValue obj) {
+        StringBuilder result = new StringBuilder();
+
+        appendValues(result, obj, "", "", "{", "}", new String[]{""}, componentOffsets);
+
+        for (int i = 0; i < dataOffsets.length; i++) {
+            result.append(" ").append(fieldNames.get(dataOffsets[i])).append(": ").append(getFieldString(obj, dataOffsets[i]));
+        }
+
+        return result.toString();
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Thu Mar 21 14:11:13 2013 +0100
@@ -70,17 +70,11 @@
  * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size of such
  * a block may be greater than the size of a normal spill slot or the word size.
  * <p>
- * A runtime has two ways to reserve space in the stack frame for its own use:
- * <ul>
- * <li>A memory block somewhere in the frame of size
- * {@link CodeCacheProvider#getCustomStackAreaSize()}. The offset to this block is returned in
- * {@link CompilationResult#getCustomStackAreaOffset()}.
- * <li>At the beginning of the overflow argument area: The calling convention can specify that the
- * first overflow stack argument is not at offset 0, but at a specified offset o. Use
- * {@link CodeCacheProvider#getMinimumOutgoingSize()} to make sure that call-free methods also have
- * this space reserved. Then the VM can use memory the memory at offset 0 relative to the stack
- * pointer.
- * </ul>
+ * A runtime can reserve space at the beginning of the overflow argument area. The calling
+ * convention can specify that the first overflow stack argument is not at offset 0, but at a
+ * specified offset. Use {@link CodeCacheProvider#getMinimumOutgoingSize()} to make sure that
+ * call-free methods also have this space reserved. Then the VM can use the memory at offset 0
+ * relative to the stack pointer.
  */
 public final class FrameMap {
 
@@ -89,14 +83,9 @@
     public final RegisterConfig registerConfig;
 
     /**
-     * The initial frame size, not including the size of the return address. This is the constant
-     * space reserved by the runtime for all compiled methods.
-     */
-    public final int initialFrameSize;
-
-    /**
-     * The final frame size, not including the size of the return address. The value is only set
-     * after register allocation is complete, i.e., after all spill slots have been allocated.
+     * The final frame size, not including the size of the
+     * {@link Architecture#getReturnAddressSize() return address slot}. The value is only set after
+     * register allocation is complete, i.e., after all spill slots have been allocated.
      */
     private int frameSize;
 
@@ -117,12 +106,6 @@
     private final List<StackSlot> objectStackBlocks;
 
     /**
-     * The stack area reserved for use by the VM, or {@code null} if the VM does not request stack
-     * space.
-     */
-    private final StackSlot customArea;
-
-    /**
      * Records whether an offset to an incoming stack argument was ever returned by
      * {@link #offsetForStackSlot(StackSlot)}.
      */
@@ -139,8 +122,6 @@
         this.spillSize = returnAddressSize() + calleeSaveAreaSize();
         this.outgoingSize = runtime.getMinimumOutgoingSize();
         this.objectStackBlocks = new ArrayList<>();
-        this.customArea = allocateStackBlock(runtime.getCustomStackAreaSize(), false);
-        this.initialFrameSize = currentFrameSize();
     }
 
     private int returnAddressSize() {
@@ -161,7 +142,8 @@
     }
 
     /**
-     * Gets the frame size of the compiled frame, not including the size of the return address.
+     * Gets the frame size of the compiled frame, not including the size of the
+     * {@link Architecture#getReturnAddressSize() return address slot}.
      * 
      * @return The size of the frame (in bytes).
      */
@@ -171,7 +153,17 @@
     }
 
     /**
-     * Gets the total frame size of the compiled frame, including the size of the return address.
+     * Determines if any space is used in the frame apart from the
+     * {@link Architecture#getReturnAddressSize() return address slot}.
+     */
+    public boolean frameNeedsAllocating() {
+        int unalignedFrameSize = outgoingSize + spillSize - returnAddressSize();
+        return unalignedFrameSize != 0;
+    }
+
+    /**
+     * Gets the total frame size of the compiled frame, including the size of the
+     * {@link Architecture#getReturnAddressSize() return address slot}.
      * 
      * @return The total size of the frame (in bytes).
      */
@@ -194,6 +186,21 @@
      */
     public void finish() {
         assert this.frameSize == -1 : "must only be set once";
+        if (freedSlots != null) {
+            // If the freed slots cover the complete spill area (except for the return
+            // address slot), then the spill size is reset to its initial value.
+            // Without this, frameNeedsAllocating() would never return true.
+            int total = 0;
+            for (StackSlot s : freedSlots) {
+                total += target.sizeInBytes(s.getKind());
+            }
+            int initialSpillSize = returnAddressSize() + calleeSaveAreaSize();
+            if (total == spillSize - initialSpillSize) {
+                // reset spill area size
+                spillSize = initialSpillSize;
+            }
+            freedSlots = null;
+        }
         frameSize = currentFrameSize();
     }
 
@@ -223,16 +230,6 @@
     }
 
     /**
-     * Gets the offset of the stack area stack block reserved for use by the VM, or -1 if the VM
-     * does not request stack space.
-     * 
-     * @return The offset to the custom area (in bytes).
-     */
-    public int offsetToCustomArea() {
-        return customArea == null ? -1 : offsetForStackSlot(customArea);
-    }
-
-    /**
      * Informs the frame map that the compiled code calls a particular method, which may need stack
      * space for outgoing arguments.
      * 
@@ -265,11 +262,36 @@
      */
     public StackSlot allocateSpillSlot(Kind kind) {
         assert frameSize == -1 : "frame size must not yet be fixed";
+        if (freedSlots != null) {
+            for (Iterator<StackSlot> iter = freedSlots.iterator(); iter.hasNext();) {
+                StackSlot s = iter.next();
+                if (s.getKind() == kind) {
+                    iter.remove();
+                    if (freedSlots.isEmpty()) {
+                        freedSlots = null;
+                    }
+                    return s;
+                }
+            }
+        }
         int size = target.sizeInBytes(kind);
         spillSize = NumUtil.roundUp(spillSize + size, size);
         return getSlot(kind, 0);
     }
 
+    private List<StackSlot> freedSlots;
+
+    /**
+     * Frees a spill slot that was obtained via {@link #allocateSpillSlot(Kind)} such that it can be
+     * reused for the next allocation request for the same kind of slot.
+     */
+    public void freeSpillSlot(StackSlot slot) {
+        if (freedSlots == null) {
+            freedSlots = new ArrayList<>();
+        }
+        freedSlots.add(slot);
+    }
+
     /**
      * Reserves a block of memory in the frame of the method being compiled. The returned block is
      * aligned on a word boundary. If the requested size is 0, the method returns {@code null}.
@@ -347,28 +369,4 @@
             }
         }
     }
-
-    /**
-     * Clears the specified location as a reference in the reference map of the debug information.
-     * The tracked location can be a {@link RegisterValue} or a {@link StackSlot}. Note that a
-     * {@link Constant} is automatically tracked.
-     * 
-     * @param location The location to be removed from the reference map.
-     * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}.
-     * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}.
-     */
-    public void clearReference(Value location, BitSet registerRefMap, BitSet frameRefMap) {
-        if (location.getKind() == Kind.Object) {
-            if (location instanceof RegisterValue) {
-                registerRefMap.clear(asRegister(location).number);
-            } else if (isStackSlot(location)) {
-                int index = frameRefMapIndex(asStackSlot(location));
-                if (index < frameRefMap.size()) {
-                    frameRefMap.clear(index);
-                }
-            } else {
-                assert isConstant(location);
-            }
-        }
-    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -55,12 +56,6 @@
      */
     private final List<Block> codeEmittingOrder;
 
-    /**
-     * Various out-of-line stubs to be emitted near the end of the method after all other LIR code
-     * has been emitted.
-     */
-    public final List<Code> stubs;
-
     private int numVariables;
 
     public SpillMoveFactory spillMoveFactory;
@@ -74,30 +69,22 @@
 
     private boolean hasArgInCallerFrame;
 
-    /**
-     * An opaque chunk of machine code.
-     */
-    public interface Code {
-
-        void emitCode(TargetMethodAssembler tasm);
-
-        /**
-         * A description of this code stub useful for commenting the code in a disassembly.
-         */
-        String description();
-    }
+    private final SpeculationLog speculationLog;
 
     /**
      * Creates a new LIR instance for the specified compilation.
      */
-    public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder) {
+    public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder, SpeculationLog speculationLog) {
         this.cfg = cfg;
         this.blockToNodesMap = blockToNodesMap;
         this.codeEmittingOrder = codeEmittingOrder;
         this.linearScanOrder = linearScanOrder;
         this.lirInstructions = new BlockMap<>(cfg);
+        this.speculationLog = speculationLog;
+    }
 
-        stubs = new ArrayList<>();
+    public SpeculationLog getDeoptimizationReasons() {
+        return speculationLog;
     }
 
     /**
@@ -108,7 +95,7 @@
     }
 
     /**
-     * Determines if any instruction in the LIR has any debug info associated with it.
+     * Determines if any instruction in the LIR has debug info associated with it.
      */
     public boolean hasDebugInfo() {
         for (Block b : linearScanOrder()) {
@@ -159,11 +146,6 @@
         for (Block b : codeEmittingOrder()) {
             emitBlock(tasm, b);
         }
-
-        // generate code stubs
-        for (Code c : stubs) {
-            emitCodeStub(tasm, c);
-        }
     }
 
     private void emitBlock(TargetMethodAssembler tasm, Block block) {
@@ -194,13 +176,6 @@
         }
     }
 
-    private static void emitCodeStub(TargetMethodAssembler tasm, Code code) {
-        if (Debug.isDumpEnabled()) {
-            tasm.blockComment(String.format("code stub: %s", code.description()));
-        }
-        code.emitCode(tasm);
-    }
-
     public void setHasArgInCallerFrame() {
         hasArgInCallerFrame = true;
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Thu Mar 21 14:11:13 2013 +0100
@@ -42,11 +42,13 @@
     private final VirtualObject[] virtualObjects;
     public final LabelRef exceptionEdge;
     private DebugInfo debugInfo;
+    private final short deoptimizationReason;
 
-    public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge) {
+    public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge, short deoptimizationReason) {
         this.topFrame = topFrame;
         this.virtualObjects = virtualObjects;
         this.exceptionEdge = exceptionEdge;
+        this.deoptimizationReason = deoptimizationReason;
     }
 
     public boolean hasDebugInfo() {
@@ -111,7 +113,7 @@
     }
 
     public void finish(BitSet registerRefMap, BitSet frameRefMap) {
-        debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap);
+        debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap, deoptimizationReason);
     }
 
     @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Thu Mar 21 14:11:13 2013 +0100
@@ -166,9 +166,9 @@
         STACK,
 
         /**
-         * The value can be a {@link Address}.
+         * The value can be a {@link CompositeValue}.
          */
-        ADDR,
+        COMPOSITE,
 
         /**
          * The value can be a {@link Constant}.
@@ -181,6 +181,11 @@
         ILLEGAL,
 
         /**
+         * The value can be {@link AllocatableValue#UNUSED}.
+         */
+        UNUSED,
+
+        /**
          * The register allocator should try to assign a certain register to improve code quality.
          * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints.
          */
@@ -200,10 +205,10 @@
 
     static {
         ALLOWED_FLAGS = new EnumMap<>(OperandMode.class);
-        ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED));
-        ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED));
-        ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, CONST, ILLEGAL, HINT));
-        ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, ILLEGAL, HINT));
+        ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNUSED, UNINITIALIZED));
+        ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNUSED, UNINITIALIZED));
+        ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, COMPOSITE, CONST, ILLEGAL, UNUSED, HINT));
+        ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, UNUSED, HINT));
     }
 
     /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,12 +22,8 @@
  */
 package com.oracle.graal.lir;
 
-import static com.oracle.graal.api.code.ValueUtil.*;
-
-import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.Map.Entry;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -37,7 +33,7 @@
 import com.oracle.graal.lir.LIRInstruction.StateProcedure;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
-public class LIRInstructionClass extends FieldIntrospection {
+public class LIRInstructionClass extends LIRIntrospection {
 
     public static final LIRInstructionClass get(Class<? extends LIRInstruction> c) {
         LIRInstructionClass clazz = (LIRInstructionClass) allClasses.get(c);
@@ -56,10 +52,8 @@
         }
     }
 
-    private static final Class<?> INSTRUCTION_CLASS = LIRInstruction.class;
-    private static final Class<?> VALUE_CLASS = Value.class;
-    private static final Class<?> VALUE_ARRAY_CLASS = Value[].class;
-    private static final Class<?> STATE_CLASS = LIRFrameState.class;
+    private static final Class<LIRInstruction> INSTRUCTION_CLASS = LIRInstruction.class;
+    private static final Class<LIRFrameState> STATE_CLASS = LIRFrameState.class;
 
     private final int directUseCount;
     private final long[] useOffsets;
@@ -80,11 +74,11 @@
     private long opcodeOffset;
 
     @SuppressWarnings("unchecked")
-    public LIRInstructionClass(Class<?> clazz) {
+    public LIRInstructionClass(Class<? extends LIRInstruction> clazz) {
         super(clazz);
         assert INSTRUCTION_CLASS.isAssignableFrom(clazz);
 
-        FieldScanner scanner = new FieldScanner(new DefaultCalcOffset());
+        InstructionFieldScanner scanner = new InstructionFieldScanner(new DefaultCalcOffset());
         scanner.scan(clazz);
 
         OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class);
@@ -119,7 +113,7 @@
 
     @Override
     protected void rescanFieldOffsets(CalcOffset calc) {
-        FieldScanner scanner = new FieldScanner(calc);
+        InstructionFieldScanner scanner = new InstructionFieldScanner(calc);
         scanner.scan(clazz);
 
         OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class);
@@ -143,44 +137,22 @@
         opcodeOffset = scanner.opcodeOffset;
     }
 
-    private static class OperandModeAnnotation {
-
-        public final ArrayList<Long> scalarOffsets = new ArrayList<>();
-        public final ArrayList<Long> arrayOffsets = new ArrayList<>();
-        public final Map<Long, EnumSet<OperandFlag>> flags = new HashMap<>();
-    }
-
-    protected static class FieldScanner extends BaseFieldScanner {
-
-        public final Map<Class<? extends Annotation>, OperandModeAnnotation> valueAnnotations;
-        public final ArrayList<Long> stateOffsets = new ArrayList<>();
+    private static class InstructionFieldScanner extends FieldScanner {
 
         private String opcodeConstant;
         private long opcodeOffset;
 
-        public FieldScanner(CalcOffset calc) {
+        public InstructionFieldScanner(CalcOffset calc) {
             super(calc);
 
-            valueAnnotations = new HashMap<>();
-            valueAnnotations.put(LIRInstruction.Use.class, new OperandModeAnnotation()); // LIRInstruction.Use.class));
-            valueAnnotations.put(LIRInstruction.Alive.class, new OperandModeAnnotation()); // LIRInstruction.Alive.class));
-            valueAnnotations.put(LIRInstruction.Temp.class, new OperandModeAnnotation()); // LIRInstruction.Temp.class));
-            valueAnnotations.put(LIRInstruction.Def.class, new OperandModeAnnotation()); // LIRInstruction.Def.class));
+            valueAnnotations.put(LIRInstruction.Use.class, new OperandModeAnnotation());
+            valueAnnotations.put(LIRInstruction.Alive.class, new OperandModeAnnotation());
+            valueAnnotations.put(LIRInstruction.Temp.class, new OperandModeAnnotation());
+            valueAnnotations.put(LIRInstruction.Def.class, new OperandModeAnnotation());
         }
 
-        private OperandModeAnnotation getOperandModeAnnotation(Field field) {
-            OperandModeAnnotation result = null;
-            for (Entry<Class<? extends Annotation>, OperandModeAnnotation> entry : valueAnnotations.entrySet()) {
-                Annotation annotation = field.getAnnotation(entry.getKey());
-                if (annotation != null) {
-                    assert result == null : "Field has two operand mode annotations: " + field;
-                    result = entry.getValue();
-                }
-            }
-            return result;
-        }
-
-        private static EnumSet<OperandFlag> getFlags(Field field) {
+        @Override
+        protected EnumSet<OperandFlag> getFlags(Field field) {
             EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class);
             // Unfortunately, annotations cannot have class hierarchies or implement interfaces, so
             // we have to duplicate the code for every operand mode.
@@ -219,26 +191,12 @@
 
         @Override
         protected void scanField(Field field, Class<?> type, long offset) {
-            if (VALUE_CLASS.isAssignableFrom(type)) {
-                assert Modifier.isProtected(field.getModifiers()) && !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final or [package] private because it is modified by register allocator: " +
-                                field;
-                OperandModeAnnotation annotation = getOperandModeAnnotation(field);
-                assert annotation != null : "Field must have operand mode annotation: " + field;
-                annotation.scalarOffsets.add(offset);
-                annotation.flags.put(offset, getFlags(field));
-            } else if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) {
-                OperandModeAnnotation annotation = getOperandModeAnnotation(field);
-                assert annotation != null : "Field must have operand mode annotation: " + field;
-                annotation.arrayOffsets.add(offset);
-                annotation.flags.put(offset, getFlags(field));
-            } else if (STATE_CLASS.isAssignableFrom(type)) {
+            if (STATE_CLASS.isAssignableFrom(type)) {
                 assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field;
                 assert field.getAnnotation(LIRInstruction.State.class) != null : "Field must have state annotation: " + field;
                 stateOffsets.add(offset);
             } else {
-                assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field;
-                assert field.getAnnotation(LIRInstruction.State.class) == null : "Field must not have state annotation: " + field;
-                dataOffsets.add(offset);
+                super.scanField(field, type, offset);
             }
 
             if (field.getAnnotation(LIRInstruction.Opcode.class) != null) {
@@ -334,37 +292,6 @@
         }
     }
 
-    private static void forEach(LIRInstruction obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValueProcedure proc) {
-        for (int i = 0; i < offsets.length; i++) {
-            assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]);
-
-            if (i < directCount) {
-                Value value = getValue(obj, offsets[i]);
-                if (isAddress(value)) {
-                    doAddress(asAddress(value), mode, flags[i], proc);
-                } else {
-                    setValue(obj, offsets[i], proc.doValue(value, mode, flags[i]));
-                }
-            } else {
-                Value[] values = getValueArray(obj, offsets[i]);
-                for (int j = 0; j < values.length; j++) {
-                    Value value = values[j];
-                    if (isAddress(value)) {
-                        doAddress(asAddress(value), mode, flags[i], proc);
-                    } else {
-                        values[j] = proc.doValue(value, mode, flags[i]);
-                    }
-                }
-            }
-        }
-    }
-
-    private static void doAddress(Address address, OperandMode mode, EnumSet<OperandFlag> flags, ValueProcedure proc) {
-        assert flags.contains(OperandFlag.ADDR);
-        address.setBase(proc.doValue(address.getBase(), mode, LIRInstruction.ADDRESS_FLAGS));
-        address.setIndex(proc.doValue(address.getIndex(), mode, LIRInstruction.ADDRESS_FLAGS));
-    }
-
     public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, ValueProcedure proc) {
         int hintDirectCount = 0;
         long[] hintOffsets = null;
@@ -399,18 +326,6 @@
         return null;
     }
 
-    private static Value getValue(LIRInstruction obj, long offset) {
-        return (Value) unsafe.getObject(obj, offset);
-    }
-
-    private static void setValue(LIRInstruction obj, long offset, Value value) {
-        unsafe.putObject(obj, offset, value);
-    }
-
-    private static Value[] getValueArray(LIRInstruction obj, long offset) {
-        return (Value[]) unsafe.getObject(obj, offset);
-    }
-
     private static LIRFrameState getState(LIRInstruction obj, long offset) {
         return (LIRFrameState) unsafe.getObject(obj, offset);
     }
@@ -445,65 +360,4 @@
 
         return result.toString();
     }
-
-    private void appendValues(StringBuilder result, LIRInstruction obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]... moffsets) {
-        int total = 0;
-        for (long[] offsets : moffsets) {
-            total += offsets.length;
-        }
-        if (total == 0) {
-            return;
-        }
-
-        result.append(start);
-        if (total > 1) {
-            result.append(startMultiple);
-        }
-        String sep = "";
-        for (int i = 0; i < moffsets.length; i++) {
-            long[] offsets = moffsets[i];
-
-            for (int j = 0; j < offsets.length; j++) {
-                result.append(sep).append(prefix[i]);
-                long offset = offsets[j];
-                if (total > 1) {
-                    result.append(fieldNames.get(offset)).append(": ");
-                }
-                result.append(getFieldString(obj, offset));
-                sep = ", ";
-            }
-        }
-        if (total > 1) {
-            result.append(endMultiple);
-        }
-        result.append(end);
-    }
-
-    private String getFieldString(Object obj, long offset) {
-        Class<?> type = fieldTypes.get(offset);
-        if (type == int.class) {
-            return String.valueOf(unsafe.getInt(obj, offset));
-        } else if (type == long.class) {
-            return String.valueOf(unsafe.getLong(obj, offset));
-        } else if (type == boolean.class) {
-            return String.valueOf(unsafe.getBoolean(obj, offset));
-        } else if (type == float.class) {
-            return String.valueOf(unsafe.getFloat(obj, offset));
-        } else if (type == double.class) {
-            return String.valueOf(unsafe.getDouble(obj, offset));
-        } else if (!type.isPrimitive()) {
-            Object value = unsafe.getObject(obj, offset);
-            if (!type.isArray()) {
-                return String.valueOf(value);
-            } else if (type == int[].class) {
-                return Arrays.toString((int[]) value);
-            } else if (type == double[].class) {
-                return Arrays.toString((double[]) value);
-            } else if (!type.getComponentType().isPrimitive()) {
-                return Arrays.toString((Object[]) value);
-            }
-        }
-        assert false : "unhandled field type: " + type;
-        return "";
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+
+abstract class LIRIntrospection extends FieldIntrospection {
+
+    private static final Class<Value> VALUE_CLASS = Value.class;
+    private static final Class<Constant> CONSTANT_CLASS = Constant.class;
+    private static final Class<RegisterValue> REGISTER_VALUE_CLASS = RegisterValue.class;
+    private static final Class<StackSlot> STACK_SLOT_CLASS = StackSlot.class;
+    private static final Class<Value[]> VALUE_ARRAY_CLASS = Value[].class;
+
+    public LIRIntrospection(Class<?> clazz) {
+        super(clazz);
+    }
+
+    protected static class OperandModeAnnotation {
+
+        public final ArrayList<Long> scalarOffsets = new ArrayList<>();
+        public final ArrayList<Long> arrayOffsets = new ArrayList<>();
+        public final Map<Long, EnumSet<OperandFlag>> flags = new HashMap<>();
+    }
+
+    protected abstract static class FieldScanner extends BaseFieldScanner {
+
+        public final Map<Class<? extends Annotation>, OperandModeAnnotation> valueAnnotations;
+        public final ArrayList<Long> stateOffsets = new ArrayList<>();
+
+        public FieldScanner(CalcOffset calc) {
+            super(calc);
+
+            valueAnnotations = new HashMap<>();
+        }
+
+        protected OperandModeAnnotation getOperandModeAnnotation(Field field) {
+            OperandModeAnnotation result = null;
+            for (Entry<Class<? extends Annotation>, OperandModeAnnotation> entry : valueAnnotations.entrySet()) {
+                Annotation annotation = field.getAnnotation(entry.getKey());
+                if (annotation != null) {
+                    assert result == null : "Field has two operand mode annotations: " + field;
+                    result = entry.getValue();
+                }
+            }
+            return result;
+        }
+
+        protected abstract EnumSet<OperandFlag> getFlags(Field field);
+
+        @Override
+        protected void scanField(Field field, Class<?> type, long offset) {
+            if (VALUE_CLASS.isAssignableFrom(type) && type != CONSTANT_CLASS) {
+                assert !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final because it is modified by register allocator: " + field;
+                OperandModeAnnotation annotation = getOperandModeAnnotation(field);
+                assert annotation != null : "Field must have operand mode annotation: " + field;
+                annotation.scalarOffsets.add(offset);
+                EnumSet<OperandFlag> flags = getFlags(field);
+                assert verifyFlags(field, type, flags);
+                annotation.flags.put(offset, getFlags(field));
+            } else if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) {
+                OperandModeAnnotation annotation = getOperandModeAnnotation(field);
+                assert annotation != null : "Field must have operand mode annotation: " + field;
+                annotation.arrayOffsets.add(offset);
+                EnumSet<OperandFlag> flags = getFlags(field);
+                assert verifyFlags(field, type.getComponentType(), flags);
+                annotation.flags.put(offset, getFlags(field));
+            } else {
+                assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field;
+                assert field.getAnnotation(LIRInstruction.State.class) == null : "Field must not have state annotation: " + field;
+                dataOffsets.add(offset);
+            }
+        }
+
+        private static boolean verifyFlags(Field field, Class<?> type, EnumSet<OperandFlag> flags) {
+            if (flags.contains(REG)) {
+                assert type.isAssignableFrom(REGISTER_VALUE_CLASS) : "Cannot assign RegisterValue to field with REG flag:" + field;
+            }
+            if (flags.contains(STACK)) {
+                assert type.isAssignableFrom(STACK_SLOT_CLASS) : "Cannot assign StackSlot to field with STACK flag:" + field;
+            }
+            if (flags.contains(CONST)) {
+                assert type.isAssignableFrom(CONSTANT_CLASS) : "Cannot assign Constant to field with CONST flag:" + field;
+            }
+            return true;
+        }
+    }
+
+    protected static void forEach(Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValueProcedure proc) {
+        for (int i = 0; i < offsets.length; i++) {
+            assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]);
+
+            if (i < directCount) {
+                Value value = getValue(obj, offsets[i]);
+                if (value instanceof CompositeValue) {
+                    CompositeValue composite = (CompositeValue) value;
+                    composite.forEachComponent(mode, proc);
+                } else {
+                    setValue(obj, offsets[i], proc.doValue(value, mode, flags[i]));
+                }
+            } else {
+                Value[] values = getValueArray(obj, offsets[i]);
+                for (int j = 0; j < values.length; j++) {
+                    Value value = values[j];
+                    if (value instanceof CompositeValue) {
+                        CompositeValue composite = (CompositeValue) value;
+                        composite.forEachComponent(mode, proc);
+                    } else {
+                        values[j] = proc.doValue(value, mode, flags[i]);
+                    }
+                }
+            }
+        }
+    }
+
+    protected static Value getValue(Object obj, long offset) {
+        return (Value) unsafe.getObject(obj, offset);
+    }
+
+    protected static void setValue(Object obj, long offset, Value value) {
+        unsafe.putObject(obj, offset, value);
+    }
+
+    protected static Value[] getValueArray(Object obj, long offset) {
+        return (Value[]) unsafe.getObject(obj, offset);
+    }
+
+    protected void appendValues(StringBuilder result, Object obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]... moffsets) {
+        int total = 0;
+        for (long[] offsets : moffsets) {
+            total += offsets.length;
+        }
+        if (total == 0) {
+            return;
+        }
+
+        result.append(start);
+        if (total > 1) {
+            result.append(startMultiple);
+        }
+        String sep = "";
+        for (int i = 0; i < moffsets.length; i++) {
+            long[] offsets = moffsets[i];
+
+            for (int j = 0; j < offsets.length; j++) {
+                result.append(sep).append(prefix[i]);
+                long offset = offsets[j];
+                if (total > 1) {
+                    result.append(fieldNames.get(offset)).append(": ");
+                }
+                result.append(getFieldString(obj, offset));
+                sep = ", ";
+            }
+        }
+        if (total > 1) {
+            result.append(endMultiple);
+        }
+        result.append(end);
+    }
+
+    protected String getFieldString(Object obj, long offset) {
+        Class<?> type = fieldTypes.get(offset);
+        if (type == int.class) {
+            return String.valueOf(unsafe.getInt(obj, offset));
+        } else if (type == long.class) {
+            return String.valueOf(unsafe.getLong(obj, offset));
+        } else if (type == boolean.class) {
+            return String.valueOf(unsafe.getBoolean(obj, offset));
+        } else if (type == float.class) {
+            return String.valueOf(unsafe.getFloat(obj, offset));
+        } else if (type == double.class) {
+            return String.valueOf(unsafe.getDouble(obj, offset));
+        } else if (!type.isPrimitive()) {
+            Object value = unsafe.getObject(obj, offset);
+            if (!type.isArray()) {
+                return String.valueOf(value);
+            } else if (type == int[].class) {
+                return Arrays.toString((int[]) value);
+            } else if (type == double[].class) {
+                return Arrays.toString((double[]) value);
+            } else if (!type.getComponentType().isPrimitive()) {
+                return Arrays.toString((Object[]) value);
+            }
+        }
+        assert false : "unhandled field type: " + type;
+        return "";
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Thu Mar 21 14:11:13 2013 +0100
@@ -232,7 +232,8 @@
 
     private static Value allowed(Object op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
         if ((isVariable(value) && flags.contains(OperandFlag.REG)) || (isRegister(value) && flags.contains(OperandFlag.REG)) || (isStackSlot(value) && flags.contains(OperandFlag.STACK)) ||
-                        (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) {
+                        (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL)) ||
+                        (value == AllocatableValue.UNUSED && flags.contains(OperandFlag.UNUSED))) {
             return value;
         }
         TTY.println("instruction %s", op);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,39 +32,13 @@
  * reference of block B from block A only via the tuple (A, successor-index-of-B), i.e., indirectly
  * by storing the index into the successor list of A. Note that therefore it is not allowed to
  * reorder the successor list!
- * 
- * Labels of out-of-line stubs can be referenced directly, therefore it is also possible to
- * construct a LabelRef for a Label directly via {@link #forLabel}.
  */
 public abstract class LabelRef {
 
     public abstract Label label();
 
     /**
-     * Returns a new reference to a statically defined label.
-     * 
-     * @param label The label that is always returned.
-     * @return The newly created label reference.
-     */
-    public static LabelRef forLabel(final Label label) {
-        return new LabelRef() {
-
-            @Override
-            public Label label() {
-                return label;
-            }
-
-            @Override
-            public String toString() {
-                return label.toString();
-            }
-        };
-    }
-
-    /**
-     * Returns a new reference to a successor of the given block. This allows to reference the given
-     * successor even when the successor list is modified between the creation of the reference and
-     * the call to {@link #forLabel(Label)}.
+     * Returns a new reference to a successor of the given block.
      * 
      * @param block The base block that contains the successor list.
      * @param suxIndex The index of the successor.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -33,8 +33,6 @@
  */
 public class StandardOp {
 
-    private static Value[] EMPTY = new Value[0];
-
     /**
      * Marker interface for LIR ops that can fall through to the next operation, like a switch
      * statement. setFallThroughTarget(null) can be used to make the operation fall through to the
@@ -82,11 +80,9 @@
     public static class JumpOp extends LIRInstruction {
 
         private final LabelRef destination;
-        @State protected LIRFrameState state;
 
-        public JumpOp(LabelRef destination, LIRFrameState state) {
+        public JumpOp(LabelRef destination) {
             this.destination = destination;
-            this.state = state;
         }
 
         @Override
@@ -99,24 +95,6 @@
         }
     }
 
-    public static class PhiJumpOp extends JumpOp {
-
-        @Alive({REG, STACK, CONST}) protected Value[] phiInputs;
-
-        public PhiJumpOp(LabelRef destination, Value[] phiInputs) {
-            super(destination, null);
-            this.phiInputs = phiInputs;
-        }
-
-        public void markResolved() {
-            phiInputs = EMPTY;
-        }
-
-        public Value[] getPhiInputs() {
-            return phiInputs;
-        }
-    }
-
     /**
      * Marker interface for a LIR operation that is a conditional jump to {@link #destination()}.
      * Conditional jumps may be negated or optimized away after register allocation.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,7 +29,7 @@
  * Represents a value that is yet to be bound to a machine location (such as a {@link RegisterValue}
  * or {@link StackSlot}) by a register allocator.
  */
-public final class Variable extends Value {
+public final class Variable extends AllocatableValue {
 
     private static final long serialVersionUID = 4507578431686109809L;
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,7 +32,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIR.Code;
 
 public class TargetMethodAssembler {
 
@@ -48,77 +47,65 @@
     }
 
     public final AbstractAssembler asm;
-    public final CompilationResult targetMethod;
+    public final CompilationResult compilationResult;
     public final TargetDescription target;
     public final CodeCacheProvider runtime;
     public final FrameMap frameMap;
 
     /**
-     * Out-of-line stubs to be emitted.
-     */
-    public final List<Code> stubs;
-
-    /**
      * The object that emits code for managing a method's frame. If null, no frame is used by the
      * method.
      */
     public final FrameContext frameContext;
 
     private List<ExceptionInfo> exceptionInfoList;
-    private int lastSafepointPos;
 
-    public TargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, List<Code> stubs) {
+    public TargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, CompilationResult compilationResult) {
         this.target = target;
         this.runtime = runtime;
         this.frameMap = frameMap;
-        this.stubs = stubs;
         this.asm = asm;
-        this.targetMethod = new CompilationResult();
+        this.compilationResult = compilationResult;
         this.frameContext = frameContext;
-        // 0 is a valid pc for safepoints in template methods
-        this.lastSafepointPos = -1;
     }
 
     public void setFrameSize(int frameSize) {
-        targetMethod.setFrameSize(frameSize);
+        compilationResult.setFrameSize(frameSize);
     }
 
     private static final CompilationResult.Mark[] NO_REFS = {};
 
     public CompilationResult.Mark recordMark(Object id) {
-        return targetMethod.recordMark(asm.codeBuffer.position(), id, NO_REFS);
+        return compilationResult.recordMark(asm.codeBuffer.position(), id, NO_REFS);
     }
 
     public CompilationResult.Mark recordMark(Object id, CompilationResult.Mark... references) {
-        return targetMethod.recordMark(asm.codeBuffer.position(), id, references);
+        return compilationResult.recordMark(asm.codeBuffer.position(), id, references);
     }
 
     public void blockComment(String s) {
-        targetMethod.addAnnotation(new CompilationResult.CodeComment(asm.codeBuffer.position(), s));
+        compilationResult.addAnnotation(new CompilationResult.CodeComment(asm.codeBuffer.position(), s));
     }
 
     public CompilationResult finishTargetMethod(Object name, boolean isStub) {
         // Install code, data and frame size
-        targetMethod.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position());
+        compilationResult.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position());
 
         // Record exception handlers if they exist
         if (exceptionInfoList != null) {
             for (ExceptionInfo ei : exceptionInfoList) {
                 int codeOffset = ei.codeOffset;
-                targetMethod.recordExceptionHandler(codeOffset, ei.exceptionEdge.label().position());
+                compilationResult.recordExceptionHandler(codeOffset, ei.exceptionEdge.label().position());
             }
         }
 
-        // Set the info on callee-saved registers
-        targetMethod.setCalleeSaveLayout(frameMap.registerConfig.getCalleeSaveLayout());
-
         Debug.metric("TargetMethods").increment();
-        Debug.metric("CodeBytesEmitted").add(targetMethod.getTargetCodeSize());
-        Debug.metric("SafepointsEmitted").add(targetMethod.getSafepoints().size());
-        Debug.metric("DataPatches").add(targetMethod.getDataReferences().size());
-        Debug.metric("ExceptionHandlersEmitted").add(targetMethod.getExceptionHandlers().size());
+        Debug.metric("CodeBytesEmitted").add(compilationResult.getTargetCodeSize());
+        Debug.metric("SafepointsEmitted").add(compilationResult.getSafepoints().size());
+        Debug.metric("DataPatches").add(compilationResult.getDataReferences().size());
+        Debug.metric("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size());
         Debug.log("Finished target method %s, isStub %b", name, isStub);
-        return targetMethod;
+        return compilationResult;
     }
 
     public void recordExceptionHandlers(int pcOffset, LIRFrameState info) {
@@ -135,45 +122,33 @@
     public void recordImplicitException(int pcOffset, LIRFrameState info) {
         // record an implicit exception point
         if (info != null) {
-            assert lastSafepointPos < pcOffset : lastSafepointPos + "<" + pcOffset;
-            lastSafepointPos = pcOffset;
-            targetMethod.recordSafepoint(pcOffset, info.debugInfo());
+            compilationResult.recordSafepoint(pcOffset, info.debugInfo());
             assert info.exceptionEdge == null;
         }
     }
 
-    public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRFrameState info) {
+    public void recordDirectCall(int posBefore, int posAfter, InvokeTarget callTarget, LIRFrameState info) {
         DebugInfo debugInfo = info != null ? info.debugInfo() : null;
-        assert lastSafepointPos < posAfter;
-        lastSafepointPos = posAfter;
-        targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, true);
+        compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, true);
     }
 
-    public void recordIndirectCall(int posBefore, int posAfter, Object callTarget, LIRFrameState info) {
+    public void recordIndirectCall(int posBefore, int posAfter, InvokeTarget callTarget, LIRFrameState info) {
         DebugInfo debugInfo = info != null ? info.debugInfo() : null;
-        assert lastSafepointPos < posAfter;
-        lastSafepointPos = posAfter;
-        targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false);
+        compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false);
     }
 
     public void recordSafepoint(int pos, LIRFrameState info) {
         // safepoints always need debug info
         DebugInfo debugInfo = info.debugInfo();
-        assert lastSafepointPos < pos;
-        lastSafepointPos = pos;
-        targetMethod.recordSafepoint(pos, debugInfo);
+        compilationResult.recordSafepoint(pos, debugInfo);
     }
 
-    public Address recordDataReferenceInCode(Constant data, int alignment, boolean inlined) {
+    public AbstractAddress recordDataReferenceInCode(Constant data, int alignment, boolean inlined) {
         assert data != null;
         int pos = asm.codeBuffer.position();
         Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString());
-        targetMethod.recordDataReference(pos, data, alignment, inlined);
-        return Address.Placeholder;
-    }
-
-    public int lastSafepointPos() {
-        return lastSafepointPos;
+        compilationResult.recordDataReference(pos, data, alignment, inlined);
+        return asm.getPlaceholder();
     }
 
     /**
@@ -181,7 +156,7 @@
      * including long constants that fit into the 32-bit range.
      */
     public int asIntConst(Value value) {
-        assert (value.getKind().getStackKind() == Kind.Int || value.getKind() == Kind.Jsr || value.getKind() == Kind.Long) && isConstant(value);
+        assert (value.getKind().getStackKind() == Kind.Int || value.getKind() == Kind.Long) && isConstant(value);
         Constant constant = (Constant) value;
         assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch";
         long c = constant.asLong();
@@ -194,11 +169,11 @@
     /**
      * Returns the address of a float constant that is embedded as a data references into the code.
      */
-    public Address asFloatConstRef(Value value) {
+    public AbstractAddress asFloatConstRef(Value value) {
         return asFloatConstRef(value, 4);
     }
 
-    public Address asFloatConstRef(Value value, int alignment) {
+    public AbstractAddress asFloatConstRef(Value value, int alignment) {
         assert value.getKind() == Kind.Float && isConstant(value);
         return recordDataReferenceInCode((Constant) value, alignment, false);
     }
@@ -206,11 +181,11 @@
     /**
      * Returns the address of a double constant that is embedded as a data references into the code.
      */
-    public Address asDoubleConstRef(Value value) {
+    public AbstractAddress asDoubleConstRef(Value value) {
         return asDoubleConstRef(value, 8);
     }
 
-    public Address asDoubleConstRef(Value value, int alignment) {
+    public AbstractAddress asDoubleConstRef(Value value, int alignment) {
         assert value.getKind() == Kind.Double && isConstant(value);
         return recordDataReferenceInCode((Constant) value, alignment, false);
     }
@@ -218,41 +193,39 @@
     /**
      * Returns the address of a long constant that is embedded as a data references into the code.
      */
-    public Address asLongConstRef(Value value) {
+    public AbstractAddress asLongConstRef(Value value) {
         assert value.getKind() == Kind.Long && isConstant(value);
         return recordDataReferenceInCode((Constant) value, 8, false);
     }
 
-    public Address asIntAddr(Value value) {
+    public AbstractAddress asIntAddr(Value value) {
         assert value.getKind() == Kind.Int;
         return asAddress(value);
     }
 
-    public Address asLongAddr(Value value) {
+    public AbstractAddress asLongAddr(Value value) {
         assert value.getKind() == Kind.Long;
         return asAddress(value);
     }
 
-    public Address asObjectAddr(Value value) {
+    public AbstractAddress asObjectAddr(Value value) {
         assert value.getKind() == Kind.Object;
         return asAddress(value);
     }
 
-    public Address asFloatAddr(Value value) {
+    public AbstractAddress asFloatAddr(Value value) {
         assert value.getKind() == Kind.Float;
         return asAddress(value);
     }
 
-    public Address asDoubleAddr(Value value) {
+    public AbstractAddress asDoubleAddr(Value value) {
         assert value.getKind() == Kind.Double;
         return asAddress(value);
     }
 
-    public Address asAddress(Value value) {
-        if (isStackSlot(value)) {
-            StackSlot slot = (StackSlot) value;
-            return new Address(slot.getKind(), frameMap.registerConfig.getFrameRegister().asValue(), frameMap.offsetForStackSlot(slot));
-        }
-        return (Address) value;
+    public AbstractAddress asAddress(Value value) {
+        assert isStackSlot(value);
+        StackSlot slot = asStackSlot(value);
+        return asm.makeAddress(frameMap.registerConfig.getFrameRegister(), frameMap.offsetForStackSlot(slot));
     }
 }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Thu Mar 21 14:11:13 2013 +0100
@@ -179,7 +179,7 @@
                 });
             }
             nodes.mark(earlyExit);
-            for (ValueProxyNode proxy : earlyExit.proxies()) {
+            for (ProxyNode proxy : earlyExit.proxies()) {
                 nodes.mark(proxy);
             }
         }
@@ -271,9 +271,9 @@
                 anchored.replaceFirstInput(earlyExit, merge);
             }
 
-            for (final ValueProxyNode vpn : earlyExit.proxies().snapshot()) {
+            for (final ProxyNode vpn : earlyExit.proxies().snapshot()) {
                 final ValueNode replaceWith;
-                ValueProxyNode newVpn = getDuplicatedNode(vpn);
+                ProxyNode newVpn = getDuplicatedNode(vpn);
                 if (newVpn != null) {
                     PhiNode phi = graph.add(vpn.type() == PhiType.Value ? vpn.stamp() == StampFactory.virtual() ? new PhiNode(vpn.stamp(), merge) : new PhiNode(vpn.kind(), merge) : new PhiNode(
                                     vpn.type(), merge));
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Thu Mar 21 14:11:13 2013 +0100
@@ -60,7 +60,7 @@
         while (!loopBegin.isDeleted()) {
             int mark = graph.getMark();
             peel(loop);
-            new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph);
+            new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph);
             if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) {
                 throw new BailoutException("FullUnroll : Graph seems to grow out of proportion");
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,10 +32,10 @@
 
     private final Stamp returnStamp;
     private final JavaType[] signature;
-    private final Object target;
+    private final ResolvedJavaMethod target;
     private final CallingConvention.Type callType;
 
-    public AbstractCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) {
+    public AbstractCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType) {
         super(arguments);
         this.returnStamp = returnStamp;
         this.signature = signature;
@@ -52,7 +52,7 @@
         return signature;
     }
 
-    public Object target() {
+    public ResolvedJavaMethod target() {
         return target;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -108,7 +108,7 @@
     }
 
     public void removeProxies() {
-        for (ValueProxyNode vpn : proxies().snapshot()) {
+        for (ProxyNode vpn : proxies().snapshot()) {
             // can not use graph.replaceFloating because vpn.value may be null during killCFG
             vpn.replaceAtUsages(vpn.value());
             vpn.safeDelete();
@@ -131,11 +131,11 @@
     }
 
     public NodeIterable<Node> anchored() {
-        return usages().filter(isNotA(ValueProxyNode.class));
+        return usages().filter(isNotA(ProxyNode.class));
     }
 
-    public NodeIterable<ValueProxyNode> proxies() {
-        return usages().filter(ValueProxyNode.class);
+    public NodeIterable<ProxyNode> proxies() {
+        return usages().filter(ProxyNode.class);
     }
 
     public NodeIterable<FixedNode> getBlockNodes() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -165,17 +165,6 @@
     }
 
     /**
-     * Returns a node for an address (jsr/ret address) constant.
-     * 
-     * @param i the address value for which to create the instruction
-     * @param graph
-     * @return a node representing the address
-     */
-    public static ConstantNode forJsr(int i, Graph graph) {
-        return graph.unique(new ConstantNode(Constant.forJsr(i)));
-    }
-
-    /**
      * Returns a node for an object constant.
      * 
      * @param o the object value for which to create the instruction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.nodes.type.*;
+
+public abstract class ControlSinkNode extends FixedNode {
+
+    public ControlSinkNode(Stamp stamp) {
+        super(stamp);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,9 +29,8 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
-public class DeoptimizeNode extends FixedNode implements Node.IterableNodeType, LIRLowerable {
+public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, LIRLowerable {
 
-    private String message;
     private final DeoptimizationAction action;
     private final DeoptimizationReason reason;
 
@@ -41,14 +40,6 @@
         this.reason = reason;
     }
 
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-    public String message() {
-        return message;
-    }
-
     public DeoptimizationAction action() {
         return action;
     }
@@ -59,7 +50,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitDeoptimize(action, reason, message);
+        gen.emitDeoptimize(action, reason);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,18 +30,12 @@
 
 public class DirectCallTargetNode extends AbstractCallTargetNode {
 
-    public DirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) {
+    public DirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType) {
         super(arguments, returnStamp, signature, target, callType);
     }
 
     @Override
     public String targetName() {
-        if (target() instanceof JavaMethod) {
-            return "Direct#" + ((JavaMethod) target()).getName();
-        } else if (target() != null) {
-            return "Direct#" + target().getClass().getSimpleName();
-        } else {
-            return "Direct#null";
-        }
+        return "Direct#" + ((JavaMethod) target()).getName();
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}")
-public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, LIRLowerable, Node.IterableNodeType, Negatable {
+public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, Negatable {
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
@@ -79,11 +79,6 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.emitGuardCheck(condition, reason, action, negated);
-    }
-
-    @Override
     public void simplify(SimplifierTool tool) {
         if (condition instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.nodes.type.*;
 
 public abstract class FixedNode extends ValueNode {
@@ -32,6 +34,10 @@
         super(stamp);
     }
 
+    public FixedNode(Stamp stamp, List<ValueNode> dependencies) {
+        super(stamp, dependencies);
+    }
+
     public FixedNode(Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.nodes.type.*;
 
 /**
@@ -43,6 +45,10 @@
         super(stamp);
     }
 
+    public FixedWithNextNode(Stamp stamp, List<ValueNode> dependencies) {
+        super(stamp, dependencies);
+    }
+
     public FixedWithNextNode(Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Thu Mar 21 14:11:13 2013 +0100
@@ -68,6 +68,12 @@
      */
     public static final int AFTER_EXCEPTION_BCI = -3;
 
+    /**
+     * This BCI should be used for frame states that cannot be the target of a deoptimization, like
+     * snippet frame states.
+     */
+    public static final int INVALID_FRAMESTATE_BCI = -5;
+
     @Input private FrameState outerFrameState;
 
     @Input private final NodeInputList<ValueNode> values;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -42,7 +42,7 @@
  * control flow would have reached the guarded node (without taking exceptions into account).
  */
 @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}")
-public final class GuardNode extends FloatingNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType, Negatable {
+public final class GuardNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType, Negatable {
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
@@ -91,24 +91,13 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.emitGuardCheck(condition(), reason(), action(), negated());
-    }
-
-    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
             if (c.getValue() != negated) {
-                if (!dependencies().isEmpty()) {
-                    for (Node usage : usages()) {
-                        if (usage instanceof ValueNode) {
-                            ((ValueNode) usage).dependencies().addAll(dependencies());
-                        }
-                    }
+                if (dependencies().size() == 1) {
+                    return dependencies().get(0);
                 }
-                this.replaceAtUsages(null);
-                return null;
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -152,10 +152,8 @@
                 ((StructuredGraph) graph()).removeSplit(this, falseSuccessor());
             }
         } else if (trueSuccessor().guards().isEmpty() && falseSuccessor().guards().isEmpty()) {
-            if (removeOrMaterializeIf(tool)) {
-                return;
-            } else if (removeIntermediateMaterialization(tool)) {
-                return;
+            if (!removeOrMaterializeIf(tool)) {
+                removeIntermediateMaterialization(tool);
             }
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,7 +32,7 @@
 
     @Input protected ValueNode computedAddress;
 
-    public IndirectCallTargetNode(ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) {
+    public IndirectCallTargetNode(ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType) {
         super(arguments, returnStamp, signature, target, callType);
         this.computedAddress = computedAddress;
     }
@@ -43,12 +43,6 @@
 
     @Override
     public String targetName() {
-        if (target() instanceof JavaMethod) {
-            return "Indirect#" + ((JavaMethod) target()).getName();
-        } else if (target() != null) {
-            return "Indirect#" + target().getClass().getSimpleName();
-        } else {
-            return "Indirect#null";
-        }
+        return "Indirect#" + ((JavaMethod) target()).getName();
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -109,6 +109,11 @@
     }
 
     @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
+    @Override
     public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -161,6 +161,11 @@
         return true;
     }
 
+    @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
     public FrameState stateDuring() {
         FrameState tempStateAfter = stateAfter();
         FrameState stateDuring = tempStateAfter.duplicateModified(bci(), tempStateAfter.rethrowException(), kind());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -37,7 +37,8 @@
 
     public static enum PhiType {
         Value(null), // normal value phis
-        Guard(StampFactory.dependency()), Memory(StampFactory.dependency());
+        Guard(StampFactory.dependency()),
+        Memory(StampFactory.dependency());
 
         public final Stamp stamp;
 
@@ -199,6 +200,7 @@
     public ValueNode singleValue() {
         ValueNode differentValue = null;
         for (ValueNode n : values()) {
+            assert n != null : "Must have input value!";
             if (n != this) {
                 if (differentValue == null) {
                     differentValue = n;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ValueNumberable;
+import com.oracle.graal.nodes.PhiNode.PhiType;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * A value proxy that is inserted in the frame state of a loop exit for any value that is created
+ * inside the loop (i.e. was not live on entry to the loop) and is (potentially) used after the
+ * loop.
+ */
+@NodeInfo(nameTemplate = "{p#type/s}Proxy")
+public class ProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable {
+
+    @Input(notDataflow = true) private BeginNode proxyPoint;
+    @Input private ValueNode value;
+    private final PhiType type;
+
+    public ProxyNode(ValueNode value, BeginNode exit, PhiType type) {
+        super(type == PhiType.Value ? value.stamp() : type.stamp);
+        this.type = type;
+        assert exit != null;
+        this.proxyPoint = exit;
+        this.value = value;
+    }
+
+    public ValueNode value() {
+        return value;
+    }
+
+    @Override
+    public boolean inferStamp() {
+        return updateStamp(value.stamp());
+    }
+
+    @Override
+    public Stamp stamp() {
+        return value().stamp();
+    }
+
+    public BeginNode proxyPoint() {
+        return proxyPoint;
+    }
+
+    public PhiType type() {
+        return type;
+    }
+
+    @Override
+    public boolean verify() {
+        assert value != null;
+        assert proxyPoint != null;
+        return super.verify();
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+        assert type == PhiType.Memory;
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (type == PhiType.Value && value.isConstant()) {
+            return value;
+        }
+        return this;
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        if (type == PhiType.Value) {
+            State state = tool.getObjectState(value);
+            if (state != null && state.getState() == EscapeState.Virtual) {
+                tool.replaceWithVirtual(state.getVirtualObject());
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class ReturnNode extends FixedNode implements LIRLowerable, Node.IterableNodeType {
+public final class ReturnNode extends ControlSinkNode implements LIRLowerable, Node.IterableNodeType {
 
     @Input private ValueNode result;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,10 +29,14 @@
 /**
  * Marks a position in the graph where a safepoint should be emitted.
  */
-public final class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
+public class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
 
     public SafepointNode() {
-        super(StampFactory.forVoid());
+        this(StampFactory.forVoid());
+    }
+
+    public SafepointNode(Stamp stamp) {
+        super(stamp);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,4 +29,8 @@
  */
 public class StartNode extends BeginStateSplitNode implements MemoryCheckpoint {
 
+    @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
@@ -33,9 +31,7 @@
  * Unwind takes an exception object, destroys the current stack frame and passes the exception
  * object to the system's exception dispatch code.
  */
-public final class UnwindNode extends FixedNode implements LIRLowerable, Node.IterableNodeType {
-
-    public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", true, void.class, Object.class);
+public final class UnwindNode extends ControlSinkNode implements Lowerable, LIRLowerable, Node.IterableNodeType {
 
     @Input private ValueNode exception;
 
@@ -51,7 +47,11 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        RuntimeCallTarget call = gen.getRuntime().lookupRuntimeCall(UNWIND_EXCEPTION);
-        gen.emitCall(call, call.getCallingConvention(), false, gen.operand(exception()));
+        gen.emitUnwind(gen.operand(exception()));
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,7 +28,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.type.GenericStamp.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -174,9 +173,6 @@
 
     @Override
     public boolean verify() {
-        for (ValueNode v : dependencies().nonNull()) {
-            assertTrue(!(v.stamp() instanceof GenericStamp) || ((GenericStamp) v.stamp()).type() == GenericStampType.Dependency, "cannot depend on node with stamp %s", v.stamp());
-        }
         assertTrue(kind() != null, "Should have a valid kind");
         assertTrue(kind() == kind().getStackKind(), "Should have a stack kind : %s", kind());
         return super.verify();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java	Thu Mar 21 14:11:13 2013 +0100
@@ -31,7 +31,7 @@
 public class ValueNodeUtil {
 
     public static ValueNode assertKind(Kind kind, ValueNode x) {
-        assert x != null && ((x.kind() == kind) || (x.kind() == Kind.Jsr && kind == Kind.Object)) : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.kind());
+        assert x != null && x.kind() == kind : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.kind());
         return x;
     }
 
@@ -48,11 +48,6 @@
         return x;
     }
 
-    public static ValueNode assertJsr(ValueNode x) {
-        assert x != null && (x.kind() == Kind.Jsr);
-        return x;
-    }
-
     public static ValueNode assertInt(ValueNode x) {
         assert x != null && (x.kind() == Kind.Int);
         return x;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.ValueNumberable;
-import com.oracle.graal.nodes.PhiNode.PhiType;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * A value proxy that is inserted in the frame state of a loop exit for any value that is created
- * inside the loop (i.e. was not live on entry to the loop) and is (potentially) used after the
- * loop.
- */
-public class ValueProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable {
-
-    @Input(notDataflow = true) private BeginNode proxyPoint;
-    @Input private ValueNode value;
-    private final PhiType type;
-
-    public ValueProxyNode(ValueNode value, BeginNode exit, PhiType type) {
-        super(value.stamp());
-        this.type = type;
-        assert exit != null;
-        this.proxyPoint = exit;
-        this.value = value;
-    }
-
-    public ValueNode value() {
-        return value;
-    }
-
-    @Override
-    public boolean inferStamp() {
-        return updateStamp(value.stamp());
-    }
-
-    @Override
-    public Stamp stamp() {
-        return value().stamp();
-    }
-
-    public BeginNode proxyPoint() {
-        return proxyPoint;
-    }
-
-    public PhiType type() {
-        return type;
-    }
-
-    @Override
-    public boolean verify() {
-        assert value != null;
-        assert proxyPoint != null;
-        return super.verify();
-    }
-
-    @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
-        if (value.isConstant()) {
-            return value;
-        }
-        return this;
-    }
-
-    @Override
-    public void virtualize(VirtualizerTool tool) {
-        State state = tool.getObjectState(value);
-        if (state != null && state.getState() == EscapeState.Virtual) {
-            tool.replaceWithVirtual(state.getVirtualObject());
-        }
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java	Thu Mar 21 14:11:13 2013 +0100
@@ -342,7 +342,6 @@
             case Byte:
             case Char:
             case Short:
-            case Jsr:
             case Int: {
                 int x = lt.asInt();
                 int y = rt.asInt();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,12 +32,29 @@
 /**
  * The {@code ConvertNode} class represents a conversion between primitive types.
  */
-public final class ConvertNode extends FloatingNode implements Canonicalizable, LIRLowerable {
+public final class ConvertNode extends FloatingNode implements Canonicalizable, LIRLowerable, Lowerable {
 
     public enum Op {
-        I2L(Int, Long), L2I(Long, Int), I2B(Int, Byte), I2C(Int, Char), I2S(Int, Short), F2D(Float, Double), D2F(Double, Float), I2F(Int, Float), I2D(Int, Double), F2I(Float, Int), D2I(Double, Int), L2F(
-                        Long, Float), L2D(Long, Double), F2L(Float, Long), D2L(Double, Long), UNSIGNED_I2L(Int, Long), MOV_I2F(Int, Float), MOV_L2D(Long, Double), MOV_F2I(Float, Int), MOV_D2L(Double,
-                        Long);
+        I2L(Int, Long),
+        L2I(Long, Int),
+        I2B(Int, Byte),
+        I2C(Int, Char),
+        I2S(Int, Short),
+        F2D(Float, Double),
+        D2F(Double, Float),
+        I2F(Int, Float),
+        I2D(Int, Double),
+        F2I(Float, Int),
+        D2I(Double, Int),
+        L2F(Long, Float),
+        L2D(Long, Double),
+        F2L(Float, Long),
+        D2L(Double, Long),
+        UNSIGNED_I2L(Int, Long),
+        MOV_I2F(Int, Float),
+        MOV_L2D(Long, Double),
+        MOV_F2I(Float, Int),
+        MOV_D2L(Double, Long);
 
         public final Kind from;
         public final Kind to;
@@ -145,6 +162,11 @@
     }
 
     @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.setResult(this, gen.emitConvert(opcode, gen.operand(value())));
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Thu Mar 21 14:11:13 2013 +0100
@@ -47,6 +47,7 @@
 
     protected Block() {
         id = ControlFlowGraph.BLOCK_ID_INITIAL;
+        this.linearScanNumber = -1;
     }
 
     public int getId() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Thu Mar 21 14:11:13 2013 +0100
@@ -67,6 +67,7 @@
                     if (!(block.isLoopHeader() && block.getLoop() == loop)) {
                         for (Block pred : block.getPredecessors()) {
                             if (!loop.blocks.contains(pred)) {
+                                assert false : "Loop " + loop + " does not contain " + pred;
                                 return false;
                             }
                         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Thu Mar 21 14:11:13 2013 +0100
@@ -108,9 +108,38 @@
         return loops;
     }
 
+    public void clearNodeToBlock() {
+        nodeToBlock.clear();
+        for (Block block : reversePostOrder) {
+            identifyBlock(block, block.beginNode);
+        }
+    }
+
     protected static final int BLOCK_ID_INITIAL = -1;
     protected static final int BLOCK_ID_VISITED = -2;
 
+    private void identifyBlock(Block block, BeginNode begin) {
+        block.beginNode = begin;
+        Node cur = begin;
+        Node last;
+        do {
+            assert !cur.isDeleted();
+
+            assert nodeToBlock.get(cur) == null;
+            nodeToBlock.set(cur, block);
+            if (cur instanceof MergeNode) {
+                for (PhiNode phi : ((MergeNode) cur).phis()) {
+                    nodeToBlock.set(phi, block);
+                }
+            }
+
+            last = cur;
+            cur = cur.successors().first();
+        } while (cur != null && !(cur instanceof BeginNode));
+
+        block.endNode = (FixedNode) last;
+    }
+
     private void identifyBlocks() {
         // Find all block headers
         int numBlocks = 0;
@@ -118,26 +147,7 @@
             if (node instanceof BeginNode) {
                 Block block = new Block();
                 numBlocks++;
-
-                block.beginNode = (BeginNode) node;
-                Node cur = node;
-                Node last;
-                do {
-                    assert !cur.isDeleted();
-
-                    assert nodeToBlock.get(cur) == null;
-                    nodeToBlock.set(cur, block);
-                    if (cur instanceof MergeNode) {
-                        for (PhiNode phi : ((MergeNode) cur).phis()) {
-                            nodeToBlock.set(phi, block);
-                        }
-                    }
-
-                    last = cur;
-                    cur = cur.successors().first();
-                } while (cur != null && !(cur instanceof BeginNode));
-
-                block.endNode = (FixedNode) last;
+                identifyBlock(block, (BeginNode) node);
             }
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.debug;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * This node can be used to add a counter to the code that will estimate the dynamic number of calls
+ * by adding an increment to the compiled code. This should of course only be used for
+ * debugging/testing purposes, and is not 100% accurate (because of concurrency issues while
+ * accessing the counters).
+ * 
+ * A unique counter will be created for each unique String passed to the constructor.
+ */
+public class DynamicCounterNode extends FixedWithNextNode implements Lowerable {
+
+    private static final int MAX_COUNTERS = 10 * 1024;
+    private static final long[] COUNTERS = new long[MAX_COUNTERS];
+    private static final HashMap<String, Integer> INDEXES = new HashMap<>();
+    private final String name;
+    private final boolean addContext;
+
+    public DynamicCounterNode(String name, boolean addContext) {
+        super(StampFactory.forVoid());
+        this.name = name;
+        this.addContext = addContext;
+    }
+
+    private static synchronized int getIndex(String name) {
+        Integer index = INDEXES.get(name);
+        if (index == null) {
+            index = INDEXES.size();
+            if (index == 0) {
+                Runtime.getRuntime().addShutdownHook(new Thread() {
+
+                    @Override
+                    public void run() {
+                        dump();
+                    }
+                });
+            }
+            INDEXES.put(name, index);
+            if (index >= MAX_COUNTERS) {
+                throw new GraalInternalError("too many dynamic counters");
+            }
+            return index;
+        } else {
+            return index;
+        }
+    }
+
+    private static synchronized void dump() {
+        TreeMap<Long, String> sorted = new TreeMap<>();
+
+        long sum = 0;
+        for (int i = 0; i < MAX_COUNTERS; i++) {
+            sum += COUNTERS[i];
+        }
+        int cnt = 0;
+        for (Map.Entry<String, Integer> entry : INDEXES.entrySet()) {
+            sorted.put(COUNTERS[entry.getValue()] * MAX_COUNTERS + cnt++, entry.getKey());
+        }
+
+        for (Map.Entry<Long, String> entry : sorted.entrySet()) {
+            System.out.println((entry.getKey() / MAX_COUNTERS) + ": " + entry.getValue());
+        }
+        System.out.println(sum + ": total");
+
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        int index = addContext ? getIndex(name + " @ " + MetaUtil.format("%h.%n", ((StructuredGraph) graph()).method())) : getIndex(name);
+
+        StructuredGraph graph = (StructuredGraph) graph();
+        ConstantNode arrayConstant = ConstantNode.forObject(COUNTERS, tool.getRuntime(), graph);
+        ConstantNode indexConstant = ConstantNode.forInt(index, graph);
+        LoadIndexedNode load = graph.add(new LoadIndexedNode(arrayConstant, indexConstant, Kind.Long));
+        IntegerAddNode add = graph.add(new IntegerAddNode(Kind.Long, load, ConstantNode.forLong(1, graph)));
+        StoreIndexedNode store = graph.add(new StoreIndexedNode(arrayConstant, indexConstant, Kind.Long, add));
+
+        graph.addBeforeFixed(this, load);
+        graph.addBeforeFixed(this, store);
+        graph.removeFixed(this);
+    }
+
+    public static void createCounter(String name, FixedNode before, boolean addContext) {
+        StructuredGraph graph = (StructuredGraph) before.graph();
+        DynamicCounterNode counter = graph.add(new DynamicCounterNode(name, addContext));
+        graph.addBeforeFixed(before, counter);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,7 +29,7 @@
 
     ValueNode object();
 
-    LocationNode location();
+    LocationNode nullCheckLocation();
 
     void setNullCheck(boolean check);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,13 +22,16 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import java.util.*;
+
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * Accesses a value at an memory address specified by an {@linkplain #object object} and a
- * {@linkplain #location() location}. The access does not include a null check on the object.
+ * {@linkplain #nullCheckLocation() location}. The access does not include a null check on the
+ * object.
  */
 public abstract class AccessNode extends FixedWithNextNode implements Access {
 
@@ -44,6 +47,10 @@
         return (LocationNode) location;
     }
 
+    public LocationNode nullCheckLocation() {
+        return (LocationNode) location;
+    }
+
     public boolean getNullCheck() {
         return nullCheck;
     }
@@ -58,6 +65,12 @@
         this.location = location;
     }
 
+    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, List<ValueNode> dependencies) {
+        super(stamp, dependencies);
+        this.object = object;
+        this.location = location;
+    }
+
     public AccessNode(ValueNode object, ValueNode location, Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
         this.object = object;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -43,6 +43,10 @@
         return location;
     }
 
+    public LocationNode nullCheckLocation() {
+        return location;
+    }
+
     public boolean getNullCheck() {
         return nullCheck;
     }
@@ -73,4 +77,6 @@
     public Node node() {
         return this;
     }
+
+    public abstract Access asFixedNode();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -53,11 +53,16 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitLoad(gen.makeAddress(location(), object()), getNullCheck()));
+        gen.setResult(this, location().generateLoad(gen, object(), getNullCheck()));
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        return ReadNode.canonicalizeRead(this, tool);
+        return ReadNode.canonicalizeRead(this, location(), object(), tool);
+    }
+
+    @Override
+    public Access asFixedNode() {
+        return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), dependencies()));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/GenerateLEANode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/GenerateLEANode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -57,7 +57,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        Value addr = gen.emitLea(gen.makeAddress(location(), object()));
+        Value addr = location().generateLea(gen, object());
         gen.setResult(this, addr);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,17 +28,14 @@
 import com.oracle.graal.nodes.spi.*;
 
 /**
- * Extension of a {@linkplain LocationNode location} to include a scaled index or an additional
- * offset.
+ * Extension of a {@linkplain LocationNode location} to include a scaled index. Can represent
+ * locations in the form of [base + index * scale + disp] where base and index are nodes and scale
+ * and disp are integer constants.
  */
 public final class IndexedLocationNode extends LocationNode implements Canonicalizable {
 
-    /**
-     * An offset or index depending on whether {@link #indexScalingEnabled} is true or false
-     * respectively.
-     */
     @Input private ValueNode index;
-    private final boolean indexScalingEnabled;
+    private final int indexScaling;
 
     /**
      * Gets the index or offset of this location.
@@ -52,21 +49,20 @@
     }
 
     /**
-     * @return whether scaling of the index by the value kind's size is enabled (the default) or
-     *         disabled.
+     * @return Constant that is used to scale the index.
      */
-    public boolean indexScalingEnabled() {
-        return indexScalingEnabled;
+    public int indexScaling() {
+        return indexScaling;
     }
 
-    public static IndexedLocationNode create(Object identity, Kind kind, int displacement, ValueNode index, Graph graph, boolean indexScalingEnabled) {
-        return graph.unique(new IndexedLocationNode(identity, kind, index, displacement, indexScalingEnabled));
+    public static IndexedLocationNode create(Object identity, Kind kind, int displacement, ValueNode index, Graph graph, int indexScaling) {
+        return graph.unique(new IndexedLocationNode(identity, kind, index, displacement, indexScaling));
     }
 
-    private IndexedLocationNode(Object identity, Kind kind, ValueNode index, int displacement, boolean indexScalingEnabled) {
+    private IndexedLocationNode(Object identity, Kind kind, ValueNode index, int displacement, int indexScaling) {
         super(identity, kind, displacement);
         this.index = index;
-        this.indexScalingEnabled = indexScalingEnabled;
+        this.indexScaling = indexScaling;
     }
 
     @Override
@@ -74,12 +70,7 @@
         Constant constantIndex = index.asConstant();
         if (constantIndex != null) {
             long constantIndexLong = constantIndex.asLong();
-            if (indexScalingEnabled) {
-                if (tool.target() == null) {
-                    return this;
-                }
-                constantIndexLong *= tool.target().sizeInBytes(getValueKind());
-            }
+            constantIndexLong *= indexScaling;
             constantIndexLong += displacement();
             int constantIndexInt = (int) constantIndexLong;
             if (constantIndexLong == constantIndexInt) {
@@ -88,4 +79,19 @@
         }
         return this;
     }
+
+    @Override
+    public Value generateLea(LIRGeneratorTool gen, ValueNode base) {
+        return gen.emitLea(gen.operand(base), displacement(), gen.operand(index()), indexScaling());
+    }
+
+    @Override
+    public Value generateLoad(LIRGeneratorTool gen, ValueNode base, boolean canTrap) {
+        return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), canTrap);
+    }
+
+    @Override
+    public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, boolean canTrap) {
+        gen.emitStore(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), gen.operand(value), canTrap);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,13 +25,15 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
- * A location for a memory access in terms of the kind of value accessed and the displacement (in
- * bytes) from a base object or address.
+ * A location for a memory access in terms of the kind of value accessed and how to access it. The
+ * base version can represent addresses of the form [base + disp] where base is a node and disp is a
+ * constant.
  */
 @NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}")
 public class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable {
@@ -41,27 +43,37 @@
     private Object locationIdentity;
 
     /**
+     * Creates a new unique location identity for read and write operations.
+     * 
+     * @param name the name of the new location identity, for debugging purposes
+     * @return the new location identity
+     */
+    public static Object createLocation(final String name) {
+        return new Object() {
+
+            @Override
+            public String toString() {
+                return name;
+            }
+        };
+    }
+
+    /**
      * Denotes any location. A write to such a location kills all values in a memory map during an
      * analysis of memory accesses in a graph.
      */
-    public static final Object ANY_LOCATION = new Object() {
+    public static final Object ANY_LOCATION = createLocation("ANY_LOCATION");
 
-        @Override
-        public String toString() {
-            return "ANY_LOCATION";
-        }
-    };
+    /**
+     * Denotes an unknown location. A read from this location cannot be moved or coalesced with
+     * other reads because its interaction with other reads is not known.
+     */
+    public static final Object UNKNOWN_LOCATION = createLocation("UNKNOWN_LOCATION");
 
     /**
      * Denotes the location of a value that is guaranteed to be final.
      */
-    public static final Object FINAL_LOCATION = new Object() {
-
-        @Override
-        public String toString() {
-            return "FINAL_LOCATION";
-        }
-    };
+    public static final Object FINAL_LOCATION = createLocation("FINAL_LOCATION");
 
     public static Object getArrayLocation(Kind elementKind) {
         return elementKind;
@@ -95,4 +107,16 @@
     public void generate(LIRGeneratorTool generator) {
         // nothing to do...
     }
+
+    public Value generateLea(LIRGeneratorTool gen, ValueNode base) {
+        return gen.emitLea(gen.operand(base), displacement(), Value.ILLEGAL, 0);
+    }
+
+    public Value generateLoad(LIRGeneratorTool gen, ValueNode base, boolean canTrap) {
+        return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, canTrap);
+    }
+
+    public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, boolean canTrap) {
+        gen.emitStore(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, gen.operand(value), canTrap);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -43,6 +43,11 @@
     }
 
     @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
+    @Override
     public void generate(LIRGeneratorTool generator) {
         generator.emitMembar(barriers);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,6 +22,21 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.nodes.*;
+
+/**
+ * This interface marks is used for subclasses of {@link FixedNode} that kill a set of memory
+ * locations represented by location identities (i.e. change a value at one or more locations that
+ * belong to these location identities).
+ */
 public interface MemoryCheckpoint {
 
+    /**
+     * This method is used to determine which set of memory locations is killed by this node.
+     * Returning the special value {@link LocationNode#ANY_LOCATION} will kill all memory locations.
+     * 
+     * @return the identities of all locations killed by this node.
+     */
+    Object[] getLocationIdentities();
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.extended;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class NullCheckNode extends FixedWithNextNode implements LIRLowerable {
+
+    @Input public ValueNode object;
+
+    public NullCheckNode(ValueNode object) {
+        super(StampFactory.dependency());
+        this.object = object;
+    }
+
+    public ValueNode getObject() {
+        return object;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+        generator.emitNullCheck(object);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -37,6 +39,10 @@
         super(object, location, stamp);
     }
 
+    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, List<ValueNode> dependencies) {
+        super(object, location, stamp, dependencies);
+    }
+
     private ReadNode(ValueNode object, int displacement, Object locationIdentity, Kind kind) {
         super(object, object.graph().add(new LocationNode(locationIdentity, kind, displacement)), StampFactory.forKind(kind));
     }
@@ -51,40 +57,40 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitLoad(gen.makeAddress(location(), object()), getNullCheck()));
+        gen.setResult(this, location().generateLoad(gen, object(), getNullCheck()));
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        return canonicalizeRead(this, tool);
+        return canonicalizeRead(this, location(), object(), tool);
     }
 
-    public static ValueNode canonicalizeRead(Access read, CanonicalizerTool tool) {
+    public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool) {
         MetaAccessProvider runtime = tool.runtime();
-        if (runtime != null && read.object() != null && read.object().isConstant()) {
-            if (read.location().locationIdentity() == LocationNode.FINAL_LOCATION && read.location().getClass() == LocationNode.class) {
-                long displacement = read.location().displacement();
-                Kind kind = read.location().getValueKind();
-                if (read.object().kind() == Kind.Object) {
-                    Object base = read.object().asConstant().asObject();
+        if (runtime != null && object != null && object.isConstant()) {
+            if (location.locationIdentity() == LocationNode.FINAL_LOCATION && location.getClass() == LocationNode.class) {
+                long displacement = location.displacement();
+                Kind kind = location.getValueKind();
+                if (object.kind() == Kind.Object) {
+                    Object base = object.asConstant().asObject();
                     if (base != null) {
                         Constant constant = tool.runtime().readUnsafeConstant(kind, base, displacement);
                         if (constant != null) {
-                            return ConstantNode.forConstant(constant, runtime, read.node().graph());
+                            return ConstantNode.forConstant(constant, runtime, read.graph());
                         }
                     }
-                } else if (read.object().kind() == Kind.Long || read.object().kind().getStackKind() == Kind.Int) {
-                    long base = read.object().asConstant().asLong();
+                } else if (object.kind() == Kind.Long || object.kind().getStackKind() == Kind.Int) {
+                    long base = object.asConstant().asLong();
                     if (base != 0L) {
                         Constant constant = tool.runtime().readUnsafeConstant(kind, null, base + displacement);
                         if (constant != null) {
-                            return ConstantNode.forConstant(constant, runtime, read.node().graph());
+                            return ConstantNode.forConstant(constant, runtime, read.graph());
                         }
                     }
                 }
             }
         }
-        return (ValueNode) read;
+        return read;
     }
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -49,6 +49,11 @@
     }
 
     @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.visitRuntimeCall(this);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -53,6 +53,9 @@
         if (kind() != Kind.Object || object().kind() != Kind.Object) {
             return false;
         }
+        if (stamp() == StampFactory.forNodeIntrinsic()) {
+            return false;
+        }
         if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) {
             // a null value flowing into a nonNull UnsafeCastNode should be guarded by a type/isNull
             // guard, but the
@@ -93,7 +96,7 @@
         if (kind() != object.kind()) {
             assert generator.target().sizeInBytes(kind()) == generator.target().sizeInBytes(object.kind()) : "unsafe cast cannot be used to change the size of a value";
             Value result = generator.newVariable(kind());
-            generator.emitMove(generator.operand(object), result);
+            generator.emitMove(result, generator.operand(object));
             generator.setResult(this, result);
         } else {
             // The LIR only cares about the kind of an operand, not the actual type of an object. So
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -33,7 +33,7 @@
  * Store of a value at a location specified as an offset relative to an object. No null check is
  * performed before the store.
  */
-public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable {
+public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable, MemoryCheckpoint {
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
@@ -72,6 +72,11 @@
     }
 
     @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
+    @Override
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object());
         if (state != null && state.getState() == EscapeState.Virtual) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,7 +28,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -38,9 +37,16 @@
 public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType, Virtualizable {
 
     public ValueAnchorNode(ValueNode... values) {
+        this(false, values);
+    }
+
+    public ValueAnchorNode(boolean permanent, ValueNode... values) {
         super(StampFactory.dependency(), values);
+        this.permanent = permanent;
     }
 
+    private final boolean permanent;
+
     @Override
     public void generate(LIRGeneratorTool gen) {
         // Nothing to emit, since this node is used for structural purposes only.
@@ -54,6 +60,9 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
+        if (permanent) {
+            return this;
+        }
         if (this.predecessor() instanceof ValueAnchorNode) {
             ValueAnchorNode previousAnchor = (ValueAnchorNode) this.predecessor();
             if (previousAnchor.usages().isEmpty()) { // avoid creating cycles
@@ -64,7 +73,7 @@
                 return previousAnchor;
             }
         }
-        for (Node node : dependencies().nonNull().and(isNotA(BeginNode.class))) {
+        for (Node node : dependencies().nonNull().and(isNotA(FixedNode.class))) {
             if (node instanceof ConstantNode) {
                 continue;
             }
@@ -88,12 +97,8 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        // don't process this node if it is anchoring the return value
-        if (next() instanceof MonitorExitNode) {
-            MonitorExitNode monitorExit = (MonitorExitNode) next();
-            if (monitorExit.stateAfter() != null && monitorExit.stateAfter().bci == FrameState.AFTER_BCI && monitorExit.next() instanceof ReturnNode) {
-                return;
-            }
+        if (permanent) {
+            return;
         }
         for (ValueNode node : dependencies().nonNull().and(isNotA(BeginNode.class))) {
             State state = tool.getObjectState(node);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -37,6 +37,11 @@
     }
 
     @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
+    @Override
     public void generate(LIRGeneratorTool generator) {
         // nothing to do...
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,7 +29,7 @@
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}.
  */
-public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable {
+public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint {
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
@@ -59,9 +59,14 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitStore(gen.makeAddress(location(), object()), gen.operand(value()), getNullCheck());
+        location().generateStore(gen, object(), value(), getNullCheck());
     }
 
     @NodeIntrinsic
     public static native void writeMemory(Object object, Object value, Object location);
+
+    @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{location().locationIdentity()};
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -71,6 +71,11 @@
     }
 
     @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.visitCompareAndSwap(this);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,7 +32,7 @@
  * The {@code ExceptionObject} instruction represents the incoming exception object to an exception
  * handler.
  */
-public class ExceptionObjectNode extends AbstractStateSplit implements StateSplit, LIRLowerable, MemoryCheckpoint {
+public class ExceptionObjectNode extends AbstractStateSplit implements StateSplit, Lowerable, LIRLowerable, MemoryCheckpoint {
 
     /**
      * Constructs a new ExceptionObject instruction.
@@ -42,11 +42,21 @@
     }
 
     @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.visitExceptionObject(this);
     }
 
     @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @Override
     public boolean verify() {
         assertTrue(stateAfter() != null, "an exception handler needs a frame state");
         return super.verify();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -80,7 +80,7 @@
     @Override
     public boolean verify() {
         for (Node usage : usages()) {
-            assertTrue(usage instanceof IfNode || usage instanceof ConditionalNode, "unsupported usage: ", usage);
+            assertTrue(usage instanceof IfNode || usage instanceof ConditionalNode, "unsupported usage: %s", usage);
         }
         return super.verify();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -40,6 +40,11 @@
         super(object);
     }
 
+    @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
     public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -41,6 +41,11 @@
         super(object);
     }
 
+    @Override
+    public Object[] getLocationIdentities() {
+        return new Object[]{LocationNode.ANY_LOCATION};
+    }
+
     public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -95,12 +95,12 @@
     public void virtualize(VirtualizerTool tool) {
         if (instanceClass != null) {
             assert !instanceClass().isArray();
-            ResolvedJavaField[] fields = instanceClass().getInstanceFields(true);
+            VirtualInstanceNode virtualObject = new VirtualInstanceNode(instanceClass());
+            ResolvedJavaField[] fields = virtualObject.getFields();
             ValueNode[] state = new ValueNode[fields.length];
             for (int i = 0; i < state.length; i++) {
                 state[i] = ConstantNode.defaultForKind(fields[i].getType().getKind(), graph());
             }
-            VirtualObjectNode virtualObject = new VirtualInstanceNode(instanceClass(), fields);
             tool.createVirtualObject(virtualObject, state, 0);
             tool.replaceWithVirtual(virtualObject);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,7 +32,7 @@
  * This node is used to perform the finalizer registration at the end of the java.lang.Object
  * constructor.
  */
-public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable {
+public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable, Virtualizable {
 
     public static final Descriptor REGISTER_FINALIZER = new Descriptor("registerFinalizer", true, void.class, Object.class);
 
@@ -74,4 +74,12 @@
 
         return this;
     }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State state = tool.getObjectState(object);
+        if (state != null && !state.getVirtualObject().type().hasFinalizer()) {
+            tool.delete();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,8 +28,6 @@
 
 public interface CanonicalizerTool {
 
-    TargetDescription target();
-
     Assumptions assumptions();
 
     MetaAccessProvider runtime();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Mar 21 14:11:13 2013 +0100
@@ -45,35 +45,25 @@
      */
     public abstract boolean canInlineConstant(Constant c);
 
-    /**
-     * Checks whether the supplied constant can be used without loading it into a register for store
-     * operations, i.e., on the right hand side of a memory access.
-     * 
-     * @param c The constant to check.
-     * @return True if the constant can be used directly, false if the constant needs to be in a
-     *         register.
-     */
-    public abstract boolean canStoreConstant(Constant c);
-
     public abstract RegisterAttributes attributes(Register register);
 
     public abstract Value operand(ValueNode object);
 
-    public abstract Value newVariable(Kind kind);
+    public abstract AllocatableValue newVariable(Kind kind);
 
     public abstract Value setResult(ValueNode x, Value operand);
 
-    public abstract Address makeAddress(LocationNode location, ValueNode object);
-
     public abstract Value emitMove(Value input);
 
-    public abstract void emitMove(Value src, Value dst);
+    public abstract void emitMove(Value dst, Value src);
 
-    public abstract Value emitLoad(Value loadAddress, boolean canTrap);
+    public abstract Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap);
 
-    public abstract void emitStore(Value storeAddress, Value input, boolean canTrap);
+    public abstract void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, boolean canTrap);
 
-    public abstract Value emitLea(Value address);
+    public abstract Value emitLea(Value base, int displacement, Value index, int scale);
+
+    public abstract Value emitLea(StackSlot slot);
 
     public abstract Value emitNegate(Value input);
 
@@ -107,9 +97,9 @@
 
     public abstract void emitMembar(int barriers);
 
-    public abstract void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo);
+    public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason);
 
-    public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo);
+    public abstract void emitNullCheck(ValueNode v);
 
     public abstract Value emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args);
 
@@ -117,8 +107,6 @@
 
     public abstract void emitConditional(ConditionalNode i);
 
-    public abstract void emitGuardCheck(LogicNode comp, DeoptimizationReason deoptReason, DeoptimizationAction deoptAction, boolean negated);
-
     public abstract void emitSwitch(SwitchNode i);
 
     public abstract void emitInvoke(Invoke i);
@@ -142,4 +130,12 @@
     public abstract void visitSafepointNode(SafepointNode i);
 
     public abstract void visitBreakpointNode(BreakpointNode i);
+
+    public abstract void emitUnwind(Value operand);
+
+    /**
+     * Called just before register allocation is performed on the LIR owned by this generator.
+     */
+    public void beforeRegisterAllocation() {
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Thu Mar 21 14:11:13 2013 +0100
@@ -48,4 +48,9 @@
      * Gets the closest fixed node preceding the node currently being lowered.
      */
     FixedWithNextNode lastFixedNode();
+
+    /**
+     * Sets the closest fixed node preceding the next node to be lowered.
+     */
+    void setLastFixedNode(FixedWithNextNode n);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Thu Mar 21 14:11:13 2013 +0100
@@ -199,7 +199,6 @@
                 return 0xffffL;
             case Short:
                 return 0xffffL;
-            case Jsr:
             case Int:
                 return 0xffffffffL;
             case Long:
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Thu Mar 21 14:11:13 2013 +0100
@@ -57,8 +57,6 @@
         setCache(Kind.Float, new FloatStamp(Kind.Float));
         setCache(Kind.Double, new FloatStamp(Kind.Double));
 
-        setCache(Kind.Jsr, new IntegerStamp(Kind.Jsr));
-
         setCache(Kind.Object, objectStamp);
         setCache(Kind.Void, voidStamp);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Mar 21 14:11:13 2013 +0100
@@ -140,18 +140,18 @@
         ValueNode singleValue = phiNode.singleValue();
         if (singleValue != null) {
             Collection<PhiNode> phiUsages = phiNode.usages().filter(PhiNode.class).snapshot();
-            Collection<ValueProxyNode> proxyUsages = phiNode.usages().filter(ValueProxyNode.class).snapshot();
+            Collection<ProxyNode> proxyUsages = phiNode.usages().filter(ProxyNode.class).snapshot();
             ((StructuredGraph) phiNode.graph()).replaceFloating(phiNode, singleValue);
             for (PhiNode phi : phiUsages) {
                 checkRedundantPhi(phi);
             }
-            for (ValueProxyNode proxy : proxyUsages) {
+            for (ProxyNode proxy : proxyUsages) {
                 checkRedundantProxy(proxy);
             }
         }
     }
 
-    public static void checkRedundantProxy(ValueProxyNode vpn) {
+    public static void checkRedundantProxy(ProxyNode vpn) {
         BeginNode proxyPoint = vpn.proxyPoint();
         if (proxyPoint instanceof LoopExitNode) {
             LoopExitNode exit = (LoopExitNode) proxyPoint;
@@ -164,12 +164,12 @@
                 }
                 if (vpnValue == v2) {
                     Collection<PhiNode> phiUsages = vpn.usages().filter(PhiNode.class).snapshot();
-                    Collection<ValueProxyNode> proxyUsages = vpn.usages().filter(ValueProxyNode.class).snapshot();
+                    Collection<ProxyNode> proxyUsages = vpn.usages().filter(ProxyNode.class).snapshot();
                     ((StructuredGraph) vpn.graph()).replaceFloating(vpn, vpnValue);
                     for (PhiNode phi : phiUsages) {
                         checkRedundantPhi(phi);
                     }
-                    for (ValueProxyNode proxy : proxyUsages) {
+                    for (ProxyNode proxy : proxyUsages) {
                         checkRedundantProxy(proxy);
                     }
                     return;
@@ -185,7 +185,7 @@
             GraphUtil.checkRedundantPhi(phi);
         }
         for (LoopExitNode exit : begin.loopExits()) {
-            for (ValueProxyNode vpn : exit.proxies().snapshot()) {
+            for (ProxyNode vpn : exit.proxies().snapshot()) {
                 GraphUtil.checkRedundantProxy(vpn);
             }
         }
@@ -259,8 +259,8 @@
 
     public static ValueNode unProxify(ValueNode proxy) {
         ValueNode v = proxy;
-        while (v instanceof ValueProxyNode) {
-            v = ((ValueProxyNode) v).value();
+        while (v instanceof ProxyNode) {
+            v = ((ProxyNode) v).value();
         }
         return v;
     }
@@ -293,8 +293,8 @@
     public static ValueNode originalValue(ValueNode proxy) {
         ValueNode v = proxy;
         do {
-            if (v instanceof ValueProxyNode) {
-                v = ((ValueProxyNode) v).value();
+            if (v instanceof ProxyNode) {
+                v = ((ProxyNode) v).value();
             } else if (v instanceof PhiNode) {
                 v = ((PhiNode) v).singleValue();
             } else {
@@ -308,8 +308,8 @@
             NodeWorkList worklist = proxy.graph().createNodeWorkList();
             worklist.add(proxy);
             for (Node node : worklist) {
-                if (node instanceof ValueProxyNode) {
-                    worklist.add(((ValueProxyNode) node).value());
+                if (node instanceof ProxyNode) {
+                    worklist.add(((ProxyNode) node).value());
                 } else if (node instanceof PhiNode) {
                     worklist.addAll(((PhiNode) node).values());
                 } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.nodes.virtual;
 
-import java.util.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 
@@ -32,21 +30,10 @@
 
     private final ResolvedJavaType type;
     private final ResolvedJavaField[] fields;
-    private final HashMap<ResolvedJavaField, Integer> fieldMap;
 
-    public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
+    public VirtualInstanceNode(ResolvedJavaType type) {
         this.type = type;
-        this.fields = fields;
-        fieldMap = new HashMap<>();
-        for (int i = 0; i < fields.length; i++) {
-            fieldMap.put(fields[i], i);
-        }
-    }
-
-    private VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, HashMap<ResolvedJavaField, Integer> fieldMap) {
-        this.type = type;
-        this.fields = fields;
-        this.fieldMap = fieldMap;
+        this.fields = type.getInstanceFields(true);
     }
 
     @Override
@@ -63,6 +50,10 @@
         return fields[index];
     }
 
+    public ResolvedJavaField[] getFields() {
+        return fields;
+    }
+
     @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name) {
@@ -78,8 +69,13 @@
     }
 
     public int fieldIndex(ResolvedJavaField field) {
-        Integer index = fieldMap.get(field);
-        return index == null ? -1 : index;
+        // on average fields.length == ~6, so a linear search is fast enough
+        for (int i = 0; i < fields.length; i++) {
+            if (fields[i] == field) {
+                return i;
+            }
+        }
+        return -1;
     }
 
     @Override
@@ -95,6 +91,6 @@
 
     @Override
     public VirtualInstanceNode duplicate() {
-        return new VirtualInstanceNode(type, fields, fieldMap);
+        return new VirtualInstanceNode(type);
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -48,7 +48,6 @@
     public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
 
     private final int newNodesMark;
-    private final TargetDescription target;
     private final Assumptions assumptions;
     private final MetaAccessProvider runtime;
     private final CustomCanonicalizer customCanonicalizer;
@@ -63,33 +62,31 @@
         ValueNode canonicalize(Node node);
     }
 
-    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
-        this(target, runtime, assumptions, null, 0, null);
+    public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions) {
+        this(runtime, assumptions, null, 0, null);
     }
 
     /**
-     * @param target
      * @param runtime
      * @param assumptions
      * @param workingSet the initial working set of nodes on which the canonicalizer works, should
      *            be an auto-grow node bitmap
      * @param customCanonicalizer
      */
-    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
-        this(target, runtime, assumptions, workingSet, 0, customCanonicalizer);
+    public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
+        this(runtime, assumptions, workingSet, 0, customCanonicalizer);
     }
 
     /**
      * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by this
      *            mark are processed otherwise all nodes in the graph are processed
      */
-    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
-        this(target, runtime, assumptions, null, newNodesMark, customCanonicalizer);
+    public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+        this(runtime, assumptions, null, newNodesMark, customCanonicalizer);
     }
 
-    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+    public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
         this.newNodesMark = newNodesMark;
-        this.target = target;
         this.assumptions = assumptions;
         this.runtime = runtime;
         this.customCanonicalizer = customCanonicalizer;
@@ -108,7 +105,7 @@
         if (newNodesMark > 0) {
             workList.addAll(graph.getNewNodes(newNodesMark));
         }
-        tool = new Tool(workList, runtime, target, assumptions);
+        tool = new Tool(workList, runtime, assumptions);
         processWorkSet(graph);
     }
 
@@ -309,13 +306,11 @@
 
         private final NodeWorkList nodeWorkSet;
         private final MetaAccessProvider runtime;
-        private final TargetDescription target;
         private final Assumptions assumptions;
 
-        public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, TargetDescription target, Assumptions assumptions) {
+        public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) {
             this.nodeWorkSet = nodeWorkSet;
             this.runtime = runtime;
-            this.target = target;
             this.assumptions = assumptions;
         }
 
@@ -326,15 +321,6 @@
         }
 
         /**
-         * @return the current target or {@code null} if no target is available in the current
-         *         context.
-         */
-        @Override
-        public TargetDescription target() {
-            return target;
-        }
-
-        /**
          * @return an object that can be used for recording assumptions or {@code null} if
          *         assumptions are not allowed in the current context.
          */
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -299,8 +299,18 @@
 
         public ConditionalElimination(FixedNode start, State initialState) {
             super(start, initialState);
-            this.trueConstant = LogicConstantNode.tautology(graph);
-            this.falseConstant = LogicConstantNode.contradiction(graph);
+            trueConstant = LogicConstantNode.tautology(graph);
+            falseConstant = LogicConstantNode.contradiction(graph);
+        }
+
+        @Override
+        public void finished() {
+            if (trueConstant.usages().isEmpty()) {
+                graph.removeFloating(trueConstant);
+            }
+            if (falseConstant.usages().isEmpty()) {
+                graph.removeFloating(falseConstant);
+            }
         }
 
         private void registerCondition(boolean isTrue, LogicNode condition, ValueNode anchor) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -51,6 +51,7 @@
         }
 
         for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.class)) {
+            assert d.isAlive();
             visitDeoptBegin(findBeginNode(d), d, graph);
         }
 
@@ -61,45 +62,53 @@
         if (deoptBegin instanceof MergeNode) {
             MergeNode mergeNode = (MergeNode) deoptBegin;
             Debug.log("Visiting %s followed by %s", mergeNode, deopt);
-            List<EndNode> ends = mergeNode.forwardEnds().snapshot();
-            for (EndNode end : ends) {
-                if (!end.isDeleted()) {
-                    BeginNode beginNode = findBeginNode(end);
-                    if (!(beginNode instanceof MergeNode)) {
-                        visitDeoptBegin(beginNode, deopt, graph);
-                    }
-                }
+            List<BeginNode> begins = new ArrayList<>();
+            for (EndNode end : mergeNode.forwardEnds()) {
+                BeginNode newBeginNode = findBeginNode(end);
+                assert !begins.contains(newBeginNode);
+                begins.add(newBeginNode);
             }
-            if (mergeNode.isDeleted()) {
-                if (!deopt.isDeleted()) {
-                    Debug.log("Merge deleted, deopt moved to %s", findBeginNode(deopt));
-                    visitDeoptBegin(findBeginNode(deopt), deopt, graph);
-                }
+            for (BeginNode begin : begins) {
+                assert !begin.isDeleted();
+                visitDeoptBegin(begin, deopt, graph);
             }
+            assert mergeNode.isDeleted();
+            return;
         } else if (deoptBegin.predecessor() instanceof IfNode) {
             IfNode ifNode = (IfNode) deoptBegin.predecessor();
             BeginNode otherBegin = ifNode.trueSuccessor();
             LogicNode conditionNode = ifNode.condition();
-            if (conditionNode instanceof InstanceOfNode) {
+            if (!(conditionNode instanceof InstanceOfNode) && !(conditionNode instanceof InstanceOfDynamicNode)) {
                 // TODO The lowering currently does not support a FixedGuard as the usage of an
                 // InstanceOfNode. Relax this restriction.
+                FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason(), deopt.action(), deoptBegin == ifNode.trueSuccessor()));
+                FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
+                if (deoptBegin == ifNode.trueSuccessor()) {
+                    graph.removeSplitPropagate(ifNode, ifNode.falseSuccessor());
+                } else {
+                    graph.removeSplitPropagate(ifNode, ifNode.trueSuccessor());
+                }
+                Debug.log("Converting %s on %-5s branch of %s to guard for remaining branch %s.", deopt, deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin);
+                FixedNode next = pred.next();
+                pred.setNext(guard);
+                guard.setNext(next);
                 return;
             }
-            boolean negated = false;
-            if (deoptBegin == ifNode.trueSuccessor()) {
-                negated = true;
-                otherBegin = ifNode.falseSuccessor();
-            }
-            BeginNode ifBlockBegin = findBeginNode(ifNode);
-            Debug.log("Converting %s on %-5s branch of %s to guard for remaining branch %s. IfBegin=%s", deopt, deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin,
-                            ifBlockBegin);
-            FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason(), deopt.action(), negated));
-            otherBegin.replaceAtUsages(ifBlockBegin);
-            FixedNode next = otherBegin.next();
-            otherBegin.setNext(null);
-            guard.setNext(next);
-            ifNode.replaceAtPredecessor(guard);
-            GraphUtil.killCFG(ifNode);
+        }
+
+        // We could not convert the control split - at least cut off control flow after the split.
+        FixedWithNextNode deoptPred = deoptBegin;
+        FixedNode next = deoptPred.next();
+        if (next instanceof ExceptionObjectNode) {
+            deoptPred = (FixedWithNextNode) next;
+            next = deoptPred.next();
+        }
+
+        if (next != deopt) {
+            DeoptimizeNode newDeoptNode = (DeoptimizeNode) deopt.clone(graph);
+            deoptPred.setNext(newDeoptNode);
+            assert deoptPred == newDeoptNode.predecessor();
+            GraphUtil.killCFG(next);
         }
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertUnreachedToGuardPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.*;
-
-public class ConvertUnreachedToGuardPhase extends Phase {
-
-    private OptimisticOptimizations opt;
-
-    public ConvertUnreachedToGuardPhase(OptimisticOptimizations opt) {
-        this.opt = opt;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        if (!opt.removeNeverExecutedCode()) {
-            return;
-        }
-        for (Node node : graph.getNodes()) {
-            if (node instanceof IfNode) {
-                IfNode ifNode = (IfNode) node;
-                BeginNode insertGuard = null;
-                BeginNode delete = null;
-                boolean inverted = false;
-                if (ifNode.probability(ifNode.trueSuccessor()) == 0) {
-                    insertGuard = ifNode.falseSuccessor();
-                    delete = ifNode.trueSuccessor();
-                    inverted = true;
-                } else if (ifNode.probability(ifNode.falseSuccessor()) == 0) {
-                    insertGuard = ifNode.trueSuccessor();
-                    delete = ifNode.falseSuccessor();
-                }
-                if (insertGuard != null) {
-                    GuardNode guard = graph.unique(new GuardNode(ifNode.condition(), BeginNode.prevBegin(ifNode), DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile,
-                                    inverted));
-                    graph.addBeforeFixed(ifNode, graph.add(new ValueAnchorNode(guard)));
-                    GraphUtil.killCFG(delete);
-                    graph.removeSplit(ifNode, inverted ? ifNode.falseSuccessor() : ifNode.trueSuccessor());
-                }
-            }
-        }
-
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -37,11 +37,14 @@
 public class CullFrameStatesPhase extends Phase {
 
     private static final DebugMetric metricFrameStatesCulled = Debug.metric("FrameStatesCulled");
+    private static final DebugMetric metricNodesRemoved = Debug.metric("NodesRemoved");
     private static final DebugMetric metricMergesTraversed = Debug.metric("MergesTraversed");
 
     @Override
     protected void run(StructuredGraph graph) {
+        int initialNodes = graph.getNodeCount();
         new CullFrameStates(graph.start(), new State(null)).apply();
+        metricNodesRemoved.add(initialNodes - graph.getNodeCount());
     }
 
     public static class State implements MergeableState<State> {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,271 +29,236 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.graph.ReentrantNodeIterator.LoopInfo;
+import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
 
 public class FloatingReadPhase extends Phase {
 
-    private IdentityHashMap<LoopBeginNode, List<MemoryMap>> loopEndStatesMap;
-
-    private static class LoopState {
-
-        public LoopBeginNode loopBegin;
-        public MemoryMap state;
-        public IdentityHashMap<PhiNode, Object> loopPhiLocations = new IdentityHashMap<>();
-        public ValueNode loopEntryAnyLocation;
-
-        public LoopState(LoopBeginNode loopBegin, MemoryMap state, ValueNode loopEntryAnyLocation) {
-            this.loopBegin = loopBegin;
-            this.state = state;
-            this.loopEntryAnyLocation = loopEntryAnyLocation;
-        }
-
-        @Override
-        public String toString() {
-            return "State@" + loopBegin;
-        }
-    }
-
-    private class MemoryMap implements MergeableState<MemoryMap> {
+    private static class MemoryMap {
 
         private IdentityHashMap<Object, ValueNode> lastMemorySnapshot;
-        private LinkedList<LoopState> loops;
 
         public MemoryMap(MemoryMap memoryMap) {
             lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot);
-            loops = new LinkedList<>(memoryMap.loops);
+        }
+
+        public MemoryMap(StartNode start) {
+            this();
+            lastMemorySnapshot.put(LocationNode.ANY_LOCATION, start);
         }
 
         public MemoryMap() {
             lastMemorySnapshot = new IdentityHashMap<>();
-            loops = new LinkedList<>();
+        }
+
+        private ValueNode getLastLocationAccess(Object locationIdentity) {
+            ValueNode lastLocationAccess;
+            if (locationIdentity == LocationNode.FINAL_LOCATION) {
+                return null;
+            } else {
+                lastLocationAccess = lastMemorySnapshot.get(locationIdentity);
+                if (lastLocationAccess == null) {
+                    lastLocationAccess = lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
+                    assert lastLocationAccess != null;
+                }
+                return lastLocationAccess;
+            }
         }
 
         @Override
         public String toString() {
-            return "Map=" + lastMemorySnapshot.toString() + " Loops=" + loops.toString();
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public boolean merge(MergeNode merge, List<MemoryMap> withStates) {
-            if (withStates.size() == 0) {
-                return true;
-            }
-
-            int minLoops = loops.size();
-            for (MemoryMap other : withStates) {
-                int otherLoops = other.loops.size();
-                if (otherLoops < minLoops) {
-                    minLoops = otherLoops;
-                }
-            }
-            while (loops.size() > minLoops) {
-                loops.pop();
-            }
-            for (MemoryMap other : withStates) {
-                while (other.loops.size() > minLoops) {
-                    other.loops.pop();
-                }
-            }
-
-            Set<Object> keys = new HashSet<>();
-            for (Object key : lastMemorySnapshot.keySet()) {
-                keys.add(key);
-            }
-            for (MemoryMap other : withStates) {
-                assert other.loops.size() == loops.size();
-                assert other.loops.size() < 1 || other.loops.peek().loopBegin == loops.peek().loopBegin;
-                for (Object key : other.lastMemorySnapshot.keySet()) {
-                    keys.add(key);
-                }
-            }
-            IdentityHashMap<Object, ValueNode> newMemorySnapshot = (IdentityHashMap<Object, ValueNode>) lastMemorySnapshot.clone();
-
-            for (Object key : keys) {
-                ValueNode merged = lastMemorySnapshot.get(key);
-                if (merged == null) {
-                    merged = lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
-                }
-                int mergedStatesCount = 1;
-                boolean isPhi = false;
-                for (MemoryMap other : withStates) {
-                    ValueNode otherValue = other.lastMemorySnapshot.get(key);
-                    if (otherValue == null) {
-                        otherValue = other.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
-                    }
-                    if (isPhi) {
-                        ((PhiNode) merged).addInput(otherValue);
-                    } else if (merged != otherValue) {
-                        PhiNode phi = merge.graph().add(new PhiNode(PhiType.Memory, merge));
-                        for (int j = 0; j < mergedStatesCount; j++) {
-                            phi.addInput(merged);
-                        }
-                        phi.addInput(otherValue);
-                        merged = phi;
-                        isPhi = true;
-                        newMemorySnapshot.put(key, phi);
-                    }
-                    mergedStatesCount++;
-                }
-            }
-
-            lastMemorySnapshot = newMemorySnapshot;
-            return true;
-        }
-
-        @Override
-        public void loopBegin(LoopBeginNode loopBegin) {
-            LoopState loopState = new LoopState(loopBegin, this, lastMemorySnapshot.get(LocationNode.ANY_LOCATION));
-            for (Map.Entry<Object, ValueNode> entry : lastMemorySnapshot.entrySet()) {
-                PhiNode phi = loopBegin.graph().add(new PhiNode(PhiType.Memory, loopBegin));
-                phi.addInput(entry.getValue());
-                entry.setValue(phi);
-                loopState.loopPhiLocations.put(phi, entry.getKey());
-            }
-            loops.push(loopState);
-        }
-
-        @Override
-        public void loopEnds(LoopBeginNode loopBegin, List<MemoryMap> loopEndStates) {
-            loopEndStatesMap.put(loopBegin, loopEndStates);
-            tryFinishLoopPhis(this, loopBegin);
-        }
-
-        @Override
-        public void afterSplit(BeginNode node) {
-            // nothing
-        }
-
-        @Override
-        public MemoryMap clone() {
-            return new MemoryMap(this);
+            return "Map=" + lastMemorySnapshot.toString();
         }
     }
 
+    private final Map<LoopBeginNode, Set<Object>> modifiedInLoops = new IdentityHashMap<>();
+
     @Override
     protected void run(StructuredGraph graph) {
-        loopEndStatesMap = new IdentityHashMap<>();
-        new PostOrderNodeIterator<MemoryMap>(graph.start(), new MemoryMap()) {
-
-            @Override
-            protected void node(FixedNode node) {
-                processNode(node, state);
-            }
-        }.apply();
-    }
-
-    private void processNode(FixedNode node, MemoryMap state) {
-        if (node instanceof ReadNode) {
-            processRead((ReadNode) node, state);
-        } else if (node instanceof WriteNode) {
-            processWrite((WriteNode) node, state);
-        } else if (node instanceof MemoryCheckpoint) {
-            processCheckpoint((MemoryCheckpoint) node, state);
-        } else if (node instanceof LoopExitNode) {
-            processLoopExit((LoopExitNode) node, state);
-        }
-    }
-
-    private static void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) {
-        processAnyLocationWrite((ValueNode) checkpoint, state);
-    }
-
-    private static void processWrite(WriteNode writeNode, MemoryMap state) {
-        if (writeNode.location().locationIdentity() == LocationNode.ANY_LOCATION) {
-            processAnyLocationWrite(writeNode, state);
-        }
-        state.lastMemorySnapshot.put(writeNode.location().locationIdentity(), writeNode);
-    }
-
-    private static void processAnyLocationWrite(ValueNode modifiying, MemoryMap state) {
-        for (Map.Entry<Object, ValueNode> entry : state.lastMemorySnapshot.entrySet()) {
-            entry.setValue(modifiying);
-        }
-        state.lastMemorySnapshot.put(LocationNode.ANY_LOCATION, modifiying);
-        state.loops.clear();
+        ReentrantNodeIterator.apply(new CollectMemoryCheckpointsClosure(), graph.start(), new HashSet<>(), null);
+        ReentrantNodeIterator.apply(new FloatingReadClosure(), graph.start(), new MemoryMap(graph.start()), null);
     }
 
-    private void processRead(ReadNode readNode, MemoryMap state) {
-        StructuredGraph graph = (StructuredGraph) readNode.graph();
-        assert readNode.getNullCheck() == false;
-        Object locationIdentity = readNode.location().locationIdentity();
-        ValueNode lastLocationAccess = getLastLocationAccessForRead(state, locationIdentity);
-        FloatingReadNode floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), lastLocationAccess, readNode.stamp(), readNode.dependencies()));
-        floatingRead.setNullCheck(readNode.getNullCheck());
-        ValueAnchorNode anchor = null;
-        for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) {
-            if (anchor == null) {
-                anchor = graph.add(new ValueAnchorNode());
-            }
-            anchor.addAnchoredNode(guard);
-        }
-        if (anchor != null) {
-            graph.addAfterFixed(readNode, anchor);
-        }
-        graph.replaceFixedWithFloating(readNode, floatingRead);
-    }
+    private class CollectMemoryCheckpointsClosure extends NodeIteratorClosure<Set<Object>> {
 
-    private ValueNode getLastLocationAccessForRead(MemoryMap state, Object locationIdentity) {
-        ValueNode lastLocationAccess;
-        if (locationIdentity == LocationNode.FINAL_LOCATION) {
-            lastLocationAccess = null;
-        } else {
-            lastLocationAccess = state.lastMemorySnapshot.get(locationIdentity);
-            if (lastLocationAccess == null) {
-                LoopState lastLoop = state.loops.peek();
-                if (lastLoop == null) {
-                    lastLocationAccess = state.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
-                } else {
-                    ValueNode phiInit;
-                    if (state.loops.size() > 1) {
-                        phiInit = getLastLocationAccessForRead(state.loops.get(1).state, locationIdentity);
-                    } else {
-                        phiInit = lastLoop.loopEntryAnyLocation;
-                    }
-                    PhiNode phi = lastLoop.loopBegin.graph().add(new PhiNode(PhiType.Memory, lastLoop.loopBegin));
-                    phi.addInput(phiInit);
-                    lastLoop.state.lastMemorySnapshot.put(locationIdentity, phi);
-                    lastLoop.loopPhiLocations.put(phi, locationIdentity);
-                    tryFinishLoopPhis(lastLoop.state, lastLoop.loopBegin);
-                    lastLocationAccess = phi;
-                }
-                state.lastMemorySnapshot.put(locationIdentity, lastLocationAccess);
-            }
-        }
-        return lastLocationAccess;
-    }
-
-    private static void processLoopExit(LoopExitNode exit, MemoryMap state) {
-        for (Map.Entry<Object, ValueNode> entry : state.lastMemorySnapshot.entrySet()) {
-            entry.setValue(exit.graph().unique(new ValueProxyNode(entry.getValue(), exit, PhiType.Memory)));
-        }
-        if (!state.loops.isEmpty()) {
-            state.loops.pop();
-        }
-    }
-
-    private void tryFinishLoopPhis(MemoryMap loopMemory, LoopBeginNode loopBegin) {
-        List<MemoryMap> loopEndStates = loopEndStatesMap.get(loopBegin);
-        if (loopEndStates == null) {
-            return;
-        }
-        LoopState loopState = loopMemory.loops.get(0);
-        int i = 0;
-        while (loopState.loopBegin != loopBegin) {
-            loopState = loopMemory.loops.get(++i);
-        }
-        for (PhiNode phi : loopBegin.phis()) {
-            if (phi.type() == PhiType.Memory && phi.valueCount() == 1) {
-                Object location = loopState.loopPhiLocations.get(phi);
-                assert location != null : "unknown location for " + phi;
-                for (MemoryMap endState : loopEndStates) {
-                    ValueNode otherNode = endState.lastMemorySnapshot.get(location);
-                    if (otherNode == null) {
-                        otherNode = endState.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
-                    }
-                    phi.addInput(otherNode);
+        @Override
+        protected void processNode(FixedNode node, Set<Object> currentState) {
+            if (node instanceof MemoryCheckpoint) {
+                for (Object identity : ((MemoryCheckpoint) node).getLocationIdentities()) {
+                    currentState.add(identity);
                 }
             }
         }
+
+        @Override
+        protected Set<Object> merge(MergeNode merge, List<Set<Object>> states) {
+            Set<Object> result = new HashSet<>();
+            for (Set<Object> other : states) {
+                result.addAll(other);
+            }
+            return result;
+        }
+
+        @Override
+        protected Set<Object> afterSplit(BeginNode node, Set<Object> oldState) {
+            return new HashSet<>(oldState);
+        }
+
+        @Override
+        protected Map<LoopExitNode, Set<Object>> processLoop(LoopBeginNode loop, Set<Object> initialState) {
+            LoopInfo<Set<Object>> loopInfo = ReentrantNodeIterator.processLoop(this, loop, new HashSet<>());
+            Set<Object> modifiedLocations = new HashSet<>();
+            for (Set<Object> end : loopInfo.endStates.values()) {
+                modifiedLocations.addAll(end);
+            }
+            for (Set<Object> exit : loopInfo.exitStates.values()) {
+                exit.addAll(modifiedLocations);
+                exit.addAll(initialState);
+            }
+            assert !modifiedLocations.contains(LocationNode.FINAL_LOCATION);
+            modifiedInLoops.put(loop, modifiedLocations);
+            return loopInfo.exitStates;
+        }
+
+    }
+
+    private class FloatingReadClosure extends NodeIteratorClosure<MemoryMap> {
+
+        @Override
+        protected void processNode(FixedNode node, MemoryMap state) {
+            if (node instanceof ReadNode) {
+                processRead((ReadNode) node, state);
+            } else if (node instanceof MemoryCheckpoint) {
+                processCheckpoint((MemoryCheckpoint) node, state);
+            }
+        }
+
+        private void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) {
+            for (Object identity : checkpoint.getLocationIdentities()) {
+                if (identity == LocationNode.ANY_LOCATION) {
+                    state.lastMemorySnapshot.clear();
+                }
+                state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint);
+            }
+        }
+
+        private void processRead(ReadNode readNode, MemoryMap state) {
+            StructuredGraph graph = (StructuredGraph) readNode.graph();
+            assert readNode.getNullCheck() == false;
+            Object locationIdentity = readNode.location().locationIdentity();
+            if (locationIdentity != LocationNode.UNKNOWN_LOCATION) {
+                ValueNode lastLocationAccess = state.getLastLocationAccess(locationIdentity);
+                FloatingReadNode floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), lastLocationAccess, readNode.stamp(), readNode.dependencies()));
+                floatingRead.setNullCheck(readNode.getNullCheck());
+                ValueAnchorNode anchor = null;
+                for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) {
+                    if (anchor == null) {
+                        anchor = graph.add(new ValueAnchorNode());
+                        graph.addAfterFixed(readNode, anchor);
+                    }
+                    anchor.addAnchoredNode(guard);
+                }
+                graph.replaceFixedWithFloating(readNode, floatingRead);
+            }
+        }
+
+        @Override
+        protected MemoryMap merge(MergeNode merge, List<MemoryMap> states) {
+            MemoryMap newState = new MemoryMap();
+
+            Set<Object> keys = new HashSet<>();
+            for (MemoryMap other : states) {
+                keys.addAll(other.lastMemorySnapshot.keySet());
+            }
+            assert !keys.contains(LocationNode.FINAL_LOCATION);
+
+            for (Object key : keys) {
+                int mergedStatesCount = 0;
+                boolean isPhi = false;
+                ValueNode merged = null;
+                for (MemoryMap state : states) {
+                    ValueNode last = state.getLastLocationAccess(key);
+                    if (isPhi) {
+                        ((PhiNode) merged).addInput(last);
+                    } else {
+                        if (merged == last) {
+                            // nothing to do
+                        } else if (merged == null) {
+                            merged = last;
+                        } else {
+                            PhiNode phi = merge.graph().add(new PhiNode(PhiType.Memory, merge));
+                            for (int j = 0; j < mergedStatesCount; j++) {
+                                phi.addInput(merged);
+                            }
+                            phi.addInput(last);
+                            merged = phi;
+                            isPhi = true;
+                        }
+                    }
+                    mergedStatesCount++;
+                }
+                newState.lastMemorySnapshot.put(key, merged);
+            }
+            return newState;
+        }
+
+        @Override
+        protected MemoryMap afterSplit(BeginNode node, MemoryMap oldState) {
+            MemoryMap result = new MemoryMap(oldState);
+            if (node.predecessor() instanceof InvokeWithExceptionNode) {
+                /*
+                 * InvokeWithException cannot be the lastLocationAccess for a FloatingReadNode.
+                 * Since it is both the invoke and a control flow split, the scheduler cannot
+                 * schedule anything immediately the invoke. It can only schedule in the normal or
+                 * exceptional successor - and we have to tell the scheduler here which side it
+                 * needs to choose by putting in the location identity on both successors.
+                 */
+                InvokeWithExceptionNode checkpoint = (InvokeWithExceptionNode) node.predecessor();
+                for (Object identity : checkpoint.getLocationIdentities()) {
+                    result.lastMemorySnapshot.put(identity, node);
+                }
+            }
+            return result;
+        }
+
+        @Override
+        protected Map<LoopExitNode, MemoryMap> processLoop(LoopBeginNode loop, MemoryMap initialState) {
+            Set<Object> modifiedLocations = modifiedInLoops.get(loop);
+            if (modifiedLocations.contains(LocationNode.ANY_LOCATION)) {
+                // create phis for all locations if ANY is modified in the loop
+                modifiedLocations = new HashSet<>(modifiedLocations);
+                modifiedLocations.addAll(initialState.lastMemorySnapshot.keySet());
+            }
+
+            Map<Object, PhiNode> phis = new HashMap<>();
+            for (Object location : modifiedLocations) {
+                PhiNode phi = loop.graph().add(new PhiNode(PhiType.Memory, loop));
+                phi.addInput(initialState.getLastLocationAccess(location));
+                phis.put(location, phi);
+                initialState.lastMemorySnapshot.put(location, phi);
+            }
+
+            LoopInfo<MemoryMap> loopInfo = ReentrantNodeIterator.processLoop(this, loop, initialState);
+
+            for (Map.Entry<LoopEndNode, MemoryMap> entry : loopInfo.endStates.entrySet()) {
+                int endIndex = loop.phiPredecessorIndex(entry.getKey());
+                for (Map.Entry<Object, PhiNode> phiEntry : phis.entrySet()) {
+                    Object key = phiEntry.getKey();
+                    PhiNode phi = phiEntry.getValue();
+                    phi.initializeValueAt(endIndex, entry.getValue().getLastLocationAccess(key));
+                }
+            }
+            for (Map.Entry<LoopExitNode, MemoryMap> entry : loopInfo.exitStates.entrySet()) {
+                LoopExitNode exit = entry.getKey();
+                MemoryMap state = entry.getValue();
+                for (Object location : modifiedLocations) {
+                    ValueNode lastAccessAtExit = state.lastMemorySnapshot.get(location);
+                    if (lastAccessAtExit != null) {
+                        state.lastMemorySnapshot.put(location, loop.graph().add(new ProxyNode(lastAccessAtExit, exit, PhiType.Memory)));
+                    }
+                }
+            }
+            return loopInfo.exitStates;
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.common;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.schedule.*;
+
+public class GuardLoweringPhase extends Phase {
+
+    private abstract static class ScheduledNodeIterator {
+
+        private FixedWithNextNode lastFixed;
+        private FixedWithNextNode reconnect;
+        private ListIterator<ScheduledNode> iterator;
+
+        public void processNodes(List<ScheduledNode> nodes, FixedWithNextNode begin) {
+            assert begin != null;
+            lastFixed = begin;
+            reconnect = null;
+            iterator = nodes.listIterator();
+            while (iterator.hasNext()) {
+                Node node = iterator.next();
+                if (!node.isAlive()) {
+                    continue;
+                }
+                if (reconnect != null && node instanceof FixedNode) {
+                    reconnect.setNext((FixedNode) node);
+                    reconnect = null;
+                }
+                if (node instanceof FixedWithNextNode) {
+                    lastFixed = (FixedWithNextNode) node;
+                }
+                processNode(node);
+            }
+        }
+
+        protected void insert(FixedNode start, FixedWithNextNode end) {
+            this.lastFixed.setNext(start);
+            this.lastFixed = end;
+            this.reconnect = end;
+        }
+
+        protected void replaceCurrent(FixedWithNextNode newNode) {
+            Node current = iterator.previous();
+            iterator.next(); // needed because of the previous() call
+            current.replaceAndDelete(newNode);
+            insert(newNode, newNode);
+            iterator.set(newNode);
+        }
+
+        protected abstract void processNode(Node node);
+    }
+
+    private class UseImplicitNullChecks extends ScheduledNodeIterator {
+
+        private final IdentityHashMap<ValueNode, GuardNode> nullGuarded = new IdentityHashMap<>();
+
+        @Override
+        protected void processNode(Node node) {
+            if (node instanceof GuardNode) {
+                processGuard(node);
+            } else if (node instanceof Access) {
+                processAccess((Access) node);
+            }
+            if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) {
+                nullGuarded.clear();
+            } else {
+                Iterator<Entry<ValueNode, GuardNode>> it = nullGuarded.entrySet().iterator();
+                while (it.hasNext()) {
+                    Entry<ValueNode, GuardNode> entry = it.next();
+                    GuardNode guard = entry.getValue();
+                    if (guard.usages().contains(node)) {
+                        it.remove();
+                    }
+                }
+            }
+        }
+
+        private void processAccess(Access access) {
+            GuardNode guard = nullGuarded.get(access.object());
+            if (guard != null && isImplicitNullCheck(access.nullCheckLocation())) {
+                NodeInputList<ValueNode> dependencies = ((ValueNode) access).dependencies();
+                dependencies.remove(guard);
+                Access fixedAccess = access;
+                if (access instanceof FloatingAccessNode) {
+                    fixedAccess = ((FloatingAccessNode) access).asFixedNode();
+                    replaceCurrent((FixedWithNextNode) fixedAccess.node());
+                }
+                assert fixedAccess instanceof FixedNode;
+                fixedAccess.setNullCheck(true);
+                LogicNode condition = guard.condition();
+                guard.replaceAndDelete(fixedAccess.node());
+                if (condition.usages().isEmpty()) {
+                    GraphUtil.killWithUnusedFloatingInputs(condition);
+                }
+                nullGuarded.remove(fixedAccess.object());
+            }
+        }
+
+        private void processGuard(Node node) {
+            GuardNode guard = (GuardNode) node;
+            if (guard.negated() && guard.condition() instanceof IsNullNode) {
+                ValueNode obj = ((IsNullNode) guard.condition()).object();
+                nullGuarded.put(obj, guard);
+            }
+        }
+    }
+
+    private class LowerGuards extends ScheduledNodeIterator {
+
+        private final Block block;
+
+        public LowerGuards(Block block) {
+            this.block = block;
+        }
+
+        @Override
+        protected void processNode(Node node) {
+            if (node instanceof GuardNode) {
+                GuardNode guard = (GuardNode) node;
+                if (guard.negated() && guard.condition() instanceof IsNullNode) {
+                    lowerToNullCheck(guard);
+                } else {
+                    lowerToIf(guard);
+                }
+            }
+        }
+
+        private void lowerToIf(GuardNode guard) {
+            StructuredGraph graph = (StructuredGraph) guard.graph();
+            BeginNode fastPath = graph.add(new BeginNode());
+            DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason()));
+            BeginNode deoptBranch = BeginNode.begin(deopt);
+            BeginNode trueSuccessor;
+            BeginNode falseSuccessor;
+            insertLoopExits(deopt);
+            if (guard.negated()) {
+                trueSuccessor = deoptBranch;
+                falseSuccessor = fastPath;
+            } else {
+                trueSuccessor = fastPath;
+                falseSuccessor = deoptBranch;
+            }
+            IfNode ifNode = graph.add(new IfNode(guard.condition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0));
+            guard.replaceAndDelete(fastPath);
+            insert(ifNode, fastPath);
+        }
+
+        private void lowerToNullCheck(GuardNode guard) {
+            IsNullNode isNull = (IsNullNode) guard.condition();
+            NullCheckNode nullCheck = guard.graph().add(new NullCheckNode(isNull.object()));
+            replaceCurrent(nullCheck);
+        }
+
+        private void insertLoopExits(DeoptimizeNode deopt) {
+            Loop loop = block.getLoop();
+            StructuredGraph graph = (StructuredGraph) deopt.graph();
+            while (loop != null) {
+                LoopExitNode exit = graph.add(new LoopExitNode(loop.loopBegin()));
+                graph.addBeforeFixed(deopt, exit);
+                loop = loop.parent;
+            }
+        }
+    }
+
+    private TargetDescription target;
+
+    public GuardLoweringPhase(TargetDescription target) {
+        this.target = target;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        SchedulePhase schedule = new SchedulePhase();
+        schedule.apply(graph);
+
+        for (Block block : schedule.getCFG().getBlocks()) {
+            processBlock(block, schedule);
+        }
+    }
+
+    private void processBlock(Block block, SchedulePhase schedule) {
+        List<ScheduledNode> nodes = schedule.nodesFor(block);
+        if (GraalOptions.OptImplicitNullChecks && target.implicitNullCheckLimit > 0) {
+            new UseImplicitNullChecks().processNodes(nodes, block.getBeginNode());
+        }
+        new LowerGuards(block).processNodes(nodes, block.getBeginNode());
+    }
+
+    private boolean isImplicitNullCheck(LocationNode location) {
+        return !(location instanceof IndexedLocationNode) && location.displacement() < target.implicitNullCheckLimit;
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,6 +24,7 @@
 
 import java.lang.reflect.*;
 import java.util.*;
+import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -47,7 +48,6 @@
      * invoke.bci, method, true);
      */
 
-    private final TargetDescription target;
     private final PhasePlan plan;
 
     private final GraalCodeCacheProvider runtime;
@@ -63,18 +63,15 @@
     private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize");
     private static final DebugMetric metricInliningRuns = Debug.metric("Runs");
 
-    public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Collection<Invoke> hints, Assumptions assumptions, GraphCache cache, PhasePlan plan,
-                    OptimisticOptimizations optimisticOpts) {
-        this(target, runtime, assumptions, cache, plan, createInliningPolicy(runtime, assumptions, optimisticOpts, hints), optimisticOpts);
+    public InliningPhase(GraalCodeCacheProvider runtime, Collection<Invoke> hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+        this(runtime, assumptions, cache, plan, createInliningPolicy(runtime, assumptions, optimisticOpts, hints), optimisticOpts);
     }
 
     public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) {
         this.customCanonicalizer = customCanonicalizer;
     }
 
-    public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy,
-                    OptimisticOptimizations optimisticOpts) {
-        this.target = target;
+    public InliningPhase(GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts) {
         this.runtime = runtime;
         this.assumptions = assumptions;
         this.cache = cache;
@@ -103,7 +100,7 @@
                         Iterable<Node> newNodes = graph.getNewNodes(mark);
                         inliningPolicy.scanInvokes(newNodes);
                         if (GraalOptions.OptCanonicalizer) {
-                            new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph);
+                            new CanonicalizerPhase(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph);
                         }
                         metricInliningPerformed.increment();
                     } catch (BailoutException bailout) {
@@ -131,26 +128,32 @@
                 return cachedGraph;
             }
         }
-        StructuredGraph newGraph = new StructuredGraph(method);
-        if (plan != null) {
-            plan.runPhases(PhasePosition.AFTER_PARSING, newGraph);
-        }
-        assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING";
+        final StructuredGraph newGraph = new StructuredGraph(method);
+        return Debug.scope("InlineGraph", newGraph, new Callable<StructuredGraph>() {
+
+            @Override
+            public StructuredGraph call() throws Exception {
+                if (plan != null) {
+                    plan.runPhases(PhasePosition.AFTER_PARSING, newGraph);
+                }
+                assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING";
 
-        if (GraalOptions.ProbabilityAnalysis) {
-            new DeadCodeEliminationPhase().apply(newGraph);
-            new ComputeProbabilityPhase().apply(newGraph);
-        }
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(newGraph);
-        }
-        if (GraalOptions.CullFrameStates) {
-            new CullFrameStatesPhase().apply(newGraph);
-        }
-        if (GraalOptions.CacheGraphs && cache != null) {
-            cache.put(newGraph);
-        }
-        return newGraph;
+                if (GraalOptions.ProbabilityAnalysis) {
+                    new DeadCodeEliminationPhase().apply(newGraph);
+                    new ComputeProbabilityPhase().apply(newGraph);
+                }
+                if (GraalOptions.OptCanonicalizer) {
+                    new CanonicalizerPhase(runtime, assumptions).apply(newGraph);
+                }
+                if (GraalOptions.CullFrameStates) {
+                    new CullFrameStatesPhase().apply(newGraph);
+                }
+                if (GraalOptions.CacheGraphs && cache != null) {
+                    cache.put(newGraph);
+                }
+                return newGraph;
+            }
+        });
     }
 
     private interface InliningDecision {
@@ -440,11 +443,7 @@
                     queueSuccessors(current);
                 } else if (current instanceof EndNode) {
                     queueMerge((EndNode) current);
-                } else if (current instanceof DeoptimizeNode) {
-                    // nothing todo
-                } else if (current instanceof ReturnNode) {
-                    // nothing todo
-                } else if (current instanceof UnwindNode) {
+                } else if (current instanceof ControlSinkNode) {
                     // nothing todo
                 } else if (current instanceof ControlSplitNode) {
                     queueSuccessors(current);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Mar 21 14:11:13 2013 +0100
@@ -696,7 +696,8 @@
                 ResolvedJavaMethod targetMethod = methodCallTarget.targetMethod();
                 ResolvedJavaType leastCommonType = getLeastCommonType();
                 // check if we have a common base type that implements the interface -> in that case
-// we have a vtable entry for the interface method and can use a less expensive virtual call
+                // we have a vtable entry for the interface method and can use a less expensive
+                // virtual call
                 if (!leastCommonType.isInterface() && targetMethod.getDeclaringClass().isAssignableFrom(leastCommonType)) {
                     ResolvedJavaMethod baseClassTargetMethod = leastCommonType.resolveMethod(targetMethod);
                     if (baseClassTargetMethod != null) {
@@ -966,8 +967,6 @@
             return logNotInlinedMethodAndReturnFalse(invoke, method, "the method's class is not initialized");
         } else if (!method.canBeInlined()) {
             return logNotInlinedMethodAndReturnFalse(invoke, method, "it is marked non-inlinable");
-        } else if (computeInliningLevel(invoke) > GraalOptions.MaximumInlineLevel) {
-            return logNotInlinedMethodAndReturnFalse(invoke, method, "it exceeds the maximum inlining depth");
         } else if (computeRecursiveInliningLevel(invoke.stateAfter(), method) > GraalOptions.MaximumRecursiveInlining) {
             return logNotInlinedMethodAndReturnFalse(invoke, method, "it exceeds the maximum recursive inlining depth");
         } else if (new OptimisticOptimizations(method).lessOptimisticThan(optimisticOpts)) {
@@ -1001,6 +1000,17 @@
         return count;
     }
 
+    static MonitorExitNode findPrecedingMonitorExit(UnwindNode unwind) {
+        Node pred = unwind.predecessor();
+        while (pred != null) {
+            if (pred instanceof MonitorExitNode) {
+                return (MonitorExitNode) pred;
+            }
+            pred = pred.predecessor();
+        }
+        return null;
+    }
+
     /**
      * Performs an actual inlining, thereby replacing the given invoke with the given inlineGraph.
      * 
@@ -1071,13 +1081,13 @@
         } else {
             if (unwindNode != null) {
                 UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode);
+                MonitorExitNode monitorExit = findPrecedingMonitorExit(unwindDuplicate);
                 DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler);
                 unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode));
                 // move the deopt upwards if there is a monitor exit that tries to use the
                 // "after exception" frame state
                 // (because there is no "after exception" frame state!)
-                if (deoptimizeNode.predecessor() instanceof MonitorExitNode) {
-                    MonitorExitNode monitorExit = (MonitorExitNode) deoptimizeNode.predecessor();
+                if (monitorExit != null) {
                     if (monitorExit.stateAfter() != null && monitorExit.stateAfter().bci == FrameState.AFTER_EXCEPTION_BCI) {
                         FrameState monitorFrameState = monitorExit.stateAfter();
                         graph.removeFixed(monitorExit);
@@ -1123,7 +1133,7 @@
                 } else {
                     // only handle the outermost frame states
                     if (frameState.outerFrameState() == null) {
-                        assert frameState.method() == inlineGraph.method();
+                        assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method() == inlineGraph.method();
                         if (outerFrameState == null) {
                             outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.node().kind());
                             outerFrameState.setDuringCall(true);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -33,12 +33,10 @@
 
 public class IterativeConditionalEliminationPhase extends Phase {
 
-    private final TargetDescription target;
     private final MetaAccessProvider runtime;
     private final Assumptions assumptions;
 
-    public IterativeConditionalEliminationPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
-        this.target = target;
+    public IterativeConditionalEliminationPhase(MetaAccessProvider runtime, Assumptions assumptions) {
         this.runtime = runtime;
         this.assumptions = assumptions;
     }
@@ -55,7 +53,7 @@
             if (canonicalizationRoots.isEmpty()) {
                 break;
             }
-            new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph);
+            new CanonicalizerPhase(runtime, assumptions, canonicalizationRoots, null).apply(graph);
             canonicalizationRoots.clear();
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common;
-
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.*;
-
-/**
- * Adds safepoints to loops.
- */
-public class LoopSafepointInsertionPhase extends Phase {
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        nextLoop: for (LoopEndNode loopEnd : graph.getNodes(LoopEndNode.class)) {
-            if (!loopEnd.canSafepoint()) {
-                continue;
-            }
-            if (GraalOptions.OptSafepointElimination) {
-                // We 'eliminate' safepoints by simply never placing them into loops that have at
-                // least one call
-                NodeIterable<FixedNode> it = NodeIterators.dominators(loopEnd).until(loopEnd.loopBegin());
-                for (FixedNode n : it) {
-                    if (n instanceof Invoke) {
-                        continue nextLoop;
-                    }
-                }
-            }
-            SafepointNode safepoint = graph.add(new SafepointNode());
-            graph.addBeforeFixed(loopEnd, safepoint);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -83,8 +83,8 @@
         public ValueNode createGuard(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
             if (GraalOptions.OptEliminateGuards) {
                 for (Node usage : condition.usages()) {
-                    if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage)) {
-                        return (ValueNode) usage;
+                    if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage) && ((GuardNode) usage).negated() == negated) {
+                        return (GuardNode) usage;
                     }
                 }
             }
@@ -104,6 +104,11 @@
         public FixedWithNextNode lastFixedNode() {
             return lastFixedNode;
         }
+
+        public void setLastFixedNode(FixedWithNextNode n) {
+            assert n == null || n.isAlive() : n;
+            lastFixedNode = n;
+        }
     }
 
     private final TargetDescription target;
@@ -139,7 +144,7 @@
             deferred = false;
             processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed);
             Debug.dump(graph, "Lowering iteration %d", i++);
-            new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph);
+            new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph);
 
             if (!deferred && !containsLowerable(graph.getNewNodes(mark))) {
                 // No new lowerable nodes - done!
@@ -187,15 +192,15 @@
         List<ScheduledNode> nodes = schedule.nodesFor(b);
 
         for (Node node : nodes) {
-            FixedNode lastFixedNext = null;
-            if (node instanceof FixedWithNextNode) {
+            FixedNode nextFixedNode = null;
+            if (node instanceof FixedWithNextNode && node.isAlive()) {
                 FixedWithNextNode fixed = (FixedWithNextNode) node;
-                lastFixedNext = fixed.next();
-                loweringTool.lastFixedNode = fixed;
+                nextFixedNode = fixed.next();
+                loweringTool.setLastFixedNode(fixed);
             }
 
             if (node.isAlive() && !processed.isMarked(node) && node instanceof Lowerable) {
-                if (loweringTool.lastFixedNode == null) {
+                if (loweringTool.lastFixedNode() == null) {
                     // We cannot lower the node now because we don't have a fixed node to anchor the
                     // replacements.
                     // This can happen when previous lowerings in this lowering iteration deleted
@@ -209,17 +214,17 @@
                 }
             }
 
-            if (loweringTool.lastFixedNode == node && !node.isAlive()) {
-                if (lastFixedNext == null) {
-                    loweringTool.lastFixedNode = null;
+            if (loweringTool.lastFixedNode() == node && !node.isAlive()) {
+                if (nextFixedNode == null || !nextFixedNode.isAlive()) {
+                    loweringTool.setLastFixedNode(null);
                 } else {
-                    Node prev = lastFixedNext.predecessor();
+                    Node prev = nextFixedNode.predecessor();
                     if (prev != node && prev instanceof FixedWithNextNode) {
-                        loweringTool.lastFixedNode = (FixedWithNextNode) prev;
-                    } else if (lastFixedNext instanceof FixedWithNextNode) {
-                        loweringTool.lastFixedNode = (FixedWithNextNode) lastFixedNext;
+                        loweringTool.setLastFixedNode((FixedWithNextNode) prev);
+                    } else if (nextFixedNode instanceof FixedWithNextNode) {
+                        loweringTool.setLastFixedNode((FixedWithNextNode) nextFixedNode);
                     } else {
-                        loweringTool.lastFixedNode = null;
+                        loweringTool.setLastFixedNode(null);
                     }
                 }
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -59,8 +59,8 @@
         if (visited.isMarked(lastLocationAccess)) {
             return true; // dataflow loops must come from Phis assume them ok until proven wrong
         }
-        if (lastLocationAccess instanceof ValueProxyNode) {
-            return isWrites(n, ((ValueProxyNode) lastLocationAccess).value(), visited);
+        if (lastLocationAccess instanceof ProxyNode) {
+            return isWrites(n, ((ProxyNode) lastLocationAccess).value(), visited);
         }
         if (lastLocationAccess instanceof WriteNode) {
             WriteNode other = (WriteNode) lastLocationAccess;
@@ -83,10 +83,10 @@
         if (exisiting != null) {
             return exisiting;
         }
-        if (lastLocationAccess instanceof ValueProxyNode) {
-            ValueProxyNode proxy = (ValueProxyNode) lastLocationAccess;
+        if (lastLocationAccess instanceof ProxyNode) {
+            ProxyNode proxy = (ProxyNode) lastLocationAccess;
             ValueNode value = getValue(n, proxy.value(), nodeMap);
-            return lastLocationAccess.graph().add(new ValueProxyNode(value, proxy.proxyPoint(), PhiType.Value));
+            return lastLocationAccess.graph().add(new ProxyNode(value, proxy.proxyPoint(), PhiType.Value));
         }
         if (lastLocationAccess instanceof WriteNode) {
             return ((WriteNode) lastLocationAccess).value();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,14 +23,17 @@
 package com.oracle.graal.phases.common;
 
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.PhiNode.*;
 import com.oracle.graal.phases.*;
 
 public class RemoveValueProxyPhase extends Phase {
 
     @Override
     protected void run(StructuredGraph graph) {
-        for (ValueProxyNode vpn : graph.getNodes(ValueProxyNode.class)) {
-            graph.replaceFloating(vpn, vpn.value());
+        for (ProxyNode vpn : graph.getNodes(ProxyNode.class)) {
+            if (vpn.type() == PhiType.Value) {
+                graph.replaceFloating(vpn, vpn.value());
+            }
         }
         for (LoopExitNode exit : graph.getNodes(LoopExitNode.class)) {
             FrameState stateAfter = exit.stateAfter();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.common;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * Adds safepoints to loops and return points.
+ */
+public class SafepointInsertionPhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        if (GraalOptions.GenLoopSafepoints) {
+            for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) {
+                if (!loopEndNode.canSafepoint()) {
+                    continue;
+                }
+                SafepointNode safepointNode = graph.add(new SafepointNode());
+                graph.addBeforeFixed(loopEndNode, safepointNode);
+            }
+        }
+
+        if (GraalOptions.GenSafepoints) {
+            if (!GraalOptions.OptEliminateSafepoints || graph.getNodes(MethodCallTargetNode.class).isNotEmpty()) {
+                for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) {
+                    SafepointNode safepoint = graph.add(new SafepointNode());
+                    graph.addBeforeFixed(returnNode, safepoint);
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu Mar 21 14:11:13 2013 +0100
@@ -43,7 +43,6 @@
            static boolean InlineMonomorphicCalls             = true;
            static boolean InlinePolymorphicCalls             = true;
            static boolean InlineMegamorphicCalls             = ____;
-    public static int     MaximumInlineLevel                 = 30;
     public static int     MaximumDesiredSize                 = 5000;
     public static int     MaximumRecursiveInlining           = 1;
     public static boolean LimitInlinedProbability            = ____;
@@ -106,11 +105,9 @@
     public static int     LoopUnswitchUncertaintyBoost       = 5;
 
     // debugging settings
-    public static int     MethodEndBreakpointGuards          = 2;
     public static boolean ZapStackOnMethodEntry              = ____;
     public static boolean DeoptALot                          = ____;
     public static boolean VerifyPhases                       = true;
-    public static boolean CreateDeoptInfo                    = ____;
 
     public static String  PrintFilter                        = null;
 
@@ -150,13 +147,16 @@
     public static boolean ExitVMOnBailout                    = ____;
     public static boolean ExitVMOnException                  = true;
 
+    // Register allocator debugging
+    public static String  RegisterPressure                   = null;
+
     // Code generator settings
-    public static boolean CheckCastElimination               = true;
+    public static boolean ConditionalElimination             = true;
     public static boolean CullFrameStates                    = ____;
     public static boolean UseProfilingInformation            = true;
            static boolean RemoveNeverExecutedCode            = true;
            static boolean UseExceptionProbability            = true;
-    public static boolean AllowExplicitExceptionChecks       = true;
+           static boolean UseExceptionProbabilityForOperations = true;
     public static boolean OmitHotExceptionStacktrace         = ____;
     public static boolean GenSafepoints                      = true;
     public static boolean GenLoopSafepoints                  = true;
@@ -169,6 +169,8 @@
     public static boolean CanOmitFrame                       = true;
     public static int     SafepointPollOffset                = 256;
 
+    public static boolean MemoryAwareScheduling              = true;
+
     // Translating tableswitch instructions
     public static int     MinimumJumpTableSize               = 5;
     public static int     RangeTestsSwitchDensity            = 5;
@@ -182,14 +184,15 @@
     public static boolean SupportJsrBytecodes                = true;
 
     public static boolean OptAssumptions                     = true;
+    public static boolean OptConvertDeoptsToGuards           = true;
     public static boolean OptReadElimination                 = true;
     public static boolean OptCanonicalizer                   = true;
     public static boolean OptScheduleOutOfLoops              = true;
     public static boolean OptEliminateGuards                 = true;
+    public static boolean OptEliminateSafepoints             = true;
     public static boolean OptImplicitNullChecks              = true;
     public static boolean OptLivenessAnalysis                = true;
     public static boolean OptLoopTransform                   = true;
-    public static boolean OptSafepointElimination            = true;
     public static boolean OptFloatingReads                   = true;
     public static boolean OptTailDuplication                 = true;
     public static boolean OptEliminatePartiallyRedundantGuards = true;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Thu Mar 21 14:11:13 2013 +0100
@@ -33,8 +33,8 @@
     public static final OptimisticOptimizations NONE = new OptimisticOptimizations(EnumSet.noneOf(Optimization.class));
     private static final DebugMetric disabledOptimisticOptsMetric = Debug.metric("DisabledOptimisticOpts");
 
-    private static enum Optimization {
-        RemoveNeverExecutedCode, UseTypeCheckedInlining, UseTypeCheckHints, UseExceptionProbability
+    public static enum Optimization {
+        RemoveNeverExecutedCode, UseTypeCheckedInlining, UseTypeCheckHints, UseExceptionProbabilityForOperations, UseExceptionProbability
     }
 
     private final Set<Optimization> enabledOpts;
@@ -42,6 +42,7 @@
     public OptimisticOptimizations(ResolvedJavaMethod method) {
         this.enabledOpts = EnumSet.noneOf(Optimization.class);
 
+        enabledOpts.add(Optimization.UseExceptionProbabilityForOperations);
         addOptimization(method, DeoptimizationReason.UnreachedCode, Optimization.RemoveNeverExecutedCode);
         addOptimization(method, DeoptimizationReason.TypeCheckedInliningViolated, Optimization.UseTypeCheckedInlining);
         addOptimization(method, DeoptimizationReason.OptimizedTypeCheckViolated, Optimization.UseTypeCheckHints);
@@ -56,11 +57,26 @@
              * TODO (chaeubl): see GRAAL-75 (remove when we are sure that optimistic optimizations
              * are not disabled unnecessarily
              */
-            TTY.println("WARN: deactivated optimistic optimization %s for %s", optimization.name(), MetaUtil.format("%H.%n(%p)", method));
             disabledOptimisticOptsMetric.increment();
         }
     }
 
+    public OptimisticOptimizations remove(Optimization... optimizations) {
+        Set<Optimization> newOptimizations = EnumSet.copyOf(enabledOpts);
+        for (Optimization o : optimizations) {
+            newOptimizations.remove(o);
+        }
+        return new OptimisticOptimizations(newOptimizations);
+    }
+
+    public OptimisticOptimizations add(Optimization... optimizations) {
+        Set<Optimization> newOptimizations = EnumSet.copyOf(enabledOpts);
+        for (Optimization o : optimizations) {
+            newOptimizations.add(o);
+        }
+        return new OptimisticOptimizations(newOptimizations);
+    }
+
     private OptimisticOptimizations(Set<Optimization> enabledOpts) {
         this.enabledOpts = enabledOpts;
     }
@@ -93,6 +109,10 @@
         return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability);
     }
 
+    public boolean useExceptionProbabilityForOperations() {
+        return GraalOptions.UseExceptionProbabilityForOperations && enabledOpts.contains(Optimization.UseExceptionProbabilityForOperations);
+    }
+
     public boolean lessOptimisticThan(OptimisticOptimizations other) {
         for (Optimization opt : Optimization.values()) {
             if (!enabledOpts.contains(opt) && other.enabledOpts.contains(opt)) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -89,14 +89,8 @@
                 end((EndNode) current);
                 queueMerge((EndNode) current);
                 current = nextQueuedNode();
-            } else if (current instanceof DeoptimizeNode) {
-                deoptimize((DeoptimizeNode) current);
-                current = nextQueuedNode();
-            } else if (current instanceof ReturnNode) {
-                returnNode((ReturnNode) current);
-                current = nextQueuedNode();
-            } else if (current instanceof UnwindNode) {
-                unwind((UnwindNode) current);
+            } else if (current instanceof ControlSinkNode) {
+                node(current);
                 current = nextQueuedNode();
             } else if (current instanceof ControlSplitNode) {
                 Set<Node> successors = controlSplit((ControlSplitNode) current);
@@ -106,6 +100,7 @@
                 assert false : current;
             }
         } while (current != null);
+        finished();
     }
 
     private void queueSuccessors(FixedNode x, Set<Node> successors) {
@@ -216,24 +211,16 @@
         node(loopEnd);
     }
 
-    protected void deoptimize(DeoptimizeNode deoptimize) {
-        node(deoptimize);
-    }
-
     protected Set<Node> controlSplit(ControlSplitNode controlSplit) {
         node(controlSplit);
         return null;
     }
 
-    protected void returnNode(ReturnNode returnNode) {
-        node(returnNode);
-    }
-
     protected void invoke(Invoke invoke) {
         node(invoke.node());
     }
 
-    protected void unwind(UnwindNode unwind) {
-        node(unwind);
+    protected void finished() {
+        // nothing to do
     }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,54 +29,49 @@
 
 public final class ReentrantBlockIterator {
 
-    public abstract static class MergeableBlockState<T> {
+    public static class LoopInfo<StateT> {
 
-        public abstract T cloneState();
+        public final List<StateT> endStates = new ArrayList<>();
+        public final List<StateT> exitStates = new ArrayList<>();
     }
 
-    public static class LoopInfo<T extends MergeableBlockState<T>> {
+    public abstract static class BlockIteratorClosure<StateT> {
 
-        public final List<T> endStates = new ArrayList<>();
-        public final List<T> exitStates = new ArrayList<>();
-    }
-
-    public abstract static class BlockIteratorClosure<T extends MergeableBlockState<T>> {
+        protected abstract void processBlock(Block block, StateT currentState);
 
-        protected abstract void processBlock(Block block, T currentState);
-
-        protected abstract T merge(MergeNode merge, List<T> states);
+        protected abstract StateT merge(MergeNode merge, List<StateT> states);
 
-        protected abstract T afterSplit(FixedNode node, T oldState);
+        protected abstract StateT afterSplit(FixedNode node, StateT oldState);
 
-        protected abstract List<T> processLoop(Loop loop, T initialState);
+        protected abstract List<StateT> processLoop(Loop loop, StateT initialState);
     }
 
     private ReentrantBlockIterator() {
         // no instances allowed
     }
 
-    public static <T extends MergeableBlockState<T>> LoopInfo<T> processLoop(BlockIteratorClosure<T> closure, Loop loop, T initialState) {
-        IdentityHashMap<FixedNode, T> blockEndStates = apply(closure, loop.header, initialState, new HashSet<>(loop.blocks));
+    public static <StateT> LoopInfo<StateT> processLoop(BlockIteratorClosure<StateT> closure, Loop loop, StateT initialState) {
+        IdentityHashMap<FixedNode, StateT> blockEndStates = apply(closure, loop.header, initialState, new HashSet<>(loop.blocks));
 
-        LoopInfo<T> info = new LoopInfo<>();
+        LoopInfo<StateT> info = new LoopInfo<>();
         List<Block> predecessors = loop.header.getPredecessors();
         for (int i = 1; i < predecessors.size(); i++) {
             info.endStates.add(blockEndStates.get(predecessors.get(i).getEndNode()));
         }
         for (Block loopExit : loop.exits) {
             assert loopExit.getPredecessorCount() == 1;
-            T exitState = blockEndStates.get(loopExit.getFirstPredecessor().getEndNode());
+            StateT exitState = blockEndStates.get(loopExit.getFirstPredecessor().getEndNode());
             assert exitState != null;
             info.exitStates.add(exitState);
         }
         return info;
     }
 
-    public static <T extends MergeableBlockState<T>> IdentityHashMap<FixedNode, T> apply(BlockIteratorClosure<T> closure, Block start, T initialState, Set<Block> boundary) {
+    public static <StateT> IdentityHashMap<FixedNode, StateT> apply(BlockIteratorClosure<StateT> closure, Block start, StateT initialState, Set<Block> boundary) {
         Deque<Block> blockQueue = new ArrayDeque<>();
-        IdentityHashMap<FixedNode, T> blockEndStates = new IdentityHashMap<>();
+        IdentityHashMap<FixedNode, StateT> blockEndStates = new IdentityHashMap<>();
 
-        T state = initialState;
+        StateT state = initialState;
         Block current = start;
 
         do {
@@ -98,7 +93,7 @@
                             LoopBeginNode loopBegin = loop.loopBegin();
                             assert successor.getBeginNode() == loopBegin;
 
-                            List<T> exitStates = closure.processLoop(loop, state);
+                            List<StateT> exitStates = closure.processLoop(loop, state);
 
                             int i = 0;
                             assert loop.exits.size() == exitStates.size();
@@ -123,8 +118,8 @@
                                 blockEndStates.put(end, state);
                                 MergeNode merge = end.merge();
                                 boolean endsVisited = true;
-                                for (int i = 0; i < merge.forwardEndCount(); i++) {
-                                    if (!blockEndStates.containsKey(merge.forwardEndAt(i))) {
+                                for (EndNode forwardEnd : merge.forwardEnds()) {
+                                    if (!blockEndStates.containsKey(forwardEnd)) {
                                         endsVisited = false;
                                         break;
                                     }
@@ -157,9 +152,9 @@
                     current = blockQueue.removeFirst();
                     if (current.getPredecessors().size() > 1) {
                         MergeNode merge = (MergeNode) current.getBeginNode();
-                        ArrayList<T> states = new ArrayList<>(merge.forwardEndCount());
+                        ArrayList<StateT> states = new ArrayList<>(merge.forwardEndCount());
                         for (int i = 0; i < merge.forwardEndCount(); i++) {
-                            T other = blockEndStates.get(merge.forwardEndAt(i));
+                            StateT other = blockEndStates.get(merge.forwardEndAt(i));
                             assert other != null;
                             states.add(other);
                         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.graph;
+
+import java.util.*;
+
+import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.nodes.*;
+
+public final class ReentrantNodeIterator {
+
+    public static class LoopInfo<StateT> {
+
+        public final Map<LoopEndNode, StateT> endStates = new IdentityHashMap<>(4);
+        public final Map<LoopExitNode, StateT> exitStates = new IdentityHashMap<>(2);
+    }
+
+    public abstract static class NodeIteratorClosure<StateT> {
+
+        protected abstract void processNode(FixedNode node, StateT currentState);
+
+        protected abstract StateT merge(MergeNode merge, List<StateT> states);
+
+        protected abstract StateT afterSplit(BeginNode node, StateT oldState);
+
+        protected abstract Map<LoopExitNode, StateT> processLoop(LoopBeginNode loop, StateT initialState);
+    }
+
+    private ReentrantNodeIterator() {
+        // no instances allowed
+    }
+
+    public static <StateT> LoopInfo<StateT> processLoop(NodeIteratorClosure<StateT> closure, LoopBeginNode loop, StateT initialState) {
+        HashSet<FixedNode> boundary = new HashSet<>();
+        for (LoopExitNode exit : loop.loopExits()) {
+            boundary.add(exit);
+        }
+        Map<FixedNode, StateT> blockEndStates = apply(closure, loop, initialState, boundary);
+
+        LoopInfo<StateT> info = new LoopInfo<>();
+        for (LoopEndNode end : loop.loopEnds()) {
+            assert blockEndStates.containsKey(end) : "no end state for " + end;
+            info.endStates.put(end, blockEndStates.get(end));
+        }
+        for (LoopExitNode exit : loop.loopExits()) {
+            assert blockEndStates.containsKey(exit) : "no exit state for " + exit;
+            info.exitStates.put(exit, blockEndStates.get(exit));
+        }
+        return info;
+    }
+
+    public static <StateT> Map<FixedNode, StateT> apply(NodeIteratorClosure<StateT> closure, FixedNode start, StateT initialState, Set<FixedNode> boundary) {
+        Deque<BeginNode> nodeQueue = new ArrayDeque<>();
+        IdentityHashMap<FixedNode, StateT> blockEndStates = new IdentityHashMap<>();
+
+        StateT state = initialState;
+        FixedNode current = start;
+        do {
+            while (current instanceof FixedWithNextNode) {
+                if (boundary != null && boundary.contains(current)) {
+                    blockEndStates.put(current, state);
+                    current = null;
+                } else {
+                    FixedNode next = ((FixedWithNextNode) current).next();
+                    closure.processNode(current, state);
+                    current = next;
+                }
+            }
+
+            if (current != null) {
+                closure.processNode(current, state);
+
+                NodeClassIterator successors = current.successors().iterator();
+                if (!successors.hasNext()) {
+                    if (current instanceof LoopEndNode) {
+                        blockEndStates.put(current, state);
+                    } else if (current instanceof EndNode) {
+                        // add the end node and see if the merge is ready for processing
+                        MergeNode merge = ((EndNode) current).merge();
+                        if (merge instanceof LoopBeginNode) {
+                            Map<LoopExitNode, StateT> loopExitState = closure.processLoop((LoopBeginNode) merge, state);
+                            for (Map.Entry<LoopExitNode, StateT> entry : loopExitState.entrySet()) {
+                                blockEndStates.put(entry.getKey(), entry.getValue());
+                                nodeQueue.add(entry.getKey());
+                            }
+                        } else {
+                            assert !blockEndStates.containsKey(current);
+                            blockEndStates.put(current, state);
+                            boolean endsVisited = true;
+                            for (EndNode forwardEnd : merge.forwardEnds()) {
+                                if (!blockEndStates.containsKey(forwardEnd)) {
+                                    endsVisited = false;
+                                    break;
+                                }
+                            }
+                            if (endsVisited) {
+                                ArrayList<StateT> states = new ArrayList<>(merge.forwardEndCount());
+                                for (int i = 0; i < merge.forwardEndCount(); i++) {
+                                    EndNode forwardEnd = merge.forwardEndAt(i);
+                                    assert blockEndStates.containsKey(forwardEnd);
+                                    StateT other = blockEndStates.get(forwardEnd);
+                                    states.add(other);
+                                }
+                                state = closure.merge(merge, states);
+                                current = merge;
+                                continue;
+                            }
+                        }
+                    }
+                } else {
+                    FixedNode firstSuccessor = (FixedNode) successors.next();
+                    if (!successors.hasNext()) {
+                        current = firstSuccessor;
+                        continue;
+                    } else {
+                        while (successors.hasNext()) {
+                            BeginNode successor = (BeginNode) successors.next();
+                            blockEndStates.put(successor, closure.afterSplit(successor, state));
+                            nodeQueue.add(successor);
+                        }
+                        state = closure.afterSplit((BeginNode) firstSuccessor, state);
+                        current = firstSuccessor;
+                        continue;
+                    }
+                }
+            }
+
+            // get next queued block
+            if (nodeQueue.isEmpty()) {
+                return blockEndStates;
+            } else {
+                current = nodeQueue.removeFirst();
+                state = blockEndStates.get(current);
+                assert !(current instanceof MergeNode) && current instanceof BeginNode;
+            }
+        } while (true);
+    }
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -73,11 +73,7 @@
                 queueSuccessors(current);
             } else if (current instanceof EndNode) {
                 queueMerge((EndNode) current);
-            } else if (current instanceof DeoptimizeNode) {
-                // nothing todo
-            } else if (current instanceof ReturnNode) {
-                // nothing todo
-            } else if (current instanceof UnwindNode) {
+            } else if (current instanceof ControlSinkNode) {
                 // nothing todo
             } else if (current instanceof ControlSplitNode) {
                 queueSuccessors(current);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,12 +28,103 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
+import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo;
 
-public class SchedulePhase extends Phase {
+public final class SchedulePhase extends Phase {
+
+    public static enum SchedulingStrategy {
+        EARLIEST, LATEST, LATEST_OUT_OF_LOOPS
+    }
+
+    /**
+     * This closure iterates over all nodes of a scheduled graph (it expects a
+     * {@link SchedulingStrategy#EARLIEST} schedule) and keeps a list of "active" reads. Whenever it
+     * encounters a read, it adds it to the active reads. Whenever it encounters a memory
+     * checkpoint, it adds all reads that need to be committed before this checkpoint to the
+     * "phantom" usages and inputs, so that the read is scheduled before the checkpoint afterwards.
+     * 
+     * At merges, the intersection of all sets of active reads is calculated. A read that was
+     * committed within one predecessor branch cannot be scheduled after the merge anyway.
+     * 
+     * Similarly for loops, all reads that are killed somewhere within the loop are removed from the
+     * exits' active reads, since they cannot be scheduled after the exit anyway.
+     */
+    private class MemoryScheduleClosure extends BlockIteratorClosure<HashSet<FloatingReadNode>> {
+
+        @Override
+        protected void processBlock(Block block, HashSet<FloatingReadNode> currentState) {
+            for (Node node : getBlockToNodesMap().get(block)) {
+                if (node instanceof FloatingReadNode) {
+                    currentState.add((FloatingReadNode) node);
+                } else if (node instanceof MemoryCheckpoint) {
+                    for (Object identity : ((MemoryCheckpoint) node).getLocationIdentities()) {
+                        for (Iterator<FloatingReadNode> iter = currentState.iterator(); iter.hasNext();) {
+                            FloatingReadNode read = iter.next();
+                            FixedNode fixed = (FixedNode) node;
+                            if (identity == LocationNode.ANY_LOCATION || read.location().locationIdentity() == identity) {
+                                addPhantomReference(read, fixed);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        public void addPhantomReference(FloatingReadNode read, FixedNode fixed) {
+            List<FixedNode> usageList = phantomUsages.get(read);
+            if (usageList == null) {
+                phantomUsages.put(read, usageList = new ArrayList<>());
+            }
+            usageList.add(fixed);
+            List<FloatingNode> inputList = phantomInputs.get(fixed);
+            if (inputList == null) {
+                phantomInputs.put(fixed, inputList = new ArrayList<>());
+            }
+            inputList.add(read);
+        }
+
+        @Override
+        protected HashSet<FloatingReadNode> merge(MergeNode merge, List<HashSet<FloatingReadNode>> states) {
+            HashSet<FloatingReadNode> state = new HashSet<>(states.get(0));
+            for (int i = 1; i < states.size(); i++) {
+                state.retainAll(states.get(i));
+            }
+            return state;
+        }
+
+        @Override
+        protected HashSet<FloatingReadNode> afterSplit(FixedNode node, HashSet<FloatingReadNode> oldState) {
+            return new HashSet<>(oldState);
+        }
+
+        @Override
+        protected List<HashSet<FloatingReadNode>> processLoop(Loop loop, HashSet<FloatingReadNode> state) {
+            LoopInfo<HashSet<FloatingReadNode>> info = ReentrantBlockIterator.processLoop(this, loop, new HashSet<>(state));
+
+            List<HashSet<FloatingReadNode>> loopEndStates = info.endStates;
+
+            // collect all reads that were killed in some branch within the loop
+            Set<FloatingReadNode> killedReads = new HashSet<>(state);
+            Set<FloatingReadNode> survivingReads = new HashSet<>(loopEndStates.get(0));
+            for (int i = 1; i < loopEndStates.size(); i++) {
+                survivingReads.retainAll(loopEndStates.get(i));
+            }
+            killedReads.removeAll(survivingReads);
+
+            // reads that were killed within the loop cannot be scheduled after the loop anyway
+            for (HashSet<FloatingReadNode> exitState : info.exitStates) {
+                exitState.removeAll(killedReads);
+            }
+            return info.exitStates;
+        }
+    }
 
     private ControlFlowGraph cfg;
     private NodeMap<Block> earliestCache;
@@ -42,9 +133,16 @@
      * Map from blocks to the nodes in each block.
      */
     private BlockMap<List<ScheduledNode>> blockToNodesMap;
+    private final Map<FloatingNode, List<FixedNode>> phantomUsages = new IdentityHashMap<>();
+    private final Map<FixedNode, List<FloatingNode>> phantomInputs = new IdentityHashMap<>();
+    private final SchedulingStrategy selectedStrategy;
 
     public SchedulePhase() {
-        super("Schedule");
+        this(GraalOptions.OptScheduleOutOfLoops ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST);
+    }
+
+    public SchedulePhase(SchedulingStrategy strategy) {
+        this.selectedStrategy = strategy;
     }
 
     @Override
@@ -53,8 +151,20 @@
         earliestCache = graph.createNodeMap();
         blockToNodesMap = new BlockMap<>(cfg);
 
-        assignBlockToNodes(graph);
-        sortNodesWithinBlocks(graph);
+        if (GraalOptions.MemoryAwareScheduling && selectedStrategy != SchedulingStrategy.EARLIEST && graph.getNodes(FloatingReadNode.class).isNotEmpty()) {
+
+            assignBlockToNodes(graph, SchedulingStrategy.EARLIEST);
+            sortNodesWithinBlocks(graph, SchedulingStrategy.EARLIEST);
+
+            MemoryScheduleClosure closure = new MemoryScheduleClosure();
+            ReentrantBlockIterator.apply(closure, getCFG().getStartBlock(), new HashSet<FloatingReadNode>(), null);
+
+            cfg.clearNodeToBlock();
+            blockToNodesMap = new BlockMap<>(cfg);
+        }
+
+        assignBlockToNodes(graph, selectedStrategy);
+        sortNodesWithinBlocks(graph, selectedStrategy);
     }
 
     /**
@@ -94,7 +204,7 @@
         return blockToNodesMap.get(block);
     }
 
-    private void assignBlockToNodes(StructuredGraph graph) {
+    private void assignBlockToNodes(StructuredGraph graph, SchedulingStrategy strategy) {
         for (Block block : cfg.getBlocks()) {
             List<ScheduledNode> nodes = new ArrayList<>();
             assert blockToNodesMap.get(block) == null;
@@ -106,7 +216,7 @@
 
         for (Node n : graph.getNodes()) {
             if (n instanceof ScheduledNode) {
-                assignBlockToNode((ScheduledNode) n);
+                assignBlockToNode((ScheduledNode) n, strategy);
             }
         }
     }
@@ -115,7 +225,7 @@
      * Assigns a block to the given node. This method expects that PhiNodes and FixedNodes are
      * already assigned to a block.
      */
-    private void assignBlockToNode(ScheduledNode node) {
+    private void assignBlockToNode(ScheduledNode node, SchedulingStrategy strategy) {
         assert !node.isDeleted();
 
         Block prevBlock = cfg.getNodeToBlock().get(node);
@@ -126,17 +236,27 @@
         // ControlFlowGraph.identifyBlocks
         assert !(node instanceof PhiNode) : node;
         assert !(node instanceof FixedNode) : node;
-        // if in CFG, schedule at the latest position possible in the outermost loop possible
-        Block latestBlock = latestBlock(node);
+
         Block block;
-        if (latestBlock == null) {
-            block = earliestBlock(node);
-        } else if (GraalOptions.OptScheduleOutOfLoops && !(node instanceof VirtualObjectNode)) {
-            Block earliestBlock = earliestBlock(node);
-            block = scheduleOutOfLoops(node, latestBlock, earliestBlock);
-            assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + node + " (" + earliestBlock + " needs to dominate " + block + ")";
-        } else {
-            block = latestBlock;
+        switch (strategy) {
+            case EARLIEST:
+                block = earliestBlock(node);
+                break;
+            case LATEST:
+            case LATEST_OUT_OF_LOOPS:
+                block = latestBlock(node, strategy);
+                if (block == null) {
+                    block = earliestBlock(node);
+                } else if (strategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS && !(node instanceof VirtualObjectNode)) {
+                    // schedule at the latest position possible in the outermost loop possible
+                    Block earliestBlock = earliestBlock(node);
+                    block = scheduleOutOfLoops(node, block, earliestBlock);
+                    assert earliestBlock.dominates(block) : "Graph cannot be scheduled : inconsistent for " + node + ", " + node.usages().count() + " usages, (" + earliestBlock +
+                                    " needs to dominate " + block + ")";
+                }
+                break;
+            default:
+                throw new GraalInternalError("unknown scheduling strategy");
         }
         cfg.getNodeToBlock().set(node, block);
         blockToNodesMap.get(block).add(node);
@@ -145,17 +265,27 @@
     /**
      * Calculates the last block that the given node could be scheduled in, i.e., the common
      * dominator of all usages. To do so all usages are also assigned to blocks.
+     * 
+     * @param strategy
      */
-    private Block latestBlock(ScheduledNode node) {
+    private Block latestBlock(ScheduledNode node, SchedulingStrategy strategy) {
         CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null);
         for (Node succ : node.successors().nonNull()) {
             assert cfg.getNodeToBlock().get(succ) != null;
             cdbc.apply(cfg.getNodeToBlock().get(succ));
         }
-        ensureScheduledUsages(node);
+        ensureScheduledUsages(node, strategy);
         for (Node usage : node.usages()) {
-            blocksForUsage(node, usage, cdbc);
+            blocksForUsage(node, usage, cdbc, strategy);
         }
+        List<FixedNode> usages = phantomUsages.get(node);
+        if (usages != null) {
+            for (FixedNode usage : usages) {
+                assert cfg.getNodeToBlock().get(usage) != null;
+                cdbc.apply(cfg.getNodeToBlock().get(usage));
+            }
+        }
+
         return cdbc.block;
     }
 
@@ -204,7 +334,12 @@
         assert node.predecessor() == null;
         for (Node input : node.inputs().nonNull()) {
             assert input instanceof ValueNode;
-            Block inputEarliest = earliestBlock(input);
+            Block inputEarliest;
+            if (input instanceof InvokeWithExceptionNode) {
+                inputEarliest = cfg.getNodeToBlock().get(((InvokeWithExceptionNode) input).next());
+            } else {
+                inputEarliest = earliestBlock(input);
+            }
             if (!dominators.get(inputEarliest.getId())) {
                 earliest = inputEarliest;
                 do {
@@ -242,7 +377,7 @@
      * @param usage the usage whose blocks need to be considered
      * @param closure the closure that will be called for each block
      */
-    private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure) {
+    private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure, SchedulingStrategy strategy) {
         assert !(node instanceof PhiNode);
 
         if (usage instanceof PhiNode) {
@@ -274,7 +409,7 @@
                 if (unscheduledUsage instanceof VirtualState) {
                     // If a FrameState is an outer FrameState this method behaves as if the inner
                     // FrameState was the actual usage, by recursing.
-                    blocksForUsage(node, unscheduledUsage, closure);
+                    blocksForUsage(node, unscheduledUsage, closure, strategy);
                 } else if (unscheduledUsage instanceof MergeNode) {
                     // Only FrameStates can be connected to MergeNodes.
                     assert usage instanceof FrameState;
@@ -288,20 +423,20 @@
                     assert usage instanceof FrameState;
                     assert unscheduledUsage instanceof StateSplit;
                     // Otherwise: Put the input into the same block as the usage.
-                    assignBlockToNode((ScheduledNode) unscheduledUsage);
+                    assignBlockToNode((ScheduledNode) unscheduledUsage, strategy);
                     closure.apply(cfg.getNodeToBlock().get(unscheduledUsage));
                 }
             }
         } else {
             // All other types of usages: Put the input into the same block as the usage.
-            assignBlockToNode((ScheduledNode) usage);
+            assignBlockToNode((ScheduledNode) usage, strategy);
             closure.apply(cfg.getNodeToBlock().get(usage));
         }
     }
 
-    private void ensureScheduledUsages(Node node) {
+    private void ensureScheduledUsages(Node node, SchedulingStrategy strategy) {
         for (Node usage : node.usages().filter(ScheduledNode.class)) {
-            assignBlockToNode((ScheduledNode) usage);
+            assignBlockToNode((ScheduledNode) usage, strategy);
         }
         // now true usages are ready
     }
@@ -316,27 +451,43 @@
         return ControlFlowGraph.commonDominator(a, b);
     }
 
-    private void sortNodesWithinBlocks(StructuredGraph graph) {
+    private void sortNodesWithinBlocks(StructuredGraph graph, SchedulingStrategy strategy) {
         NodeBitMap visited = graph.createNodeBitMap();
         for (Block b : cfg.getBlocks()) {
-            sortNodesWithinBlock(b, visited);
+            sortNodesWithinBlock(b, visited, strategy);
         }
     }
 
+    private void sortNodesWithinBlock(Block b, NodeBitMap visited, SchedulingStrategy strategy) {
+        assert !visited.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b;
+        assert !visited.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b;
+
+        List<ScheduledNode> sortedInstructions;
+        switch (strategy) {
+            case EARLIEST:
+                sortedInstructions = sortNodesWithinBlockEarliest(b, visited);
+                break;
+            case LATEST:
+            case LATEST_OUT_OF_LOOPS:
+                sortedInstructions = sortNodesWithinBlockLatest(b, visited);
+                break;
+            default:
+                throw new GraalInternalError("unknown scheduling strategy");
+        }
+        blockToNodesMap.put(b, sortedInstructions);
+    }
+
     /**
      * Sorts the nodes within a block by adding the nodes to a list in a post-order iteration over
      * all inputs. This means that a node is added to the list after all its inputs have been
      * processed.
      */
-    private void sortNodesWithinBlock(Block b, NodeBitMap visited) {
+    private List<ScheduledNode> sortNodesWithinBlockLatest(Block b, NodeBitMap visited) {
         List<ScheduledNode> instructions = blockToNodesMap.get(b);
-        List<ScheduledNode> sortedInstructions = new ArrayList<>(instructions.size() + 2);
-
-        assert !visited.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b;
-        assert !visited.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b;
+        List<ScheduledNode> sortedInstructions = new ArrayList<>(blockToNodesMap.get(b).size() + 2);
 
         for (ScheduledNode i : instructions) {
-            addToSorting(b, i, sortedInstructions, visited);
+            addToLatestSorting(b, i, sortedInstructions, visited);
         }
 
         // Make sure that last node gets really last (i.e. when a frame state successor hangs off
@@ -363,25 +514,25 @@
                 sortedInstructions.add(b.getEndNode());
             }
         }
-        blockToNodesMap.put(b, sortedInstructions);
+        return sortedInstructions;
     }
 
-    private void addUnscheduledToSorting(Block b, VirtualState state, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
+    private void addUnscheduledToLatestSorting(Block b, VirtualState state, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
         if (state != null) {
             // UnscheduledNodes should never be marked as visited.
             assert !visited.isMarked(state);
 
             for (Node input : state.inputs()) {
                 if (input instanceof VirtualState) {
-                    addUnscheduledToSorting(b, (VirtualState) input, sortedInstructions, visited);
+                    addUnscheduledToLatestSorting(b, (VirtualState) input, sortedInstructions, visited);
                 } else {
-                    addToSorting(b, (ScheduledNode) input, sortedInstructions, visited);
+                    addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited);
                 }
             }
         }
     }
 
-    private void addToSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
+    private void addToLatestSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
         if (i == null || visited.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) {
             return;
         }
@@ -396,17 +547,74 @@
                 assert state == null;
                 state = (FrameState) input;
             } else {
-                addToSorting(b, (ScheduledNode) input, sortedInstructions, visited);
+                addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited);
+            }
+        }
+        List<FloatingNode> inputs = phantomInputs.get(i);
+        if (inputs != null) {
+            for (FloatingNode input : inputs) {
+                addToLatestSorting(b, input, sortedInstructions, visited);
             }
         }
 
-        addToSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited);
+        addToLatestSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited);
         visited.mark(i);
-        addUnscheduledToSorting(b, state, sortedInstructions, visited);
+        addUnscheduledToLatestSorting(b, state, sortedInstructions, visited);
         assert write == null || !visited.isMarked(write);
-        addToSorting(b, write, sortedInstructions, visited);
+        addToLatestSorting(b, write, sortedInstructions, visited);
 
         // Now predecessors and inputs are scheduled => we can add this node.
         sortedInstructions.add(i);
     }
+
+    /**
+     * Sorts the nodes within a block by adding the nodes to a list in a post-order iteration over
+     * all usages. The resulting list is reversed to create an earliest-possible scheduling of
+     * nodes.
+     */
+    private List<ScheduledNode> sortNodesWithinBlockEarliest(Block b, NodeBitMap visited) {
+        List<ScheduledNode> sortedInstructions = new ArrayList<>(blockToNodesMap.get(b).size() + 2);
+        addToEarliestSorting(b, b.getEndNode(), sortedInstructions, visited);
+        Collections.reverse(sortedInstructions);
+        return sortedInstructions;
+    }
+
+    private void addToEarliestSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
+        if (i == null || visited.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) {
+            return;
+        }
+
+        visited.mark(i);
+        for (Node usage : i.usages()) {
+            if (usage instanceof VirtualState) {
+                // only fixed nodes can have VirtualState -> no need to schedule them
+            } else {
+                if (i instanceof LoopExitNode && usage instanceof ProxyNode) {
+                    // value proxies should be scheduled before the loopexit, not after
+                } else {
+                    addToEarliestSorting(b, (ScheduledNode) usage, sortedInstructions, visited);
+                }
+            }
+        }
+
+        if (i instanceof BeginNode) {
+            ArrayList<ProxyNode> proxies = (i instanceof LoopExitNode) ? new ArrayList<ProxyNode>() : null;
+            for (ScheduledNode inBlock : blockToNodesMap.get(b)) {
+                if (!visited.isMarked(inBlock)) {
+                    if (inBlock instanceof ProxyNode) {
+                        proxies.add((ProxyNode) inBlock);
+                    } else {
+                        addToEarliestSorting(b, inBlock, sortedInstructions, visited);
+                    }
+                }
+            }
+            sortedInstructions.add(i);
+            if (proxies != null) {
+                sortedInstructions.addAll(proxies);
+            }
+        } else {
+            sortedInstructions.add(i);
+            addToEarliestSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited);
+        }
+    }
 }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,7 +28,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.debug.*;
@@ -55,6 +54,7 @@
             dumpSandboxed(object, message);
         } catch (Throwable ex) {
             TTY.println("CFGPrinter: Exception during output of " + message + ": " + ex);
+            ex.printStackTrace();
         }
     }
 
@@ -100,10 +100,6 @@
     private static final AtomicInteger uniqueId = new AtomicInteger();
 
     public void dumpSandboxed(Object object, String message) {
-        GraalCompiler compiler = Debug.contextLookup(GraalCompiler.class);
-        if (compiler == null) {
-            return;
-        }
 
         if (cfgPrinter == null) {
             cfgFile = new File("compilations-" + timestamp + "_" + uniqueId.incrementAndGet() + ".cfg");
@@ -120,18 +116,23 @@
             return;
         }
 
-        cfgPrinter.target = compiler.target;
         if (object instanceof LIR) {
             cfgPrinter.lir = (LIR) object;
         } else {
             cfgPrinter.lir = Debug.contextLookup(LIR.class);
         }
         cfgPrinter.lirGenerator = Debug.contextLookup(LIRGenerator.class);
+        if (cfgPrinter.lirGenerator != null) {
+            cfgPrinter.target = cfgPrinter.lirGenerator.target();
+        }
         if (cfgPrinter.lir != null) {
             cfgPrinter.cfg = cfgPrinter.lir.cfg;
         }
 
-        CodeCacheProvider runtime = compiler.runtime;
+        CodeCacheProvider runtime = Debug.contextLookup(CodeCacheProvider.class);
+        if (runtime != null) {
+            cfgPrinter.target = runtime.getTarget();
+        }
 
         if (object instanceof BciBlockMapping) {
             BciBlockMapping blockMap = (BciBlockMapping) object;
@@ -150,32 +151,11 @@
             cfgPrinter.printCFG(message, Arrays.asList(cfgPrinter.cfg.getBlocks()));
 
         } else if (object instanceof CompilationResult) {
-            final CompilationResult tm = (CompilationResult) object;
-            final byte[] code = Arrays.copyOf(tm.getTargetCode(), tm.getTargetCodeSize());
-            CodeInfo info = new CodeInfo() {
-
-                public ResolvedJavaMethod getMethod() {
-                    return curMethod;
-                }
-
-                public long getStart() {
-                    return 0L;
-                }
-
-                public byte[] getCode() {
-                    return code;
-                }
-
-                @Override
-                public String toString() {
-                    int size = code == null ? 0 : code.length;
-                    return getMethod() + " installed code; length = " + size;
-                }
-            };
-            cfgPrinter.printMachineCode(runtime.disassemble(info, tm), message);
-        } else if (isCompilationResultAndCodeInfo(object)) {
+            final CompilationResult compResult = (CompilationResult) object;
+            cfgPrinter.printMachineCode(runtime.disassemble(compResult, null), message);
+        } else if (isCompilationResultAndInstalledCode(object)) {
             Object[] tuple = (Object[]) object;
-            cfgPrinter.printMachineCode(runtime.disassemble((CodeInfo) tuple[1], (CompilationResult) tuple[0]), message);
+            cfgPrinter.printMachineCode(runtime.disassemble((CompilationResult) tuple[0], (InstalledCode) tuple[1]), message);
         } else if (object instanceof Interval[]) {
             cfgPrinter.printIntervals(message, (Interval[]) object);
 
@@ -188,10 +168,10 @@
         cfgPrinter.flush();
     }
 
-    private static boolean isCompilationResultAndCodeInfo(Object object) {
+    private static boolean isCompilationResultAndInstalledCode(Object object) {
         if (object instanceof Object[]) {
             Object[] tuple = (Object[]) object;
-            if (tuple.length == 2 && tuple[0] instanceof CompilationResult && tuple[1] instanceof CodeInfo) {
+            if (tuple.length == 2 && tuple[0] instanceof CompilationResult && tuple[1] instanceof InstalledCode) {
                 return true;
             }
         }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Thu Mar 21 14:11:13 2013 +0100
@@ -33,6 +33,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.schedule.*;
 
 /**
  * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation
@@ -81,16 +82,22 @@
         if (sdf == null) {
             sdf = new SimpleDateFormat("YYYY-MM-dd-HHmm");
         }
-        String fileName = "Graphs-" + Thread.currentThread().getName() + "-" + sdf.format(new Date()) + ext;
+        String prefix = "Graphs-" + Thread.currentThread().getName() + "-" + sdf.format(new Date());
+        String num = "";
+        File file;
+        int i = 0;
+        while ((file = new File(prefix + num + ext)).exists()) {
+            num = "-" + Integer.toString(++i);
+        }
         try {
             if (GraalOptions.PrintBinaryGraphs) {
-                printer = new BinaryGraphPrinter(FileChannel.open(new File(fileName).toPath(), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW));
+                printer = new BinaryGraphPrinter(FileChannel.open(file.toPath(), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW));
             } else {
-                printer = new IdealGraphPrinter(new FileOutputStream(fileName));
+                printer = new IdealGraphPrinter(new FileOutputStream(file));
             }
-            TTY.println("Dumping IGV graphs to %s", fileName);
+            TTY.println("Dumping IGV graphs to %s", file.getName());
         } catch (IOException e) {
-            TTY.println("Failed to open %s to dump IGV graphs : %s", fileName, e);
+            TTY.println("Failed to open %s to dump IGV graphs : %s", file.getName(), e);
             failuresCount++;
             printer = null;
         }
@@ -153,13 +160,14 @@
                 // Save inline context for next dump.
                 previousInlineContext = inlineContext;
 
+                final SchedulePhase predefinedSchedule = getPredefinedSchedule();
                 Debug.sandbox("PrintingGraph", new Runnable() {
 
                     @Override
                     public void run() {
                         // Finally, output the graph.
                         try {
-                            printer.print(graph, message, null);
+                            printer.print(graph, message, predefinedSchedule);
                         } catch (IOException e) {
                             failuresCount++;
                             printer = null;
@@ -191,6 +199,16 @@
         return result;
     }
 
+    private static SchedulePhase getPredefinedSchedule() {
+        SchedulePhase result = null;
+        for (Object o : Debug.context()) {
+            if (o instanceof SchedulePhase) {
+                result = (SchedulePhase) o;
+            }
+        }
+        return result;
+    }
+
     private void openScope(String name, boolean showThread) {
         String prefix = showThread ? Thread.currentThread().getName() + ":" : "";
         try {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,7 +30,6 @@
 import com.oracle.graal.api.code.CompilationResult.CodeAnnotation;
 import com.oracle.graal.api.code.CompilationResult.CodeComment;
 import com.oracle.graal.api.code.CompilationResult.JumpTable;
-import com.oracle.graal.api.code.CompilationResult.LookupTable;
 
 /**
  * A HexCodeFile is a textual format for representing a chunk of machine code along with extra
@@ -122,8 +121,6 @@
 
     public final ArrayList<JumpTable> jumpTables = new ArrayList<>();
 
-    public final ArrayList<LookupTable> lookupTables = new ArrayList<>();
-
     public final String isa;
 
     public final int wordWidth;
@@ -169,10 +166,6 @@
             ps.printf("JumpTable %d %d %d %d %s%n", table.position, table.entrySize, table.low, table.high, SECTION_DELIM);
         }
 
-        for (LookupTable table : lookupTables) {
-            ps.printf("LookupTable %d %d %d %d %s%n", table.position, table.npairs, table.keySize, table.keySize, SECTION_DELIM);
-        }
-
         for (Map.Entry<Integer, List<String>> e : comments.entrySet()) {
             int pos = e.getKey();
             for (String comment : e.getValue()) {
@@ -233,9 +226,6 @@
             if (a instanceof JumpTable) {
                 JumpTable table = (JumpTable) a;
                 hcf.jumpTables.add(table);
-            } else if (a instanceof LookupTable) {
-                LookupTable table = (LookupTable) a;
-                hcf.lookupTables.add(table);
             } else if (a instanceof CodeComment) {
                 CodeComment comment = (CodeComment) a;
                 hcf.addComment(comment.position, comment.value);
@@ -422,15 +412,6 @@
                 int low = parseInt(bodyOffset + m.start(3), m.group(3));
                 int high = parseInt(bodyOffset + m.start(4), m.group(4));
                 hcf.jumpTables.add(new JumpTable(pos, low, high, entrySize));
-            } else if (header.equals("LookupTable")) {
-                checkHCF("LookupTable", headerOffset);
-                m = HexCodeFile.LOOKUP_TABLE.matcher(body);
-                check(m.matches(), bodyOffset, "LookupTable does not match pattern " + HexCodeFile.LOOKUP_TABLE);
-                int pos = parseInt(bodyOffset + m.start(1), m.group(1));
-                int npairs = parseInt(bodyOffset + m.start(2), m.group(2));
-                int keySize = parseInt(bodyOffset + m.start(3), m.group(3));
-                int offsetSize = parseInt(bodyOffset + m.start(4), m.group(4));
-                hcf.lookupTables.add(new LookupTable(pos, npairs, keySize, offsetSize));
             } else {
                 error(offset, "Unknown section header: " + header);
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.ptx;
+
+import static com.oracle.graal.api.code.MemoryBarriers.*;
+import static com.oracle.graal.api.code.Register.RegisterFlag.*;
+
+import java.nio.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.Register.*;
+
+/**
+ * Represents the PTX architecture.
+ */
+public class PTX extends Architecture {
+
+    // @formatter:off
+
+    /*
+     * Register State Space
+     *
+     * Registers (.reg state space) are fast storage locations. The number of
+     * registers is limited, and will vary from platform to platform. When the
+     * limit is exceeded, register variables will be spilled to memory, causing
+     * changes in performance. For each architecture, there is a recommended
+     * maximum number of registers to use (see the "CUDA Programming Guide" for
+     * details).
+     */
+
+    // General purpose registers
+    public static final Register r0  = new Register(0,  0,  8, "r0",  CPU, RegisterFlag.Byte);
+    public static final Register r1  = new Register(1,  1,  8, "r1",  CPU, RegisterFlag.Byte);
+    public static final Register r2  = new Register(2,  2,  8, "r2",  CPU, RegisterFlag.Byte);
+    public static final Register r3  = new Register(3,  3,  8, "r3",  CPU, RegisterFlag.Byte);
+    public static final Register r4  = new Register(4,  4,  8, "r4",  CPU, RegisterFlag.Byte);
+    public static final Register r5  = new Register(5,  5,  8, "r5",  CPU, RegisterFlag.Byte);
+    public static final Register r6  = new Register(6,  6,  8, "r6",  CPU, RegisterFlag.Byte);
+    public static final Register r7  = new Register(7,  7,  8, "r7",  CPU, RegisterFlag.Byte);
+
+    public static final Register r8  = new Register(8,  8,  8, "r8",  CPU, RegisterFlag.Byte);
+    public static final Register r9  = new Register(9,  9,  8, "r9",  CPU, RegisterFlag.Byte);
+    public static final Register r10 = new Register(10, 10, 8, "r10", CPU, RegisterFlag.Byte);
+    public static final Register r11 = new Register(11, 11, 8, "r11", CPU, RegisterFlag.Byte);
+    public static final Register r12 = new Register(12, 12, 8, "r12", CPU, RegisterFlag.Byte);
+    public static final Register r13 = new Register(13, 13, 8, "r13", CPU, RegisterFlag.Byte);
+    public static final Register r14 = new Register(14, 14, 8, "r14", CPU, RegisterFlag.Byte);
+    public static final Register r15 = new Register(15, 15, 8, "r15", CPU, RegisterFlag.Byte);
+
+    public static final Register[] gprRegisters = {
+        r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
+        r8,  r9,  r10, r11, r12, r13, r14, r15
+    };
+
+    // Floating point registers
+    public static final Register f0  = new Register(16, 0,  8, "f0",  FPU);
+    public static final Register f1  = new Register(17, 1,  8, "f1",  FPU);
+    public static final Register f2  = new Register(18, 2,  8, "f2",  FPU);
+    public static final Register f3  = new Register(19, 3,  8, "f3",  FPU);
+    public static final Register f4  = new Register(20, 4,  8, "f4",  FPU);
+    public static final Register f5  = new Register(21, 5,  8, "f5",  FPU);
+    public static final Register f6  = new Register(22, 6,  8, "f6",  FPU);
+    public static final Register f7  = new Register(23, 7,  8, "f7",  FPU);
+
+    public static final Register f8  = new Register(24, 8,  8, "f8",  FPU);
+    public static final Register f9  = new Register(25, 9,  8, "f9",  FPU);
+    public static final Register f10 = new Register(26, 10, 8, "f10", FPU);
+    public static final Register f11 = new Register(27, 11, 8, "f11", FPU);
+    public static final Register f12 = new Register(28, 12, 8, "f12", FPU);
+    public static final Register f13 = new Register(29, 13, 8, "f13", FPU);
+    public static final Register f14 = new Register(30, 14, 8, "f14", FPU);
+    public static final Register f15 = new Register(31, 15, 8, "f15", FPU);
+
+    public static final Register[] fpuRegisters = {
+        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+        f8,  f9,  f10, f11, f12, f13, f14, f15
+    };
+
+    public static final Register[] allRegisters = {
+        // GPR
+        r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
+        r8,  r9,  r10, r11, r12, r13, r14, r15,
+        // FPU
+        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+        f8,  f9,  f10, f11, f12, f13, f14, f15
+    };
+
+    public PTX() {
+        super("PTX",
+              8,
+              ByteOrder.LITTLE_ENDIAN,
+              allRegisters,
+              LOAD_STORE | STORE_STORE,
+              0,
+              r15.encoding + 1,
+              8);
+    }
+    // @formatter:on
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.amd64/src/com/oracle/graal/snippets/amd64/AMD64ConvertSnippets.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.snippets.amd64;
+
+import static com.oracle.graal.snippets.SnippetTemplate.*;
+import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
+import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.calc.ConvertNode.Op;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.snippets.*;
+import com.oracle.graal.snippets.Snippet.Parameter;
+import com.oracle.graal.snippets.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.snippets.SnippetTemplate.Arguments;
+import com.oracle.graal.snippets.SnippetTemplate.Key;
+
+/**
+ * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match
+ * the semantics of the JVM specification.
+ */
+public class AMD64ConvertSnippets implements SnippetsInterface {
+
+    /**
+     * Converts a float to an int.
+     * <p>
+     * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the
+     * conversion. If the float value is a NaN, infinity or if the result of the conversion is
+     * larger than {@link Integer#MAX_VALUE} then CVTTSS2SI returns {@link Integer#MIN_VALUE} and
+     * extra tests are required on the float value to return the correct int value.
+     * 
+     * @param input the float being converted
+     * @param result the result produced by the CVTTSS2SI instruction
+     */
+    @Snippet
+    public static int f2i(@Parameter("input") float input, @Parameter("result") int result) {
+        if (result == Integer.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
+            if (Float.isNaN(input)) {
+                // input is NaN -> return 0
+                return 0;
+            } else if (input > 0.0f) {
+                // input is > 0 -> return max int
+                return Integer.MAX_VALUE;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Converts a float to a long.
+     * <p>
+     * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the
+     * conversion. If the float value is a NaN or infinity then CVTTSS2SI returns
+     * {@link Long#MIN_VALUE} and extra tests are required on the float value to return the correct
+     * long value.
+     * 
+     * @param input the float being converted
+     * @param result the result produced by the CVTTSS2SI instruction
+     */
+    @Snippet
+    public static long f2l(@Parameter("input") float input, @Parameter("result") long result) {
+        if (result == Long.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
+            if (Float.isNaN(input)) {
+                // input is NaN -> return 0
+                return 0;
+            } else if (input > 0.0f) {
+                // input is > 0 -> return max int
+                return Long.MAX_VALUE;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Converts a double to an int.
+     * <p>
+     * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the
+     * conversion. If the double value is a NaN, infinity or if the result of the conversion is
+     * larger than {@link Integer#MAX_VALUE} then CVTTSD2SI returns {@link Integer#MIN_VALUE} and
+     * extra tests are required on the double value to return the correct int value.
+     * 
+     * @param input the double being converted
+     * @param result the result produced by the CVTTSS2SI instruction
+     */
+    @Snippet
+    public static int d2i(@Parameter("input") double input, @Parameter("result") int result) {
+        if (result == Integer.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
+            if (Double.isNaN(input)) {
+                // input is NaN -> return 0
+                return 0;
+            } else if (input > 0.0d) {
+                // input is positive -> return maxInt
+                return Integer.MAX_VALUE;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Converts a double to a long.
+     * <p>
+     * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the
+     * conversion. If the double value is a NaN, infinity or if the result of the conversion is
+     * larger than {@link Long#MAX_VALUE} then CVTTSD2SI returns {@link Long#MIN_VALUE} and extra
+     * tests are required on the double value to return the correct long value.
+     * 
+     * @param input the double being converted
+     * @param result the result produced by the CVTTSS2SI instruction
+     */
+    @Snippet
+    public static long d2l(@Parameter("input") double input, @Parameter("result") long result) {
+        if (result == Long.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
+            if (Double.isNaN(input)) {
+                // input is NaN -> return 0
+                return 0;
+            } else if (input > 0.0d) {
+                // input is positive -> return maxInt
+                return Long.MAX_VALUE;
+            }
+        }
+        return result;
+    }
+
+    public static class Templates extends AbstractTemplates<AMD64ConvertSnippets> {
+
+        private final ResolvedJavaMethod f2i;
+        private final ResolvedJavaMethod f2l;
+        private final ResolvedJavaMethod d2i;
+        private final ResolvedJavaMethod d2l;
+
+        public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target) {
+            super(runtime, assumptions, target, AMD64ConvertSnippets.class);
+            f2i = snippet("f2i", float.class, int.class);
+            f2l = snippet("f2l", float.class, long.class);
+            d2i = snippet("d2i", double.class, int.class);
+            d2l = snippet("d2l", double.class, long.class);
+        }
+
+        public void lower(ConvertNode convert, LoweringTool tool) {
+            if (convert.opcode == Op.F2I) {
+                lower0(convert, tool, f2i);
+            } else if (convert.opcode == Op.F2L) {
+                lower0(convert, tool, f2l);
+            } else if (convert.opcode == Op.D2I) {
+                lower0(convert, tool, d2i);
+            } else if (convert.opcode == Op.D2L) {
+                lower0(convert, tool, d2l);
+            }
+        }
+
+        private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) {
+            StructuredGraph graph = (StructuredGraph) convert.graph();
+
+            // Insert a unique placeholder node in place of the Convert node so that the
+            // Convert node can be used as an input to the snippet. All usage of the
+            // Convert node are replaced by the placeholder which in turn is replaced by the
+            // snippet.
+
+            LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp()));
+            convert.replaceAtUsages(replacee);
+            Key key = new Key(snippet);
+            Arguments arguments = arguments("input", convert.value()).add("result", convert);
+            SnippetTemplate template = cache.get(key, assumptions);
+            Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments);
+            template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments);
+        }
+    }
+}
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/CheckCastTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/CheckCastTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.snippets;
 
-import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.test.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 
@@ -42,7 +42,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void test1() {
         test("asNumber", profile(), 111);
         test("asNumber", profile(Integer.class), 111);
@@ -52,7 +52,7 @@
         test("asNumberExt", profile(Long.class, Short.class), 111);
     }
 
-    @Test
+    @LongTest
     public void test2() {
         test("asString", profile(), "111");
         test("asString", profile(String.class), "111");
@@ -68,27 +68,27 @@
         test("asStringExt", profile(String.class), "111");
     }
 
-    @Test
+    @LongTest
     public void test3() {
         test("asNumber", profile(), "111");
     }
 
-    @Test
+    @LongTest
     public void test4() {
         test("asString", profile(String.class), 111);
     }
 
-    @Test
+    @LongTest
     public void test5() {
         test("asNumberExt", profile(), "111");
     }
 
-    @Test
+    @LongTest
     public void test6() {
         test("asStringExt", profile(String.class), 111);
     }
 
-    @Test
+    @LongTest
     public void test7() {
         Throwable throwable = new Exception();
         test("asThrowable", profile(), throwable);
@@ -96,12 +96,12 @@
         test("asThrowable", profile(Exception.class, Error.class), throwable);
     }
 
-    @Test
+    @LongTest
     public void test8() {
         test("arrayStore", new Object[100], "111");
     }
 
-    @Test
+    @LongTest
     public void test8_1() {
         test("arrayFill", new Object[100], "111");
     }
@@ -198,7 +198,7 @@
         return (Cloneable) o;
     }
 
-    @Test
+    @LongTest
     public void test9() {
         Object o = new Depth13();
         test("asDepth12", profile(), o);
@@ -206,7 +206,7 @@
         test("asDepth12", profile(Depth13.class, Depth14.class), o);
     }
 
-    @Test
+    @LongTest
     public void test10() {
         Object o = new Depth13[3][];
         test("asDepth12Arr", o);
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfDynamicTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfDynamicTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,8 +22,7 @@
  */
 package com.oracle.graal.snippets;
 
-import org.junit.*;
-
+import com.oracle.graal.test.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.java.*;
 
@@ -36,7 +35,7 @@
         return value;
     }
 
-    @Test
+    @LongTest
     public void test100() {
         final Object nul = null;
         test("isStringDynamic", nul);
@@ -44,7 +43,7 @@
         test("isStringDynamic", Object.class);
     }
 
-    @Test
+    @LongTest
     public void test101() {
         final Object nul = null;
         test("isStringIntDynamic", nul);
@@ -52,7 +51,7 @@
         test("isStringIntDynamic", Object.class);
     }
 
-    @Test
+    @LongTest
     public void test103() {
         test("isInstanceDynamic", String.class, null);
         test("isInstanceDynamic", String.class, "object");
@@ -62,7 +61,7 @@
         test("isInstanceDynamic", int.class, Object.class);
     }
 
-    @Test
+    @LongTest
     public void test104() {
         test("isInstanceIntDynamic", String.class, null);
         test("isInstanceIntDynamic", String.class, "object");
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,12 +24,12 @@
 
 import java.util.*;
 
-import org.junit.*;
 
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.api.code.CompilationResult.Site;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.test.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
@@ -57,7 +57,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void test1() {
         test("isString", profile(), "object");
         test("isString", profile(String.class), "object");
@@ -66,7 +66,7 @@
         test("isString", profile(String.class), Object.class);
     }
 
-    @Test
+    @LongTest
     public void test2() {
         test("isStringInt", profile(), "object");
         test("isStringInt", profile(String.class), "object");
@@ -75,7 +75,7 @@
         test("isStringInt", profile(String.class), Object.class);
     }
 
-    @Test
+    @LongTest
     public void test2_1() {
         test("isStringIntComplex", profile(), "object");
         test("isStringIntComplex", profile(String.class), "object");
@@ -84,7 +84,7 @@
         test("isStringIntComplex", profile(String.class), Object.class);
     }
 
-    @Test
+    @LongTest
     public void test3() {
         Throwable throwable = new Exception();
         test("isThrowable", profile(), throwable);
@@ -96,7 +96,7 @@
         test("isThrowable", profile(Exception.class, Error.class), Object.class);
     }
 
-    @Test
+    @LongTest
     public void test3_1() {
         onlyFirstIsException(new Exception(), new Error());
         test("onlyFirstIsException", profile(), new Exception(), new Error());
@@ -105,7 +105,7 @@
         test("onlyFirstIsException", profile(), new Error(), new Error());
     }
 
-    @Test
+    @LongTest
     public void test4() {
         Throwable throwable = new Exception();
         test("isThrowableInt", profile(), throwable);
@@ -117,7 +117,7 @@
         test("isThrowableInt", profile(Exception.class, Error.class), Object.class);
     }
 
-    @Test
+    @LongTest
     public void test5() {
         Map map = new HashMap<>();
         test("isMap", profile(), map);
@@ -129,7 +129,7 @@
         test("isMap", profile(TreeMap.class, HashMap.class), Object.class);
     }
 
-    @Test
+    @LongTest
     public void test6() {
         Map map = new HashMap<>();
         test("isMapInt", profile(), map);
@@ -141,7 +141,7 @@
         test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class);
     }
 
-    @Test
+    @LongTest
     public void test7() {
         Object o = new Depth13();
         test("isDepth12", profile(), o);
@@ -154,7 +154,7 @@
         test("isDepth12", profile(Depth13.class, Depth14.class), o);
     }
 
-    @Test
+    @LongTest
     public void test8() {
         Object o = new Depth13();
         test("isDepth12Int", profile(), o);
@@ -260,7 +260,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void test9() {
         MyCall callAt63 = new MyCall(63);
         MyMark markAt63 = new MyMark(63);
@@ -277,10 +277,10 @@
         return s1.offset - s2.offset;
     }
 
-    @Test
+    @LongTest
     public void test10() {
         Mark[] noMarks = {};
-        Call callAt63 = new Call("ignore", 63, 5, true, null);
+        Call callAt63 = new Call(null, 63, 5, true, null);
         Mark markAt63 = new Mark(63, "1", noMarks);
         test("compareSites", callAt63, callAt63);
         test("compareSites", callAt63, markAt63);
@@ -302,7 +302,7 @@
      * The test exists in this source file as the transformation was originally motivated by the
      * need to remove use of special JumpNodes in the {@code InstanceOfSnippets}.
      */
-    @Test
+    @LongTest
     public void test_removeIntermediateMaterialization() {
         List<String> list = Arrays.asList("1", "2", "3", "4");
         test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no");
@@ -357,7 +357,7 @@
         return o instanceof D[];
     }
 
-    @Test
+    @LongTest
     public void testArray() {
         Object aArray = new A[10];
         test("isArrayOfA", aArray);
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -426,9 +426,9 @@
                 Assumptions assumptions = new Assumptions(true);
                 new ComputeProbabilityPhase().apply(graph);
                 Debug.dump(graph, "Graph");
-                new InliningPhase(null, runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                new InliningPhase(runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 Debug.dump(graph, "Graph");
-                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase(runtime(), assumptions).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
 
                 assertNotInGraph(graph, Invoke.class);
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewArrayTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewArrayTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,6 +25,7 @@
 import org.junit.*;
 
 import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.test.*;
 
 /**
  * Tests the implementation of {@code [A]NEWARRAY}.
@@ -57,7 +58,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void test1() {
         for (String type : new String[]{"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) {
             test("new" + type + "Array7");
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewInstanceTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewInstanceTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -27,6 +27,7 @@
 import org.junit.*;
 
 import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.test.*;
 
 /**
  * Tests the implementation of {@code NEW}.
@@ -56,12 +57,12 @@
         }
     }
 
-    @Test
+    @LongTest
     public void test1() {
         test("newObject");
     }
 
-    @Test
+    @LongTest
     public void test2() {
         test("newObjectTwice");
     }
@@ -70,37 +71,37 @@
         return new Object();
     }
 
-    @Test
+    @LongTest
     public void test3() {
         test("newObjectLoop", 100);
     }
 
-    @Test
+    @LongTest
     public void test4() {
         test("newBigObject");
     }
 
-    @Test
+    @LongTest
     public void test5() {
         test("newSomeObject");
     }
 
-    @Test
+    @LongTest
     public void test6() {
         test("newEmptyString");
     }
 
-    @Test
+    @LongTest
     public void test7() {
         test("newString", "value");
     }
 
-    @Test
+    @LongTest
     public void test8() {
         test("newHashMap", 31);
     }
 
-    @Test
+    @LongTest
     public void test9() {
         test("newRegression", true);
     }
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewMultiArrayTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewMultiArrayTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,11 +25,10 @@
 import java.lang.reflect.*;
 import java.util.*;
 
-import org.junit.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.test.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 
@@ -87,7 +86,7 @@
     Class bottomClass;
     int[] dimensions;
 
-    @Test
+    @LongTest
     public void test1() {
         for (Class clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) {
             bottomClass = clazz;
@@ -118,7 +117,7 @@
         return new Object[10][9][8];
     }
 
-    @Test
+    @LongTest
     public void test2() {
         test("newMultiArrayException");
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/PointerTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.snippets;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.snippets.Snippet.SnippetInliningPolicy;
+import com.oracle.graal.word.*;
+
+/**
+ * Tests for the {@link Pointer} read and write operations.
+ */
+public class PointerTest extends GraalCompilerTest implements SnippetsInterface {
+
+    private static final Object ID = new Object();
+    private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object};
+    private final TargetDescription target;
+    private final SnippetInstaller installer;
+
+    public PointerTest() {
+        target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget();
+        installer = new SnippetInstaller(runtime, new Assumptions(false), target);
+    }
+
+    private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>();
+
+    @Override
+    protected StructuredGraph parse(Method m) {
+        ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m);
+        return installer.makeGraph(resolvedMethod, inliningPolicy.get());
+    }
+
+    @Test
+    public void test_read1() {
+        for (Kind kind : KINDS) {
+            assertRead(parse("read" + kind.name() + "1"), kind, false, ID);
+        }
+    }
+
+    @Test
+    public void test_read2() {
+        for (Kind kind : KINDS) {
+            assertRead(parse("read" + kind.name() + "2"), kind, true, ID);
+        }
+    }
+
+    @Test
+    public void test_read3() {
+        for (Kind kind : KINDS) {
+            assertRead(parse("read" + kind.name() + "3"), kind, false, LocationNode.UNKNOWN_LOCATION);
+        }
+    }
+
+    @Test
+    public void test_write1() {
+        for (Kind kind : KINDS) {
+            assertWrite(parse("write" + kind.name() + "1"), kind, false, ID);
+        }
+    }
+
+    @Test
+    public void test_write2() {
+        for (Kind kind : KINDS) {
+            assertWrite(parse("write" + kind.name() + "2"), kind, true, ID);
+        }
+    }
+
+    @Test
+    public void test_write3() {
+        for (Kind kind : KINDS) {
+            assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION);
+        }
+    }
+
+    private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) {
+        ReadNode read = (ReadNode) graph.start().next();
+        Assert.assertEquals(kind.getStackKind(), read.kind());
+
+        UnsafeCastNode cast = (UnsafeCastNode) read.object();
+        Assert.assertEquals(graph.getLocal(0), cast.object());
+        Assert.assertEquals(target.wordKind, cast.kind());
+
+        IndexedLocationNode location = (IndexedLocationNode) read.location();
+        Assert.assertEquals(kind, location.getValueKind());
+        Assert.assertEquals(locationIdentity, location.locationIdentity());
+        Assert.assertEquals(1, location.indexScaling());
+
+        if (indexConvert) {
+            ConvertNode convert = (ConvertNode) location.index();
+            Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode);
+            Assert.assertEquals(graph.getLocal(1), convert.value());
+        } else {
+            Assert.assertEquals(graph.getLocal(1), location.index());
+        }
+
+        ReturnNode ret = (ReturnNode) read.next();
+        Assert.assertEquals(read, ret.result());
+    }
+
+    private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) {
+        WriteNode write = (WriteNode) graph.start().next();
+        Assert.assertEquals(graph.getLocal(2), write.value());
+        Assert.assertEquals(Kind.Void, write.kind());
+        Assert.assertEquals(FrameState.INVALID_FRAMESTATE_BCI, write.stateAfter().bci);
+
+        UnsafeCastNode cast = (UnsafeCastNode) write.object();
+        Assert.assertEquals(graph.getLocal(0), cast.object());
+        Assert.assertEquals(target.wordKind, cast.kind());
+
+        IndexedLocationNode location = (IndexedLocationNode) write.location();
+        Assert.assertEquals(kind, location.getValueKind());
+        Assert.assertEquals(locationIdentity, location.locationIdentity());
+        Assert.assertEquals(1, location.indexScaling());
+
+        if (indexConvert) {
+            ConvertNode convert = (ConvertNode) location.index();
+            Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode);
+            Assert.assertEquals(graph.getLocal(1), convert.value());
+        } else {
+            Assert.assertEquals(graph.getLocal(1), location.index());
+        }
+
+        AbstractStateSplit stateSplit = (AbstractStateSplit) write.next();
+        Assert.assertEquals(FrameState.AFTER_BCI, stateSplit.stateAfter().bci);
+
+        ReturnNode ret = (ReturnNode) stateSplit.next();
+        Assert.assertEquals(null, ret.result());
+    }
+
+    @Snippet
+    public static byte readByte1(Object o, int offset) {
+        return Word.fromObject(o).readByte(offset, ID);
+    }
+
+    @Snippet
+    public static byte readByte2(Object o, int offset) {
+        return Word.fromObject(o).readByte(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static byte readByte3(Object o, int offset) {
+        return Word.fromObject(o).readByte(offset);
+    }
+
+    @Snippet
+    public static void writeByte1(Object o, int offset, byte value) {
+        Word.fromObject(o).writeByte(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeByte2(Object o, int offset, byte value) {
+        Word.fromObject(o).writeByte(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeByte3(Object o, int offset, byte value) {
+        Word.fromObject(o).writeByte(offset, value);
+    }
+
+    @Snippet
+    public static char readChar1(Object o, int offset) {
+        return Word.fromObject(o).readChar(offset, ID);
+    }
+
+    @Snippet
+    public static char readChar2(Object o, int offset) {
+        return Word.fromObject(o).readChar(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static char readChar3(Object o, int offset) {
+        return Word.fromObject(o).readChar(offset);
+    }
+
+    @Snippet
+    public static void writeChar1(Object o, int offset, char value) {
+        Word.fromObject(o).writeChar(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeChar2(Object o, int offset, char value) {
+        Word.fromObject(o).writeChar(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeChar3(Object o, int offset, char value) {
+        Word.fromObject(o).writeChar(offset, value);
+    }
+
+    @Snippet
+    public static short readShort1(Object o, int offset) {
+        return Word.fromObject(o).readShort(offset, ID);
+    }
+
+    @Snippet
+    public static short readShort2(Object o, int offset) {
+        return Word.fromObject(o).readShort(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static short readShort3(Object o, int offset) {
+        return Word.fromObject(o).readShort(offset);
+    }
+
+    @Snippet
+    public static void writeShort1(Object o, int offset, short value) {
+        Word.fromObject(o).writeShort(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeShort2(Object o, int offset, short value) {
+        Word.fromObject(o).writeShort(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeShort3(Object o, int offset, short value) {
+        Word.fromObject(o).writeShort(offset, value);
+    }
+
+    @Snippet
+    public static int readInt1(Object o, int offset) {
+        return Word.fromObject(o).readInt(offset, ID);
+    }
+
+    @Snippet
+    public static int readInt2(Object o, int offset) {
+        return Word.fromObject(o).readInt(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static int readInt3(Object o, int offset) {
+        return Word.fromObject(o).readInt(offset);
+    }
+
+    @Snippet
+    public static void writeInt1(Object o, int offset, int value) {
+        Word.fromObject(o).writeInt(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeInt2(Object o, int offset, int value) {
+        Word.fromObject(o).writeInt(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeInt3(Object o, int offset, int value) {
+        Word.fromObject(o).writeInt(offset, value);
+    }
+
+    @Snippet
+    public static long readLong1(Object o, int offset) {
+        return Word.fromObject(o).readLong(offset, ID);
+    }
+
+    @Snippet
+    public static long readLong2(Object o, int offset) {
+        return Word.fromObject(o).readLong(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static long readLong3(Object o, int offset) {
+        return Word.fromObject(o).readLong(offset);
+    }
+
+    @Snippet
+    public static void writeLong1(Object o, int offset, long value) {
+        Word.fromObject(o).writeLong(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeLong2(Object o, int offset, long value) {
+        Word.fromObject(o).writeLong(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeLong3(Object o, int offset, long value) {
+        Word.fromObject(o).writeLong(offset, value);
+    }
+
+    @Snippet
+    public static float readFloat1(Object o, int offset) {
+        return Word.fromObject(o).readFloat(offset, ID);
+    }
+
+    @Snippet
+    public static float readFloat2(Object o, int offset) {
+        return Word.fromObject(o).readFloat(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static float readFloat3(Object o, int offset) {
+        return Word.fromObject(o).readFloat(offset);
+    }
+
+    @Snippet
+    public static void writeFloat1(Object o, int offset, float value) {
+        Word.fromObject(o).writeFloat(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeFloat2(Object o, int offset, float value) {
+        Word.fromObject(o).writeFloat(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeFloat3(Object o, int offset, float value) {
+        Word.fromObject(o).writeFloat(offset, value);
+    }
+
+    @Snippet
+    public static double readDouble1(Object o, int offset) {
+        return Word.fromObject(o).readDouble(offset, ID);
+    }
+
+    @Snippet
+    public static double readDouble2(Object o, int offset) {
+        return Word.fromObject(o).readDouble(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static double readDouble3(Object o, int offset) {
+        return Word.fromObject(o).readDouble(offset);
+    }
+
+    @Snippet
+    public static void writeDouble1(Object o, int offset, double value) {
+        Word.fromObject(o).writeDouble(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeDouble2(Object o, int offset, double value) {
+        Word.fromObject(o).writeDouble(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeDouble3(Object o, int offset, double value) {
+        Word.fromObject(o).writeDouble(offset, value);
+    }
+
+    @Snippet
+    public static Object readObject1(Object o, int offset) {
+        return Word.fromObject(o).readObject(offset, ID);
+    }
+
+    @Snippet
+    public static Object readObject2(Object o, int offset) {
+        return Word.fromObject(o).readObject(Word.signed(offset), ID);
+    }
+
+    @Snippet
+    public static Object readObject3(Object o, int offset) {
+        return Word.fromObject(o).readObject(offset);
+    }
+
+    @Snippet
+    public static void writeObject1(Object o, int offset, Object value) {
+        Word.fromObject(o).writeObject(offset, value, ID);
+    }
+
+    @Snippet
+    public static void writeObject2(Object o, int offset, Object value) {
+        Word.fromObject(o).writeObject(Word.signed(offset), value, ID);
+    }
+
+    @Snippet
+    public static void writeObject3(Object o, int offset, Object value) {
+        Word.fromObject(o).writeObject(offset, value);
+    }
+
+}
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,13 +24,11 @@
 
 import java.lang.reflect.*;
 
-import org.junit.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.test.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.snippets.Snippet.SnippetInliningPolicy;
 import com.oracle.graal.word.*;
@@ -43,7 +41,7 @@
     private final SnippetInstaller installer;
 
     public WordTest() {
-        TargetDescription target = Graal.getRequiredCapability(GraalCompiler.class).target;
+        TargetDescription target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget();
         installer = new SnippetInstaller(runtime, new Assumptions(false), target);
     }
 
@@ -52,10 +50,10 @@
     @Override
     protected StructuredGraph parse(Method m) {
         ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m);
-        return installer.makeGraph(resolvedMethod, inliningPolicy.get(), false);
+        return installer.makeGraph(resolvedMethod, inliningPolicy.get());
     }
 
-    @Test
+    @LongTest
     public void construction() {
         long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L,
                         Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L};
@@ -67,7 +65,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void test_arithmetic() {
         long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L,
                         Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L};
@@ -104,7 +102,7 @@
         }
     }
 
-    @Test
+    @LongTest
     public void test_compare() {
         long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE};
         for (long word1 : words) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java	Thu Mar 21 14:11:13 2013 +0100
@@ -56,6 +56,12 @@
     String className() default "";
 
     /**
+     * Determines if the substitutions are for classes that may not be part of the runtime.
+     * Substitutions for such classes are omitted if the original classes cannot be found.
+     */
+    boolean optional() default false;
+
+    /**
      * Denotes a substitute method. A substitute method can call the original/substituted method by
      * making a recursive call to itself.
      */
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java	Thu Mar 21 14:11:13 2013 +0100
@@ -95,7 +95,7 @@
             } else {
                 KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool);
                 SnippetTemplate template = cache.get(keyAndArguments.key, assumptions);
-                template.instantiate(runtime, instanceOf, replacer, tool.lastFixedNode(), keyAndArguments.arguments);
+                template.instantiate(runtime, instanceOf, replacer, tool, keyAndArguments.arguments);
             }
         }
 
@@ -223,11 +223,15 @@
             usage.replaceFirstInput(instanceOf, instantiation.asCondition(trueValue));
         }
 
+        private boolean usageFollowsInstantiation() {
+            return instantiation.result != null && instantiation.result.merge().next() == usage;
+        }
+
         @Override
         public void replace(ValueNode oldNode, ValueNode newNode) {
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
-            if (sameBlock && solitaryUsage) {
+            if (sameBlock && solitaryUsage && usageFollowsInstantiation()) {
                 removeIntermediateMaterialization(newNode);
             } else {
                 newNode.inferStamp();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetFrameStateCleanupPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetFrameStateCleanupPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,30 +22,98 @@
  */
 package com.oracle.graal.snippets;
 
-import com.oracle.graal.graph.*;
+import java.util.*;
+
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.graph.ReentrantNodeIterator.LoopInfo;
+import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
 
 /**
  * Removes frame states from {@linkplain StateSplit#hasSideEffect() non-side-effecting} nodes in a
  * snippet.
+ * 
+ * The frame states of side-effecting nodes are replaced with
+ * {@linkplain FrameState#INVALID_FRAMESTATE_BCI invalid} frame states. Loops that contain invalid
+ * frame states are also assigned an invalid frame state.
+ * 
+ * The invalid frame states ensure that no deoptimization to a snippet frame state will happen.
  */
 public class SnippetFrameStateCleanupPhase extends Phase {
 
     @Override
     protected void run(StructuredGraph graph) {
-        for (Node node : graph.getNodes().filterInterface(StateSplit.class)) {
-            StateSplit stateSplit = (StateSplit) node;
-            FrameState frameState = stateSplit.stateAfter();
-            if (!stateSplit.hasSideEffect()) {
+        ReentrantNodeIterator.apply(new SnippetFrameStateCleanupClosure(), graph.start(), new CleanupState(false), null);
+    }
+
+    private static class CleanupState {
+
+        public boolean containsFrameState;
+
+        public CleanupState(boolean containsFrameState) {
+            this.containsFrameState = containsFrameState;
+        }
+    }
+
+    /**
+     * A proper (loop-aware) iteration over the graph is used to detect loops that contain invalid
+     * frame states, so that they can be marked with an invalid frame state.
+     */
+    private static class SnippetFrameStateCleanupClosure extends NodeIteratorClosure<CleanupState> {
+
+        @Override
+        protected void processNode(FixedNode node, CleanupState currentState) {
+            if (node instanceof StateSplit) {
+                StateSplit stateSplit = (StateSplit) node;
+                FrameState frameState = stateSplit.stateAfter();
                 if (frameState != null) {
-                    stateSplit.setStateAfter(null);
+                    if (stateSplit.hasSideEffect()) {
+                        currentState.containsFrameState = true;
+                        stateSplit.setStateAfter(node.graph().add(new FrameState(FrameState.INVALID_FRAMESTATE_BCI)));
+                    } else {
+                        stateSplit.setStateAfter(null);
+                    }
                     if (frameState.usages().isEmpty()) {
                         GraphUtil.killWithUnusedFloatingInputs(frameState);
                     }
                 }
             }
         }
+
+        @Override
+        protected CleanupState merge(MergeNode merge, List<CleanupState> states) {
+            for (CleanupState state : states) {
+                if (state.containsFrameState) {
+                    return new CleanupState(true);
+                }
+            }
+            return new CleanupState(false);
+        }
+
+        @Override
+        protected CleanupState afterSplit(BeginNode node, CleanupState oldState) {
+            return new CleanupState(oldState.containsFrameState);
+        }
+
+        @Override
+        protected Map<LoopExitNode, CleanupState> processLoop(LoopBeginNode loop, CleanupState initialState) {
+            LoopInfo<CleanupState> info = ReentrantNodeIterator.processLoop(this, loop, new CleanupState(false));
+            boolean containsFrameState = false;
+            for (CleanupState state : info.endStates.values()) {
+                containsFrameState |= state.containsFrameState;
+            }
+            if (containsFrameState) {
+                loop.setStateAfter(loop.graph().add(new FrameState(FrameState.INVALID_FRAMESTATE_BCI)));
+            }
+            if (containsFrameState || initialState.containsFrameState) {
+                for (CleanupState state : info.exitStates.values()) {
+                    state.containsFrameState = true;
+                }
+            }
+            return info.exitStates;
+        }
+
     }
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Thu Mar 21 14:11:13 2013 +0100
@@ -53,10 +53,10 @@
  */
 public class SnippetInstaller {
 
-    private final MetaAccessProvider runtime;
-    private final TargetDescription target;
-    private final Assumptions assumptions;
-    private final BoxingMethodPool pool;
+    protected final MetaAccessProvider runtime;
+    protected final TargetDescription target;
+    protected final Assumptions assumptions;
+    protected final BoxingMethodPool pool;
     private final Thread owner;
 
     /**
@@ -89,7 +89,7 @@
                 }
                 ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method);
                 assert snippet.getCompilerStorage().get(Graph.class) == null : method;
-                StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet), false);
+                StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet));
                 // System.out.println("snippet: " + graph);
                 snippet.getCompilerStorage().put(Graph.class, graph);
             }
@@ -125,14 +125,18 @@
                 }
                 String originalName = originalName(substituteMethod, methodSubstitution.value());
                 Class[] originalParameters = originalParameters(substituteMethod, methodSubstitution.signature(), methodSubstitution.isStatic());
-                Method originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
-                installMethodSubstitution(originalMethod, substituteMethod);
+                Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
+                if (originalMethod != null) {
+                    installMethodSubstitution(originalMethod, substituteMethod);
+                }
             }
             if (macroSubstitution != null) {
                 String originalName = originalName(substituteMethod, macroSubstitution.value());
                 Class[] originalParameters = originalParameters(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic());
-                Method originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
-                installMacroSubstitution(originalMethod, macroSubstitution.macro());
+                Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
+                if (originalMethod != null) {
+                    installMacroSubstitution(originalMethod, macroSubstitution.macro());
+                }
             }
         }
     }
@@ -145,16 +149,19 @@
     /**
      * Installs a method substitution.
      * 
-     * @param originalMethod a method being substituted
+     * @param originalMethod a method or constructor being substituted
      * @param substituteMethod the substitute method
      */
-    protected void installMethodSubstitution(Method originalMethod, Method substituteMethod) {
+    protected void installMethodSubstitution(Member originalMethod, Method substituteMethod) {
         substitute = runtime.lookupJavaMethod(substituteMethod);
-        original = runtime.lookupJavaMethod(originalMethod);
+        if (originalMethod instanceof Method) {
+            original = runtime.lookupJavaMethod((Method) originalMethod);
+        } else {
+            original = runtime.lookupJavaConstructor((Constructor) originalMethod);
+        }
         try {
-            // System.out.println("substitution: " + MetaUtil.format("%H.%n(%p)", original) +
-            // " --> " + MetaUtil.format("%H.%n(%p)", substitute));
-            StructuredGraph graph = makeGraph(substitute, inliningPolicy(substitute), true);
+            Debug.log("substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute));
+            StructuredGraph graph = makeGraph(substitute, inliningPolicy(substitute));
             Object oldValue = original.getCompilerStorage().put(Graph.class, graph);
             assert oldValue == null;
         } finally {
@@ -167,11 +174,16 @@
     /**
      * Installs a macro substitution.
      * 
-     * @param originalMethod a method being substituted
+     * @param originalMethod a method or constructor being substituted
      * @param macro the substitute macro node class
      */
-    protected void installMacroSubstitution(Method originalMethod, Class<? extends FixedWithNextNode> macro) {
-        ResolvedJavaMethod originalJavaMethod = runtime.lookupJavaMethod(originalMethod);
+    protected void installMacroSubstitution(Member originalMethod, Class<? extends FixedWithNextNode> macro) {
+        ResolvedJavaMethod originalJavaMethod;
+        if (originalMethod instanceof Method) {
+            originalJavaMethod = runtime.lookupJavaMethod((Method) originalMethod);
+        } else {
+            originalJavaMethod = runtime.lookupJavaConstructor((Constructor) originalMethod);
+        }
         Object oldValue = originalJavaMethod.getCompilerStorage().put(Node.class, macro);
         assert oldValue == null;
     }
@@ -192,23 +204,27 @@
         }
     }
 
-    public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy, final boolean isSubstitution) {
+    /**
+     * Does final processing of a snippet graph.
+     */
+    protected void finalizeGraph(ResolvedJavaMethod method, StructuredGraph graph) {
+        new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
+        assert SnippetTemplate.hasConstantParameter(method) || SnippetIntrinsificationVerificationPhase.verify(graph);
+
+        new SnippetFrameStateCleanupPhase().apply(graph);
+        new DeadCodeEliminationPhase().apply(graph);
+
+        new InsertStateAfterPlaceholderPhase().apply(graph);
+    }
+
+    public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
         return Debug.scope("BuildSnippetGraph", new Object[]{method}, new Callable<StructuredGraph>() {
 
             @Override
             public StructuredGraph call() throws Exception {
                 StructuredGraph graph = parseGraph(method, policy);
 
-                new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph);
-
-                if (isSubstitution && !substituteCallsOriginal) {
-                    // TODO (ds) remove the constraint of only processing substitutions
-                    // once issues with the arraycopy snippets have been resolved
-                    new SnippetFrameStateCleanupPhase().apply(graph);
-                    new DeadCodeEliminationPhase().apply(graph);
-                }
-
-                new InsertStateAfterPlaceholderPhase().apply(graph);
+                finalizeGraph(method, graph);
 
                 Debug.dump(graph, "%s: Final", method.getName());
 
@@ -221,14 +237,15 @@
         StructuredGraph graph = graphCache.get(method);
         if (graph == null) {
             graph = buildGraph(method, policy == null ? inliningPolicy(method) : policy);
-            // System.out.println("built " + graph);
             graphCache.put(method, graph);
         }
         return graph;
     }
 
-    private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
-        assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method;
+    /**
+     * Builds the initial graph for a snippet.
+     */
+    protected StructuredGraph buildInitialGraph(final ResolvedJavaMethod method) {
         final StructuredGraph graph = new StructuredGraph(method);
         GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
         GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE);
@@ -237,8 +254,41 @@
         Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName());
 
         new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph);
+        new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
 
-        new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
+        return graph;
+    }
+
+    /**
+     * Called after a graph is inlined.
+     * 
+     * @param caller the graph into which {@code callee} was inlined
+     * @param callee the graph that was inlined into {@code caller}
+     */
+    protected void afterInline(StructuredGraph caller, StructuredGraph callee) {
+        if (GraalOptions.OptCanonicalizer) {
+            new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller);
+            new CanonicalizerPhase(runtime, assumptions).apply(caller);
+        }
+    }
+
+    /**
+     * Called after all inlining for a given graph is complete.
+     */
+    protected void afterInlining(StructuredGraph graph) {
+        new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
+
+        new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
+
+        new DeadCodeEliminationPhase().apply(graph);
+        if (GraalOptions.OptCanonicalizer) {
+            new CanonicalizerPhase(runtime, assumptions).apply(graph);
+        }
+    }
+
+    private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
+        assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method;
+        final StructuredGraph graph = buildInitialGraph(method);
 
         for (Invoke invoke : graph.getInvokes()) {
             MethodCallTargetNode callTarget = invoke.methodCallTarget();
@@ -248,36 +298,20 @@
                 new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(originalGraph);
                 InliningUtil.inline(invoke, originalGraph, true);
 
-                // TODO the inlined frame states still show the call from the substitute to the
-                // original.
-                // If this poses a problem, a phase should added to fix up these frame states.
-
                 Debug.dump(graph, "after inlining %s", callee);
-                if (GraalOptions.OptCanonicalizer) {
-                    new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
-                }
+                afterInline(graph, originalGraph);
                 substituteCallsOriginal = true;
             } else {
                 if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) {
                     StructuredGraph targetGraph = parseGraph(callee, policy);
                     InliningUtil.inline(invoke, targetGraph, true);
                     Debug.dump(graph, "after inlining %s", callee);
-                    if (GraalOptions.OptCanonicalizer) {
-                        new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
-                        new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
-                    }
+                    afterInline(graph, targetGraph);
                 }
             }
         }
 
-        new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
-
-        new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
-
-        new DeadCodeEliminationPhase().apply(graph);
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
-        }
+        afterInlining(graph);
 
         for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
             end.disableSafepoint();
@@ -298,13 +332,23 @@
         }
     }
 
-    private static Class resolveType(String className) {
+    /**
+     * Resolves a name to a class.
+     * 
+     * @param className the name of the class to resolve
+     * @param optional if true, resolution failure returns null
+     * @return the resolved class or null if resolution fails and {@code optional} is true
+     */
+    private static Class resolveType(String className, boolean optional) {
         try {
             // Need to use launcher class path to handle classes
             // that are not on the boot class path
             ClassLoader cl = Launcher.getLauncher().getClassLoader();
             return Class.forName(className, false, cl);
         } catch (ClassNotFoundException e) {
+            if (optional) {
+                return null;
+            }
             throw new GraalInternalError("Could not resolve type " + className);
         }
     }
@@ -317,7 +361,7 @@
             dimensions++;
         }
 
-        Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base));
+        Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base), false);
         return dimensions == 0 ? baseClass : Array.newInstance(baseClass, new int[dimensions]).getClass();
     }
 
@@ -339,13 +383,21 @@
         return parameters;
     }
 
-    private static Method originalMethod(ClassSubstitution classSubstitution, String name, Class[] parameters) {
+    private static Member originalMethod(ClassSubstitution classSubstitution, String name, Class[] parameters) {
         Class<?> originalClass = classSubstitution.value();
         if (originalClass == ClassSubstitution.class) {
-            originalClass = resolveType(classSubstitution.className());
+            originalClass = resolveType(classSubstitution.className(), classSubstitution.optional());
+            if (originalClass == null) {
+                // optional class was not found
+                return null;
+            }
         }
         try {
-            return originalClass.getDeclaredMethod(name, parameters);
+            if (name.equals("<init>")) {
+                return originalClass.getDeclaredConstructor(parameters);
+            } else {
+                return originalClass.getDeclaredMethod(name, parameters);
+            }
         } catch (NoSuchMethodException | SecurityException e) {
             throw new GraalInternalError(e);
         }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -43,45 +43,21 @@
 
     private final MetaAccessProvider runtime;
     private final BoxingMethodPool pool;
-    private final boolean intrinsificationOrFoldingCanBeDeferred;
 
-    /**
-     * @param intrinsificationOrFoldingCanBeDeferred if true, then {@link NonConstantParameterError}
-     *            s are not fatal
-     */
-    public SnippetIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool, boolean intrinsificationOrFoldingCanBeDeferred) {
+    public SnippetIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool) {
         this.runtime = runtime;
         this.pool = pool;
-        this.intrinsificationOrFoldingCanBeDeferred = intrinsificationOrFoldingCanBeDeferred;
     }
 
     @Override
     protected void run(StructuredGraph graph) {
         for (Invoke i : graph.getInvokes()) {
-            try {
-                if (i.callTarget() instanceof MethodCallTargetNode) {
-                    tryIntrinsify(i);
-                }
-            } catch (NonConstantParameterError t) {
-                if (!intrinsificationOrFoldingCanBeDeferred) {
-                    throw t;
-                }
+            if (i.callTarget() instanceof MethodCallTargetNode) {
+                tryIntrinsify(i);
             }
         }
     }
 
-    /**
-     * Exception raised when an argument to a {@linkplain Fold foldable} or {@link NodeIntrinsic}
-     * method is not a constant.
-     */
-    @SuppressWarnings("serial")
-    public static class NonConstantParameterError extends Error {
-
-        public NonConstantParameterError(String message) {
-            super(message);
-        }
-    }
-
     public static Class<?>[] signatureToTypes(Signature signature, ResolvedJavaType accessingClass) {
         int count = signature.getParameterCount(false);
         Class<?>[] result = new Class<?>[count];
@@ -91,7 +67,7 @@
         return result;
     }
 
-    private void tryIntrinsify(Invoke invoke) {
+    private boolean tryIntrinsify(Invoke invoke) {
         ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod();
         NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class);
         ResolvedJavaType declaringClass = target.getDeclaringClass();
@@ -104,6 +80,9 @@
 
             // Prepare the arguments for the reflective constructor call on the node class.
             Object[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false);
+            if (nodeConstructorArguments == null) {
+                return false;
+            }
 
             // Create the new node instance.
             Class<?> c = getNodeClass(target, intrinsic);
@@ -120,6 +99,9 @@
 
             // Prepare the arguments for the reflective method call
             Object[] arguments = prepareArguments(invoke, parameterTypes, target, true);
+            if (arguments == null) {
+                return false;
+            }
             Object receiver = null;
             if (!invoke.methodCallTarget().isStatic()) {
                 receiver = arguments[0];
@@ -142,6 +124,7 @@
                 invoke.intrinsify(null);
             }
         }
+        return true;
     }
 
     /**
@@ -149,6 +132,8 @@
      * to a reflective invocation of a Java constructor or method.
      * 
      * @param folding specifies if the invocation is for handling a {@link Fold} annotation
+     * @return the arguments for the reflective invocation or null if an argument of {@code invoke}
+     *         that is expected to be constant isn't
      */
     private Object[] prepareArguments(Invoke invoke, Class<?>[] parameterTypes, ResolvedJavaMethod target, boolean folding) {
         NodeInputList<ValueNode> arguments = invoke.callTarget().arguments();
@@ -161,8 +146,7 @@
             ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i));
             if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) {
                 if (!(argument instanceof ConstantNode)) {
-                    throw new NonConstantParameterError("parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.methodCallTarget().targetMethod() + " at " +
-                                    sourceLocation(invoke.node()) + ": " + argument);
+                    return null;
                 }
                 ConstantNode constantNode = (ConstantNode) argument;
                 Constant constant = constantNode.asConstant();
@@ -364,7 +348,7 @@
         if (newInstance instanceof ValueNode && (((ValueNode) newInstance).kind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) {
             StructuredGraph graph = (StructuredGraph) newInstance.graph();
             for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) {
-                for (ValueProxyNode vpn : checkCastNode.usages().filter(ValueProxyNode.class).snapshot()) {
+                for (ProxyNode vpn : checkCastNode.usages().filter(ProxyNode.class).snapshot()) {
                     graph.replaceFloating(vpn, checkCastNode);
                 }
                 for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
@@ -373,20 +357,25 @@
                         graph.removeFixed(valueAnchorNode);
                     } else if (checkCastUsage instanceof MethodCallTargetNode) {
                         MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage;
-                        assert pool.isUnboxingMethod(checkCastCallTarget.targetMethod()) : "checkcast at " + sourceLocation(checkCastNode) + " not used by an unboxing method but by a call at " +
-                                        sourceLocation(checkCastCallTarget.usages().first()) + " to " + checkCastCallTarget.targetMethod();
-                        Invoke invokeNode = checkCastCallTarget.invoke();
-                        invokeNode.node().replaceAtUsages(newInstance);
-                        if (invokeNode instanceof InvokeWithExceptionNode) {
-                            // Destroy exception edge & clear stateAfter.
-                            InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
+                        if (pool.isUnboxingMethod(checkCastCallTarget.targetMethod())) {
+                            Invoke invokeNode = checkCastCallTarget.invoke();
+                            invokeNode.node().replaceAtUsages(newInstance);
+                            if (invokeNode instanceof InvokeWithExceptionNode) {
+                                // Destroy exception edge & clear stateAfter.
+                                InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
 
-                            invokeWithExceptionNode.killExceptionEdge();
-                            graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next());
+                                invokeWithExceptionNode.killExceptionEdge();
+                                graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next());
+                            } else {
+                                graph.removeFixed((InvokeNode) invokeNode);
+                            }
+                            checkCastCallTarget.safeDelete();
                         } else {
-                            graph.removeFixed((InvokeNode) invokeNode);
+                            assert checkCastCallTarget.targetMethod().getAnnotation(NodeIntrinsic.class) != null : "checkcast at " + sourceLocation(checkCastNode) +
+                                            " not used by an unboxing method or node intrinsic, but by a call at " + sourceLocation(checkCastCallTarget.usages().first()) + " to " +
+                                            checkCastCallTarget.targetMethod();
+                            checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object());
                         }
-                        checkCastCallTarget.safeDelete();
                     } else if (checkCastUsage instanceof FrameState) {
                         checkCastUsage.replaceFirstInput(checkCastNode, null);
                     } else if (checkCastUsage instanceof ReturnNode && checkCastNode.object().stamp() == StampFactory.forNodeIntrinsic()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationVerificationPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.snippets;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.snippets.Snippet.Fold;
+
+/**
+ * Checks that a graph contains no calls to {@link NodeIntrinsic} or {@link Fold} methods.
+ */
+public class SnippetIntrinsificationVerificationPhase extends Phase {
+
+    public static boolean verify(StructuredGraph graph) {
+        new SnippetIntrinsificationVerificationPhase().apply(graph);
+        return true;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (Invoke i : graph.getInvokes()) {
+            if (i.callTarget() instanceof MethodCallTargetNode) {
+                checkInvoke(i);
+            }
+        }
+    }
+
+    private static void checkInvoke(Invoke invoke) {
+        ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod();
+        NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class);
+        if (intrinsic != null) {
+            throw new GraalInternalError("Illegal call to node intrinsic in " + invoke.graph() + ": " + invoke);
+        } else if (target.getAnnotation(Fold.class) != null) {
+            throw new GraalInternalError("Illegal call to foldable method in " + invoke.graph() + ": " + invoke);
+        }
+    }
+}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetProvider.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetProvider.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,8 +23,9 @@
 package com.oracle.graal.snippets;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.target.*;
 
 public interface SnippetProvider {
 
-    void installSnippets(SnippetInstaller installer, Assumptions assumptions);
+    void installSnippets(Backend backend, SnippetInstaller installer, Assumptions assumptions);
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Thu Mar 21 14:11:13 2013 +0100
@@ -36,6 +36,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.common.*;
@@ -282,11 +283,12 @@
         Debug.dump(snippetCopy, "Before specialization");
         if (!replacements.isEmpty()) {
             // Do deferred intrinsification of node intrinsics
-            new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy);
+            new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime)).apply(snippetCopy);
             new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy);
 
-            new CanonicalizerPhase(null, runtime, assumptions, 0, null).apply(snippetCopy);
+            new CanonicalizerPhase(runtime, assumptions, 0, null).apply(snippetCopy);
         }
+        assert SnippetIntrinsificationVerificationPhase.verify(snippetCopy);
 
         // Gather the template parameters
         parameters = new HashMap<>();
@@ -344,7 +346,7 @@
                     LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
                     int mark = snippetCopy.getMark();
                     LoopTransformations.fullUnroll(loop, runtime, null);
-                    new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(snippetCopy);
+                    new CanonicalizerPhase(runtime, assumptions, mark, null).apply(snippetCopy);
                 }
                 FixedNode explodeLoopNext = explodeLoop.next();
                 explodeLoop.clearSuccessors();
@@ -558,7 +560,7 @@
      * @param args the arguments to be bound to the flattened positional parameters of the snippet
      * @return the map of duplicated nodes (original -> duplicate)
      */
-    public Map<Node, Node> instantiate(MetaAccessProvider runtime, FixedWithNextNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) {
+    public Map<Node, Node> instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) {
 
         // Inline the snippet nodes, replacing parameters with the given args in the process
         String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}";
@@ -573,8 +575,12 @@
         // Re-wire the control flow graph around the replacee
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
         replacee.replaceAtPredecessor(firstCFGNodeDuplicate);
-        FixedNode next = replacee.next();
-        replacee.setNext(null);
+        FixedNode next = null;
+        if (replacee instanceof FixedWithNextNode) {
+            FixedWithNextNode fwn = (FixedWithNextNode) replacee;
+            next = fwn.next();
+            fwn.setNext(null);
+        }
 
         if (replacee instanceof StateSplit) {
             for (StateSplit sideEffectNode : sideEffectNodes) {
@@ -628,10 +634,9 @@
      * @param runtime
      * @param replacee the node that will be replaced
      * @param replacer object that replaces the usages of {@code replacee}
-     * @param lastFixedNode the CFG of the snippet is inserted after this node
      * @param args the arguments to be bound to the flattened positional parameters of the snippet
      */
-    public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, FixedWithNextNode lastFixedNode, SnippetTemplate.Arguments args) {
+    public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, SnippetTemplate.Arguments args) {
 
         // Inline the snippet nodes, replacing parameters with the given args in the process
         String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}";
@@ -643,7 +648,8 @@
         Map<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, replacements);
         Debug.dump(replaceeGraph, "After inlining snippet %s", snippetCopy.method());
 
-        assert lastFixedNode != null : replaceeGraph;
+        FixedWithNextNode lastFixedNode = tool.lastFixedNode();
+        assert lastFixedNode != null && lastFixedNode.isAlive() : replaceeGraph;
         FixedNode next = lastFixedNode.next();
         lastFixedNode.setNext(null);
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
@@ -672,10 +678,14 @@
         assert returnValue != null || replacee.usages().isEmpty();
         replacer.replace(replacee, returnValue);
 
+        tool.setLastFixedNode(null);
         Node returnDuplicate = duplicates.get(returnNode);
         if (returnDuplicate.isAlive()) {
             returnDuplicate.clearInputs();
             returnDuplicate.replaceAndDelete(next);
+            if (next != null && next.predecessor() instanceof FixedWithNextNode) {
+                tool.setLastFixedNode((FixedWithNextNode) next.predecessor());
+            }
         }
 
         Debug.dump(replaceeGraph, "After lowering %s with %s", replacee, this);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -62,7 +62,7 @@
     @Override
     public void lower(LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) this.graph();
-        IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, false);
+        IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, 1);
         WriteNode write = graph.add(new WriteNode(object, value, location));
         graph.replaceFixedWithFixed(this, write);
     }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectReadNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectReadNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.snippets.nodes;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -46,7 +45,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitLoad(new Address(readKind, gen.operand(address)), false));
+        gen.setResult(this, gen.emitLoad(readKind, gen.operand(address), 0, Value.ILLEGAL, 0, false));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectStoreNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectStoreNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.snippets.nodes;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -49,7 +48,7 @@
     @Override
     public void generate(LIRGeneratorTool gen) {
         Value v = gen.operand(value);
-        gen.emitStore(new Address(kind, gen.operand(address)), v, false);
+        gen.emitStore(kind, gen.operand(address), 0, Value.ILLEGAL, 0, v, false);
     }
 
     /*
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MacroNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MacroNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.common.*;
 
 public class MacroNode extends AbstractStateSplit implements Lowerable {
 
@@ -47,14 +48,32 @@
         this.returnType = invoke.methodCallTarget().returnType();
     }
 
+    public int getBci() {
+        return bci;
+    }
+
+    public ResolvedJavaMethod getTargetMethod() {
+        return targetMethod;
+    }
+
+    @SuppressWarnings("unused")
+    protected StructuredGraph getSnippetGraph(LoweringTool tool) {
+        return null;
+    }
+
     @Override
     public void lower(LoweringTool tool) {
-        replaceWithInvoke();
+        StructuredGraph snippetGraph = getSnippetGraph(tool);
+
+        InvokeNode invoke = replaceWithInvoke();
+
+        if (snippetGraph != null) {
+            InliningUtil.inline(invoke, snippetGraph, false);
+        }
     }
 
-    public InvokeNode replaceWithInvoke() {
+    private InvokeNode replaceWithInvoke() {
         InvokeNode invoke = createInvoke();
-
         ((StructuredGraph) graph()).replaceFixedWithFixed(this, invoke);
         return invoke;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/ReadRegisterNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.snippets.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Access the value of a specific register.
+ */
+@NodeInfo(nameTemplate = "ReadRegister %{p#register}")
+public final class ReadRegisterNode extends FixedWithNextNode implements LIRGenLowerable {
+
+    /**
+     * The fixed register to access.
+     */
+    private final Register register;
+
+    /**
+     * When true, subsequent uses of this node use the fixed register; when false, the value is
+     * moved into a new virtual register so that the fixed register is not seen by uses.
+     */
+    private final boolean directUse;
+
+    /**
+     * When true, this node is also an implicit definition of the value for the register allocator,
+     * i.e., the register is an implicit incoming value; when false, the register must be defined in
+     * the same method or must be an register excluded from register allocation.
+     */
+    private final boolean incoming;
+
+    public ReadRegisterNode(Register register, Kind kind, boolean directUse, boolean incoming) {
+        super(StampFactory.forKind(kind));
+        this.register = register;
+        this.directUse = directUse;
+        this.incoming = incoming;
+    }
+
+    /**
+     * Constructor to be used by node intrinsics where the stamp is inferred from the intrinsic
+     * definition.
+     */
+    public ReadRegisterNode(Register register, boolean directUse, boolean incoming) {
+        super(StampFactory.forNodeIntrinsic());
+        this.register = register;
+        this.directUse = directUse;
+        this.incoming = incoming;
+    }
+
+    @Override
+    public void generate(LIRGenerator generator) {
+        Value result = register.asValue(kind());
+        if (incoming) {
+            generator.emitIncomingValues(new Value[]{result});
+        }
+        if (!directUse) {
+            result = generator.emitMove(result);
+        }
+        generator.setResult(this, result);
+    }
+
+    @Override
+    public String toString(Verbosity verbosity) {
+        if (verbosity == Verbosity.Name) {
+            return super.toString(Verbosity.Name) + "%" + register;
+        } else {
+            return super.toString(verbosity);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/WriteRegisterNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.snippets.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Changes the value of a specific register.
+ */
+@NodeInfo(nameTemplate = "WriteRegister %{p#register}")
+public final class WriteRegisterNode extends FixedWithNextNode implements LIRLowerable {
+
+    /**
+     * The fixed register to access.
+     */
+    private final Register register;
+
+    /**
+     * The new value assigned to the register.
+     */
+    @Input private ValueNode value;
+
+    public WriteRegisterNode(Register register, ValueNode value) {
+        super(StampFactory.forVoid());
+        this.register = register;
+        this.value = value;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+        Value val = generator.operand(value);
+        generator.emitMove(val, register.asValue(val.getKind()));
+    }
+
+    @Override
+    public String toString(Verbosity verbosity) {
+        if (verbosity == Verbosity.Name) {
+            return super.toString(Verbosity.Name) + "%" + register;
+        } else {
+            return super.toString(verbosity);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalLongUnitTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.test;
+
+import java.util.*;
+
+import org.junit.*;
+import org.junit.runners.*;
+import org.junit.runners.model.*;
+
+public class GraalLongUnitTest extends BlockJUnit4ClassRunner {
+
+    public GraalLongUnitTest(Class<?> klass) throws InitializationError {
+        super(klass);
+    }
+
+    @Override
+    protected List<FrameworkMethod> computeTestMethods() {
+        List<FrameworkMethod> methods = new ArrayList<>(5);
+        methods.addAll(getTestClass().getAnnotatedMethods(Test.class));
+        methods.addAll(getTestClass().getAnnotatedMethods(LongTest.class));
+        return methods;
+    }
+}
--- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,12 +25,14 @@
 import java.lang.reflect.*;
 
 import org.junit.*;
+import org.junit.runner.*;
 
 /**
  * Base class for Graal tests.
  * <p>
  * This contains common utility methods that are used in multiple test projects.
  */
+@RunWith(GraalLongUnitTest.class)
 public class GraalTest {
 
     protected Method getMethod(String methodName) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/LongTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.test;
+
+import java.lang.annotation.*;
+
+/* copy of org.junit.Test */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface LongTest {
+
+    static final class None extends Throwable {
+
+        private static final long serialVersionUID = 1L;
+
+        private None() {
+        }
+    }
+
+    Class<? extends Throwable> expected() default None.class;
+
+    long timeout() default 0L;
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,10 +32,9 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
 import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.graph.ReentrantBlockIterator.MergeableBlockState;
 import com.oracle.graal.virtual.nodes.*;
 
-class BlockState extends MergeableBlockState<BlockState> {
+class BlockState {
 
     private final HashMap<VirtualObjectNode, ObjectState> objectStates = new HashMap<>();
     private final HashMap<ValueNode, VirtualObjectNode> objectAliases = new HashMap<>();
@@ -70,7 +69,6 @@
         return object == null ? null : getObjectState(object);
     }
 
-    @Override
     public BlockState cloneState() {
         return new BlockState(this);
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -40,14 +40,12 @@
 
 public class PartialEscapeAnalysisPhase extends Phase {
 
-    private final TargetDescription target;
     private final MetaAccessProvider runtime;
     private final Assumptions assumptions;
     private CustomCanonicalizer customCanonicalizer;
     private final boolean iterative;
 
-    public PartialEscapeAnalysisPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, boolean iterative) {
-        this.target = target;
+    public PartialEscapeAnalysisPhase(MetaAccessProvider runtime, Assumptions assumptions, boolean iterative) {
         this.runtime = runtime;
         this.assumptions = assumptions;
         this.iterative = iterative;
@@ -114,7 +112,7 @@
                         return false;
                     }
                     if (GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase(target, runtime, assumptions, null, customCanonicalizer).apply(graph);
+                        new CanonicalizerPhase(runtime, assumptions, null, customCanonicalizer).apply(graph);
                     }
                     return true;
                 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Thu Mar 21 14:11:13 2013 +0100
@@ -457,9 +457,9 @@
     }
 
     private void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState) {
-        HashMap<VirtualObjectNode, ValueProxyNode> proxies = new HashMap<>();
+        HashMap<VirtualObjectNode, ProxyNode> proxies = new HashMap<>();
 
-        for (ValueProxyNode proxy : exitNode.proxies()) {
+        for (ProxyNode proxy : exitNode.proxies()) {
             ObjectState obj = exitState.getObjectState(proxy.value());
             if (obj != null) {
                 proxies.put(obj.virtual, proxy);
@@ -473,7 +473,7 @@
                     ObjectState valueObj = exitState.getObjectState(value);
                     if (valueObj == null) {
                         if ((value instanceof PhiNode && ((PhiNode) value).merge() == exitNode.loopBegin()) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) {
-                            ValueProxyNode proxy = new ValueProxyNode(value, exitNode, PhiType.Value);
+                            ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value);
                             obj.setEntry(i, proxy);
                             effects.addFloatingNode(proxy);
                         }
@@ -481,9 +481,9 @@
                 }
             } else {
                 if (initialObj == null || initialObj.isVirtual()) {
-                    ValueProxyNode proxy = proxies.get(obj.virtual);
+                    ProxyNode proxy = proxies.get(obj.virtual);
                     if (proxy == null) {
-                        proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value);
+                        proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value);
                         effects.addFloatingNode(proxy);
                     } else {
                         effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.word;
 
+import com.oracle.graal.nodes.extended.*;
+
 public interface Pointer extends Unsigned {
 
     /**
@@ -42,6 +44,438 @@
      * knows that the highest-order bit of the unsigned value is never used).
      * 
      * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    byte readByte(WordBase offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    char readChar(WordBase offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    short readShort(WordBase offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    int readInt(WordBase offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    long readLong(WordBase offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    float readFloat(WordBase offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    double readDouble(WordBase offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    Word readWord(WordBase offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    Object readObject(WordBase offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    byte readByte(int offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    char readChar(int offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    short readShort(int offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    int readInt(int offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    long readLong(int offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    float readFloat(int offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    double readDouble(int offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    Word readWord(int offset, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read (see {@link LocationNode})
+     * @return the result of the memory access
+     */
+    Object readObject(int offset, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeByte(WordBase offset, byte val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeChar(WordBase offset, char val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeShort(WordBase offset, short val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeInt(WordBase offset, int val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeLong(WordBase offset, long val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeFloat(WordBase offset, float val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeDouble(WordBase offset, double val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeWord(WordBase offset, WordBase val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeObject(WordBase offset, Object val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeByte(int offset, byte val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeChar(int offset, char val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeShort(int offset, short val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeInt(int offset, int val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeLong(int offset, long val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeFloat(int offset, float val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeDouble(int offset, double val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeWord(int offset, WordBase val, Object locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * 
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write (see {@link LocationNode})
+     * @param val the value to be written to memory
+     */
+    void writeObject(int offset, Object val, Object locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     * <p>
+     * The offset is always treated as a {@link Signed} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * knows that the highest-order bit of the unsigned value is never used).
+     * 
+     * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
     byte readByte(WordBase offset);
@@ -232,150 +666,6 @@
     Object readObject(int offset);
 
     /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    byte readFinalByte(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    char readFinalChar(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    short readFinalShort(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    int readFinalInt(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    long readFinalLong(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    float readFinalFloat(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    double readFinalDouble(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    Word readFinalWord(WordBase offset);
-
-    /**
-     * Reads the constant memory at address {@code (this + offset)}. Both the base address and
-     * offset are in bytes.
-     * <p>
-     * The caller guarantees that the memory content is final, i.e., never changing. The compiler
-     * can therefore eliminate memory accesses more aggressively.
-     * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
-     * knows that the highest-order bit of the unsigned value is never used).
-     * 
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    Object readFinalObject(WordBase offset);
-
-    /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
@@ -412,7 +702,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
-    void writeShort(WordBase offset, Short val);
+    void writeShort(WordBase offset, short val);
 
     /**
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java	Thu Mar 21 14:11:13 2013 +0100
@@ -58,7 +58,6 @@
          COMPARISON,
          NOT,
          READ,
-         READ_FINAL,
          WRITE,
          ZERO,
          FROM_UNSIGNED,
@@ -602,6 +601,218 @@
 
     @Override
     @Operation(opcode = Opcode.READ)
+    public byte readByte(WordBase offset, Object locationIdentity) {
+        return unsafe.getByte(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public char readChar(WordBase offset, Object locationIdentity) {
+        return unsafe.getChar(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public short readShort(WordBase offset, Object locationIdentity) {
+        return unsafe.getShort(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public int readInt(WordBase offset, Object locationIdentity) {
+        return unsafe.getInt(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public long readLong(WordBase offset, Object locationIdentity) {
+        return unsafe.getLong(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public float readFloat(WordBase offset, Object locationIdentity) {
+        return unsafe.getFloat(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public double readDouble(WordBase offset, Object locationIdentity) {
+        return unsafe.getDouble(add((Word) offset).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public Word readWord(WordBase offset, Object locationIdentity) {
+        return box(unsafe.getAddress(add((Word) offset).unbox()));
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public native Object readObject(WordBase offset, Object locationIdentity);
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public byte readByte(int offset, Object locationIdentity) {
+        return readByte(signed(offset), locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public char readChar(int offset, Object locationIdentity) {
+        return readChar(signed(offset), locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public short readShort(int offset, Object locationIdentity) {
+        return readShort(signed(offset), locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public int readInt(int offset, Object locationIdentity) {
+        return readInt(signed(offset), locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public long readLong(int offset, Object locationIdentity) {
+        return readLong(signed(offset), locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public float readFloat(int offset, Object locationIdentity) {
+        return readFloat(signed(offset), locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public double readDouble(int offset, Object locationIdentity) {
+        return readDouble(signed(offset), locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public Word readWord(int offset, Object locationIdentity) {
+        return readWord(signed(offset), locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
+    public Object readObject(int offset, Object locationIdentity) {
+        return readObject(signed(offset), locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeByte(WordBase offset, byte val, Object locationIdentity) {
+        unsafe.putByte(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeChar(WordBase offset, char val, Object locationIdentity) {
+        unsafe.putChar(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeShort(WordBase offset, short val, Object locationIdentity) {
+        unsafe.putShort(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeInt(WordBase offset, int val, Object locationIdentity) {
+        unsafe.putInt(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeLong(WordBase offset, long val, Object locationIdentity) {
+        unsafe.putLong(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeFloat(WordBase offset, float val, Object locationIdentity) {
+        unsafe.putFloat(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeDouble(WordBase offset, double val, Object locationIdentity) {
+        unsafe.putDouble(add((Word) offset).unbox(), val);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeWord(WordBase offset, WordBase val, Object locationIdentity) {
+        unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox());
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public native void writeObject(WordBase offset, Object val, Object locationIdentity);
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeByte(int offset, byte val, Object locationIdentity) {
+        writeByte(signed(offset), val, locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeChar(int offset, char val, Object locationIdentity) {
+        writeChar(signed(offset), val, locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeShort(int offset, short val, Object locationIdentity) {
+        writeShort(signed(offset), val, locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeInt(int offset, int val, Object locationIdentity) {
+        writeInt(signed(offset), val, locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeLong(int offset, long val, Object locationIdentity) {
+        writeLong(signed(offset), val, locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeFloat(int offset, float val, Object locationIdentity) {
+        writeFloat(signed(offset), val, locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeDouble(int offset, double val, Object locationIdentity) {
+        writeDouble(signed(offset), val, locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeWord(int offset, WordBase val, Object locationIdentity) {
+        writeWord(signed(offset), val, locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.WRITE)
+    public void writeObject(int offset, Object val, Object locationIdentity) {
+        writeObject(signed(offset), val, locationIdentity);
+    }
+
+    @Override
+    @Operation(opcode = Opcode.READ)
     public byte readByte(WordBase offset) {
         return unsafe.getByte(add((Word) offset).unbox());
     }
@@ -707,60 +918,6 @@
     }
 
     @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public byte readFinalByte(WordBase offset) {
-        return readByte(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public char readFinalChar(WordBase offset) {
-        return readChar(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public short readFinalShort(WordBase offset) {
-        return readShort(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public int readFinalInt(WordBase offset) {
-        return readInt(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public long readFinalLong(WordBase offset) {
-        return readLong(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public float readFinalFloat(WordBase offset) {
-        return readFloat(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public double readFinalDouble(WordBase offset) {
-        return readDouble(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public Word readFinalWord(WordBase offset) {
-        return readWord(offset);
-    }
-
-    @Override
-    @Operation(opcode = Opcode.READ_FINAL)
-    public Object readFinalObject(WordBase offset) {
-        return readObject(offset);
-    }
-
-    @Override
     @Operation(opcode = Opcode.WRITE)
     public void writeByte(WordBase offset, byte val) {
         unsafe.putByte(add((Word) offset).unbox(), val);
@@ -774,7 +931,7 @@
 
     @Override
     @Operation(opcode = Opcode.WRITE)
-    public void writeShort(WordBase offset, Short val) {
+    public void writeShort(WordBase offset, short val) {
         unsafe.putShort(add((Word) offset).unbox(), val);
     }
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Mar 21 14:11:13 2013 +0100
@@ -138,21 +138,17 @@
                         break;
 
                     case READ:
-                        assert arguments.size() == 2;
+                        assert arguments.size() == 2 || arguments.size() == 3;
                         Kind readKind = asKind(callTargetNode.returnType());
-                        replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, readKind, LocationNode.ANY_LOCATION));
-                        break;
-
-                    case READ_FINAL:
-                        assert arguments.size() == 2;
-                        Kind readFinalKind = asKind(callTargetNode.returnType());
-                        replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, readFinalKind, LocationNode.ANY_LOCATION));
+                        Object readLocation = arguments.size() == 2 ? LocationNode.UNKNOWN_LOCATION : arguments.get(2).asConstant().asObject();
+                        replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, readKind, readLocation));
                         break;
 
                     case WRITE:
-                        assert arguments.size() == 3;
-                        Kind writeKind = asKind(targetMethod.getSignature().getParameterType(1, null));
-                        replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, writeKind, LocationNode.ANY_LOCATION));
+                        assert arguments.size() == 3 || arguments.size() == 4;
+                        Kind writeKind = asKind(targetMethod.getSignature().getParameterType(1, targetMethod.getDeclaringClass()));
+                        Object writeLocation = arguments.size() == 3 ? LocationNode.ANY_LOCATION : arguments.get(3).asConstant().asObject();
+                        replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, writeKind, writeLocation));
                         break;
 
                     case ZERO:
@@ -256,19 +252,21 @@
         } else {
             comparison = new IntegerLessThanNode(a, b);
         }
-        ConditionalNode materialize = graph.unique(new ConditionalNode(graph.unique(comparison), ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph)));
 
-        ValueNode op;
+        ConstantNode trueValue = ConstantNode.forInt(1, graph);
+        ConstantNode falseValue = ConstantNode.forInt(0, graph);
+
         if (condition.canonicalNegate()) {
-            op = (ValueNode) materialize.negate();
-        } else {
-            op = materialize;
+            ConstantNode temp = trueValue;
+            trueValue = falseValue;
+            falseValue = temp;
         }
-        return op;
+        ConditionalNode materialize = graph.unique(new ConditionalNode(graph.unique(comparison), trueValue, falseValue));
+        return materialize;
     }
 
     private static ValueNode readOp(StructuredGraph graph, ValueNode base, ValueNode offset, Invoke invoke, Kind readKind, Object locationIdentity) {
-        IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, readKind, 0, offset, graph, false);
+        IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, readKind, 0, offset, graph, 1);
         ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp()));
         graph.addBeforeFixed(invoke.node(), read);
         // The read must not float outside its block otherwise it may float above an explicit zero
@@ -278,8 +276,9 @@
     }
 
     private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode offset, ValueNode value, Invoke invoke, Kind writeKind, Object locationIdentity) {
-        IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, writeKind, 0, offset, graph, false);
+        IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, writeKind, 0, offset, graph, 1);
         WriteNode write = graph.add(new WriteNode(base, value, location));
+        write.setStateAfter(invoke.stateAfter());
         graph.addBeforeFixed(invoke.node(), write);
         return write;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryOperationTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen.test;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode;
+
+public class BinaryOperationTest {
+
+    static int convertInt(Object value) {
+        if (value instanceof Number) {
+            return ((Number) value).intValue();
+        } else if (value instanceof String) {
+            return Integer.parseInt((String) value);
+        }
+        throw new RuntimeException("Invalid datatype");
+    }
+
+    @NodeClass(BinaryNode.class)
+    abstract static class BinaryNode extends ValueNode {
+
+        @Child protected ValueNode leftNode;
+        @Child protected ValueNode rightNode;
+
+        public BinaryNode(ValueNode left, ValueNode right) {
+            this.leftNode = left;
+            this.rightNode = right;
+        }
+
+        public BinaryNode(BinaryNode prev) {
+            this(prev.leftNode, prev.rightNode);
+        }
+
+        @Specialization
+        int add(int left, int right) {
+            return left + right;
+        }
+
+        @Generic
+        int add(Object left, Object right) {
+            return convertInt(left) + convertInt(right);
+        }
+
+        @Specialization
+        int sub(int left, int right) {
+            return left + right;
+        }
+
+        @Generic
+        int sub(Object left, Object right) {
+            return convertInt(left) + convertInt(right);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/RuntimeStringTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode;
+
+public class RuntimeStringTest {
+
+    @Test
+    public void testSubstr() {
+        assertExecute(new RuntimeString("es"), "substr", new RuntimeString("test"), 1, 3);
+    }
+
+    @Test
+    public void testConcat() {
+        assertExecute(new RuntimeString("concatconcat"), "concat", new RuntimeString("concat"), new RuntimeString("concat"));
+    }
+
+    @Test(expected = ArrayIndexOutOfBoundsException.class)
+    public void testConcatFail() {
+        assertExecute(new RuntimeString("concatconcat"), "concat", new RuntimeString("concat"));
+    }
+
+    @Test
+    public void testFindMethodByMethodName() {
+        // TODO
+    }
+
+    private static void assertExecute(Object expectedResult, String name, Object... argumentsArray) {
+        ArgNode[] args = new ArgNode[argumentsArray.length];
+        for (int i = 0; i < args.length; i++) {
+            args[i] = new ArgNode(argumentsArray, i);
+        }
+
+        BuiltinNode node = null;
+        for (NodeFactory<BuiltinNode> nodeFactory : RuntimeStringTestFactory.getFactories()) {
+            GeneratedBy generated = nodeFactory.getClass().getAnnotation(GeneratedBy.class);
+            Assert.assertNotNull(generated);
+            Assert.assertNotSame("", generated.methodName());
+            if (generated.methodName().equals(name)) {
+                node = nodeFactory.createNode((Object) args);
+                break;
+            }
+        }
+        Assert.assertNotNull("Node not found", node);
+        CallTarget target = Truffle.getRuntime().createCallTarget(new TestRootNode(node));
+        Assert.assertEquals(expectedResult, target.call());
+    }
+
+    static class ArgNode extends ValueNode {
+
+        final Object[] arguments;
+        final int index;
+
+        ArgNode(Object[] args, int index) {
+            this.arguments = args;
+            this.index = index;
+        }
+
+        @Override
+        Object execute() {
+            return arguments[index];
+        }
+
+    }
+
+    abstract static class BuiltinNode extends ValueNode {
+
+        @Children ArgNode[] parameters;
+
+        BuiltinNode(ArgNode[] parameters) {
+            this.parameters = adoptChildren(parameters);
+        }
+
+        BuiltinNode(BuiltinNode prev) {
+            this(prev.parameters);
+        }
+
+    }
+
+    @NodeClass(BuiltinNode.class)
+    static class RuntimeString {
+
+        private final String internal;
+
+        public RuntimeString(String internal) {
+            this.internal = internal;
+        }
+
+        @Specialization
+        static RuntimeString concat(RuntimeString s1, RuntimeString s2) {
+            return new RuntimeString(s1.internal + s2.internal);
+        }
+
+        @Specialization
+        RuntimeString substr(int beginIndex, int endIndex) {
+            return new RuntimeString(internal.substring(beginIndex, endIndex));
+        }
+
+        @Generic
+        RuntimeString substr(Object beginIndex, Object endIndex) {
+            return substr(convertInt(beginIndex), convertInt(endIndex));
+        }
+
+        static int convertInt(Object value) {
+            if (value instanceof Number) {
+                return ((Number) value).intValue();
+            } else if (value instanceof String) {
+                return Integer.parseInt((String) value);
+            }
+            throw new RuntimeException("Invalid datatype");
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof RuntimeString) {
+                return internal.equals(((RuntimeString) obj).internal);
+            }
+            return super.equals(obj);
+        }
+
+        @Override
+        public int hashCode() {
+            return internal.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return internal;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen.test;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.api.codegen.test.RuntimeStringTest.RuntimeString;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class TypeSystemTest {
+
+    @TypeSystem({int.class, RuntimeString.class})
+    static class SimpleTypes {
+    }
+
+    @TypeSystemReference(SimpleTypes.class)
+    abstract static class ValueNode extends Node {
+
+        int executeInt() throws UnexpectedResultException {
+            return SimpleTypesGen.SIMPLETYPES.expectInteger(execute());
+        }
+
+        RuntimeString executeString() {
+            return new RuntimeString(execute().toString());
+        }
+
+        @SuppressWarnings("static-method")
+        final long executeSpecial() {
+            return 42L;
+        }
+
+        abstract Object execute();
+
+    }
+
+    @TypeSystemReference(SimpleTypes.class)
+    static class TestRootNode extends RootNode {
+
+        @Child private ValueNode node;
+
+        public TestRootNode(ValueNode node) {
+            this.node = adoptChild(node);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return node.execute();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/package-info.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/**
+ * <p>This package contains basic tests of the Truffle-Source-Code-Generation (short Codegen) API and serves at the same
+ * time as an introduction to the Codegen API for language implementors. Every test gives an example on how to use the construct explained in the class description.</p>
+ *
+ * <p>
+ * This API relies heavily on the concepts described in com.oracle.truffle.api.test. We assume that the
+ * reader is already familiarized with those concepts.
+ * </p>
+ *
+ * <p>
+ * TODO general description
+ * </p>
+ *
+ * <p>
+ * This introduction to Codegen contains items in the following recommended order:
+ *
+ * Prerequisites:
+ * 
+ *
+ * <ul>
+ * <li>What do I need to get started? {@link com.oracle.truffle.api.codegen.test.TypeSystemTest}</li>
+ * <li>How would you generate function nodes for runtime objects? {@link com.oracle.truffle.api.codegen.test.RuntimeStringTest}</li>
+ * </ul>
+ * </p>
+ *
+ */
+package com.oracle.truffle.api.codegen.test;
+
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,12 +25,14 @@
 import java.lang.annotation.*;
 
 /**
- * Marks a type to be generated by another class.
+ * Marks a type to be generated by another class or a method.
  */
-@Retention(RetentionPolicy.CLASS)
+@Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.TYPE})
 public @interface GeneratedBy {
 
     Class<?> value();
 
+    String methodName() default "";
+
 }
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GuardCheck.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.codegen;
-
-import java.lang.annotation.*;
-
-/**
- * 
- * 
- * @see SpecializationGuard
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface GuardCheck {
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface NodeClass {
+
+    Class<? extends Node> value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeFactory.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Enables the dynamic creation of generated nodes. It provides an convenient way to instantiate
+ * generated node classes without using reflection.
+ */
+public interface NodeFactory<T> {
+
+    /**
+     * Instantiates the node using the arguments array. The arguments length and types must suffice
+     * one of the returned signatures in {@link #getNodeSignatures()}. If the arguments array does
+     * not suffice one of the node signatures an {@link IllegalArgumentException} is thrown.
+     * 
+     * @param arguments the argument values
+     * @return the instantiated node
+     * @throws IllegalArgumentException
+     */
+    T createNode(Object... arguments);
+
+    /**
+     * Instantiates a new specialized variant of the node. This is an optional method and throws an
+     * {@link UnsupportedOperationException} if not supported.
+     * 
+     * @param thisNode the current node
+     * @param specializionClasses
+     * @return the specialized node
+     */
+    T createNodeSpecialized(T thisNode, Class<?>... specializionClasses);
+
+    /**
+     * Returns the node class that will get created by {@link #createNode(Object...)}. The node
+     * class does not match exactly to the instantiated object but they are guaranteed to be
+     * assignable.
+     */
+    Class<T> getNodeClass();
+
+    /**
+     * Returns a list of signatures that can be used to invoke {@link #createNode(Object...)}.
+     */
+    List<List<Class<?>>> getNodeSignatures();
+
+    /**
+     * Returns a list of children that will be executed by the created node. This is useful for base
+     * nodes that can execute a variable amount of nodes.
+     */
+    List<Class<? extends Node>> getExecutionSignature();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeId.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface NodeId {
+
+    String value();
+
+}
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,8 +32,8 @@
 
     int order() default DEFAULT_ORDER;
 
-    SpecializationThrows[] exceptions() default {};
+    Class<? extends Throwable>[] rewriteOn() default {};
 
-    SpecializationGuard[] guards() default {};
+    String[] guards() default {};
 
 }
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.codegen;
-
-import java.lang.annotation.*;
-
-/**
- * Specifies the use of a guard for a specialization.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface SpecializationGuard {
-
-    /**
-     * Specifies the name of the guard method annotated by {@link GuardCheck} specified as method in
-     * the {@link TypeSystem} class.
-     */
-    String methodName();
-
-    /**
-     * Determines if a guard check is invoked on specialization. Defaults to true.
-     */
-    boolean onSpecialization() default true;
-
-    /**
-     * Determines if a guard check is invoked on execution. Defaults to true.
-     */
-    boolean onExecution() default true;
-
-}
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationThrows.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.codegen;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface SpecializationThrows {
-
-    Class<? extends Throwable> javaClass();
-
-    String transitionTo();
-}
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,8 +28,8 @@
  * <p>
  * Annotates a type system class that represents type information for a node. Generates code for
  * converting and managing types. Methods contained in the type system may be annotated with
- * {@link TypeCast}, {@link TypeCheck} or {@link GuardCheck}. These methods alter the default
- * behavior of the type system.
+ * {@link TypeCast} or {@link TypeCheck}. These methods alter the default behavior of the type
+ * system.
  * </p>
  * 
  * 
@@ -62,7 +62,6 @@
  * 
  * @see TypeCast
  * @see TypeCheck
- * @see GuardCheck
  */
 @Retention(RetentionPolicy.CLASS)
 @Target({ElementType.TYPE})
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -38,7 +38,7 @@
  * should be speculated on. When the speculation fails and the child node cannot return the
  * appropriate type of value, it can use an {@link UnexpectedResultException} to still pass the
  * result to the caller. In such a case, the caller must rewrite itself to a more general version in
- * oder to avoid future failures of this kind.
+ * order to avoid future failures of this kind.
  * </p>
  */
 public class ReturnTypeSpecializationTest {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -58,12 +58,22 @@
             if (!context.getTruffleTypes().verify(context, element, mirror)) {
                 return null;
             }
-            return parse(element, mirror);
+            M model = parse(element, mirror);
+            if (model == null) {
+                return null;
+            }
+
+            model.emitMessages((TypeElement) element, log);
+            return filterErrorElements(model);
         } finally {
             this.roundEnv = null;
         }
     }
 
+    protected M filterErrorElements(M model) {
+        return model.hasErrors() ? null : model;
+    }
+
     protected abstract M parse(Element element, AnnotationMirror mirror);
 
     public abstract Class<? extends Annotation> getAnnotationType();
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java	Thu Mar 21 14:11:13 2013 +0100
@@ -41,30 +41,6 @@
         this.processingEnv = env;
     }
 
-    public void warning(Element element, String format, Object... args) {
-        message(Kind.WARNING, element, null, null, format, args);
-    }
-
-    public void warning(Element element, AnnotationMirror mirror, String format, Object... args) {
-        message(Kind.WARNING, element, mirror, null, format, args);
-    }
-
-    public void error(Element element, String format, Object... args) {
-        message(Kind.ERROR, element, null, null, format, args);
-    }
-
-    public void error(String format, Object... args) {
-        message(Kind.ERROR, null, null, null, format, args);
-    }
-
-    public void error(Element element, AnnotationMirror mirror, String format, Object... args) {
-        message(Kind.ERROR, element, mirror, null, format, args);
-    }
-
-    public void error(Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) {
-        message(Kind.ERROR, element, mirror, value, format, args);
-    }
-
     public void message(Kind kind, Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) {
         AnnotationMirror usedMirror = mirror;
         Element usedElement = element;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,6 +28,7 @@
 import javax.annotation.processing.*;
 import javax.lang.model.*;
 import javax.lang.model.element.*;
+import javax.tools.Diagnostic.*;
 
 import com.oracle.truffle.codegen.processor.ProcessorContext.ProcessCallback;
 import com.oracle.truffle.codegen.processor.node.*;
@@ -95,7 +96,7 @@
 
     private static void handleThrowable(AnnotationProcessor generator, Throwable t, Element e) {
         String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e;
-        generator.getContext().getLog().error(e, message + ": " + Utils.printException(t));
+        generator.getContext().getLog().message(Kind.ERROR, e, null, null, message + ": " + Utils.printException(t));
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,8 +26,10 @@
 
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
+import javax.tools.Diagnostic.*;
 
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.intrinsics.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.nodes.Node.Child;
 import com.oracle.truffle.api.nodes.Node.Children;
@@ -44,6 +46,7 @@
     private final TypeMirror stableAnnotation;
     private final TypeMirror contentStableAnnotation;
     private final TypeMirror typeConversion;
+    private final TypeMirror truffleIntrinsics;
 
     private final List<String> errors = new ArrayList<>();
 
@@ -55,6 +58,7 @@
         stableAnnotation = getRequired(context, Child.class);
         contentStableAnnotation = getRequired(context, Children.class);
         typeConversion = getRequired(context, TypeConversion.class);
+        truffleIntrinsics = getRequired(context, TruffleIntrinsics.class);
     }
 
     public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) {
@@ -63,7 +67,7 @@
         }
 
         for (String error : errors) {
-            context.getLog().error(element, mirror, error);
+            context.getLog().message(Kind.ERROR, element, mirror, null, error);
         }
 
         return false;
@@ -77,6 +81,10 @@
         return type;
     }
 
+    public TypeMirror getTruffleIntrinsics() {
+        return truffleIntrinsics;
+    }
+
     public TypeMirror getTypeConversion() {
         return typeConversion;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Thu Mar 21 14:11:13 2013 +0100
@@ -47,9 +47,25 @@
         }
     }
 
+    public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) {
+        TypeMirror boxedType = primitiveType;
+        if (boxedType.getKind().isPrimitive()) {
+            boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
+        }
+        return boxedType;
+    }
+
+    public static List<TypeMirror> asTypeMirrors(List<? extends Element> elements) {
+        List<TypeMirror> types = new ArrayList<>(elements.size());
+        for (Element element : elements) {
+            types.add(element.asType());
+        }
+        return types;
+    }
+
     public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element,
                     Class<? extends Annotation> annotationClass) {
-        List<AnnotationMirror> result = Utils.getAnnotationValueList(markerAnnotation, elementName);
+        List<AnnotationMirror> result = Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName);
         AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass);
         if (explicit != null) {
             result.add(explicit);
@@ -61,6 +77,42 @@
         return result;
     }
 
+    public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) {
+        if (types.length == 0) {
+            return context.getType(Object.class);
+        }
+        TypeMirror prev = types[0];
+        for (int i = 1; i < types.length; i++) {
+            prev = getCommonSuperType(context, prev, types[i]);
+        }
+        return prev;
+    }
+
+    public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) {
+        if (typeEquals(type1, type2)) {
+            return type1;
+        }
+        TypeElement element1 = fromTypeMirror(type1);
+        TypeElement element2 = fromTypeMirror(type2);
+        if (element1 == null || element2 == null) {
+            return context.getType(Object.class);
+        }
+
+        List<TypeElement> element1Types = getDirectSuperTypes(element1);
+        element1Types.add(0, element1);
+        List<TypeElement> element2Types = getDirectSuperTypes(element2);
+        element2Types.add(0, element2);
+
+        for (TypeElement superType1 : element1Types) {
+            for (TypeElement superType2 : element2Types) {
+                if (typeEquals(superType1.asType(), superType2.asType())) {
+                    return superType2.asType();
+                }
+            }
+        }
+        return context.getType(Object.class);
+    }
+
     public static String getReadableSignature(ExecutableElement method) {
         // TODO toString does not guarantee a good signature
         return method.toString();
@@ -123,6 +175,46 @@
         return new LinkedHashSet<>(Arrays.asList(modifier));
     }
 
+    public static String getTypeId(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+                return "Boolean";
+            case BYTE:
+                return "Byte";
+            case CHAR:
+                return "Char";
+            case DOUBLE:
+                return "Double";
+            case FLOAT:
+                return "Float";
+            case SHORT:
+                return "Short";
+            case INT:
+                return "Int";
+            case LONG:
+                return "Long";
+            case DECLARED:
+                return ((DeclaredType) mirror).asElement().getSimpleName().toString();
+            case ARRAY:
+                return getTypeId(((ArrayType) mirror).getComponentType()) + "Array";
+            case VOID:
+                return "Void";
+            case WILDCARD:
+                StringBuilder b = new StringBuilder();
+                WildcardType type = (WildcardType) mirror;
+                if (type.getExtendsBound() != null) {
+                    b.append("Extends").append(getTypeId(type.getExtendsBound()));
+                } else if (type.getSuperBound() != null) {
+                    b.append("Super").append(getTypeId(type.getExtendsBound()));
+                }
+                return b.toString();
+            case TYPEVAR:
+                return "Any";
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
     public static String getSimpleName(TypeElement element) {
         return getSimpleName(element.asType());
     }
@@ -146,31 +238,43 @@
             case LONG:
                 return "long";
             case DECLARED:
-                return getGenericName(fromTypeMirror(mirror));
+                return getDeclaredName((DeclaredType) mirror);
             case ARRAY:
                 return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]";
             case VOID:
                 return "void";
+            case WILDCARD:
+                return getWildcardName((WildcardType) mirror);
             case TYPEVAR:
-                return ((TypeParameterElement) ((TypeVariable) mirror).asElement()).getSimpleName().toString();
+                return "?";
             default:
                 throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
         }
     }
 
-    private static String getGenericName(TypeElement element) {
-        String simpleName = element.getSimpleName().toString();
+    private static String getWildcardName(WildcardType type) {
+        StringBuilder b = new StringBuilder();
+        if (type.getExtendsBound() != null) {
+            b.append("? extends ").append(getSimpleName(type.getExtendsBound()));
+        } else if (type.getSuperBound() != null) {
+            b.append("? super ").append(getSimpleName(type.getExtendsBound()));
+        }
+        return b.toString();
+    }
 
-        if (element.getTypeParameters().size() == 0) {
+    private static String getDeclaredName(DeclaredType element) {
+        String simpleName = element.asElement().getSimpleName().toString();
+
+        if (element.getTypeArguments().size() == 0) {
             return simpleName;
         }
 
         StringBuilder b = new StringBuilder(simpleName);
         b.append("<");
-        if (element.getTypeParameters().size() > 0) {
-            for (int i = 0; i < element.getTypeParameters().size(); i++) {
-                b.append("?");
-                if (i < element.getTypeParameters().size() - 1) {
+        if (element.getTypeArguments().size() > 0) {
+            for (int i = 0; i < element.getTypeArguments().size(); i++) {
+                b.append(getSimpleName(element.getTypeArguments().get(i)));
+                if (i < element.getTypeArguments().size() - 1) {
                     b.append(", ");
                 }
             }
@@ -282,6 +386,19 @@
         return null;
     }
 
+    public static List<TypeElement> getDirectSuperTypes(TypeElement element) {
+        List<TypeElement> types = new ArrayList<>();
+        if (element.getSuperclass() != null) {
+            TypeElement superElement = fromTypeMirror(element.getSuperclass());
+            if (superElement != null) {
+                types.add(superElement);
+                types.addAll(getDirectSuperTypes(superElement));
+            }
+        }
+
+        return types;
+    }
+
     public static List<TypeElement> getSuperTypes(TypeElement element) {
         List<TypeElement> types = new ArrayList<>();
         List<TypeElement> superTypes = null;
@@ -359,29 +476,32 @@
     }
 
     @SuppressWarnings("unchecked")
-    public static <T> List<T> getAnnotationValueList(AnnotationMirror mirror, String name) {
+    public static <T> List<T> getAnnotationValueList(Class<T> expectedListType, AnnotationMirror mirror, String name) {
+        List<? extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name);
         List<T> result = new ArrayList<>();
-        List<? extends AnnotationValue> values = (List<? extends AnnotationValue>) getAnnotationValue(mirror, name).getValue();
+
         for (AnnotationValue value : values) {
-            result.add((T) value.getValue());
+            result.add(resolveAnnotationValue(expectedListType, value));
         }
         return result;
     }
 
-    public static TypeMirror getAnnotationValueType(AnnotationMirror mirror, String name) {
-        return (TypeMirror) getAnnotationValue(mirror, name).getValue();
+    public static <T> T getAnnotationValue(Class<T> expectedType, AnnotationMirror mirror, String name) {
+        return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name));
     }
 
-    public static TypeMirror getAnnotationValueTypeMirror(AnnotationMirror mirror, String name) {
-        return (TypeMirror) getAnnotationValue(mirror, name).getValue();
-    }
-
-    public static String getAnnotationValueString(AnnotationMirror mirror, String name) {
-        return (String) getAnnotationValue(mirror, name).getValue();
-    }
-
-    public static int getAnnotationValueInt(AnnotationMirror mirror, String name) {
-        return (int) getAnnotationValue(mirror, name).getValue();
+    @SuppressWarnings({"unchecked"})
+    private static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
+        Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null);
+        if (unboxedValue != null) {
+            if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
+                return null;
+            }
+            if (!expectedType.isAssignableFrom(unboxedValue.getClass())) {
+                throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName());
+            }
+        }
+        return (T) unboxedValue;
     }
 
     public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) {
@@ -401,9 +521,79 @@
         if (value == null) {
             value = valueMethod.getDefaultValue();
         }
+
         return value;
     }
 
+    private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7<Object, Void> {
+
+        @Override
+        public Object visitBoolean(boolean b, Void p) {
+            return Boolean.valueOf(b);
+        }
+
+        @Override
+        public Object visitByte(byte b, Void p) {
+            return Byte.valueOf(b);
+        }
+
+        @Override
+        public Object visitChar(char c, Void p) {
+            return c;
+        }
+
+        @Override
+        public Object visitDouble(double d, Void p) {
+            return d;
+        }
+
+        @Override
+        public Object visitFloat(float f, Void p) {
+            return f;
+        }
+
+        @Override
+        public Object visitInt(int i, Void p) {
+            return i;
+        }
+
+        @Override
+        public Object visitLong(long i, Void p) {
+            return i;
+        }
+
+        @Override
+        public Object visitShort(short s, Void p) {
+            return s;
+        }
+
+        @Override
+        public Object visitString(String s, Void p) {
+            return s;
+        }
+
+        @Override
+        public Object visitType(TypeMirror t, Void p) {
+            return t;
+        }
+
+        @Override
+        public Object visitEnumConstant(VariableElement c, Void p) {
+            return c.getConstantValue();
+        }
+
+        @Override
+        public Object visitAnnotation(AnnotationMirror a, Void p) {
+            return a;
+        }
+
+        @Override
+        public Object visitArray(List<? extends AnnotationValue> vals, Void p) {
+            return vals;
+        }
+
+    }
+
     public static boolean getAnnotationValueBoolean(AnnotationMirror mirror, String name) {
         return (Boolean) getAnnotationValue(mirror, name).getValue();
     }
@@ -468,8 +658,10 @@
             for (int i = 0; i < params.length; i++) {
                 TypeMirror param1 = params[i];
                 TypeMirror param2 = method.getParameters().get(i).asType();
-                if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
-                    continue method;
+                if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) {
+                    if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
+                        continue method;
+                    }
                 }
             }
             return method;
@@ -520,6 +712,14 @@
         }
         String qualified1 = getQualifiedName(type1);
         String qualified2 = getQualifiedName(type2);
+
+        if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) {
+            if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) {
+                return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType());
+            } else {
+                return false;
+            }
+        }
         return qualified1.equals(qualified2);
     }
 
@@ -548,7 +748,7 @@
             return true;
         }
 
-        // search for any supertypes
+        // search for any super types
         TypeElement exceptionTypeElement = fromTypeMirror(exceptionType);
         List<TypeElement> superTypes = getSuperTypes(exceptionTypeElement);
         for (TypeElement typeElement : superTypes) {
@@ -577,7 +777,7 @@
         Set<String> typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type)));
         String typeName = getQualifiedName(type);
         if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) {
-            throw new IllegalArgumentException("Given does not extend Throwable.");
+            throw new IllegalArgumentException("Given type does not extend Throwable.");
         }
         return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName());
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java	Thu Mar 21 14:11:13 2013 +0100
@@ -103,6 +103,18 @@
         return annotations;
     }
 
+    /* Support JDK8 langtools. */
+    @SuppressWarnings("unused")
+    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /* Support for some JDK8 builds. (remove after jdk8 is released) */
+    @SuppressWarnings("unused")
+    public <A extends Annotation> A[] getAnnotations(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
         throw new UnsupportedOperationException();
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java	Thu Mar 21 14:11:13 2013 +0100
@@ -59,6 +59,7 @@
         }
     }
 
+    /* Support JDK8 langtools. */
     public boolean isDefault() {
         return false;
     }
@@ -113,7 +114,7 @@
     }
 
     public CodeTreeBuilder createBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder();
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
         this.bodyTree = builder.getTree();
         this.bodyTree.setEnclosingElement(this);
         this.body = null;
@@ -203,7 +204,7 @@
         return v.visitExecutable(this, p);
     }
 
-    public static CodeExecutableElement clone(ProcessingEnvironment env, ExecutableElement method) {
+    public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) {
         CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString());
         for (TypeMirror thrownType : method.getThrownTypes()) {
             copy.addThrownType(thrownType);
@@ -219,7 +220,6 @@
         for (Element element : method.getEnclosedElements()) {
             copy.add(element);
         }
-        copy.setBody(Utils.getMethodBody(env, method));
         copy.getModifiers().addAll(method.getModifiers());
         return copy;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Thu Mar 21 14:11:13 2013 +0100
@@ -33,17 +33,25 @@
 
 public class CodeTreeBuilder {
 
+    private final CodeTreeBuilder parent;
+
     private BuilderCodeTree currentElement;
     private final BuilderCodeTree root;
 
-    public CodeTreeBuilder() {
+    private int treeCount;
+
+    public CodeTreeBuilder(CodeTreeBuilder parent) {
         this.root = new BuilderCodeTree(GROUP, null, null);
         this.currentElement = root;
+        this.parent = parent;
     }
 
-    public CodeTreeBuilder(CodeTree tree) {
-        this.root = (BuilderCodeTree) tree;
-        this.currentElement = root;
+    public int getTreeCount() {
+        return treeCount;
+    }
+
+    public boolean isEmpty() {
+        return treeCount == 0;
     }
 
     public CodeTreeBuilder statement(String statement) {
@@ -55,11 +63,11 @@
     }
 
     public static CodeTreeBuilder createBuilder() {
-        return new CodeTreeBuilder();
+        return new CodeTreeBuilder(null);
     }
 
     public static CodeTree singleString(String s) {
-        return new CodeTreeBuilder().string(s).getTree();
+        return new CodeTreeBuilder(null).string(s).getTree();
     }
 
     private CodeTreeBuilder push(CodeTreeKind kind) {
@@ -89,11 +97,14 @@
                 currentElement = tree;
                 break;
         }
+        treeCount++;
         return this;
     }
 
     private void clearLast(CodeTreeKind kind) {
-        clearLastRec(kind, currentElement.getEnclosedElements());
+        if (clearLastRec(kind, currentElement.getEnclosedElements())) {
+            treeCount--;
+        }
     }
 
     public CodeTreeBuilder startStatement() {
@@ -193,6 +204,24 @@
         return this;
     }
 
+    private CodeTreeBuilder startCurlyBracesCommaGroup() {
+        startGroup();
+        string("{").startCommaGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string("}");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
     public CodeTreeBuilder startParantheses() {
         startGroup();
         string("(").startGroup();
@@ -211,6 +240,10 @@
         return this;
     }
 
+    public CodeTreeBuilder doubleQuote(String s) {
+        return startGroup().string("\"").string(s).string("\"").end();
+    }
+
     public CodeTreeBuilder startDoubleQuote() {
         startGroup().string("\"");
         registerCallBack(new EndCallback() {
@@ -271,6 +304,15 @@
         return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
     }
 
+    public boolean startIf(boolean elseIf) {
+        if (elseIf) {
+            startElseIf();
+        } else {
+            startIf();
+        }
+        return true;
+    }
+
     public CodeTreeBuilder startElseIf() {
         clearLast(CodeTreeKind.NEW_LINE);
         return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
@@ -346,6 +388,19 @@
         return startStatement().string("assert ");
     }
 
+    public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) {
+        startGroup().string("new ").type(arrayType.getComponentType()).string("[");
+        if (size != null) {
+            tree(size);
+        }
+        string("]");
+        if (size == null) {
+            string(" ");
+            startCurlyBracesCommaGroup().endAfter();
+        }
+        return this;
+    }
+
     public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) {
         return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter();
     }
@@ -358,6 +413,13 @@
         return push(CodeTreeKind.INDENT);
     }
 
+    public CodeTreeBuilder end(int times) {
+        for (int i = 0; i < times; i++) {
+            end();
+        }
+        return this;
+    }
+
     public CodeTreeBuilder end() {
         BuilderCodeTree tree = currentElement;
         EndCallback callback = tree.getAtEndListener();
@@ -372,9 +434,9 @@
     }
 
     private void toParent() {
-        Element parent = currentElement.getEnclosingElement();
+        Element parentElement = currentElement.getEnclosingElement();
         if (currentElement != root) {
-            this.currentElement = (BuilderCodeTree) parent;
+            this.currentElement = (BuilderCodeTree) parentElement;
         } else {
             this.currentElement = root;
         }
@@ -433,7 +495,7 @@
     }
 
     public CodeTreeBuilder create() {
-        return new CodeTreeBuilder();
+        return new CodeTreeBuilder(this);
     }
 
     public CodeTreeBuilder type(TypeMirror type) {
@@ -471,7 +533,7 @@
         if (Utils.isVoid(type)) {
             tree(content);
             return this;
-        } else if (Utils.getQualifiedName(type).equals("java.lang.Object")) {
+        } else if (type.getKind() == TypeKind.DECLARED && Utils.getQualifiedName(type).equals("java.lang.Object")) {
             tree(content);
             return this;
         } else {
@@ -496,7 +558,11 @@
         while (element != null && (element.getKind() != ElementKind.METHOD)) {
             element = element.getEnclosingElement();
         }
-        return element != null ? (ExecutableElement) element : null;
+        ExecutableElement found = element != null ? (ExecutableElement) element : null;
+        if (found == null && parent != null) {
+            found = parent.findMethod();
+        }
+        return found;
     }
 
     public CodeTreeBuilder returnTrue() {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java	Thu Mar 21 14:11:13 2013 +0100
@@ -58,7 +58,7 @@
     }
 
     public CodeTreeBuilder createInitBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder();
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
         init = builder.getTree();
         init.setEnclosingElement(this);
         return builder;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java	Thu Mar 21 14:11:13 2013 +0100
@@ -36,9 +36,16 @@
 
 public abstract class AbstractCodeWriter extends CodeElementScanner<Void, Void> {
 
+    private static final int LINE_LENGTH = 200;
+    private static final int LINE_WRAP_INDENTS = 3;
+    private static final String IDENT_STRING = "    ";
+    private static final String LN = "\n"; /* unix style */
+
     protected Writer writer;
     private int indent;
     private boolean newLine;
+    private int lineLength;
+    private boolean lineWrapping = false;
 
     private OrganizedImports imports;
 
@@ -56,8 +63,7 @@
             Writer w = null;
             try {
                 imports = OrganizedImports.organize(e);
-
-                w = createWriter(e);
+                w = new TrimTrailingSpaceWriter(createWriter(e));
                 writer = w;
                 writeRootClass(e);
             } catch (IOException ex) {
@@ -117,6 +123,14 @@
         writeClassImpl(e);
     }
 
+    private String useImport(TypeMirror type) {
+        if (imports != null) {
+            return imports.useImport(type);
+        } else {
+            return Utils.getSimpleName(type);
+        }
+    }
+
     private void writeClassImpl(CodeTypeElement e) {
         for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
             visitAnnotation(annotation);
@@ -131,12 +145,12 @@
         }
         write(e.getSimpleName());
         if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) {
-            write(" extends ").write(typeSimpleName(e.getSuperclass()));
+            write(" extends ").write(useImport(e.getSuperclass()));
         }
         if (e.getImplements().size() > 0) {
             write(" implements ");
             for (int i = 0; i < e.getImplements().size(); i++) {
-                write(typeSimpleName(e.getImplements().get(i)));
+                write(useImport(e.getImplements().get(i)));
                 if (i < e.getImplements().size() - 1) {
                     write(", ");
                 }
@@ -145,7 +159,7 @@
 
         write(" {").writeLn();
         writeEmptyLn();
-        indent();
+        indent(1);
 
         List<VariableElement> staticFields = getStaticFields(e);
         List<VariableElement> instanceFields = getInstanceFields(e);
@@ -191,7 +205,7 @@
             clazz.accept(this, null);
         }
 
-        dedent();
+        dedent(1);
         write("}");
         writeEmptyLn();
     }
@@ -261,7 +275,15 @@
             }
         } else {
             writeModifiers(f.getModifiers());
-            write(typeSimpleName(f.asType()));
+            write(useImport(f.asType()));
+
+            if (f.getEnclosingElement().getKind() == ElementKind.METHOD) {
+                ExecutableElement method = (ExecutableElement) f.getEnclosingElement();
+                if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) {
+                    write("...");
+                }
+            }
+
             write(" ");
             write(f.getSimpleName());
             if (init != null) {
@@ -273,7 +295,7 @@
     }
 
     public void visitAnnotation(AnnotationMirror e) {
-        write("@").write(typeSimpleName(e.getAnnotationType()));
+        write("@").write(useImport(e.getAnnotationType()));
 
         if (!e.getElementValues().isEmpty()) {
             write("(");
@@ -381,14 +403,14 @@
 
         @Override
         public Void visitType(TypeMirror t, Void p) {
-            write(typeSimpleName(t));
+            write(useImport(t));
             write(".class");
             return null;
         }
 
         @Override
         public Void visitEnumConstant(VariableElement c, Void p) {
-            write(typeSimpleName(c.asType()));
+            write(useImport(c.asType()));
             write(".");
             write(c.getSimpleName().toString());
             return null;
@@ -444,7 +466,7 @@
         writeModifiers(e.getModifiers());
 
         if (e.getReturnType() != null) {
-            write(typeSimpleName(e.getReturnType()));
+            write(useImport(e.getReturnType()));
             write(" ");
         }
         write(e.getSimpleName());
@@ -463,7 +485,7 @@
         if (throwables.size() > 0) {
             write(" throws ");
             for (int i = 0; i < throwables.size(); i++) {
-                write(typeSimpleName(throwables.get(i)));
+                write(useImport(throwables.get(i)));
                 if (i < throwables.size() - 1) {
                     write(", ");
                 }
@@ -474,9 +496,9 @@
             writeLn(";");
         } else if (e.getBodyTree() != null) {
             writeLn(" {");
-            indent();
+            indent(1);
             e.getBodyTree().acceptCodeElementScanner(this, p);
-            dedent();
+            dedent(1);
             writeLn("}");
         } else if (e.getBody() != null) {
             write(" {");
@@ -509,11 +531,11 @@
                 }
                 break;
             case INDENT:
-                indent();
+                indent(1);
                 for (CodeTree tree : e.getEnclosedElements()) {
                     tree.acceptCodeElementScanner(this, p);
                 }
-                dedent();
+                dedent(1);
                 break;
             case NEW_LINE:
                 writeLn();
@@ -540,7 +562,7 @@
                 }
                 break;
             case TYPE:
-                write(imports.useImport(e.getType()));
+                write(useImport(e.getType()));
                 break;
             default:
                 assert false;
@@ -548,10 +570,6 @@
         }
     }
 
-    private static String typeSimpleName(TypeMirror type) {
-        return Utils.getSimpleName(type);
-    }
-
     protected void writeHeader() {
         // default implementation does nothing
     }
@@ -565,25 +583,28 @@
         }
     }
 
-    private static final String LN = "\n";
-
-    protected void indent() {
-        indent++;
+    protected void indent(int count) {
+        indent += count;
     }
 
-    protected void dedent() {
-        indent--;
+    protected void dedent(int count) {
+        indent -= count;
     }
 
     protected void writeLn() {
-        write(LN);
-        newLine = true;
+        writeLn("");
     }
 
     protected void writeLn(String text) {
         write(text);
         write(LN);
+        lineLength = 0;
         newLine = true;
+        if (lineWrapping) {
+            dedent(LINE_WRAP_INDENTS);
+            lineWrapping = false;
+        }
+        lineWrapping = false;
     }
 
     protected void writeEmptyLn() {
@@ -596,10 +617,23 @@
 
     private AbstractCodeWriter write(String m) {
         try {
+            lineLength += m.length();
             if (newLine && m != LN) {
                 writeIndent();
                 newLine = false;
             }
+            if (lineLength > LINE_LENGTH && m.length() > 0) {
+                char firstChar = m.charAt(0);
+                if (Character.isAlphabetic(firstChar)) {
+                    if (!lineWrapping) {
+                        indent(LINE_WRAP_INDENTS);
+                    }
+                    lineWrapping = true;
+                    lineLength = 0;
+                    write(LN);
+                    writeIndent();
+                }
+            }
             writer.write(m);
         } catch (IOException e) {
             throw new RuntimeException(e);
@@ -609,7 +643,57 @@
 
     private void writeIndent() throws IOException {
         for (int i = 0; i < indent; i++) {
-            writer.write("    ");
+            lineLength += IDENT_STRING.length();
+            writer.write(IDENT_STRING);
         }
     }
+
+    private static class TrimTrailingSpaceWriter extends Writer {
+
+        private final Writer delegate;
+        private final StringBuilder buffer = new StringBuilder();
+
+        public TrimTrailingSpaceWriter(Writer delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public void close() throws IOException {
+            this.delegate.close();
+        }
+
+        @Override
+        public void flush() throws IOException {
+            this.delegate.flush();
+        }
+
+        @Override
+        public void write(char[] cbuf, int off, int len) throws IOException {
+            buffer.append(cbuf, off, len);
+            int newLinePoint = buffer.indexOf(LN);
+
+            if (newLinePoint != -1) {
+                String lhs = trimTrailing(buffer.substring(0, newLinePoint));
+                delegate.write(lhs);
+                delegate.write(LN);
+                buffer.delete(0, newLinePoint + 1);
+            }
+        }
+
+        private static String trimTrailing(String s) {
+            int cut = 0;
+            for (int i = s.length() - 1; i >= 0; i--) {
+                if (Character.isWhitespace(s.charAt(i))) {
+                    cut++;
+                } else {
+                    break;
+                }
+            }
+            if (cut > 0) {
+                return s.substring(0, s.length() - cut);
+            }
+            return s;
+        }
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java	Thu Mar 21 14:11:13 2013 +0100
@@ -63,19 +63,71 @@
     }
 
     public String useImport(TypeMirror type) {
-        String simpleName = getSimpleName(type);
-        TypeMirror usedByType = simpleNamesUsed.get(type);
+        switch (type.getKind()) {
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case DOUBLE:
+            case FLOAT:
+            case SHORT:
+            case INT:
+            case LONG:
+            case VOID:
+                return Utils.getSimpleName(type);
+            case DECLARED:
+                return createDeclaredTypeName((DeclaredType) type);
+            case ARRAY:
+                return useImport(((ArrayType) type).getComponentType()) + "[]";
+            case WILDCARD:
+                return createWildcardName((WildcardType) type);
+            case TYPEVAR:
+                return "?";
+            default:
+                throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
+        }
+    }
+
+    private String createWildcardName(WildcardType type) {
+        StringBuilder b = new StringBuilder();
+        if (type.getExtendsBound() != null) {
+            b.append("? extends ").append(useImport(type.getExtendsBound()));
+        } else if (type.getSuperBound() != null) {
+            b.append("? super ").append(useImport(type.getExtendsBound()));
+        }
+        return b.toString();
+    }
+
+    private String createDeclaredTypeName(DeclaredType type) {
+        String name = type.asElement().getSimpleName().toString();
+
+        TypeMirror usedByType = simpleNamesUsed.get(name);
         if (usedByType == null) {
-            simpleNamesUsed.put(simpleName, type);
+            simpleNamesUsed.put(name, type);
             usedByType = type;
-        } else if (!typeEquals(type, usedByType)) {
-            // we need a qualified name
-            return getQualifiedName(type);
         }
 
-        // we can use the simple name
-        addUsage(type, importUsage);
-        return simpleName;
+        if (typeEquals(type, usedByType)) {
+            addUsage(type, importUsage);
+        } else {
+            name = getQualifiedName(type);
+        }
+
+        if (type.getTypeArguments().size() == 0) {
+            return name;
+        }
+
+        StringBuilder b = new StringBuilder(name);
+        b.append("<");
+        if (type.getTypeArguments().size() > 0) {
+            for (int i = 0; i < type.getTypeArguments().size(); i++) {
+                b.append(useImport(type.getTypeArguments().get(i)));
+                if (i < type.getTypeArguments().size() - 1) {
+                    b.append(", ");
+                }
+            }
+        }
+        b.append(">");
+        return b.toString();
     }
 
     public String useStaticFieldImport(TypeMirror type, String fieldName) {
@@ -307,6 +359,100 @@
 
         public void visitAnnotation(AnnotationMirror e) {
             addImport(e.getAnnotationType());
+            if (!e.getElementValues().isEmpty()) {
+                Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
+                Set<? extends ExecutableElement> methodsSet = values.keySet();
+                List<ExecutableElement> methodsList = new ArrayList<>();
+                for (ExecutableElement method : methodsSet) {
+                    if (values.get(method) == null) {
+                        continue;
+                    }
+                    methodsList.add(method);
+                }
+
+                for (int i = 0; i < methodsList.size(); i++) {
+                    AnnotationValue value = values.get(methodsList.get(i));
+                    visitAnnotationValue(value);
+                }
+            }
+        }
+
+        public void visitAnnotationValue(AnnotationValue e) {
+            e.accept(new AnnotationValueReferenceVisitor(), null);
+        }
+
+        private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
+
+            @Override
+            public Void visitBoolean(boolean b, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitByte(byte b, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitChar(char c, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitDouble(double d, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitFloat(float f, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitInt(int i, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitLong(long i, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitShort(short s, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitString(String s, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitType(TypeMirror t, Void p) {
+                addImport(t);
+                return null;
+            }
+
+            @Override
+            public Void visitEnumConstant(VariableElement c, Void p) {
+                addImport(c.asType());
+                return null;
+            }
+
+            @Override
+            public Void visitAnnotation(AnnotationMirror a, Void p) {
+                ReferenceCollector.this.visitAnnotation(a);
+                return null;
+            }
+
+            @Override
+            public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
+                for (int i = 0; i < vals.size(); i++) {
+                    ReferenceCollector.this.visitAnnotationValue(vals.get(i));
+                }
+                return null;
+            }
         }
 
         @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java	Thu Mar 21 14:11:13 2013 +0100
@@ -39,6 +39,9 @@
     }
 
     protected static Object field(Object o, String fieldName) throws Exception {
+        if (o == null) {
+            return null;
+        }
         Field field = o.getClass().getField(fieldName);
         field.setAccessible(true);
         return field.get(o);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -31,6 +31,7 @@
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.api.*;
 import com.oracle.truffle.codegen.processor.api.element.*;
+import com.oracle.truffle.codegen.processor.template.*;
 
 public class ExtensionParser {
 
@@ -45,25 +46,25 @@
         this.extensionContext = new ExtensionContextImpl(context.getEnvironment(), null, factory);
     }
 
-    public List<WritableElement> parseAll(TypeElement typeElement, List<? extends Element> elements) {
+    public List<WritableElement> parseAll(Template template, List<? extends Element> elements) {
         List<WritableElement> generatedMethods = new ArrayList<>();
-        parseElement(generatedMethods, typeElement);
+        parseElement(template, generatedMethods, template.getTemplateType());
 
         List<? extends ExecutableElement> methods = ElementFilter.methodsIn(elements);
         for (ExecutableElement method : methods) {
             for (VariableElement var : method.getParameters()) {
-                parseElement(generatedMethods, var);
+                parseElement(template, generatedMethods, var);
             }
-            parseElement(generatedMethods, method);
+            parseElement(template, generatedMethods, method);
         }
 
         return generatedMethods;
     }
 
-    private void parseElement(List<WritableElement> elements, Element element) {
+    private void parseElement(Template template, List<WritableElement> elements, Element element) {
         List<? extends AnnotationMirror> mirrors = element.getAnnotationMirrors();
         for (AnnotationMirror mirror : mirrors) {
-            ExtensionProcessor processor = findProcessor(element, mirror);
+            ExtensionProcessor processor = findProcessor(template, mirror);
             if (processor != null) {
                 try {
                     factory.generatorAnnotationMirror = mirror;
@@ -71,7 +72,7 @@
                     processor.process(extensionContext, mirror, element);
                     elements.addAll(extensionContext.returnElements());
                 } catch (Throwable e) {
-                    context.getLog().error(element, mirror, "Processor for '%s' failed with exception: \n\n%s.", Utils.getQualifiedName(mirror.getAnnotationType()), Utils.printException(e));
+                    template.addError("Processor for '%s' failed with exception: \n\n%s.", Utils.getQualifiedName(mirror.getAnnotationType()), Utils.printException(e));
                 } finally {
                     factory.generatorAnnotationMirror = null;
                     factory.generatorElement = null;
@@ -80,7 +81,7 @@
         }
     }
 
-    private ExtensionProcessor findProcessor(Element element, AnnotationMirror mirror) {
+    private ExtensionProcessor findProcessor(Template template, AnnotationMirror mirror) {
         String processorName = Utils.getQualifiedName(mirror.getAnnotationType());
         ExtensionProcessor processor = null;
         if (extensions.containsKey(processorName)) {
@@ -88,24 +89,24 @@
         } else {
             AnnotationMirror foundExtension = Utils.findAnnotationMirror(context.getEnvironment(), mirror.getAnnotationType().asElement(), ExtensionAnnotation.class);
             if (foundExtension != null) {
-                String className = Utils.getAnnotationValueString(foundExtension, "processorClassName");
+                String className = Utils.getAnnotationValue(String.class, foundExtension, "processorClassName");
                 Class<?> processorClass;
                 try {
                     processorClass = Class.forName(className);
                 } catch (ClassNotFoundException e) {
-                    context.getLog().error(element, mirror, "Could not find processor class '%s' configured in '@%s'.", className, processorName);
+                    template.addError("Could not find processor class '%s' configured in '@%s'.", className, processorName);
                     return null;
                 }
                 try {
                     processor = (ExtensionProcessor) processorClass.newInstance();
                 } catch (InstantiationException e) {
-                    context.getLog().error(element, mirror, "Could not instantiate processor class '%s' configured in '@%s'.", className, processorName);
+                    template.addError("Could not instantiate processor class '%s' configured in '@%s'.", className, processorName);
                     return null;
                 } catch (IllegalAccessException e) {
-                    context.getLog().error(element, mirror, "Could not access processor class '%s' configured in '@%s'.", className, processorName);
+                    template.addError("Could not access processor class '%s' configured in '@%s'.", className, processorName);
                     return null;
                 } catch (ClassCastException e) {
-                    context.getLog().error(element, mirror, "Processor class '%s' configured in '@%s' does not implement '%s'.", className, processorName, ExtensionProcessor.class.getName());
+                    template.addError("Processor class '%s' configured in '@%s' does not implement '%s'.", className, processorName, ExtensionProcessor.class.getName());
                     return null;
                 }
             }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -44,14 +44,14 @@
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         List<TypeMirror> types = new ArrayList<>();
-        types.addAll(Arrays.asList(getNode().getTypeSystem().getPrimitiveTypeMirrors()));
+        types.addAll(getNode().getTypeSystem().getPrimitiveTypeMirrors());
         types.add(getContext().getType(void.class));
 
-        ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types.toArray(new TypeMirror[types.size()]), getNode().getTypeSystem().getGenericType(), false, Cardinality.ONE);
+        ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types, false, Cardinality.ONE);
 
         List<ParameterSpec> parameters = new ArrayList<>();
         parameters.add(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true));
-        return new MethodSpec(returnTypeSpec, parameters);
+        return new MethodSpec(new ArrayList<TypeMirror>(), returnTypeSpec, parameters);
     }
 
     @Override
@@ -63,9 +63,6 @@
     @Override
     public ExecutableTypeData create(TemplateMethod method) {
         TypeData resolvedType = method.getReturnType().getActualTypeData(getNode().getTypeSystem());
-        if (resolvedType == null) {
-            return null;
-        }
         return new ExecutableTypeData(method, getNode().getTypeSystem(), resolvedType);
     }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,12 +23,15 @@
 package com.oracle.truffle.codegen.processor.node;
 
 import java.lang.annotation.*;
+import java.util.*;
 
 import javax.lang.model.element.*;
+import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.*;
 
 public class GenericParser extends MethodParser<SpecializationData> {
 
@@ -38,17 +41,22 @@
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return createDefaultMethodSpec(null);
+        return createDefaultMethodSpec(method, mirror, null);
     }
 
     @Override
-    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) {
-        return new ParameterSpec(valueName, nodeData.findGenericExecutableType(getContext()).getType().getPrimitiveType(), false);
+    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, boolean optional) {
+        List<ExecutableTypeData> execTypes = nodeData.findGenericExecutableTypes(getContext());
+        List<TypeMirror> types = new ArrayList<>();
+        for (ExecutableTypeData type : execTypes) {
+            types.add(type.getType().getPrimitiveType());
+        }
+        return new ParameterSpec(valueName, types, false, Cardinality.ONE);
     }
 
     @Override
     protected ParameterSpec createReturnParameterSpec() {
-        return super.createValueParameterSpec("returnValue", getNode());
+        return super.createValueParameterSpec("returnValue", getNode(), false);
     }
 
     @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,9 +25,10 @@
 import java.util.*;
 
 import javax.lang.model.element.*;
+import javax.lang.model.type.*;
 
 import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.*;
 import com.oracle.truffle.codegen.processor.template.*;
 import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
 
@@ -41,12 +42,12 @@
         return template;
     }
 
-    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) {
-        return new ParameterSpec(valueName, nodeData, false, Cardinality.ONE);
+    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, boolean optional) {
+        return new ParameterSpec(valueName, nodeData, optional, Cardinality.ONE);
     }
 
     protected ParameterSpec createReturnParameterSpec() {
-        return createValueParameterSpec("operation", getNode());
+        return createValueParameterSpec("operation", getNode(), false);
     }
 
     @Override
@@ -54,10 +55,29 @@
         return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
     }
 
-    protected final MethodSpec createDefaultMethodSpec(String shortCircuitName) {
+    @SuppressWarnings("unused")
+    protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, String shortCircuitName) {
         List<ParameterSpec> defaultParameters = new ArrayList<>();
-        ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true);
-        defaultParameters.add(frameSpec);
+
+        if (getNode().supportsFrame()) {
+            defaultParameters.add(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true));
+        }
+
+        TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType();
+
+        List<TypeMirror> prefixTypes = new ArrayList<>();
+
+        if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(declaredType, template.getNodeType())) {
+            prefixTypes.add(getNode().getTemplateType().asType());
+        }
+
+        for (NodeFieldData field : getNode().getFields()) {
+            if (field.getKind() == FieldKind.FIELD) {
+                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType(), true);
+                spec.setLocal(true);
+                defaultParameters.add(spec);
+            }
+        }
 
         for (NodeFieldData field : getNode().getFields()) {
             if (field.getExecutionKind() == ExecutionKind.IGNORE) {
@@ -65,7 +85,12 @@
             }
 
             if (field.getExecutionKind() == ExecutionKind.DEFAULT) {
-                defaultParameters.add(createValueParameterSpec(field.getName(), field.getNodeData()));
+                ParameterSpec spec = createValueParameterSpec(field.getName(), field.getNodeData(), false);
+                if (field.getKind() == FieldKind.CHILDREN) {
+                    spec.setCardinality(Cardinality.MULTIPLE);
+                    spec.setIndexed(true);
+                }
+                defaultParameters.add(spec);
             } else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
                 String valueName = field.getName();
                 if (shortCircuitName != null && valueName.equals(shortCircuitName)) {
@@ -73,14 +98,13 @@
                 }
 
                 defaultParameters.add(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class), false));
-
-                defaultParameters.add(createValueParameterSpec(valueName, field.getNodeData()));
+                defaultParameters.add(createValueParameterSpec(valueName, field.getNodeData(), false));
             } else {
                 assert false;
             }
         }
 
-        return new MethodSpec(createReturnParameterSpec(), defaultParameters);
+        return new MethodSpec(prefixTypes, createReturnParameterSpec(), defaultParameters);
     }
 
     private static String shortCircuitValueName(String valueName) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -31,9 +31,11 @@
 import javax.lang.model.type.*;
 import javax.lang.model.util.*;
 
+import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.ast.*;
 import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.FieldKind;
 import com.oracle.truffle.codegen.processor.template.*;
 import com.oracle.truffle.codegen.processor.typesystem.*;
 
@@ -50,64 +52,49 @@
     }
 
     private static String factoryClassName(NodeData node) {
-        return nodeClassName(node) + "Factory";
-    }
-
-    private static String nodeClassName(NodeData node) {
-        return Utils.getSimpleName(node.getTemplateType().asType());
+        return node.getNodeId() + "Factory";
     }
 
-    private static String nodeClassName(SpecializationData specialization) {
-        String name = specializationId(specialization);
-        name += nodeClassName(specialization.getNode());
-        if (name.equals(Utils.getSimpleName(specialization.getNode().getNodeType())) || name.equals(Utils.getSimpleName(specialization.getNode().getTemplateType()))) {
-            name = name + "Impl";
+    private static String nodeSpecializationClassName(SpecializationData specialization) {
+        String nodeid = specialization.getNode().getNodeId();
+        if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
+            nodeid = nodeid.substring(0, nodeid.length() - 4);
         }
 
+        String name = Utils.firstLetterUpperCase(nodeid);
+        name += Utils.firstLetterUpperCase(specialization.getId());
+        name += "Node";
         return name;
     }
 
-    private static String specializationId(SpecializationData specialization) {
-        String name = "";
-        if (specialization.getNode().getSpecializations().length > 1) {
-            name = specialization.getMethodName();
-            if (name.startsWith("do")) {
-                name = name.substring(2);
-            }
-        }
-        return name;
+    private static String valueName(ActualParameter param) {
+        return param.getLocalName();
     }
 
-    private static String valueName(NodeFieldData field) {
-        return field.getName() + "Value";
+    private static String castValueName(ActualParameter parameter) {
+        return valueName(parameter) + "Cast";
     }
 
-    private static String valueName(TemplateMethod method, ActualParameter param) {
-        NodeData node = (NodeData) method.getTemplate();
-        NodeFieldData field = node.findField(param.getSpecification().getName());
-        if (field != null) {
-            return valueName(field);
-        } else {
-            return param.getSpecification().getName();
-        }
-    }
-
-    private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) {
-        if (forceFrame) {
-            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frame"));
+    private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) {
+        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
+            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
         }
         for (ActualParameter parameter : specialization.getParameters()) {
             ParameterSpec spec = parameter.getSpecification();
             if (forceFrame && spec.getName().equals("frame")) {
                 continue;
             }
-            method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(specialization, parameter)));
+            if (spec.isLocal()) {
+                continue;
+            }
+
+            method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter)));
         }
     }
 
-    private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame) {
-        if (forceFrame) {
-            builder.string("frame");
+    private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) {
+        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
+            builder.string("frameValue");
         }
         for (ActualParameter parameter : specialization.getParameters()) {
             ParameterSpec spec = parameter.getSpecification();
@@ -115,57 +102,137 @@
                 continue;
             }
 
-            if (unexpectedValueName != null && spec.getName().equals(unexpectedValueName)) {
-                builder.string("ex.getResult()");
+            if (!includeImplicit && (parameter.isImplicit())) {
+                continue;
+            }
+            if (parameter.getSpecification().isLocal()) {
+                continue;
+            }
+
+            if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) {
+                builder.cast(parameter.getActualType(), CodeTreeBuilder.singleString("ex.getResult()"));
             } else {
-                builder.string(valueName(specialization, parameter));
+                builder.string(valueName(parameter));
             }
         }
     }
 
-    private static void addValueParameterNamesWithCasts(ProcessorContext context, CodeTreeBuilder body, SpecializationData specialization) {
-        for (ActualParameter param : specialization.getParameters()) {
-            TypeData typeData = param.getActualTypeData(specialization.getNode().getTypeSystem());
-            if (typeData == null || typeData.isGeneric()) {
-                body.string(valueName(specialization, param));
+    private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod target, TemplateMethod sourceMethod, TemplateMethod castMethod, String unexpectedValueName) {
+        CodeTreeBuilder builder = parent.create();
+
+        boolean castedValues = sourceMethod != castMethod;
+
+        builder.startGroup();
+        ExecutableElement method = target.getMethod();
+        if (method == null) {
+            throw new IllegalStateException("Cannot call synthtetic operation methods.");
+        }
+        TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement());
+        NodeData node = (NodeData) castMethod.getTemplate();
+        TypeSystemData typeSystem = node.getTypeSystem();
+
+        boolean accessible = target.canBeAccessedByInstanceOf(node.getNodeType());
+        if (accessible) {
+            if (builder.findMethod().getModifiers().contains(STATIC)) {
+                builder.string(THIS_NODE_LOCAL_VAR_NAME);
+            } else {
+                builder.string("super");
+            }
+        } else {
+            if (method.getModifiers().contains(STATIC)) {
+                builder.type(targetClass.asType());
             } else {
-                String methodName = TypeSystemCodeGenerator.asTypeMethodName(typeData);
-                startCallTypeSystemMethod(context, body, specialization.getNode(), methodName);
-                body.string(valueName(specialization, param));
-                body.end().end();
+                ActualParameter parameter = null;
+                for (ActualParameter searchParameter : target.getParameters()) {
+                    if (!searchParameter.getSpecification().isOptional()) {
+                        parameter = searchParameter;
+                        break;
+                    }
+                }
+                assert parameter != null;
+
+                if (castedValues) {
+                    NodeFieldData field = node.findField(parameter.getSpecification().getName());
+                    if (field == null) {
+                        builder.string(valueName(parameter));
+                    } else {
+                        NodeData fieldNode = field.getNodeData();
+                        ExecutableTypeData execType = fieldNode.findExecutableType(parameter.getActualTypeData(node.getTypeSystem()));
+                        if (execType.hasUnexpectedValue(getContext())) {
+                            builder.string(castValueName(parameter));
+                        } else {
+                            builder.string(valueName(parameter));
+                        }
+                    }
+                } else {
+                    builder.string(valueName(parameter));
+                }
             }
         }
+        builder.string(".");
+        builder.startCall(method.getSimpleName().toString());
+
+        for (ActualParameter targetParameter : castMethod.getParameters()) {
+            ActualParameter valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
+            if (valueParameter == null) {
+                continue;
+            }
+            TypeData targetType = targetParameter.getActualTypeData(typeSystem);
+
+            if (targetParameter.isImplicit() || valueParameter.isImplicit()) {
+                continue;
+            }
+
+            TypeData valueType = null;
+            if (valueParameter != null) {
+                valueType = valueParameter.getActualTypeData(typeSystem);
+            }
+
+            if (targetParameter.getSpecification().isLocal()) {
+                builder.startGroup();
+                if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) {
+                    builder.string(THIS_NODE_LOCAL_VAR_NAME).string(".");
+                } else {
+                    builder.string("this.");
+                }
+                builder.string(targetParameter.getSpecification().getName());
+                builder.end();
+            } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) {
+                builder.string("ex.getResult()");
+            } else if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) {
+                builder.string(valueName(targetParameter));
+            } else {
+                builder.string(castValueName(targetParameter));
+            }
+        }
+
+        builder.end().end();
+
+        return builder.getRoot();
     }
 
     private static String genClassName(Template operation) {
         return getSimpleName(operation.getTemplateType()) + "Gen";
     }
 
-    private static void startCallOperationMethod(CodeTreeBuilder body, TemplateMethod method) {
-        body.startGroup();
-        if (body.findMethod().getModifiers().contains(STATIC)) {
-            body.string(THIS_NODE_LOCAL_VAR_NAME);
-        } else {
-            body.string("super");
-        }
-        body.string(".");
-        body.startCall(method.getMethodName());
-    }
-
-    private static String generatedGenericMethodName(SpecializationData specialization) {
+    private String generatedGenericMethodName(SpecializationData specialization) {
         final String prefix = "generic";
 
         if (specialization == null) {
             return prefix;
         }
 
+        if (!specialization.getNode().needsRewrites(context)) {
+            return prefix;
+        }
+
         SpecializationData prev = null;
         for (SpecializationData current : specialization.getNode().getSpecializations()) {
             if (specialization == current) {
                 if (prev == null || prev.isUninitialized()) {
                     return prefix;
                 } else {
-                    return prefix + specializationId(current);
+                    return prefix + current.getId();
                 }
             }
             prev = current;
@@ -173,6 +240,14 @@
         return prefix;
     }
 
+    private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, String value) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        startCallTypeSystemMethod(context, builder, node, methodName);
+        builder.string(value);
+        builder.end().end();
+        return builder.getRoot();
+    }
+
     private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) {
         VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem());
         assert singleton != null;
@@ -182,42 +257,205 @@
         body.string(".").startCall(methodName);
     }
 
-    private static void emitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData specialization, boolean onSpecialization, boolean needsCast) {
-        TypeSystemData typeSystem = specialization.getNode().getTypeSystem();
-        // Implict guards based on method signature
-        String andOperator = prefix;
-        for (NodeFieldData field : specialization.getNode().getFields()) {
-            ActualParameter param = specialization.findParameter(field.getName());
-            TypeData type = param.getActualTypeData(typeSystem);
-            if (type == null || type.isGeneric()) {
-                continue;
-            }
+    private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean onSpecialization,
+                    CodeTree guardedStatements, CodeTree elseStatements) {
+
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, valueSpecialization, guardedSpecialization);
+        CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, valueSpecialization, guardedSpecialization, onSpecialization);
+
+        int ifCount = 0;
 
-            body.string(andOperator);
-            startCallTypeSystemMethod(context, body, specialization.getNode(), TypeSystemCodeGenerator.isTypeMethodName(type));
-            body.string(valueName(specialization, param));
-            body.end().end(); // call
-            andOperator = " && ";
+        if (implicitGuards != null) {
+            builder.startIf();
+            builder.tree(implicitGuards);
+            builder.end();
+            builder.startBlock();
+            ifCount++;
+        }
+
+        if (explicitGuards != null || !onSpecialization) {
+            builder.tree(createCasts(parent, valueSpecialization, guardedSpecialization));
         }
 
-        if (specialization.getGuards().length > 0) {
-            // Explicitly specified guards
-            for (SpecializationGuardData guard : specialization.getGuards()) {
-                if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) {
-                    body.string(andOperator);
+        if (explicitGuards != null) {
+            builder.startIf();
+            builder.tree(explicitGuards);
+            builder.end();
+            builder.startBlock();
+            ifCount++;
+        }
+
+        if (implicitGuards == null && explicitGuards == null && conditionPrefix != null && !conditionPrefix.isEmpty()) {
+            builder.startIf();
+            builder.string(conditionPrefix);
+            builder.end().startBlock();
+            ifCount++;
+        }
+
+        builder.tree(guardedStatements);
 
-                    startCallOperationMethod(body, guard.getGuardDeclaration());
+        builder.end(ifCount);
+        if (elseStatements != null && ifCount > 0) {
+            builder.tree(elseStatements);
+        }
+        return builder.getRoot();
+    }
 
-                    if (needsCast) {
-                        addValueParameterNamesWithCasts(context, body, specialization);
-                    } else {
-                        addValueParameterNames(body, specialization, null, false);
-                    }
-                    body.end().end(); // call
+    private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean onSpecialization) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        String andOperator = conditionPrefix != null ? conditionPrefix + " && " : "";
+        if (guardedSpecialization.getGuards().size() > 0) {
+            // Explicitly specified guards
+            for (SpecializationGuardData guard : guardedSpecialization.getGuards()) {
+                if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) {
+                    builder.string(andOperator);
+                    builder.tree(createTemplateMethodCall(parent, guard.getGuardDeclaration(), valueSpecialization, guardedSpecialization, null));
                     andOperator = " && ";
                 }
             }
         }
+
+        return builder.isEmpty() ? null : builder.getRoot();
+    }
+
+    private CodeTree createCasts(CodeTreeBuilder parent, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        // Implict guards based on method signature
+        for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
+            NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName());
+            if (field == null || field.getKind() == FieldKind.FIELD) {
+                continue;
+            }
+            ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName());
+
+            CodeTree cast = createCast(parent, field, valueParam, guardedParam);
+            if (cast == null) {
+                continue;
+            }
+            builder.tree(cast);
+        }
+
+        return builder.getRoot();
+    }
+
+    private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        // Implict guards based on method signature
+        String andOperator = conditionPrefix != null ? conditionPrefix + " && " : "";
+        for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
+            NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName());
+            if (field == null || field.getKind() == FieldKind.FIELD) {
+                continue;
+            }
+            ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName());
+
+            CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam);
+            if (implicitGuard == null) {
+                continue;
+            }
+
+            builder.string(andOperator);
+            builder.tree(implicitGuard);
+            andOperator = " && ";
+        }
+
+        return builder.isEmpty() ? null : builder.getRoot();
+    }
+
+    private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) {
+        NodeData node = field.getNodeData();
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+        TypeData targetType = target.getActualTypeData(node.getTypeSystem());
+        TypeData sourceType = source.getActualTypeData(node.getTypeSystem());
+
+        if (targetType.equalsType(sourceType) || targetType.isGeneric()) {
+            return null;
+        }
+
+        builder.startGroup();
+
+        if (field.isShortCircuit()) {
+            ActualParameter shortCircuit = target.getPreviousParameter();
+            assert shortCircuit != null;
+            builder.string("(");
+            builder.string("!").string(valueName(shortCircuit));
+            builder.string(" || ");
+        }
+
+        startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getActualTypeData(node.getTypeSystem())));
+        builder.string(valueName(source));
+        builder.end().end(); // call
+
+        if (field.isShortCircuit()) {
+            builder.string(")");
+        }
+
+        builder.end(); // group
+
+        return builder.getRoot();
+    }
+
+    private CodeTree createCast(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) {
+        NodeData node = field.getNodeData();
+        TypeSystemData typeSystem = node.getTypeSystem();
+
+        TypeData sourceType = source.getActualTypeData(typeSystem);
+        TypeData targetType = target.getActualTypeData(typeSystem);
+
+        if (targetType.equalsType(sourceType) || targetType.isGeneric()) {
+            return null;
+        }
+
+        CodeTree condition = null;
+        if (field.isShortCircuit()) {
+            ActualParameter shortCircuit = target.getPreviousParameter();
+            assert shortCircuit != null;
+            condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
+        }
+
+        CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), valueName(target));
+
+        return createLazyAssignment(parent, castValueName(target), target.getActualType(), condition, value);
+    }
+
+    /**
+     * <pre>
+     * variant1 $condition != null
+     * 
+     * $type $name = defaultValue($type);
+     * if ($condition) {
+     *     $name = $value;
+     * }
+     * 
+     * variant2 $condition != null
+     * $type $name = $value;
+     * </pre>
+     * 
+     * .
+     */
+    private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        if (condition == null) {
+            builder.declaration(type, name, value);
+        } else {
+            builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot());
+
+            builder.startIf().tree(condition).end();
+            builder.startBlock();
+            builder.startStatement();
+            builder.string(name);
+            builder.string(" = ");
+            builder.tree(value);
+            builder.end(); // statement
+            builder.end(); // block
+        }
+        return builder.getRoot();
+    }
+
+    private void emitEncounteredSynthetic(CodeTreeBuilder builder) {
+        builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
     }
 
     @Override
@@ -235,11 +473,7 @@
             add(factory, node);
         }
 
-        if (node.getSpecializations() == null) {
-            return;
-        }
-
-        if (node.needsFactory() || childTypes.size() > 0) {
+        if (node.needsFactory() || node.getNodeChildren().size() > 0) {
             add(new NodeFactoryFactory(context, childTypes), node);
         }
     }
@@ -308,13 +542,15 @@
             if (node.needsFactory()) {
                 createFactoryMethods(node, clazz, createVisibility);
 
-                if (node.getSpecializations().length > 1) {
+                if (node.getSpecializations().size() > 1) {
                     clazz.add(createCreateSpecializedMethod(node, createVisibility));
                 }
 
-                if (node.needsRewrites(getContext())) {
+                if (node.needsRewrites(context)) {
                     clazz.add(createSpecializeMethod(node));
+                }
 
+                if (node.getGenericSpecialization() != null) {
                     List<CodeExecutableElement> genericMethods = createGeneratedGenericMethod(node);
                     for (CodeExecutableElement method : genericMethods) {
                         clazz.add(method);
@@ -324,6 +560,16 @@
                 for (SpecializationData specialization : node.getSpecializations()) {
                     add(new SpecializedNodeFactory(context), specialization);
                 }
+
+                TypeMirror nodeFactory = getContext().getEnvironment().getTypeUtils().getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType());
+                clazz.getImplements().add(nodeFactory);
+                clazz.add(createCreateNodeMethod(node));
+                clazz.add(createCreateNodeSpecializedMethod(node));
+                clazz.add(createGetNodeClassMethod(node));
+                clazz.add(createGetNodeSignaturesMethod(node));
+                clazz.add(createGetChildrenSignatureMethod(node));
+                clazz.add(createGetInstanceMethod(node, createVisibility));
+                clazz.add(createInstanceConstant(node, clazz.asType()));
             }
 
             for (NodeData childNode : childTypes.keySet()) {
@@ -344,9 +590,283 @@
                     clazz.add(type);
                 }
             }
+
+            List<NodeData> children = node.getNodeChildren();
+            if (node.getParent() == null && children.size() > 0) {
+                clazz.add(createGetFactories(node));
+            }
+
+        }
+
+        private CodeExecutableElement createGetNodeClassMethod(NodeData node) {
+            Types types = getContext().getEnvironment().getTypeUtils();
+            TypeMirror returnType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType());
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass");
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn().typeLiteral(node.getNodeType()).end();
+            return method;
+        }
+
+        private CodeExecutableElement createGetNodeSignaturesMethod(NodeData node) {
+            Types types = getContext().getEnvironment().getTypeUtils();
+            TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class));
+            TypeMirror classType = getContext().getType(Class.class);
+            TypeMirror returnType = types.getDeclaredType(listType, types.getDeclaredType(listType, classType));
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures");
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            builder.startStaticCall(getContext().getType(Arrays.class), "asList");
+            List<ExecutableElement> constructors = findUserConstructors(node);
+            for (ExecutableElement constructor : constructors) {
+                builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType));
+            }
+            builder.end();
+            builder.end();
+            return method;
+        }
+
+        private CodeExecutableElement createGetChildrenSignatureMethod(NodeData node) {
+            Types types = getContext().getEnvironment().getTypeUtils();
+            TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class));
+            TypeMirror classType = getContext().getType(Class.class);
+            TypeMirror nodeType = getContext().getTruffleTypes().getNode();
+            TypeMirror wildcardNodeType = types.getWildcardType(nodeType, null);
+            classType = types.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType);
+            TypeMirror returnType = types.getDeclaredType(listType, classType);
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature");
+            CodeTreeBuilder builder = method.createBuilder();
+
+            List<TypeMirror> signatureTypes = new ArrayList<>();
+            assert !node.getSpecializations().isEmpty();
+            SpecializationData data = node.getSpecializations().get(0);
+            for (ActualParameter parameter : data.getParameters()) {
+                ParameterSpec spec = parameter.getSpecification();
+                NodeFieldData field = node.findField(spec.getName());
+                if (field == null || field.getKind() == FieldKind.FIELD) {
+                    continue;
+                }
+
+                TypeMirror type;
+                if (field.getKind() == FieldKind.CHILDREN && field.getType().getKind() == TypeKind.ARRAY) {
+                    type = ((ArrayType) field.getType()).getComponentType();
+                } else {
+                    type = field.getType();
+                }
+
+                signatureTypes.add(type);
+            }
+
+            builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end();
+            return method;
+        }
+
+        private CodeTree createAsList(CodeTreeBuilder parent, List<TypeMirror> types, TypeMirror elementClass) {
+            CodeTreeBuilder builder = parent.create();
+            builder.startGroup();
+            builder.type(getContext().getType(Arrays.class));
+            builder.string(".<").type(elementClass).string(">");
+            builder.startCall("asList");
+            for (TypeMirror typeMirror : types) {
+                builder.typeLiteral(typeMirror);
+            }
+            builder.end().end();
+            return builder.getRoot();
+        }
+
+        private CodeExecutableElement createCreateNodeMethod(NodeData node) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode");
+            CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments");
+            method.setVarArgs(true);
+            method.addParameter(arguments);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            List<ExecutableElement> signatures = findUserConstructors(node);
+            boolean ifStarted = false;
+
+            for (ExecutableElement element : signatures) {
+                ifStarted = builder.startIf(ifStarted);
+                builder.string("arguments.length == " + element.getParameters().size());
+
+                int index = 0;
+                for (VariableElement param : element.getParameters()) {
+                    builder.string(" && ");
+                    if (!param.asType().getKind().isPrimitive()) {
+                        builder.string("(arguments[" + index + "] == null || ");
+                    }
+                    builder.string("arguments[" + index + "] instanceof ");
+                    builder.type(Utils.boxType(getContext(), param.asType()));
+                    if (!param.asType().getKind().isPrimitive()) {
+                        builder.string(")");
+                    }
+                    index++;
+                }
+                builder.end();
+                builder.startBlock();
+
+                builder.startReturn().startCall("create");
+                index = 0;
+                for (VariableElement param : element.getParameters()) {
+                    builder.startGroup();
+                    builder.string("(").type(param.asType()).string(") ");
+                    builder.string("arguments[").string(String.valueOf(index)).string("]");
+                    builder.end();
+                    index++;
+                }
+                builder.end().end();
+
+                builder.end(); // block
+            }
+
+            builder.startElseBlock();
+            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
+            builder.doubleQuote("Invalid create signature.");
+            builder.end().end();
+            builder.end(); // else block
+            return method;
+        }
+
+        private CodeExecutableElement createCreateNodeSpecializedMethod(NodeData node) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNodeSpecialized");
+            CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), "thisNode");
+            CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Class.class), "types");
+            method.addParameter(nodeParam);
+            method.addParameter(arguments);
+            method.setVarArgs(true);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            if (!node.needsRewrites(getContext())) {
+                builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
+            } else {
+                builder.startIf();
+                builder.string("types.length == 1");
+                builder.end();
+                builder.startBlock();
+
+                builder.startReturn().startCall("createSpecialized");
+                builder.string("thisNode");
+                builder.string("types[0]");
+                builder.end().end();
+
+                builder.end();
+                builder.startElseBlock();
+                builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
+                builder.doubleQuote("Invalid createSpecialized signature.");
+                builder.end().end();
+                builder.end();
+            }
+
+            return method;
+        }
+
+        private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) {
+            Types types = getContext().getEnvironment().getTypeUtils();
+            TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class));
+            TypeMirror returnType = types.getDeclaredType(nodeFactoryType, node.getNodeType());
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance");
+            if (visibility != null) {
+                method.getModifiers().add(visibility);
+            }
+            method.getModifiers().add(Modifier.STATIC);
+
+            String varName = instanceVarName(node);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startIf();
+            builder.string(varName).string(" == null");
+            builder.end().startBlock();
+
+            builder.startStatement();
+            builder.string(varName);
+            builder.string(" = ");
+            builder.startNew(factoryClassName(node)).end();
+            builder.end();
+
+            builder.end();
+            builder.startReturn().string(varName).end();
+            return method;
+        }
+
+        private String instanceVarName(NodeData node) {
+            if (node.getParent() != null) {
+                return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
+            } else {
+                return "instance";
+            }
+        }
+
+        private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) {
+            String varName = instanceVarName(node);
+            CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName);
+            var.getModifiers().add(Modifier.PRIVATE);
+            var.getModifiers().add(Modifier.STATIC);
+            return var;
+        }
+
+        private ExecutableElement createGetFactories(NodeData node) {
+            List<NodeData> children = node.getNodeChildren();
+            if (node.needsFactory()) {
+                children.add(node);
+            }
+
+            List<TypeMirror> nodeTypesList = new ArrayList<>();
+            TypeMirror prev = null;
+            boolean allSame = true;
+            for (NodeData child : children) {
+                nodeTypesList.add(child.getNodeType());
+                if (prev != null && !Utils.typeEquals(child.getNodeType(), prev)) {
+                    allSame = false;
+                }
+                prev = child.getNodeType();
+            }
+            TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()]));
+
+            Types types = getContext().getEnvironment().getTypeUtils();
+            TypeMirror factoryType = getContext().getType(NodeFactory.class);
+            TypeMirror baseType;
+            if (allSame) {
+                baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType);
+            } else {
+                baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
+            }
+            TypeMirror listType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType);
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
+
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            builder.startStaticCall(getContext().getType(Arrays.class), "asList");
+
+            for (NodeData child : children) {
+                builder.startGroup();
+                NodeData childNode = child;
+                List<NodeData> factories = new ArrayList<>();
+                while (childNode.getParent() != null) {
+                    factories.add(childNode);
+                    childNode = childNode.getParent();
+                }
+                Collections.reverse(factories);
+                for (NodeData nodeData : factories) {
+                    builder.string(factoryClassName(nodeData)).string(".");
+                }
+                builder.string("getInstance()");
+                builder.end();
+            }
+            builder.end();
+            builder.end();
+            return method;
         }
 
         private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) {
+            List<ExecutableElement> constructors = findUserConstructors(node);
+            for (ExecutableElement constructor : constructors) {
+                clazz.add(createCreateMethod(node, createVisibility, constructor));
+            }
+        }
+
+        private List<ExecutableElement> findUserConstructors(NodeData node) {
+            List<ExecutableElement> constructors = new ArrayList<>();
             for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements())) {
                 if (constructor.getModifiers().contains(PRIVATE)) {
                     continue;
@@ -356,9 +876,9 @@
                 if (constructor.getParameters().size() == 1 && typeEquals(constructor.getParameters().get(0).asType(), node.getNodeType())) {
                     continue;
                 }
-
-                clazz.add(createCreateMethod(node, createVisibility, constructor));
+                constructors.add(constructor);
             }
+            return constructors;
         }
 
         private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) {
@@ -373,10 +893,10 @@
 
             CodeTreeBuilder body = method.createBuilder();
             body.startReturn();
-            if (node.getSpecializations().length == 0) {
+            if (node.getSpecializations().isEmpty()) {
                 body.null_();
             } else {
-                body.startNew(nodeClassName(node.getSpecializations()[0]));
+                body.startNew(nodeSpecializationClassName(node.getSpecializations().get(0)));
                 for (VariableElement var : method.getParameters()) {
                     body.string(var.getSimpleName().toString());
                 }
@@ -408,14 +928,14 @@
                         body.startElseIf();
                     }
                     body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock();
-                    body.startReturn().startNew(nodeClassName(specialization));
+                    body.startReturn().startNew(nodeSpecializationClassName(specialization));
                     body.string(THIS_NODE_LOCAL_VAR_NAME);
                     body.end().end(); // new, return
 
                     body.end(); // if
                 }
             }
-            body.startReturn().startNew(nodeClassName(node.getGenericSpecialization()));
+            body.startReturn().startNew(nodeSpecializationClassName(node.getGenericSpecialization()));
             body.string(THIS_NODE_LOCAL_VAR_NAME);
             body.end().end();
             return method;
@@ -425,26 +945,21 @@
             CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize");
             method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
             method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
-            addValueParameters(method, node.getGenericSpecialization(), false);
+            addInternalValueParameters(method, node.getGenericSpecialization(), false);
 
             CodeTreeBuilder body = method.createBuilder();
-            body.startStatement().string("boolean allowed = (minimumState == ").string(nodeClassName(node.getSpecializations()[0])).string(".class)").end();
+            body.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end();
 
-            for (int i = 1; i < node.getSpecializations().length; i++) {
-                SpecializationData specialization = node.getSpecializations()[i];
-                body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end();
+            for (int i = 1; i < node.getSpecializations().size(); i++) {
+                SpecializationData specialization = node.getSpecializations().get(i);
+                body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(specialization)).string(".class)").end();
 
-                if (specialization.isGeneric()) {
-                    body.startIf().string("allowed").end().startBlock();
-                } else {
-                    body.startIf().string("allowed");
-                    emitGuards(getContext(), body, " && ", specialization, true, true);
-                    body.end().startBlock();
-                }
-                body.startReturn().startNew(nodeClassName(specialization));
-                body.string(THIS_NODE_LOCAL_VAR_NAME);
-                body.end().end();
-                body.end(); // block
+                CodeTreeBuilder guarded = new CodeTreeBuilder(body);
+                guarded.startReturn().startNew(nodeSpecializationClassName(specialization));
+                guarded.string(THIS_NODE_LOCAL_VAR_NAME);
+                guarded.end().end();
+
+                body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null));
             }
             body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end();
 
@@ -453,14 +968,14 @@
 
         private List<CodeExecutableElement> createGeneratedGenericMethod(NodeData node) {
             TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getActualType();
-            if (node.getGenericSpecialization().isUseSpecializationsForGeneric()) {
+            if (node.needsRewrites(context)) {
                 List<CodeExecutableElement> methods = new ArrayList<>();
 
-                SpecializationData[] specializations = node.getSpecializations();
+                List<SpecializationData> specializations = node.getSpecializations();
                 SpecializationData prev = null;
-                for (int i = 0; i < specializations.length; i++) {
-                    SpecializationData current = specializations[i];
-                    SpecializationData next = i + 1 < specializations.length ? specializations[i + 1] : null;
+                for (int i = 0; i < specializations.size(); i++) {
+                    SpecializationData current = specializations.get(i);
+                    SpecializationData next = i + 1 < specializations.size() ? specializations.get(i + 1) : null;
                     if (prev == null || current.isUninitialized()) {
                         prev = current;
                         continue;
@@ -468,7 +983,7 @@
                         String methodName = generatedGenericMethodName(current);
                         CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, methodName);
                         method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
-                        addValueParameters(method, node.getGenericSpecialization(), true);
+                        addInternalValueParameters(method, node.getGenericSpecialization(), true);
 
                         emitGeneratedGenericSpecialization(method.createBuilder(), current, next);
 
@@ -481,57 +996,61 @@
             } else {
                 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, generatedGenericMethodName(null));
                 method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
-                addValueParameters(method, node.getGenericSpecialization(), true);
+                addInternalValueParameters(method, node.getGenericSpecialization(), true);
                 emitInvokeDoMethod(method.createBuilder(), node.getGenericSpecialization(), 0);
                 return Arrays.asList(method);
             }
         }
 
         private void emitGeneratedGenericSpecialization(CodeTreeBuilder builder, SpecializationData current, SpecializationData next) {
-            if (next != null) {
-                builder.startIf();
-                emitGuards(context, builder, "", current, false, true);
-                builder.end().startBlock();
-            }
-
-            emitInvokeDoMethod(builder, current, 0);
+            CodeTreeBuilder invokeMethodBuilder = new CodeTreeBuilder(builder);
+            emitInvokeDoMethod(invokeMethodBuilder, current, 0);
+            CodeTree invokeMethod = invokeMethodBuilder.getRoot();
 
             if (next != null) {
-                builder.end();
-                builder.startElseBlock();
+                CodeTreeBuilder nextBuilder = builder.create();
+
+                nextBuilder.startReturn().startCall(generatedGenericMethodName(next));
+                nextBuilder.string(THIS_NODE_LOCAL_VAR_NAME);
+                addInternalValueParameterNames(nextBuilder, next, null, true, true);
+                nextBuilder.end().end();
 
-                builder.startReturn().startCall(generatedGenericMethodName(next));
-                builder.string(THIS_NODE_LOCAL_VAR_NAME);
-                addValueParameterNames(builder, next, null, true);
-                builder.end().end();
+                invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, nextBuilder.getRoot());
+            }
 
+            builder.tree(invokeMethod);
+
+            if (next != null) {
                 builder.end();
             }
         }
 
         private void emitInvokeDoMethod(CodeTreeBuilder builder, SpecializationData specialization, int level) {
-            if (specialization.getExceptions().length > 0) {
+            if (!specialization.getExceptions().isEmpty()) {
                 builder.startTryBlock();
             }
 
-            builder.startReturn();
-            startCallOperationMethod(builder, specialization);
-            addValueParameterNamesWithCasts(context, builder, specialization);
-            builder.end().end(); // start call operation
-            builder.end(); // return
+            if (specialization.getMethod() == null) {
+                emitEncounteredSynthetic(builder);
+            } else {
+                builder.startReturn();
+                builder.tree(createTemplateMethodCall(builder, specialization, specialization.getNode().getGenericSpecialization(), specialization, null));
+                builder.end(); // return
+            }
 
-            if (specialization.getExceptions().length > 0) {
+            if (!specialization.getExceptions().isEmpty()) {
                 for (SpecializationThrowsData exception : specialization.getExceptions()) {
                     builder.end().startCatchBlock(exception.getJavaClass(), "ex" + level);
 
                     builder.startReturn().startCall(generatedGenericMethodName(exception.getTransitionTo()));
                     builder.string(THIS_NODE_LOCAL_VAR_NAME);
-                    addValueParameterNames(builder, exception.getTransitionTo(), null, true);
+                    addInternalValueParameterNames(builder, exception.getTransitionTo(), null, true, true);
                     builder.end().end();
                 }
                 builder.end();
             }
         }
+
     }
 
     private class SpecializedNodeFactory extends ClassElementFactory<SpecializationData> {
@@ -543,7 +1062,7 @@
         @Override
         public CodeTypeElement create(SpecializationData specialization) {
             NodeData node = specialization.getNode();
-            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeClassName(specialization), node.getNodeType(), false);
+            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), node.getNodeType(), false);
             return clazz;
         }
 
@@ -567,7 +1086,7 @@
                 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
                 if (method.getParameters().size() == 1) {
                     CodeVariableElement var = CodeVariableElement.clone(method.getParameters().get(0));
-                    var.setName("frame");
+                    var.setName("frameValue");
                     method.getParameters().set(0, var);
                 }
                 method.getModifiers().remove(Modifier.ABSTRACT);
@@ -582,7 +1101,7 @@
             }
 
             if (node.needsRewrites(getContext()) && !specialization.isGeneric() && !specialization.isUninitialized()) {
-                buildSpecializeStateMethod(clazz, specialization);
+                buildSpecializeAndExecute(clazz, specialization);
             }
         }
 
@@ -600,7 +1119,7 @@
             CodeTree primaryExecuteCall = null;
 
             CodeTreeBuilder executeBuilder = CodeTreeBuilder.createBuilder();
-            buildExecute(executeBuilder, null, execType);
+            buildExecute(executeBuilder, null, null, execType);
             primaryExecuteCall = executeBuilder.getRoot();
 
             if (needsTry) {
@@ -623,14 +1142,14 @@
                     builder.string("// ignore").newLine();
                 } else {
                     builder.startReturn();
-                    builder.tree(castPrimaryExecute(node, castedType, CodeTreeBuilder.singleString("ex.getResult()")));
+                    builder.tree(createExpectType(node, castedType, CodeTreeBuilder.singleString("ex.getResult()")));
                     builder.end();
                 }
                 builder.end();
 
                 if (!returnVoid) {
                     builder.startReturn();
-                    builder.tree(castPrimaryExecute(node, castedType, CodeTreeBuilder.singleString("value")));
+                    builder.tree(createExpectType(node, castedType, CodeTreeBuilder.singleString("value")));
                     builder.end();
                 }
             } else {
@@ -638,137 +1157,195 @@
                     builder.statement(primaryExecuteCall);
                 } else {
                     builder.startReturn();
-                    builder.tree(castPrimaryExecute(node, castedType, primaryExecuteCall));
+                    builder.tree(createExpectType(node, castedType, primaryExecuteCall));
                     builder.end();
                 }
             }
         }
 
-        private CodeTree castPrimaryExecute(NodeData node, ExecutableTypeData castedType, CodeTree value) {
-            if (castedType.getType().isVoid()) {
+        private CodeTree createExpectType(NodeData node, ExecutableTypeData castedType, CodeTree value) {
+            if (castedType == null) {
                 return value;
-            }
-            if (castedType.getType().isGeneric()) {
+            } else if (castedType.getType().isVoid()) {
+                return value;
+            } else if (castedType.getType().isGeneric()) {
                 return value;
             }
 
             CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+            String targetMethodName;
             if (castedType.hasUnexpectedValue(getContext())) {
-                startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.expectTypeMethodName(castedType.getType()));
+                targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(castedType.getType());
             } else {
-                startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.asTypeMethodName(castedType.getType()));
+                targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(castedType.getType());
             }
+            startCallTypeSystemMethod(getContext(), builder, node, targetMethodName);
+
             builder.tree(value);
             builder.end().end();
             return builder.getRoot();
         }
 
         private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            TypeSystemData typeSystem = node.getTypeSystem();
-
-            for (NodeFieldData field : node.getFields()) {
-                if (field.getExecutionKind() == ExecutionKind.IGNORE) {
-                    continue;
-                }
-
-                ActualParameter parameterType = specialization.findParameter(field.getName());
-
-                if (parameterType.getActualTypeData(typeSystem).isGeneric()) {
-                    buildGenericValueExecute(builder, specialization, field, null);
-                } else {
-                    buildSpecializedValueExecute(builder, specialization, field);
-                }
+            if (specialization.isUninitialized()) {
+                builder.tree(createDeoptimize(builder));
             }
 
-            if (specialization.hasDynamicGuards()) {
-                builder.startIf();
-                emitGuards(getContext(), builder, "", specialization, false, false);
-                builder.end().startBlock();
+            builder.tree(createExecuteChildren(builder, specialization));
+
+            CodeTree executeNode;
+            if (specialization.isUninitialized()) {
+                builder.tree(createSpecializeCall(builder, specialization));
+            }
+            executeNode = createExecute(builder, specialization);
+
+            SpecializationData next = specialization.findNextSpecialization();
+            CodeTree returnSpecialized = null;
+            if (next != null) {
+                returnSpecialized = createReturnSpecializeAndExecute(builder, next, null);
             }
-            if (specialization.getExceptions().length > 0) {
+            builder.tree(createGuardAndCast(builder, null, specialization, specialization, false, executeNode, returnSpecialized));
+        }
+
+        private CodeTree createDeoptimize(CodeTreeBuilder parent) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            builder.startStatement();
+            builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end();
+            builder.end();
+            return builder.getRoot();
+        }
+
+        private CodeTree createSpecializeCall(CodeTreeBuilder parent, SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            emitSpecializationListeners(builder, node);
+
+            builder.startStatement();
+            builder.startCall("replace");
+            if (node.needsRewrites(getContext())) {
+                builder.startCall(factoryClassName(node), "specialize");
+                builder.string("this");
+                builder.typeLiteral(builder.findMethod().getEnclosingElement().asType());
+                addInternalValueParameterNames(builder, specialization, null, false, true);
+                builder.end(); // call replace, call specialize
+            } else {
+                builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end();
+            }
+            builder.end().end();
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecute(CodeTreeBuilder parent, SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            if (!specialization.getExceptions().isEmpty()) {
                 builder.startTryBlock();
             }
 
             if (specialization.isUninitialized()) {
-                for (TemplateMethod listener : node.getSpecializationListeners()) {
-                    builder.startStatement();
-                    startCallOperationMethod(builder, listener);
-                    addValueParameterNames(builder, listener, null, false);
-                    builder.end().end();
-                    builder.end(); // statement
+                String genericMethodName = generatedGenericMethodName(null);
+                builder.startReturn().startCall(factoryClassName(node), genericMethodName);
+                builder.string("this");
+                addInternalValueParameterNames(builder, specialization, null, true, true);
+                builder.end().end();
+            } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
+                emitEncounteredSynthetic(builder);
+            } else if (specialization.isGeneric()) {
+                String genericMethodName;
+                if (!specialization.isUseSpecializationsForGeneric()) {
+                    genericMethodName = generatedGenericMethodName(specialization);
+                } else {
+                    genericMethodName = generatedGenericMethodName(null);
                 }
 
-                builder.startStatement();
-                builder.startCall("replace");
-                if (node.needsRewrites(getContext())) {
-                    builder.startCall(factoryClassName(node), "specialize");
-                    builder.string("this");
-                    builder.typeLiteral(builder.getRoot().getEnclosingClass().asType());
-                    addValueParameterNames(builder, specialization, null, false);
-                    builder.end(); // call replace, call specialize
-                } else {
-                    builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end();
-                }
-                builder.end().end();
-            }
-
-            if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) {
-                builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null));
+                builder.startReturn().startCall(factoryClassName(node), genericMethodName);
                 builder.string("this");
-                addValueParameterNames(builder, specialization, null, true);
+                addInternalValueParameterNames(builder, specialization, null, true, true);
                 builder.end().end();
             } else {
                 builder.startReturn();
-
-                if (specialization.isUninitialized()) {
-                    startCallOperationMethod(builder, specialization.getNode().getGenericSpecialization());
-                } else {
-                    startCallOperationMethod(builder, specialization);
-                }
-                addValueParameterNames(builder, specialization, null, false);
-                builder.end().end(); // operation call
+                builder.tree(createTemplateMethodCall(builder, specialization, specialization, specialization, null));
                 builder.end(); // return
             }
 
-            if (specialization.getExceptions().length > 0) {
+            if (!specialization.getExceptions().isEmpty()) {
                 for (SpecializationThrowsData exception : specialization.getExceptions()) {
                     builder.end().startCatchBlock(exception.getJavaClass(), "ex");
-                    buildThrowSpecialize(builder, specialization, exception.getTransitionTo(), null);
+                    builder.tree(createReturnSpecializeAndExecute(parent, exception.getTransitionTo(), null));
                 }
                 builder.end();
             }
-            if (specialization.hasDynamicGuards()) {
-                builder.end().startElseBlock();
-                buildThrowSpecialize(builder, specialization, specialization.findNextSpecialization(), null);
-                builder.end();
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            for (ActualParameter parameter : specialization.getParameters()) {
+                NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName());
+                if (field == null || field.getKind() == FieldKind.FIELD) {
+                    continue;
+                }
+
+                buildFieldExecute(builder, specialization, parameter, field, null);
+            }
+            return builder.getRoot();
+        }
+
+        private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) {
+            for (TemplateMethod listener : node.getSpecializationListeners()) {
+                builder.startStatement();
+                builder.tree(createTemplateMethodCall(builder, listener, listener, listener, null));
+                builder.end(); // statement
             }
         }
 
-        private void buildGenericValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field, NodeFieldData exceptionSpec) {
-            ActualParameter specParameter = specialization.findParameter(field.getName());
-
-            boolean shortCircuit = startShortCircuit(builder, specialization, field, exceptionSpec);
+        private void buildFieldExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) {
+            boolean shortCircuit = startShortCircuit(builder, specialization, param, exceptionParam);
+            ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem()));
+            boolean unexpected = execType.hasUnexpectedValue(getContext());
 
-            builder.startStatement();
-            if (!shortCircuit) {
-                builder.type(specialization.getNode().getTypeSystem().getGenericType());
-                builder.string(" ");
+            if (!shortCircuit && unexpected) {
+                builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end();
+            }
+
+            if (unexpected) {
+                builder.startTryBlock();
             }
 
-            builder.string(valueName(specialization, specParameter));
-            builder.string(" = ");
-            ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext());
-            if (genericExecutableType == null) {
-                throw new AssertionError("Must have generic executable type. Parser validation most likely failed. " + Arrays.toString(field.getNodeData().getExecutableTypes()));
+            if (!shortCircuit && !unexpected) {
+                builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).string(" = ");
+            } else {
+                builder.startStatement().string(valueName(param)).string(" = ");
             }
-            buildExecute(builder, field, genericExecutableType);
+            buildExecute(builder, param, field, execType);
             builder.end();
 
+            if (unexpected) {
+                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+                SpecializationData generic = specialization.getNode().getGenericSpecialization();
+                boolean execute = false;
+                for (ActualParameter exParam : generic.getParameters()) {
+                    NodeFieldData exField = generic.getNode().findField(exParam.getSpecification().getName());
+                    if (exField == null || field.getKind() == FieldKind.FIELD) {
+                        continue;
+                    }
+                    if (execute) {
+                        buildFieldExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param);
+                    } else if (exParam.getLocalName().equals(param.getLocalName())) {
+                        execute = true;
+                    }
+                }
+                builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param));
+                builder.end(); // catch block
+            }
+
             endShortCircuit(builder, shortCircuit);
+            builder.newLine();
         }
 
-        private void buildExecute(CodeTreeBuilder builder, NodeFieldData field, ExecutableTypeData execType) {
+        private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) {
             if (field != null) {
                 Element accessElement = field.getAccessElement();
                 if (accessElement.getKind() == ElementKind.METHOD) {
@@ -778,60 +1355,28 @@
                 } else {
                     throw new AssertionError();
                 }
+                if (parameter.getSpecification().isIndexed()) {
+                    builder.string("[" + parameter.getIndex() + "]");
+                }
                 builder.string(".");
             }
             builder.startCall(execType.getMethodName());
-            if (execType.getParameters().length == 1) {
-                builder.string("frame");
+            if (execType.getParameters().size() == 1) {
+                builder.string("frameValue");
             }
             builder.end();
         }
 
-        private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field) {
-            ActualParameter param = specialization.findParameter(field.getName());
-            boolean shortCircuit = startShortCircuit(builder, specialization, field, null);
-
-            if (!shortCircuit) {
-                builder.startStatement().type(param.getActualType()).string(" ").string(valueName(specialization, param)).end();
-            }
-
-            ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem()));
-
-            if (execType.hasUnexpectedValue(getContext())) {
-                builder.startTryBlock();
+        private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) {
+            NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName());
+            if (forField == null) {
+                return false;
             }
 
-            builder.startStatement().string(valueName(field)).string(" = ");
-            buildExecute(builder, field, execType);
-            builder.end();
-
-            if (execType.hasUnexpectedValue(getContext())) {
-                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
-                boolean execute = false;
-                for (NodeFieldData exField : specialization.getNode().getFields()) {
-                    if (exField.getExecutionKind() == ExecutionKind.IGNORE) {
-                        continue;
-                    }
-                    if (execute) {
-                        buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exField, field);
-                    } else if (exField == field) {
-                        execute = true;
-                    }
-                }
-                buildThrowSpecialize(builder, specialization, specialization.findNextSpecialization(), param.getSpecification());
-                builder.end(); // catch block
-            }
-
-            endShortCircuit(builder, shortCircuit);
-            builder.newLine();
-        }
-
-        private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData forField, NodeFieldData exceptionField) {
             if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) {
                 return false;
             }
 
-            ActualParameter parameter = specialization.findParameter(forField.getName());
             ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
 
             int shortCircuitIndex = 0;
@@ -844,17 +1389,15 @@
                 }
             }
 
-            builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(specialization, shortCircuitParam)).string(" = ");
-            ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex];
+            builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = ");
+            ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex);
 
-            startCallOperationMethod(builder, shortCircuitData);
-            addValueParameterNames(builder, shortCircuitData, exceptionField != null ? exceptionField.getName() : null, false);
-            builder.end().end(); // call operation
+            builder.tree(createTemplateMethodCall(builder, shortCircuitData, shortCircuitData, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null));
 
             builder.end(); // statement
 
-            builder.declaration(parameter.getActualType(), valueName(specialization, parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType()));
-            builder.startIf().string(shortCircuitParam.getSpecification().getName()).end();
+            builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType()));
+            builder.startIf().string(shortCircuitParam.getLocalName()).end();
             builder.startBlock();
 
             return true;
@@ -866,74 +1409,66 @@
             }
         }
 
-        private void buildThrowSpecialize(CodeTreeBuilder builder, SpecializationData currentSpecialization, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) {
-            boolean canThrowUnexpected = Utils.canThrowType(builder.findMethod().getThrownTypes(), getContext().getTruffleTypes().getUnexpectedValueException());
-
-            CodeTreeBuilder specializeCall = CodeTreeBuilder.createBuilder();
-            specializeCall.startCall("specialize");
-            specializeCall.string(nodeClassName(nextSpecialization) + ".class");
-            addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true);
+        private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) {
+            CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
+            specializeCall.startCall("specializeAndExecute");
+            specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class");
+            addInternalValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true);
             specializeCall.end().end();
 
-            TypeData expectedType = currentSpecialization.getReturnType().getActualTypeData(currentSpecialization.getNode().getTypeSystem());
-            if (canThrowUnexpected) {
-                builder.startReturn();
-                startCallTypeSystemMethod(context, builder, currentSpecialization.getNode(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType));
-                builder.tree(specializeCall.getRoot());
-                builder.end().end();
-                builder.end(); // return
-            } else {
-                builder.startReturn();
-                if (!expectedType.isVoid() && !expectedType.isGeneric()) {
-                    startCallTypeSystemMethod(context, builder, currentSpecialization.getNode(), TypeSystemCodeGenerator.asTypeMethodName(expectedType));
-                    builder.tree(specializeCall.getRoot());
-                    builder.end().end();
-                } else {
-                    builder.tree(specializeCall.getRoot());
-                }
-                builder.end();
-            }
-
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            builder.startReturn();
+            builder.tree(specializeCall.getRoot());
+            builder.end();
+            return builder.getRoot();
         }
 
-        private void buildSpecializeStateMethod(CodeTypeElement clazz, SpecializationData specialization) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), specialization.getNode().getTypeSystem().getGenericType(), "specialize");
+        private void buildSpecializeAndExecute(CodeTypeElement clazz, SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem());
+            ExecutableTypeData returnExecutableType = node.findExecutableType(returnType);
+            boolean canThrowUnexpected = returnExecutableType == null ? true : returnExecutableType.hasUnexpectedValue(getContext());
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute");
             method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
-            addValueParameters(method, specialization.getNode().getGenericSpecialization(), true);
+            if (canThrowUnexpected) {
+                method.addThrownType(getUnexpectedValueException());
+            }
+            addInternalValueParameters(method, specialization.getNode().getGenericSpecialization(), true);
             clazz.add(method);
 
             CodeTreeBuilder builder = method.createBuilder();
-            for (TemplateMethod listener : specialization.getNode().getSpecializationListeners()) {
-                builder.startStatement();
-                startCallOperationMethod(builder, listener);
-                addValueParameterNames(builder, listener, null, false);
-                builder.end().end(); // call operation
-                builder.end(); // statement
-            }
+
+            builder.tree(createDeoptimize(builder));
+            emitSpecializationListeners(builder, specialization.getNode());
 
             builder.startStatement();
             builder.startCall("replace");
             builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState");
-            addValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false);
+            addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false, true);
             builder.end();
             builder.end(); // call replace
             builder.end(); // statement
 
             String generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization());
-
             ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod(generatedMethodName);
 
-            CodeTreeBuilder genericBuilder = CodeTreeBuilder.createBuilder();
-            genericBuilder.startCall(factoryClassName(specialization.getNode()), generatedMethodName);
-            genericBuilder.string("this");
-            addValueParameterNames(genericBuilder, specialization.getNode().getGenericSpecialization(), null, true);
-            genericBuilder.end(); // call generated generic
+            CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder();
+            genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName);
+            genericExecute.string("this");
+            addInternalValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true, true);
+            genericExecute.end(); // call generated generic
+
+            CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot());
 
             if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) {
-                builder.declaration(generatedGeneric.getReturnType(), "genericResult", genericBuilder.getRoot());
-                builder.startReturn().string("null").end();
+                builder.statement(genericInvocation);
+
+                if (!Utils.isVoid(builder.findMethod().asType())) {
+                    builder.startReturn().defaultValue(returnType.getPrimitiveType()).end();
+                }
             } else {
-                builder.startReturn().tree(genericBuilder.getRoot()).end();
+                builder.startReturn().tree(genericInvocation).end();
             }
         }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -35,22 +35,89 @@
 
 public class NodeData extends Template {
 
-    private NodeData parent;
-    private List<NodeData> declaredChildren;
+    private final String nodeId;
+    private NodeData declaringNode;
+    private List<NodeData> declaredChildren = new ArrayList<>();
+
+    private TypeSystemData typeSystem;
+    private List<NodeFieldData> fields;
+    private TypeMirror nodeType;
+    private ParameterSpec instanceParameterSpec;
+
+    private List<SpecializationData> specializations;
+    private List<SpecializationListenerData> specializationListeners;
+    private List<GuardData> guards;
+    private List<ExecutableTypeData> executableTypes;
+    private List<ShortCircuitData> shortCircuits;
 
-    private final TypeSystemData typeSystem;
+    public NodeData(TypeElement type, String id) {
+        super(type, null, null);
+        this.nodeId = id;
+    }
+
+    public NodeData(NodeData splitSource, String templateMethodName, String nodeId) {
+        super(splitSource.getTemplateType(), templateMethodName, null);
+        this.nodeId = nodeId;
+        this.declaringNode = splitSource.declaringNode;
+        this.declaredChildren = splitSource.declaredChildren;
+        this.typeSystem = splitSource.typeSystem;
+        this.nodeType = splitSource.nodeType;
+        this.specializations = splitSource.specializations;
+        this.specializationListeners = splitSource.specializationListeners;
+        this.guards = splitSource.guards;
+        this.executableTypes = splitSource.executableTypes;
+        this.shortCircuits = splitSource.shortCircuits;
+        this.fields = splitSource.fields;
+    }
+
+    void setTypeSystem(TypeSystemData typeSystem) {
+        this.typeSystem = typeSystem;
+    }
 
-    private NodeFieldData[] fields;
-    private SpecializationData[] specializations;
-    private TemplateMethod[] specializationListeners;
-    private GuardData[] guards;
-    private ExecutableTypeData[] executableTypes;
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> children = new ArrayList<>();
+        if (declaredChildren != null) {
+            children.addAll(declaredChildren);
+        }
+        if (typeSystem != null) {
+            children.add(typeSystem);
+        }
+        if (specializations != null) {
+            for (MessageContainer specialization : specializations) {
+                if (specialization.getMessageElement() != null) {
+                    children.add(specialization);
+                }
+            }
+        }
+        if (specializationListeners != null) {
+            children.addAll(specializationListeners);
+        }
+        if (guards != null) {
+            children.addAll(guards);
+        }
+        if (executableTypes != null) {
+            children.addAll(executableTypes);
+        }
+        if (shortCircuits != null) {
+            children.addAll(shortCircuits);
+        }
+        if (fields != null) {
+            children.addAll(fields);
+        }
+        return children;
+    }
 
-    private TypeMirror nodeType;
+    public ParameterSpec getInstanceParameterSpec() {
+        return instanceParameterSpec;
+    }
 
-    public NodeData(TypeElement type, TypeSystemData typeSystem) {
-        super(type, null);
-        this.typeSystem = typeSystem;
+    public void setInstanceParameterSpec(ParameterSpec instanceParameter) {
+        this.instanceParameterSpec = instanceParameter;
+    }
+
+    public String getNodeId() {
+        return nodeId;
     }
 
     public TypeMirror getNodeType() {
@@ -71,16 +138,36 @@
         return !noSpecialization;
     }
 
+    public boolean supportsFrame() {
+        for (ExecutableTypeData execType : executableTypes) {
+            if (execType.findParameter("frameValue") == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public List<NodeData> getNodeChildren() {
+        List<NodeData> children = new ArrayList<>();
+        for (NodeData child : getDeclaredChildren()) {
+            if (child.needsFactory()) {
+                children.add(child);
+            }
+            children.addAll(child.getNodeChildren());
+        }
+        return children;
+    }
+
     void setDeclaredChildren(List<NodeData> declaredChildren) {
         this.declaredChildren = declaredChildren;
 
         for (NodeData child : declaredChildren) {
-            child.parent = this;
+            child.declaringNode = this;
         }
     }
 
     public NodeData getParent() {
-        return parent;
+        return declaringNode;
     }
 
     public List<NodeData> getDeclaredChildren() {
@@ -96,22 +183,16 @@
 
         for (SpecializationData specialization : getSpecializations()) {
             methods.add(specialization);
-            if (specialization.getShortCircuits() != null) {
-                methods.addAll(Arrays.asList(specialization.getShortCircuits()));
-            }
         }
 
-        methods.addAll(Arrays.asList(getSpecializationListeners()));
-        methods.addAll(Arrays.asList(getExecutableTypes()));
-        methods.addAll(Arrays.asList(getGuards()));
+        methods.addAll(getSpecializationListeners());
+        methods.addAll(getExecutableTypes());
+        methods.addAll(getGuards());
+        methods.addAll(getShortCircuits());
 
         return methods;
     }
 
-    public TemplateMethod[] getSpecializationListeners() {
-        return specializationListeners;
-    }
-
     public List<GuardData> findGuards(String name) {
         List<GuardData> foundGuards = new ArrayList<>();
         for (GuardData guardData : getGuards()) {
@@ -122,38 +203,33 @@
         return foundGuards;
     }
 
-    public ExecutableTypeData[] getExecutableTypes() {
-        return executableTypes;
+    public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type) {
+        List<ExecutableTypeData> types = findGenericExecutableTypes(context);
+        for (ExecutableTypeData availableType : types) {
+            if (Utils.typeEquals(availableType.getType().getBoxedType(), type.getBoxedType())) {
+                return availableType;
+            }
+        }
+        return null;
     }
 
-    public ExecutableTypeData findGenericExecutableType(ProcessorContext context) {
+    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) {
         List<ExecutableTypeData> types = findGenericExecutableTypes(context);
-        if (types.isEmpty()) {
-            return null;
-        } else if (types.size() == 1) {
-            return types.get(0);
-        } else if (types.size() == 2) {
-            if (types.get(0).getType().isVoid()) {
-                return types.get(1);
-            } else if (types.get(1).getType().isVoid()) {
-                return types.get(0);
+        for (ExecutableTypeData type : types) {
+            if (type.getType().isGeneric()) {
+                return type;
             }
         }
 
-        ExecutableTypeData execType = null;
         for (ExecutableTypeData type : types) {
-            TypeData returnType = type.getReturnType().getActualTypeData(getTypeSystem());
-            if (returnType.isGeneric()) {
-                if (execType != null) {
-                    return null;
-                }
-                execType = type;
+            if (!type.getType().isVoid()) {
+                return type;
             }
         }
-        return execType;
+        return null;
     }
 
-    private List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
+    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
         List<ExecutableTypeData> types = new ArrayList<>();
         for (ExecutableTypeData type : executableTypes) {
             if (!type.hasUnexpectedValue(context)) {
@@ -186,47 +262,20 @@
         return result;
     }
 
-    public TypeMirror[] getExecutablePrimitiveTypeMirrors() {
-        TypeMirror[] typeMirrors = new TypeMirror[executableTypes.length];
-        for (int i = 0; i < executableTypes.length; i++) {
-            typeMirrors[i] = executableTypes[i].getType().getPrimitiveType();
+    public List<TypeMirror> getExecutablePrimitiveTypeMirrors() {
+        List<TypeMirror> typeMirrors = new ArrayList<>();
+        for (ExecutableTypeData executableType : executableTypes) {
+            typeMirrors.add(executableType.getType().getPrimitiveType());
         }
         return typeMirrors;
     }
 
-    void setExecutableTypes(ExecutableTypeData[] declaredExecuableTypes) {
-        this.executableTypes = declaredExecuableTypes;
-    }
-
-    void setFields(NodeFieldData[] fields) {
-        this.fields = fields;
-    }
-
-    void setSpecializations(SpecializationData[] specializations) {
-        this.specializations = specializations;
-    }
-
-    void setSpecializationListeners(TemplateMethod[] specializationListeners) {
-        this.specializationListeners = specializationListeners;
-    }
-
-    void setGuards(GuardData[] guards) {
-        this.guards = guards;
-    }
-
-    public GuardData[] getGuards() {
-        return guards;
-    }
-
     public NodeFieldData[] filterFields(FieldKind fieldKind, ExecutionKind usage) {
         List<NodeFieldData> filteredFields = new ArrayList<>();
-        NodeFieldData[] resolvedFields = getFields();
-        if (fields != null) {
-            for (NodeFieldData field : resolvedFields) {
-                if (usage == null || field.getExecutionKind() == usage) {
-                    if (fieldKind == null || field.getKind() == fieldKind) {
-                        filteredFields.add(field);
-                    }
+        for (NodeFieldData field : getFields()) {
+            if (usage == null || field.getExecutionKind() == usage) {
+                if (fieldKind == null || field.getKind() == fieldKind) {
+                    filteredFields.add(field);
                 }
             }
         }
@@ -244,18 +293,13 @@
 
     public boolean needsRewrites(ProcessorContext context) {
         boolean needsRewrites = false;
-        for (NodeFieldData field : getFields()) {
-            if (field.getExecutionKind() == ExecutionKind.DEFAULT || field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
-                if (!field.getNodeData().hasUnexpectedExecutableTypes(context)) {
-                    continue;
-                }
 
+        for (SpecializationData specialization : getSpecializations()) {
+            if (specialization.hasRewrite(context)) {
                 needsRewrites = true;
                 break;
             }
         }
-
-        needsRewrites &= specializations.length >= 2;
         return needsRewrites;
     }
 
@@ -269,37 +313,65 @@
     }
 
     public TypeSystemData getTypeSystem() {
-        if (typeSystem != null) {
-            return typeSystem;
+        return typeSystem;
+    }
+
+    public String dump() {
+        return dump(0);
+    }
+
+    private String dump(int level) {
+        String indent = "";
+        for (int i = 0; i < level; i++) {
+            indent += "  ";
+        }
+        StringBuilder builder = new StringBuilder();
+
+        builder.append(String.format("%s%s {", indent, toString()));
+
+        dumpProperty(builder, indent, "templateClass", Utils.getQualifiedName(getTemplateType()));
+        dumpProperty(builder, indent, "typeSystem", getTypeSystem());
+        dumpProperty(builder, indent, "fields", getFields());
+        dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
+        dumpProperty(builder, indent, "specializations", getSpecializations());
+        dumpProperty(builder, indent, "guards", getGuards());
+        dumpProperty(builder, indent, "messages", collectMessages());
+        if (getDeclaredChildren().size() > 0) {
+            builder.append(String.format("\n%s  children = [", indent));
+            for (NodeData node : getDeclaredChildren()) {
+                builder.append("\n");
+                builder.append(node.dump(level + 1));
+            }
+            builder.append(String.format("\n%s  ]", indent));
+        }
+        builder.append(String.format("%s}", indent));
+        return builder.toString();
+    }
+
+    private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) {
+        if (value instanceof List) {
+            List<?> list = (List<?>) value;
+            if (!list.isEmpty()) {
+                b.append(String.format("\n%s  %s = %s", indent, propertyName, dumpList((List<?>) value)));
+            }
         } else {
-            return null;
+            if (value != null) {
+                b.append(String.format("\n%s  %s = %s", indent, propertyName, value));
+            }
         }
     }
 
-    public NodeFieldData[] getFields() {
-        return fields;
-    }
-
-    public NodeFieldData[] getDeclaredFields() {
-        return fields;
-    }
-
-    public SpecializationData[] getSpecializations() {
-        return specializations;
-    }
-
-    public String dump() {
-        StringBuilder b = new StringBuilder();
-        b.append(String.format("[name = %s\n" + "  typeSystem = %s\n" + "  fields = %s\n" + "  types = %s\n" + "  specializations = %s\n" + "  guards = %s\n" + "]",
-                        Utils.getQualifiedName(getTemplateType()), getTypeSystem(), dumpList(fields), dumpList(getExecutableTypes()), dumpList(getSpecializations()), dumpList(guards)));
-        return b.toString();
-    }
-
-    private static String dumpList(Object[] array) {
+    private static String dumpList(List<?> array) {
         if (array == null) {
             return "null";
         }
 
+        if (array.isEmpty()) {
+            return "[]";
+        } else if (array.size() == 1) {
+            return "[" + array.get(0).toString() + "]";
+        }
+
         StringBuilder b = new StringBuilder();
         b.append("[");
         for (Object object : array) {
@@ -321,4 +393,76 @@
         return null;
     }
 
+    public List<NodeFieldData> getFields() {
+        return fields;
+    }
+
+    void setFields(List<NodeFieldData> fields) {
+        this.fields = fields;
+    }
+
+    public List<SpecializationData> getSpecializations() {
+        return getSpecializations(false);
+    }
+
+    public List<SpecializationData> getSpecializations(boolean userDefinedOnly) {
+        if (userDefinedOnly) {
+            List<SpecializationData> specs = new ArrayList<>();
+            for (SpecializationData spec : specializations) {
+                if (spec.getMethod() != null) {
+                    specs.add(spec);
+                }
+            }
+            return specs;
+        } else {
+            return specializations;
+        }
+    }
+
+    public List<SpecializationListenerData> getSpecializationListeners() {
+        return specializationListeners;
+    }
+
+    public List<GuardData> getGuards() {
+        return guards;
+    }
+
+    public List<ExecutableTypeData> getExecutableTypes() {
+        return executableTypes;
+    }
+
+    public List<ShortCircuitData> getShortCircuits() {
+        return shortCircuits;
+    }
+
+    void setSpecializations(List<SpecializationData> specializations) {
+        this.specializations = specializations;
+        if (this.specializations != null) {
+            for (SpecializationData specialization : specializations) {
+                specialization.setNode(this);
+            }
+        }
+    }
+
+    void setSpecializationListeners(List<SpecializationListenerData> specializationListeners) {
+        this.specializationListeners = specializationListeners;
+    }
+
+    void setGuards(List<GuardData> guards) {
+        this.guards = guards;
+    }
+
+    void setExecutableTypes(List<ExecutableTypeData> executableTypes) {
+        this.executableTypes = executableTypes;
+    }
+
+    void setShortCircuits(List<ShortCircuitData> shortCircuits) {
+        this.shortCircuits = shortCircuits;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + getNodeId() + "]";
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,10 +25,12 @@
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
 
-public class NodeFieldData {
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class NodeFieldData extends MessageContainer {
 
     public enum FieldKind {
-        FIELD, CHILD, CHILDREN
+        CHILD, CHILDREN, FIELD
     }
 
     public enum ExecutionKind {
@@ -41,17 +43,39 @@
 
     private final FieldKind fieldKind;
     private final ExecutionKind executionKind;
-    private final NodeData nodeData;
+    private NodeData nodeData;
 
-    public NodeFieldData(NodeData typeNodeData, VariableElement fieldElement, Element accessElement, AnnotationMirror childAnnotationMirror, FieldKind fieldKind, ExecutionKind executionKind) {
+    public NodeFieldData(VariableElement fieldElement, Element accessElement, AnnotationMirror childAnnotationMirror, FieldKind fieldKind, ExecutionKind executionKind) {
         this.fieldElement = fieldElement;
         this.accessElement = accessElement;
         this.childAnnotationMirror = childAnnotationMirror;
-        this.nodeData = typeNodeData;
         this.fieldKind = fieldKind;
         this.executionKind = executionKind;
     }
 
+    NodeFieldData(NodeFieldData field) {
+        this.fieldElement = field.fieldElement;
+        this.accessElement = field.accessElement;
+        this.childAnnotationMirror = field.childAnnotationMirror;
+        this.fieldKind = field.fieldKind;
+        this.executionKind = field.executionKind;
+        this.nodeData = field.nodeData;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return fieldElement;
+    }
+
+    public boolean isShortCircuit() {
+        return executionKind == ExecutionKind.SHORT_CIRCUIT;
+    }
+
+    void setNode(NodeData nodeData) {
+        this.nodeData = nodeData;
+        getMessages().addAll(nodeData.collectMessages());
+    }
+
     public VariableElement getFieldElement() {
         return fieldElement;
     }
@@ -86,7 +110,7 @@
 
     @Override
     public String toString() {
-        return "NodeFieldData[name=" + getName() + ", kind=" + fieldKind + ", execution=" + executionKind + "]";
+        return "NodeFieldData[name=" + getName() + ", kind=" + fieldKind + ", execution=" + executionKind + ", node=" + getNodeData() + "]";
     }
 
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -28,12 +28,12 @@
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
 import javax.lang.model.util.*;
+import javax.tools.Diagnostic.Kind;
 
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.api.nodes.Node.Child;
 import com.oracle.truffle.api.nodes.Node.Children;
 import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.ast.*;
 import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
 import com.oracle.truffle.codegen.processor.node.NodeFieldData.FieldKind;
 import com.oracle.truffle.codegen.processor.template.*;
@@ -41,11 +41,10 @@
 
 public class NodeParser extends TemplateParser<NodeData> {
 
-    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, GuardCheck.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class,
-                    SpecializationGuard.class, SpecializationListener.class, SpecializationThrows.class);
+    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class,
+                    ExecuteChildren.class, NodeClass.class, NodeId.class);
 
     private Map<String, NodeData> parsedNodes;
-    private TypeElement originalType;
 
     public NodeParser(ProcessorContext c) {
         super(c);
@@ -54,23 +53,37 @@
     @Override
     protected NodeData parse(Element element, AnnotationMirror mirror) {
         assert element instanceof TypeElement;
+        NodeData node = null;
         try {
             parsedNodes = new HashMap<>();
-            originalType = (TypeElement) element;
-
-            return parseInnerClassHierarchy((TypeElement) element);
-        } finally {
+            node = resolveNode((TypeElement) element);
             if (Log.DEBUG) {
-                NodeData parsed = parsedNodes.get(Utils.getQualifiedName(originalType));
-                if (parsed != null) {
+                NodeData parsed = parsedNodes.get(Utils.getQualifiedName((TypeElement) element));
+                if (node != null) {
                     String dump = parsed.dump();
-                    log.error("Node parsed: %s", dump);
-                    System.out.println("Parsed: " + dump);
+                    log.message(Kind.ERROR, null, null, null, dump);
+                    System.out.println(dump);
                 }
             }
+        } finally {
             parsedNodes = null;
-            originalType = null;
         }
+
+        return node;
+    }
+
+    @Override
+    protected NodeData filterErrorElements(NodeData model) {
+        for (Iterator<NodeData> iterator = model.getDeclaredChildren().iterator(); iterator.hasNext();) {
+            NodeData node = filterErrorElements(iterator.next());
+            if (node == null) {
+                iterator.remove();
+            }
+        }
+        if (model.hasErrors()) {
+            return null;
+        }
+        return model;
     }
 
     @Override
@@ -78,178 +91,474 @@
         return true;
     }
 
-    private NodeData parseInnerClassHierarchy(TypeElement rootType) {
+    private NodeData resolveNode(TypeElement rootType) {
+        String typeName = Utils.getQualifiedName(rootType);
+        if (parsedNodes.containsKey(typeName)) {
+            return parsedNodes.get(typeName);
+        }
+
         List<? extends TypeElement> types = ElementFilter.typesIn(rootType.getEnclosedElements());
+
         List<NodeData> children = new ArrayList<>();
         for (TypeElement childElement : types) {
-            NodeData childNode = parseInnerClassHierarchy(childElement);
+            NodeData childNode = resolveNode(childElement);
             if (childNode != null) {
                 children.add(childNode);
             }
         }
-        NodeData rootNode = resolveNode(rootType);
-        if (rootNode == null && children.size() > 0) {
-            rootNode = new NodeData(rootType, null);
+
+        NodeData rootNode = parseNode(rootType);
+        boolean hasErrors = rootNode != null ? rootNode.hasErrors() : false;
+        if ((rootNode == null || hasErrors) && children.size() > 0) {
+            rootNode = new NodeData(rootType, rootType.getSimpleName().toString());
         }
+
+        parsedNodes.put(typeName, rootNode);
+
         if (rootNode != null) {
+            children.addAll(rootNode.getDeclaredChildren());
             rootNode.setDeclaredChildren(children);
         }
+
         return rootNode;
     }
 
-    private NodeData resolveNode(TypeElement currentType) {
-        String typeName = Utils.getQualifiedName(currentType);
-        if (!parsedNodes.containsKey(typeName)) {
-            NodeData node = parseNode(currentType);
-            if (node != null) {
-                parsedNodes.put(typeName, node);
-            }
-            return node;
-        }
-        return parsedNodes.get(typeName);
-    }
-
     private NodeData parseNode(TypeElement type) {
         if (Utils.findAnnotationMirror(processingEnv, type, GeneratedBy.class) != null) {
-            // generated nodes get called again.
+            // generated nodes should not get called again.
             return null;
         }
-        if (!Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) {
+
+        AnnotationMirror methodNodes = Utils.findAnnotationMirror(processingEnv, type, NodeClass.class);
+
+        if (methodNodes == null && !Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) {
             return null; // not a node
         }
 
+        if (type.getModifiers().contains(Modifier.PRIVATE)) {
+            // TODO error message here!?
+            return null; // not visible, not a node
+        }
+
+        TypeElement nodeType;
+        boolean needsSplit;
+        if (methodNodes != null) {
+            needsSplit = methodNodes != null;
+            nodeType = Utils.fromTypeMirror(Utils.getAnnotationValue(TypeMirror.class, methodNodes, "value"));
+        } else {
+            needsSplit = false;
+            nodeType = type;
+        }
+
+        NodeData nodeData = parseNodeData(type, nodeType);
+
+        if (Utils.typeEquals(nodeType.asType(), type.asType())) {
+            // filter fields if they were not split. (field are accessible anyway)
+            for (ListIterator<NodeFieldData> iterator = nodeData.getFields().listIterator(); iterator.hasNext();) {
+                NodeFieldData field = iterator.next();
+                if (field.getKind() == FieldKind.FIELD) {
+                    iterator.remove();
+                }
+            }
+        }
+
+        if (nodeData.hasErrors()) {
+            return nodeData; // error sync point
+        }
+
         List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type));
-        List<TypeElement> typeHierarchy = findSuperClasses(new ArrayList<TypeElement>(), type);
-        Collections.reverse(typeHierarchy);
-
-        AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
-        if (typeSystemMirror == null) {
-            log.error(originalType, "No @%s annotation found in type hierarchy.", TypeSystemReference.class.getSimpleName());
-            return null;
-        }
-
-        TypeMirror typeSytemType = Utils.getAnnotationValueType(typeSystemMirror, "value");
-        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true);
-        if (typeSystem == null) {
-            log.error(originalType, "The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType));
-            return null;
-        }
-
-        NodeData nodeData = new NodeData(type, typeSystem);
-
-        nodeData.setExtensionElements(getExtensionParser().parseAll(type, elements));
+        nodeData.setExtensionElements(getExtensionParser().parseAll(nodeData, elements));
         if (nodeData.getExtensionElements() != null) {
             elements.addAll(nodeData.getExtensionElements());
         }
+        parseMethods(nodeData, elements);
 
-        List<ExecutableTypeData> executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements));
-
-        nodeData.setExecutableTypes(executableTypes.toArray(new ExecutableTypeData[executableTypes.size()]));
+        if (nodeData.hasErrors()) {
+            return nodeData;
+        }
 
-        parsedNodes.put(Utils.getQualifiedName(type), nodeData); // node fields will resolve node
-// types, to avoid endless loops
+        List<NodeData> nodes;
+        if (needsSplit) {
+            nodes = splitNodeData(nodeData);
+        } else {
+            nodes = new ArrayList<>();
+            nodes.add(nodeData);
+        }
 
-        NodeFieldData[] fields = parseFields(nodeData, elements, typeHierarchy);
-        if (fields == null) {
-            return null;
+        for (NodeData splittedNode : nodes) {
+            finalizeSpecializations(splittedNode);
+            verifyNode(splittedNode);
+        }
+
+        if (needsSplit) {
+            nodeData.setDeclaredChildren(nodes);
+            nodeData.setSpecializationListeners(new ArrayList<SpecializationListenerData>());
+            nodeData.setSpecializations(new ArrayList<SpecializationData>());
+            return nodeData;
+        } else {
+            return nodeData;
         }
-        nodeData.setFields(fields);
+    }
+
+    private static List<NodeData> splitNodeData(NodeData node) {
+        SortedMap<String, List<SpecializationData>> groupedSpecializations = groupByNodeId(node.getSpecializations());
+        SortedMap<String, List<SpecializationListenerData>> groupedListeners = groupByNodeId(node.getSpecializationListeners());
+
+        Set<String> ids = new TreeSet<>();
+        ids.addAll(groupedSpecializations.keySet());
+        ids.addAll(groupedListeners.keySet());
+
+        List<NodeData> splitted = new ArrayList<>();
+        for (String id : ids) {
+            List<SpecializationData> specializations = groupedSpecializations.get(id);
+            List<SpecializationListenerData> listeners = groupedListeners.get(id);
+
+            if (specializations == null) {
+                specializations = new ArrayList<>();
+            }
 
-        List<SpecializationData> genericSpecializations = new GenericParser(context, nodeData).parse(elements);
-        List<GuardData> guards = new GuardParser(context, nodeData, nodeData.getTypeSystem()).parse(elements);
-        nodeData.setGuards(guards.toArray(new GuardData[guards.size()]));
+            if (listeners == null) {
+                listeners = new ArrayList<>();
+            }
+
+            String nodeId = node.getNodeId();
+            if (nodeId.endsWith("Node") && !nodeId.equals("Node")) {
+                nodeId = nodeId.substring(0, nodeId.length() - 4);
+            }
+            String newNodeId = nodeId + Utils.firstLetterUpperCase(id);
+            NodeData copy = new NodeData(node, id, newNodeId);
+
+            copy.setSpecializations(specializations);
+            copy.setSpecializationListeners(listeners);
+
+            splitted.add(copy);
+        }
+
+        node.setSpecializations(new ArrayList<SpecializationData>());
+        node.setSpecializationListeners(new ArrayList<SpecializationListenerData>());
+
+        return splitted;
+    }
 
-        SpecializationMethodParser specializationParser = new SpecializationMethodParser(context, nodeData);
-        List<SpecializationData> specializations = specializationParser.parse(elements);
-        List<ShortCircuitData> shortCircuits = new ShortCircuitParser(context, nodeData).parse(elements);
-        List<TemplateMethod> listeners = new SpecializationListenerParser(context, nodeData).parse(elements);
+    private static <M extends TemplateMethod> SortedMap<String, List<M>> groupByNodeId(List<M> methods) {
+        SortedMap<String, List<M>> grouped = new TreeMap<>();
+        for (M m : methods) {
+            List<M> list = grouped.get(m.getId());
+            if (list == null) {
+                list = new ArrayList<>();
+                grouped.put(m.getId(), list);
+            }
+            list.add(m);
+        }
+        return grouped;
+    }
+
+    private void parseMethods(final NodeData node, List<Element> elements) {
+        node.setGuards(new GuardParser(context, node, node.getTypeSystem()).parse(elements));
+        node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements));
+        node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements));
+        List<SpecializationData> generics = new GenericParser(context, node).parse(elements);
+        List<SpecializationData> specializations = new SpecializationMethodParser(context, node).parse(elements);
 
-        if (specializations == null || genericSpecializations == null || shortCircuits == null || listeners == null || guards == null) {
-            return null;
+        List<SpecializationData> allSpecializations = new ArrayList<>();
+        allSpecializations.addAll(generics);
+        allSpecializations.addAll(specializations);
+
+        node.setSpecializations(allSpecializations);
+    }
+
+    private void finalizeSpecializations(final NodeData node) {
+        List<SpecializationData> specializations = new ArrayList<>(node.getSpecializations());
+
+        if (specializations.isEmpty()) {
+            return;
+        }
+
+        List<SpecializationData> generics = new ArrayList<>();
+        for (SpecializationData spec : specializations) {
+            if (spec.isGeneric()) {
+                generics.add(spec);
+            }
+        }
+
+        if (generics.size() == 1 && specializations.size() == 1) {
+            for (SpecializationData generic : generics) {
+                generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName());
+            }
         }
 
         SpecializationData genericSpecialization = null;
-        if (genericSpecializations.size() > 1) {
-            for (SpecializationData generic : genericSpecializations) {
-                log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName());
+        if (generics.size() > 1) {
+            for (SpecializationData generic : generics) {
+                generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName());
             }
-            return null;
-        } else if (genericSpecializations.size() == 1) {
-            genericSpecialization = genericSpecializations.get(0);
+            return;
+        } else if (generics.size() == 1) {
+            genericSpecialization = generics.get(0);
+        } else if (node.needsRewrites(context)) {
+            SpecializationData specialization = specializations.get(0);
+            GenericParser parser = new GenericParser(context, node);
+            MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, null);
+
+            ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context);
+            assert anyGenericReturnType != null;
+
+            ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType().getPrimitiveType(), 0, false);
+            List<ActualParameter> parameters = new ArrayList<>();
+            for (ActualParameter specializationParameter : specialization.getParameters()) {
+                ParameterSpec parameterSpec = specification.findParameterSpec(specializationParameter.getSpecification().getName());
+                NodeFieldData field = node.findField(parameterSpec.getName());
+                TypeMirror actualType;
+                if (field == null || field.getKind() == FieldKind.FIELD) {
+                    actualType = specializationParameter.getActualType();
+                } else {
+                    ExecutableTypeData paramType = field.getNodeData().findAnyGenericExecutableType(context);
+                    assert paramType != null;
+                    actualType = paramType.getType().getPrimitiveType();
+                }
+                parameters.add(new ActualParameter(parameterSpec, actualType, specializationParameter.getIndex(), specializationParameter.isImplicit()));
+            }
+            TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters);
+            genericSpecialization = new SpecializationData(genericMethod, true, false);
+
+            specializations.add(genericSpecialization);
         }
 
-        if (specializations.size() > 1 && genericSpecialization == null) {
-            log.error(originalType, "Need a @%s method.", Generic.class.getSimpleName());
-            return null;
+        if (genericSpecialization != null) {
+            TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, genericSpecialization.getSpecification(), null, null, genericSpecialization.getReturnType(),
+                            genericSpecialization.getParameters());
+            // should not use messages from generic specialization
+            uninializedMethod.getMessages().clear();
+            specializations.add(new SpecializationData(uninializedMethod, false, true));
         }
 
         Collections.sort(specializations, new Comparator<SpecializationData>() {
 
             @Override
             public int compare(SpecializationData o1, SpecializationData o2) {
-                return compareSpecialization(typeSystem, o1, o2);
+                return compareSpecialization(node.getTypeSystem(), o1, o2);
             }
         });
 
-        List<SpecializationData> allSpecializations = new ArrayList<>(specializations);
-        if (genericSpecialization != null) {
-            allSpecializations.add(genericSpecialization);
-            CodeExecutableElement uninitializedMethod = new CodeExecutableElement(Utils.modifiers(Modifier.PUBLIC), context.getType(void.class), "doUninitialized");
-            TemplateMethod uninializedMethod = new TemplateMethod(nodeData, genericSpecialization.getSpecification(), uninitializedMethod, genericSpecialization.getMarkerAnnotation(),
-                            genericSpecialization.getReturnType(), genericSpecialization.getParameters());
-            allSpecializations.add(0, new SpecializationData(uninializedMethod, false, true));
+        node.setSpecializations(specializations);
+
+        List<SpecializationData> needsId = new ArrayList<>();
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isGeneric()) {
+                specialization.setId("Generic");
+            } else if (specialization.isUninitialized()) {
+                specialization.setId("Uninitialized");
+            } else {
+                needsId.add(specialization);
+            }
+        }
+        List<String> ids = calculateSpecializationIds(needsId);
+        for (int i = 0; i < ids.size(); i++) {
+            needsId.get(i).setId(ids.get(i));
+        }
+    }
+
+    private static List<String> calculateSpecializationIds(List<SpecializationData> specializations) {
+        int lastSize = -1;
+        List<List<String>> signatureChunks = new ArrayList<>();
+        for (SpecializationData other : specializations) {
+            if (other.isUninitialized() || other.isGeneric()) {
+                continue;
+            }
+            List<String> paramIds = new LinkedList<>();
+            paramIds.add(Utils.getTypeId(other.getReturnType().getActualType()));
+            for (ActualParameter param : other.getParameters()) {
+                if (other.getNode().findField(param.getSpecification().getName()) == null) {
+                    continue;
+                }
+                paramIds.add(Utils.getTypeId(param.getActualType()));
+            }
+            assert lastSize == -1 || lastSize == paramIds.size();
+            if (lastSize != -1 && lastSize != paramIds.size()) {
+                throw new AssertionError();
+            }
+            signatureChunks.add(paramIds);
+            lastSize = paramIds.size();
         }
 
-        for (SpecializationData specialization : allSpecializations) {
-            specialization.setNode(nodeData);
+        // reduce id vertically
+        for (int i = 0; i < lastSize; i++) {
+            String prev = null;
+            boolean allSame = true;
+            for (List<String> signature : signatureChunks) {
+                String arg = signature.get(i);
+                if (prev == null) {
+                    prev = arg;
+                    continue;
+                } else if (!prev.equals(arg)) {
+                    allSame = false;
+                    break;
+                }
+                prev = arg;
+            }
+
+            if (allSame) {
+                for (List<String> signature : signatureChunks) {
+                    signature.remove(i);
+                }
+                lastSize--;
+            }
         }
 
-        // verify order is not ambiguous
-        if (!verifySpecializationOrder(typeSystem, specializations)) {
-            return null;
+        // reduce id horizontally
+        for (List<String> signature : signatureChunks) {
+            if (signature.isEmpty()) {
+                continue;
+            }
+            String prev = null;
+            boolean allSame = true;
+            for (String arg : signature) {
+                if (prev == null) {
+                    prev = arg;
+                    continue;
+                } else if (!prev.equals(arg)) {
+                    allSame = false;
+                    break;
+                }
+                prev = arg;
+            }
+
+            if (allSame) {
+                signature.clear();
+                signature.add(prev);
+            }
         }
 
-        nodeData.setSpecializations(allSpecializations.toArray(new SpecializationData[allSpecializations.size()]));
-        nodeData.setSpecializationListeners(listeners.toArray(new TemplateMethod[listeners.size()]));
-
-        if (!verifyMissingAbstractMethods(nodeData, elements)) {
-            return null;
+        // create signatures
+        List<String> signatures = new ArrayList<>();
+        for (List<String> signatureChunk : signatureChunks) {
+            StringBuilder b = new StringBuilder();
+            if (signatureChunk.isEmpty()) {
+                b.append("Default");
+            } else {
+                for (String s : signatureChunk) {
+                    b.append(s);
+                }
+            }
+            signatures.add(b.toString());
         }
 
-        if (!assignShortCircuitsToSpecializations(nodeData, allSpecializations, shortCircuits)) {
-            return null;
+        Map<String, Integer> counts = new HashMap<>();
+        for (String s1 : signatures) {
+            Integer count = counts.get(s1);
+            if (count == null) {
+                count = 0;
+            }
+            count++;
+            counts.put(s1, count);
         }
 
-        if (!verifyConstructors(nodeData)) {
-            return null;
+        for (String s : counts.keySet()) {
+            int count = counts.get(s);
+            if (count > 1) {
+                int number = 0;
+                for (ListIterator<String> iterator = signatures.listIterator(); iterator.hasNext();) {
+                    String s2 = iterator.next();
+                    if (s.equals(s2)) {
+                        iterator.set(s2 + number);
+                        number++;
+                    }
+                }
+            }
         }
 
-        if (!verifyNamingConvention(specializations, "do")) {
-            return null;
-        }
+        return signatures;
+    }
+
+    private void verifyNode(NodeData nodeData) {
+        // verify specialization parameter length
+        verifySpecializationParameters(nodeData);
+
+        // verify order is not ambiguous
+        verifySpecializationOrder(nodeData);
+
+        verifyMissingAbstractMethods(nodeData);
+
+        assignShortCircuitsToSpecializations(nodeData);
+
+        verifyConstructors(nodeData);
 
-        if (!verifyNamesUnique(specializations)) {
-            return null;
+// if (!verifyNamingConvention(specializations, "do")) {
+// return null;
+// }
+//
+// if (!verifyNamesUnique(specializations)) {
+// return null;
+// }
+
+        verifyNamingConvention(nodeData.getShortCircuits(), "needs");
+
+        verifySpecializationThrows(nodeData);
+    }
+
+    private NodeData parseNodeData(TypeElement templateType, TypeElement nodeType) {
+        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeType));
+        List<TypeElement> typeHierarchy = findSuperClasses(new ArrayList<TypeElement>(), nodeType);
+        Collections.reverse(typeHierarchy);
+        NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString());
+
+        AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
+        if (typeSystemMirror == null) {
+            nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), nodeType.getQualifiedName().toString());
+            return nodeData;
         }
 
-        if (!verifyNamingConvention(shortCircuits, "needs")) {
-            return null;
+        TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
+        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true);
+        if (typeSystem == null) {
+            nodeData.addError("The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType));
+            return nodeData;
         }
 
-        if (!verifySpecializationThrows(typeSystem, specializations)) {
-            return null;
-        }
+        nodeData.setNodeType(nodeType.asType());
+        nodeData.setTypeSystem(typeSystem);
+
+        List<ExecutableTypeData> executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements));
+        nodeData.setExecutableTypes(executableTypes);
+        parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
+
+        nodeData.setFields(parseFields(elements, typeHierarchy));
 
         return nodeData;
     }
 
-    private boolean verifyMissingAbstractMethods(NodeData nodeData, List<Element> elements) {
-        if (nodeData.needsFactory()) {
+    private static void verifySpecializationParameters(NodeData nodeData) {
+        boolean valid = true;
+        int args = -1;
+        for (SpecializationData specializationData : nodeData.getSpecializations()) {
+            int specializationArgs = 0;
+            for (ActualParameter param : specializationData.getParameters()) {
+                if (!param.getSpecification().isOptional()) {
+                    specializationArgs++;
+                }
+            }
+            if (args != -1 && args != specializationArgs) {
+                valid = false;
+                break;
+            }
+            args = specializationArgs;
+        }
+        if (!valid) {
+            for (SpecializationData specialization : nodeData.getSpecializations()) {
+                specialization.addError("All specializations must have the same number of arguments.");
+            }
+        }
+    }
+
+    private void verifyMissingAbstractMethods(NodeData nodeData) {
+        if (!nodeData.needsFactory()) {
             // missing abstract methods only needs to be implemented
             // if we need go generate factory for it.
-            return true;
+            return;
         }
 
+        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeData.getTemplateType()));
+
         Set<Element> unusedElements = new HashSet<>(elements);
         for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
             unusedElements.remove(method.getMethod());
@@ -258,24 +567,20 @@
             unusedElements.removeAll(nodeData.getExtensionElements());
         }
 
-        boolean valid = true;
         for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) {
             if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) {
-                context.getLog().error(nodeData.getTemplateType(), "The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()),
-                                Utils.getReadableSignature(unusedMethod));
-                valid = false;
+                nodeData.addError("The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod));
             }
         }
+    }
+
+    private void verifyConstructors(NodeData nodeData) {
+        if (!nodeData.needsRewrites(context)) {
+            // no specialization constructor is needed if the node never rewrites.
+            return;
+        }
 
-        return valid;
-    }
-
-    private boolean verifyConstructors(NodeData nodeData) {
         TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType());
-        if (!nodeData.needsRewrites(context)) {
-            // no specialization constructor is needed if the node never rewrites.
-            return true;
-        }
 
         List<ExecutableElement> constructors = ElementFilter.constructorsIn(type.getEnclosedElements());
         for (ExecutableElement e : constructors) {
@@ -283,20 +588,17 @@
                 TypeMirror firstArg = e.getParameters().get(0).asType();
                 if (Utils.typeEquals(firstArg, nodeData.getNodeType())) {
                     if (e.getModifiers().contains(Modifier.PRIVATE)) {
-                        context.getLog().error(e, "The specialization constructor must not be private.");
-                        return false;
+                        nodeData.addError("The specialization constructor must not be private.");
                     } else if (constructors.size() <= 1) {
-                        context.getLog().error(e, "The specialization constructor must not be the only constructor. The definition of an alternative constructor is required.");
-                        return false;
+                        nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required.");
                     }
-                    return true;
+                    return;
                 }
             }
         }
 
         // not found
-        context.getLog().error(type, "Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type));
-        return false;
+        nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type));
     }
 
     private static List<ExecutableTypeData> filterExecutableTypes(List<ExecutableTypeData> executableTypes) {
@@ -343,13 +645,13 @@
         return null;
     }
 
-    private NodeFieldData[] parseFields(NodeData nodeData, List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
+    private List<NodeFieldData> parseFields(List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
         AnnotationMirror executionOrderMirror = findFirstAnnotation(typeHierarchy, ExecuteChildren.class);
         List<String> executionDefinition = null;
         if (executionOrderMirror != null) {
             executionDefinition = new ArrayList<>();
-            for (Object object : Utils.getAnnotationValueList(executionOrderMirror, "value")) {
-                executionDefinition.add((String) object);
+            for (String object : Utils.getAnnotationValueList(String.class, executionOrderMirror, "value")) {
+                executionDefinition.add(object);
             }
         }
 
@@ -357,12 +659,10 @@
         for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
             AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
             if (mirror != null) {
-                shortCircuits.add(Utils.getAnnotationValueString(mirror, "value"));
+                shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
             }
         }
 
-        boolean valid = true;
-
         List<NodeFieldData> fields = new ArrayList<>();
         for (VariableElement var : ElementFilter.fieldsIn(elements)) {
             if (var.getModifiers().contains(Modifier.STATIC)) {
@@ -375,27 +675,16 @@
                 }
             }
 
-            NodeFieldData field = parseField(nodeData, var, shortCircuits);
+            NodeFieldData field = parseField(var, shortCircuits);
             if (field != null) {
-                if (field.getExecutionKind() != ExecutionKind.IGNORE) {
-                    fields.add(field);
-                }
-            } else {
-                valid = false;
+                fields.add(field);
             }
         }
-
-        // TODO parse getters
-        if (!valid) {
-            return null;
-        }
-
-        NodeFieldData[] fieldArray = fields.toArray(new NodeFieldData[fields.size()]);
-        sortByExecutionOrder(fieldArray, executionDefinition == null ? Collections.<String> emptyList() : executionDefinition, typeHierarchy);
-        return fieldArray;
+        sortByExecutionOrder(fields, executionDefinition == null ? Collections.<String> emptyList() : executionDefinition, typeHierarchy);
+        return fields;
     }
 
-    private NodeFieldData parseField(NodeData parentNodeData, VariableElement var, Set<String> foundShortCircuits) {
+    private NodeFieldData parseField(VariableElement var, Set<String> foundShortCircuits) {
         AnnotationMirror childMirror = Utils.findAnnotationMirror(processingEnv, var, Child.class);
         AnnotationMirror childrenMirror = Utils.findAnnotationMirror(processingEnv, var, Children.class);
 
@@ -409,45 +698,40 @@
         }
 
         AnnotationMirror mirror;
-        TypeMirror nodeType;
+        TypeMirror type;
 
         if (childMirror != null) {
             mirror = childMirror;
-            nodeType = var.asType();
+            type = var.asType();
             kind = FieldKind.CHILD;
         } else if (childrenMirror != null) {
             mirror = childrenMirror;
-            nodeType = getComponentType(var.asType());
+            type = getComponentType(var.asType());
             kind = FieldKind.CHILDREN;
         } else {
+            execution = ExecutionKind.IGNORE;
+            type = var.asType();
             mirror = null;
-            nodeType = null;
             kind = FieldKind.FIELD;
-            execution = ExecutionKind.IGNORE;
         }
 
-        NodeData fieldNodeData = null;
-        if (nodeType != null) {
-            fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeType));
-            Element errorElement = Utils.typeEquals(parentNodeData.getTemplateType().asType(), var.getEnclosingElement().asType()) ? var : parentNodeData.getTemplateType();
+        NodeFieldData fieldData = new NodeFieldData(var, findAccessElement(var), mirror, kind, execution);
+        if (type != null && mirror != null) {
+            NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(type));
+            fieldData.setNode(fieldNodeData);
 
             if (fieldNodeData == null) {
-                // TODO redirect errors from resolve.
-                context.getLog().error(errorElement, "Node type '%s' is invalid.", Utils.getQualifiedName(nodeType));
-                return null;
-            } else if (fieldNodeData.findGenericExecutableType(context) == null) {
-                // TODO better error handling for (no or multiple?)
-                context.getLog().error(errorElement, "No or multiple executable generic types found for node '%s'.", Utils.getQualifiedName(nodeType));
-                return null;
+                fieldData.addError("Node type '%s' is invalid.", Utils.getQualifiedName(type));
+            } else if (fieldNodeData.findGenericExecutableTypes(context).isEmpty()) {
+                fieldData.addError("No executable generic types found for node '%s'.", Utils.getQualifiedName(type));
             }
         }
 
-        // TODO correct handling of access elements
-        if (var.getModifiers().contains(Modifier.PRIVATE) && Utils.typeEquals(var.getEnclosingElement().asType(), parentNodeData.getTemplateType().asType())) {
-            execution = ExecutionKind.IGNORE;
+        if (fieldData.getAccessElement().getModifiers().contains(Modifier.PRIVATE)) {
+            return null;
         }
 
-        return new NodeFieldData(fieldNodeData, var, findAccessElement(var), mirror, kind, execution);
+        return fieldData;
     }
 
     private Element findAccessElement(VariableElement variableElement) {
@@ -470,16 +754,15 @@
                 break;
             }
         }
-
-        if (getter != null) {
+        if (getter != null && !getter.getModifiers().contains(Modifier.PRIVATE)) {
             return getter;
         } else {
             return variableElement;
         }
     }
 
-    private static void sortByExecutionOrder(NodeFieldData[] fields, final List<String> executionOrder, final List<TypeElement> typeHierarchy) {
-        Arrays.sort(fields, new Comparator<NodeFieldData>() {
+    private static void sortByExecutionOrder(List<NodeFieldData> fields, final List<String> executionOrder, final List<TypeElement> typeHierarchy) {
+        Collections.sort(fields, new Comparator<NodeFieldData>() {
 
             @Override
             public int compare(NodeFieldData o1, NodeFieldData o2) {
@@ -501,18 +784,16 @@
         });
     }
 
-    private boolean assignShortCircuitsToSpecializations(NodeData nodeData, List<SpecializationData> specializations, List<ShortCircuitData> shortCircuits) {
-
-        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(shortCircuits);
+    private void assignShortCircuitsToSpecializations(NodeData node) {
+        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
 
         boolean valid = true;
-
-        for (NodeFieldData field : nodeData.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) {
+        for (NodeFieldData field : node.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) {
             String valueName = field.getName();
             List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
 
             if (availableCircuits == null || availableCircuits.isEmpty()) {
-                log.error(nodeData.getTemplateType(), "@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
+                node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
                 valid = false;
                 continue;
             }
@@ -527,7 +808,7 @@
 
             if (!sameMethodName) {
                 for (ShortCircuitData circuit : availableCircuits) {
-                    log.error(circuit.getMethod(), circuit.getMarkerAnnotation(), "All short circuits for short cut value '%s' must have the same method name.", valueName);
+                    circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
                 }
                 valid = false;
                 continue;
@@ -535,14 +816,14 @@
 
             ShortCircuitData genericCircuit = null;
             for (ShortCircuitData circuit : availableCircuits) {
-                if (isGenericShortCutMethod(nodeData, circuit)) {
+                if (isGenericShortCutMethod(node, circuit)) {
                     genericCircuit = circuit;
                     break;
                 }
             }
 
             if (genericCircuit == null) {
-                log.error(nodeData.getTemplateType(), "No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
+                node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
                 valid = false;
                 continue;
             }
@@ -555,70 +836,59 @@
         }
 
         if (!valid) {
-            return valid;
+            return;
         }
 
-        NodeFieldData[] fields = nodeData.filterFields(null, ExecutionKind.SHORT_CIRCUIT);
-        for (SpecializationData specialization : specializations) {
-            ShortCircuitData[] assignedShortCuts = new ShortCircuitData[fields.length];
+        NodeFieldData[] fields = node.filterFields(null, ExecutionKind.SHORT_CIRCUIT);
+        for (SpecializationData specialization : node.getSpecializations()) {
+            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(fields.length);
 
             for (int i = 0; i < fields.length; i++) {
                 List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName());
 
                 ShortCircuitData genericShortCircuit = null;
+                ShortCircuitData compatibleShortCircuit = null;
                 for (ShortCircuitData circuit : availableShortCuts) {
                     if (circuit.isGeneric()) {
                         genericShortCircuit = circuit;
                     } else if (circuit.isCompatibleTo(specialization)) {
-                        assignedShortCuts[i] = circuit;
+                        compatibleShortCircuit = circuit;
                     }
                 }
 
-                if (assignedShortCuts[i] == null) {
-                    assignedShortCuts[i] = genericShortCircuit;
+                if (compatibleShortCircuit == null) {
+                    compatibleShortCircuit = genericShortCircuit;
                 }
+                assignedShortCuts.add(compatibleShortCircuit);
             }
             specialization.setShortCircuits(assignedShortCuts);
         }
-        return true;
     }
 
-    private boolean verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
-        boolean valid = true;
+    private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
         for (int i = 0; i < methods.size(); i++) {
             TemplateMethod m1 = methods.get(i);
             if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
-                log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Naming convention: method name must start with '%s'.", prefix);
-                valid = false;
+                m1.addError("Naming convention: method name must start with '%s'.", prefix);
             }
         }
-        return valid;
     }
 
-    private boolean verifyNamesUnique(List<? extends TemplateMethod> methods) {
-        boolean valid = true;
-        for (int i = 0; i < methods.size(); i++) {
-            TemplateMethod m1 = methods.get(i);
-            for (int j = i + 1; j < methods.size(); j++) {
-                TemplateMethod m2 = methods.get(j);
-
-                if (m1.getMethodName().equalsIgnoreCase(m2.getMethodName())) {
-                    log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName());
-                    log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName());
-                    return false;
+    private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
+        for (ActualParameter parameter : method.getParameters()) {
+            NodeFieldData field = node.findField(parameter.getSpecification().getName());
+            if (field == null || field.getKind() == FieldKind.FIELD) {
+                continue;
+            }
+            ExecutableTypeData found = null;
+            List<ExecutableTypeData> executableElements = field.getNodeData().findGenericExecutableTypes(context);
+            for (ExecutableTypeData executable : executableElements) {
+                if (executable.getType().equalsType(parameter.getActualTypeData(node.getTypeSystem()))) {
+                    found = executable;
+                    break;
                 }
             }
-        }
-        return valid;
-    }
-
-    private static boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
-        for (NodeFieldData field : node.getFields()) {
-            ActualParameter parameter = method.findParameter(field.getName());
-            if (parameter == null) {
-                continue;
-            }
-            if (!Utils.typeEquals(node.getTypeSystem().getGenericType(), parameter.getActualType())) {
+            if (found == null) {
                 return false;
             }
         }
@@ -656,7 +926,10 @@
         return collection;
     }
 
-    private boolean verifySpecializationOrder(TypeSystemData typeSystem, List<SpecializationData> specializations) {
+    private static void verifySpecializationOrder(NodeData node) {
+        TypeSystemData typeSystem = node.getTypeSystem();
+        List<SpecializationData> specializations = node.getSpecializations();
+
         for (int i = 0; i < specializations.size(); i++) {
             SpecializationData m1 = specializations.get(i);
             for (int j = i + 1; j < specializations.size(); j++) {
@@ -666,56 +939,39 @@
                 if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
                     int specOrder = m1.getOrder() - m2.getOrder();
                     if (specOrder == 0) {
-                        log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder());
-                        log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder());
-                        return false;
+                        m1.addError("Order value %d used multiple times", m1.getOrder());
+                        m2.addError("Order value %d used multiple times", m1.getOrder());
+                        return;
                     } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) {
-                        log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
-                        log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
-                        return false;
+                        m1.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
+                        m2.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
+                        return;
                     }
                 } else if (inferredOrder == 0) {
                     SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2);
-                    log.error(m.getMethod(), m.getMarkerAnnotation(), "Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this.");
-                    return false;
+                    m.addError("Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this.");
+                    return;
                 }
             }
         }
-        return true;
     }
 
-    private boolean verifySpecializationThrows(TypeSystemData typeSystem, List<SpecializationData> specializations) {
+    private static void verifySpecializationThrows(NodeData node) {
         Map<String, SpecializationData> specializationMap = new HashMap<>();
-        for (SpecializationData spec : specializations) {
+        for (SpecializationData spec : node.getSpecializations()) {
             specializationMap.put(spec.getMethodName(), spec);
         }
-        boolean valid = true;
-        for (SpecializationData sourceSpecialization : specializations) {
+        for (SpecializationData sourceSpecialization : node.getSpecializations()) {
             if (sourceSpecialization.getExceptions() != null) {
                 for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
-                    SpecializationData targetSpecialization = specializationMap.get(throwsData.getTransitionToName());
-                    AnnotationValue value = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "transitionTo");
-
-                    if (targetSpecialization == null) {
-                        log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value, "Specialization with name '%s' not found.", throwsData.getTransitionToName());
-                        valid = false;
-                    } else if (compareSpecialization(typeSystem, sourceSpecialization, targetSpecialization) >= 0) {
-                        log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value,
-                                        "The order of the target specializalization must be higher than the source specialization.", throwsData.getTransitionToName());
-                        valid = false;
-                    }
-
                     for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
                         if (otherThrowsData != throwsData && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
-                            AnnotationValue javaClassValue = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "javaClass");
-                            log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), javaClassValue, "Duplicate exception type.", throwsData.getTransitionToName());
-                            valid = false;
+                            throwsData.addError("Duplicate exception type.");
                         }
                     }
                 }
             }
         }
-        return valid;
     }
 
     private static int compareSpecialization(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) {
@@ -732,15 +988,34 @@
     }
 
     private static int compareSpecializationWithoutOrder(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) {
-        if (m1.getSpecification() != m2.getSpecification()) {
-            throw new UnsupportedOperationException("Cannot compare two specializations with different specifications.");
+        if (m1 == m2) {
+            return 0;
+        }
+
+        if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
+            return m1.getOrder() - m2.getOrder();
+        } else if (m1.isUninitialized() && !m2.isUninitialized()) {
+            return -1;
+        } else if (!m1.isUninitialized() && m2.isUninitialized()) {
+            return 1;
+        } else if (m1.isGeneric() && !m2.isGeneric()) {
+            return 1;
+        } else if (!m1.isGeneric() && m2.isGeneric()) {
+            return -1;
+        }
+
+        if (m1.getTemplate() != m2.getTemplate()) {
+            throw new UnsupportedOperationException("Cannot compare two specializations with different templates.");
         }
 
         int result = compareActualParameter(typeSystem, m1.getReturnType(), m2.getReturnType());
 
-        for (ParameterSpec spec : m1.getSpecification().getParameters()) {
-            ActualParameter p1 = m1.findParameter(spec);
-            ActualParameter p2 = m2.findParameter(spec);
+        for (ActualParameter p1 : m1.getParameters()) {
+            NodeFieldData field = m1.getNode().findField(p1.getSpecification().getName());
+            if (field == null) {
+                continue;
+            }
+            ActualParameter p2 = m2.findParameter(p1.getLocalName());
 
             if (p1 != null && p2 != null && !Utils.typeEquals(p1.getActualType(), p2.getActualType())) {
                 int typeResult = compareActualParameter(typeSystem, p1, p2);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -61,8 +61,7 @@
         }
 
         for (ActualParameter param : getParameters()) {
-            ParameterSpec paramSpec = param.getSpecification();
-            ActualParameter specializationParam = specialization.findParameter(paramSpec.getName());
+            ActualParameter specializationParam = specialization.findParameter(param.getLocalName());
             if (!Utils.typeEquals(param.getActualType(), specializationParam.getActualType())) {
                 return false;
             }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -48,14 +48,8 @@
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        String shortCircuitValue = Utils.getAnnotationValueString(mirror, "value");
-
-        if (!shortCircuitValues.contains(shortCircuitValue)) {
-            getContext().getLog().error(method, mirror, "Invalid short circuit value %s.", shortCircuitValue);
-            return null;
-        }
-
-        return createDefaultMethodSpec(shortCircuitValue);
+        String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value");
+        return createDefaultMethodSpec(method, mirror, shortCircuitValue);
     }
 
     @Override
@@ -65,9 +59,12 @@
 
     @Override
     public ShortCircuitData create(TemplateMethod method) {
-        String shortCircuitValue = Utils.getAnnotationValueString(method.getMarkerAnnotation(), "value");
-        assert shortCircuitValue != null;
-        assert shortCircuitValues.contains(shortCircuitValue);
+        String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value");
+
+        if (!shortCircuitValues.contains(shortCircuitValue)) {
+            method.addError("Invalid short circuit value %s.", shortCircuitValue);
+        }
+
         return new ShortCircuitData(method, shortCircuitValue);
     }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,7 +22,11 @@
  */
 package com.oracle.truffle.codegen.processor.node;
 
+import java.util.*;
+
 import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.*;
 import com.oracle.truffle.codegen.processor.template.*;
 
 public class SpecializationData extends TemplateMethod {
@@ -30,13 +34,13 @@
     private final int order;
     private final boolean generic;
     private final boolean uninitialized;
-    private final SpecializationThrowsData[] exceptions;
-    private SpecializationGuardData[] guards;
-    private ShortCircuitData[] shortCircuits;
+    private final List<SpecializationThrowsData> exceptions;
+    private List<SpecializationGuardData> guards;
+    private List<ShortCircuitData> shortCircuits;
     private boolean useSpecializationsForGeneric = true;
     private NodeData node;
 
-    public SpecializationData(TemplateMethod template, int order, SpecializationThrowsData[] exceptions) {
+    public SpecializationData(TemplateMethod template, int order, List<SpecializationThrowsData> exceptions) {
         super(template);
         this.order = order;
         this.generic = false;
@@ -53,8 +57,40 @@
         this.order = Specialization.DEFAULT_ORDER;
         this.generic = generic;
         this.uninitialized = uninitialized;
-        this.exceptions = new SpecializationThrowsData[0];
-        this.guards = new SpecializationGuardData[0];
+        this.exceptions = Collections.emptyList();
+        this.guards = new ArrayList<>();
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> sinks = new ArrayList<>();
+        if (exceptions != null) {
+            sinks.addAll(exceptions);
+        }
+        if (guards != null) {
+            sinks.addAll(guards);
+        }
+        return sinks;
+    }
+
+    public boolean hasRewrite(ProcessorContext context) {
+        if (!getExceptions().isEmpty()) {
+            return true;
+        }
+        if (!getGuards().isEmpty()) {
+            return true;
+        }
+        for (ActualParameter parameter : getParameters()) {
+            NodeFieldData field = getNode().findField(parameter.getSpecification().getName());
+            if (field == null || field.getKind() == FieldKind.FIELD) {
+                continue;
+            }
+            ExecutableTypeData type = field.getNodeData().findExecutableType(parameter.getActualTypeData(field.getNodeData().getTypeSystem()));
+            if (type.hasUnexpectedValue(context)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     public NodeData getNode() {
@@ -65,7 +101,7 @@
         this.node = node;
     }
 
-    public void setGuards(SpecializationGuardData[] guards) {
+    public void setGuards(List<SpecializationGuardData> guards) {
         this.guards = guards;
     }
 
@@ -81,19 +117,19 @@
         return uninitialized;
     }
 
-    public SpecializationThrowsData[] getExceptions() {
+    public List<SpecializationThrowsData> getExceptions() {
         return exceptions;
     }
 
-    public SpecializationGuardData[] getGuards() {
+    public List<SpecializationGuardData> getGuards() {
         return guards;
     }
 
-    public void setShortCircuits(ShortCircuitData[] shortCircuits) {
+    public void setShortCircuits(List<ShortCircuitData> shortCircuits) {
         this.shortCircuits = shortCircuits;
     }
 
-    public ShortCircuitData[] getShortCircuits() {
+    public List<ShortCircuitData> getShortCircuits() {
         return shortCircuits;
     }
 
@@ -106,10 +142,10 @@
     }
 
     public SpecializationData findNextSpecialization() {
-        SpecializationData[] specializations = node.getSpecializations();
-        for (int i = 0; i < specializations.length - 1; i++) {
-            if (specializations[i] == this) {
-                return specializations[i + 1];
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = 0; i < specializations.size() - 1; i++) {
+            if (specializations.get(i) == this) {
+                return specializations.get(i + 1);
             }
         }
         return null;
@@ -124,15 +160,4 @@
         return false;
     }
 
-    public ActualParameter getPreviousParam(ActualParameter searchParam) {
-        ActualParameter prev = null;
-        for (ActualParameter param : getParameters()) {
-            if (param == searchParam) {
-                return prev;
-            }
-            prev = param;
-        }
-        return prev;
-    }
-
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,20 +22,42 @@
  */
 package com.oracle.truffle.codegen.processor.node;
 
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.codegen.processor.template.*;
 import com.oracle.truffle.codegen.processor.typesystem.*;
 
-public class SpecializationGuardData {
+public class SpecializationGuardData extends MessageContainer {
 
+    private final SpecializationData specialization;
+    private final AnnotationValue value;
     private final String guardMethod;
     private final boolean onSpecialization;
     private final boolean onExecution;
 
     private GuardData guardDeclaration;
 
-    public SpecializationGuardData(String guardMethod, boolean onSpecialization, boolean onExecution) {
+    public SpecializationGuardData(SpecializationData specialization, AnnotationValue value, String guardMethod, boolean onSpecialization, boolean onExecution) {
+        this.specialization = specialization;
         this.guardMethod = guardMethod;
         this.onSpecialization = onSpecialization;
         this.onExecution = onExecution;
+        this.value = value;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return specialization.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return specialization.getMessageAnnotation();
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return value;
     }
 
     public String getGuardMethod() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.node;
+
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class SpecializationListenerData extends TemplateMethod {
+
+    public SpecializationListenerData(TemplateMethod method) {
+        super(method);
+    }
+
+}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,18 +30,15 @@
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.template.*;
 
-public class SpecializationListenerParser extends MethodParser<TemplateMethod> {
-
-    private final MethodSpec specification;
+public class SpecializationListenerParser extends MethodParser<SpecializationListenerData> {
 
     public SpecializationListenerParser(ProcessorContext context, NodeData node) {
         super(context, node);
-        this.specification = createDefaultMethodSpec(null);
     }
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return specification;
+        return createDefaultMethodSpec(method, mirror, null);
     }
 
     @Override
@@ -50,8 +47,8 @@
     }
 
     @Override
-    public TemplateMethod create(TemplateMethod method) {
-        return method;
+    public SpecializationListenerData create(TemplateMethod method) {
+        return new SpecializationListenerData(method);
     }
 
     @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -35,20 +35,13 @@
 
 public class SpecializationMethodParser extends MethodParser<SpecializationData> {
 
-    private final MethodSpec specification;
-
     public SpecializationMethodParser(ProcessorContext context, NodeData operation) {
         super(context, operation);
-        this.specification = createDefaultMethodSpec(null);
     }
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return specification;
-    }
-
-    public MethodSpec getSpecification() {
-        return specification;
+        return createDefaultMethodSpec(method, mirror, null);
     }
 
     @Override
@@ -62,27 +55,24 @@
     }
 
     private SpecializationData parseSpecialization(TemplateMethod method) {
-        int order = Utils.getAnnotationValueInt(method.getMarkerAnnotation(), "order");
+        int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order");
         if (order < 0 && order != Specialization.DEFAULT_ORDER) {
-            getContext().getLog().error(method.getMethod(), method.getMarkerAnnotation(), "Invalid order attribute %d. The value must be >= 0 or the default value.");
+            method.addError("Invalid order attribute %d. The value must be >= 0 or the default value.");
             return null;
         }
 
-        List<AnnotationMirror> exceptionDefs = Utils.collectAnnotations(getContext(), method.getMarkerAnnotation(), "exceptions", method.getMethod(), SpecializationThrows.class);
-        SpecializationThrowsData[] exceptionData = new SpecializationThrowsData[exceptionDefs.size()];
-        for (int i = 0; i < exceptionData.length; i++) {
-            AnnotationMirror mirror = exceptionDefs.get(i);
-            TypeMirror javaClass = Utils.getAnnotationValueType(mirror, "javaClass");
-            String transitionTo = Utils.getAnnotationValueString(mirror, "transitionTo");
-            exceptionData[i] = new SpecializationThrowsData(mirror, javaClass, transitionTo);
-
-            if (!Utils.canThrowType(method.getMethod().getThrownTypes(), javaClass)) {
-                getContext().getLog().error(method.getMethod(), "Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(javaClass));
-                return null;
+        AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn");
+        List<TypeMirror> exceptionTypes = Utils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn");
+        List<SpecializationThrowsData> exceptionData = new ArrayList<>();
+        for (TypeMirror exceptionType : exceptionTypes) {
+            SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType);
+            if (!Utils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) {
+                throwsData.addError("Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(exceptionType));
             }
+            exceptionData.add(throwsData);
         }
 
-        Arrays.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
+        Collections.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
 
             @Override
             public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
@@ -90,42 +80,28 @@
             }
         });
         SpecializationData specialization = new SpecializationData(method, order, exceptionData);
-        boolean valid = true;
-        List<AnnotationMirror> guardDefs = Utils.collectAnnotations(getContext(), method.getMarkerAnnotation(), "guards", method.getMethod(), SpecializationGuard.class);
-        SpecializationGuardData[] guardData = new SpecializationGuardData[guardDefs.size()];
-        for (int i = 0; i < guardData.length; i++) {
-            AnnotationMirror guardMirror = guardDefs.get(i);
-            String guardMethod = Utils.getAnnotationValueString(guardMirror, "methodName");
-            boolean onSpecialization = Utils.getAnnotationValueBoolean(guardMirror, "onSpecialization");
-            boolean onExecution = Utils.getAnnotationValueBoolean(guardMirror, "onExecution");
+        AnnotationValue guardsValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "guards");
+        List<String> guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
+        List<SpecializationGuardData> guardData = new ArrayList<>(guardDefs.size());
+        for (int i = 0; i < guardDefs.size(); i++) {
+            String guardMethod = guardDefs.get(i);
 
-            if (!onSpecialization && !onExecution) {
-                String message = "Either onSpecialization, onExecution or both must be enabled.";
-                getContext().getLog().error(method.getMethod(), guardMirror, message);
-                valid = false;
-                continue;
-            }
+            SpecializationGuardData assignedGuard = new SpecializationGuardData(specialization, guardsValue, guardMethod, true, true);
 
-            guardData[i] = new SpecializationGuardData(guardMethod, onSpecialization, onExecution);
+            guardData.add(assignedGuard);
 
-            GuardData compatibleGuard = matchSpecializationGuard(guardMirror, specialization, guardData[i]);
+            GuardData compatibleGuard = matchSpecializationGuard(specialization, assignedGuard);
             if (compatibleGuard != null) {
-                guardData[i].setGuardDeclaration(compatibleGuard);
-            } else {
-                valid = false;
+                assignedGuard.setGuardDeclaration(compatibleGuard);
             }
         }
 
-        if (!valid) {
-            return null;
-        }
-
         specialization.setGuards(guardData);
 
         return specialization;
     }
 
-    private GuardData matchSpecializationGuard(AnnotationMirror mirror, SpecializationData specialization, SpecializationGuardData specializationGuard) {
+    private GuardData matchSpecializationGuard(SpecializationData specialization, SpecializationGuardData specializationGuard) {
         List<GuardData> foundGuards = getNode().findGuards(specializationGuard.getGuardMethod());
 
         GuardData compatibleGuard = null;
@@ -146,28 +122,33 @@
             }
             List<TypeDef> typeDefs = createTypeDefinitions(returnTypeSpec, expectedParameterSpecs);
             String expectedSignature = TemplateMethodParser.createExpectedSignature(specializationGuard.getGuardMethod(), returnTypeSpec, expectedParameterSpecs, typeDefs);
-            AnnotationValue value = Utils.getAnnotationValue(mirror, "methodName");
-            getContext().getLog().error(specialization.getMethod(), mirror, value, "No guard with signature '%s' found in type system.", expectedSignature);
-            return null;
+            specializationGuard.addError("No guard with signature '%s' found in type system.", expectedSignature);
         }
 
         return compatibleGuard;
     }
 
     private static boolean isGuardCompatible(SpecializationData specialization, GuardData guard) {
-        Iterator<ActualParameter> guardParameters = Arrays.asList(guard.getParameters()).iterator();
+        Iterator<ActualParameter> guardParameters = guard.getParameters().iterator();
         for (ActualParameter param : specialization.getParameters()) {
+            if (param.getSpecification().isOptional()) {
+                continue;
+            }
             if (!guardParameters.hasNext()) {
                 return false;
             }
             ActualParameter guardParam = guardParameters.next();
-            if (!Utils.typeEquals(guardParam.getActualType(), param.getActualType())) {
+            if (!Utils.typeEquals(guardParam.getActualType(), param.getActualType()) && !guardParam.getSpecification().isOptional()) {
                 return false;
             }
         }
-        if (guardParameters.hasNext()) {
-            return false;
+        while (guardParameters.hasNext()) {
+            ActualParameter param = guardParameters.next();
+            if (!param.getSpecification().isOptional()) {
+                return false;
+            }
         }
+
         return true;
     }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -25,23 +25,40 @@
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
 
-public class SpecializationThrowsData {
+import com.oracle.truffle.codegen.processor.template.*;
 
+public class SpecializationThrowsData extends MessageContainer {
+
+    private final AnnotationValue annotationValue;
     private final AnnotationMirror annotationMirror;
     private final TypeMirror javaClass;
-    private final String transitionTo;
     private SpecializationData specialization;
 
-    public SpecializationThrowsData(AnnotationMirror annotationMirror, TypeMirror javaClass, String transitionTo) {
+    public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) {
         this.annotationMirror = annotationMirror;
+        this.annotationValue = value;
         this.javaClass = javaClass;
-        this.transitionTo = transitionTo;
     }
 
     void setSpecialization(SpecializationData specialization) {
         this.specialization = specialization;
     }
 
+    @Override
+    public Element getMessageElement() {
+        return specialization.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return annotationMirror;
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return annotationValue;
+    }
+
     public TypeMirror getJavaClass() {
         return javaClass;
     }
@@ -54,16 +71,7 @@
         return annotationMirror;
     }
 
-    public String getTransitionToName() {
-        return transitionTo;
-    }
-
     public SpecializationData getTransitionTo() {
-        for (SpecializationData s : specialization.getNode().getSpecializations()) {
-            if (s.getMethodName().equals(transitionTo)) {
-                return s;
-            }
-        }
-        return null;
+        return specialization.findNextSpecialization();
     }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,16 +30,49 @@
 
     private final ParameterSpec specification;
     private final TypeMirror actualType;
+    private TemplateMethod method;
+    private final String localName;
+    private final int index;
+    private final boolean implicit;
 
-    public ActualParameter(ParameterSpec specification, TypeMirror actualType) {
+    public ActualParameter(ParameterSpec specification, TypeMirror actualType, int index, boolean implicit) {
         this.specification = specification;
         this.actualType = actualType;
+
+        this.index = index;
+        this.implicit = implicit;
+        String valueName = specification.getName() + "Value";
+
+        if (specification.isIndexed()) {
+            valueName += index;
+        }
+        this.localName = valueName;
+    }
+
+    public boolean isImplicit() {
+        return implicit;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public String getLocalName() {
+        return localName;
+    }
+
+    void setMethod(TemplateMethod method) {
+        this.method = method;
     }
 
     public ParameterSpec getSpecification() {
         return specification;
     }
 
+    public TemplateMethod getMethod() {
+        return method;
+    }
+
     public TypeMirror getActualType() {
         return actualType;
     }
@@ -47,4 +80,8 @@
     public TypeData getActualTypeData(TypeSystemData typeSystem) {
         return typeSystem.findTypeData(actualType);
     }
+
+    public ActualParameter getPreviousParameter() {
+        return method.getPreviousParam(this);
+    }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java	Thu Mar 21 14:11:13 2013 +0100
@@ -128,6 +128,10 @@
 
         CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class));
         generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType()));
+        if (model.getTemplateMethodName() != null) {
+            generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName()));
+        }
+
         clazz.addAnnotationMirror(generatedByAnnotation);
 
         context.registerType(model.getTemplateType(), clazz.asType());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MessageContainer.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.codegen.processor.*;
+
+public abstract class MessageContainer {
+
+    private final List<Message> messages = new ArrayList<>();
+
+    public final void addWarning(String text, Object... params) {
+        getMessages().add(new Message(this, String.format(text, params), Kind.WARNING));
+    }
+
+    public final void addError(String text, Object... params) {
+        getMessages().add(new Message(this, String.format(text, params), Kind.ERROR));
+    }
+
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public abstract Element getMessageElement();
+
+    public final void emitMessages(TypeElement baseElement, Log log) {
+        emitMessagesImpl(baseElement, log, new HashSet<MessageContainer>());
+    }
+
+    private void emitMessagesImpl(TypeElement baseElement, Log log, Set<MessageContainer> visitedSinks) {
+        for (Message message : getMessages()) {
+            emitDefault(baseElement, log, message);
+        }
+
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                continue;
+            }
+
+            visitedSinks.add(sink);
+            sink.emitMessagesImpl(baseElement, log, visitedSinks);
+        }
+    }
+
+    private void emitDefault(TypeElement baseType, Log log, Message message) {
+        TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement());
+        if (rootEnclosing != null && Utils.typeEquals(baseType.asType(), rootEnclosing.asType()) && this == message.getOriginalContainer()) {
+            log.message(message.getKind(), getMessageElement(), getMessageAnnotation(), getMessageAnnotationValue(), message.getText());
+        } else {
+            MessageContainer original = message.getOriginalContainer();
+            log.message(message.getKind(), baseType, null, null, wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText()));
+        }
+    }
+
+    private static String wrapText(Element element, AnnotationMirror mirror, String text) {
+        StringBuilder b = new StringBuilder();
+        if (element != null) {
+            b.append("Element " + element.toString());
+        }
+        if (mirror != null) {
+            b.append(" at annotation @" + Utils.getSimpleName(mirror.getAnnotationType()));
+        }
+
+        if (b.length() > 0) {
+            b.append(" is erroneous: ").append(text);
+            return b.toString();
+        } else {
+            return text;
+        }
+    }
+
+    public AnnotationMirror getMessageAnnotation() {
+        return null;
+    }
+
+    public AnnotationValue getMessageAnnotationValue() {
+        return null;
+    }
+
+    public final boolean hasErrors() {
+        return hasErrorsImpl(new HashSet<MessageContainer>());
+    }
+
+    public final List<Message> collectMessages() {
+        List<Message> collectedMessages = new ArrayList<>();
+        collectMessagesImpl(collectedMessages, new HashSet<MessageContainer>());
+        return collectedMessages;
+    }
+
+    private void collectMessagesImpl(List<Message> collectedMessages, Set<MessageContainer> visitedSinks) {
+        collectedMessages.addAll(getMessages());
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                return;
+            }
+
+            visitedSinks.add(sink);
+            sink.collectMessagesImpl(collectedMessages, visitedSinks);
+        }
+    }
+
+    private boolean hasErrorsImpl(Set<MessageContainer> visitedSinks) {
+        for (Message msg : getMessages()) {
+            if (msg.getKind() == Kind.ERROR) {
+                return true;
+            }
+        }
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                return false;
+            }
+
+            visitedSinks.add(sink);
+
+            if (sink.hasErrorsImpl(visitedSinks)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public List<Message> getMessages() {
+        return messages;
+    }
+
+    public static final class Message {
+
+        private final MessageContainer originalContainer;
+        private final String text;
+        private final Kind kind;
+
+        public Message(MessageContainer originalContainer, String text, Kind kind) {
+            this.originalContainer = originalContainer;
+            this.text = text;
+            this.kind = kind;
+        }
+
+        public MessageContainer getOriginalContainer() {
+            return originalContainer;
+        }
+
+        public String getText() {
+            return text;
+        }
+
+        public Kind getKind() {
+            return kind;
+        }
+
+        @Override
+        public String toString() {
+            return kind + ": " + text;
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,16 +24,25 @@
 
 import java.util.*;
 
+import javax.lang.model.type.*;
+
 public class MethodSpec {
 
+    private final List<TypeMirror> implicitTypes;
+
     private final ParameterSpec returnType;
     private final List<ParameterSpec> parameters;
 
-    public MethodSpec(ParameterSpec returnType, List<ParameterSpec> parameters) {
+    public MethodSpec(List<TypeMirror> prefixTypes, ParameterSpec returnType, List<ParameterSpec> parameters) {
+        this.implicitTypes = prefixTypes;
         this.returnType = returnType;
         this.parameters = parameters;
     }
 
+    public List<TypeMirror> getImplicitTypes() {
+        return implicitTypes;
+    }
+
     public ParameterSpec getReturnType() {
         return returnType;
     }
@@ -41,4 +50,14 @@
     public List<ParameterSpec> getParameters() {
         return parameters;
     }
+
+    public ParameterSpec findParameterSpec(String name) {
+        for (ParameterSpec spec : parameters) {
+            if (spec.getName().equals(name)) {
+                return spec;
+            }
+        }
+        return null;
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Thu Mar 21 14:11:13 2013 +0100
@@ -37,13 +37,13 @@
     }
 
     private final String name;
-    private final TypeMirror[] allowedTypes;
-    private final TypeMirror valueType;
+    private final List<TypeMirror> allowedTypes;
     private final boolean optional;
-    private final Cardinality cardinality;
+    private Cardinality cardinality;
+    private boolean indexed;
+    private boolean local;
 
-    public ParameterSpec(String name, TypeMirror[] allowedTypes, TypeMirror valueType, boolean optional, Cardinality cardinality) {
-        this.valueType = valueType;
+    public ParameterSpec(String name, List<TypeMirror> allowedTypes, boolean optional, Cardinality cardinality) {
         this.allowedTypes = allowedTypes;
         this.name = name;
         this.optional = optional;
@@ -52,20 +52,40 @@
 
     /** Type constructor. */
     public ParameterSpec(String name, TypeMirror singleFixedType, boolean optional) {
-        this(name, new TypeMirror[]{singleFixedType}, singleFixedType, optional, Cardinality.ONE);
+        this(name, Arrays.asList(singleFixedType), optional, Cardinality.ONE);
     }
 
     /** Type system value constructor. */
     public ParameterSpec(String name, TypeSystemData typeSystem, boolean optional, Cardinality cardinality) {
-        this(name, typeSystem.getPrimitiveTypeMirrors(), typeSystem.getGenericType(), optional, cardinality);
+        this(name, typeSystem.getPrimitiveTypeMirrors(), optional, cardinality);
     }
 
     /** Node value constructor. */
     public ParameterSpec(String name, NodeData nodeData, boolean optional, Cardinality cardinality) {
-        this(name, nodeTypeMirrors(nodeData), nodeData.getTypeSystem().getGenericType(), optional, cardinality);
+        this(name, nodeTypeMirrors(nodeData), optional, cardinality);
+    }
+
+    public void setLocal(boolean local) {
+        this.local = local;
+    }
+
+    public boolean isLocal() {
+        return local;
     }
 
-    private static TypeMirror[] nodeTypeMirrors(NodeData nodeData) {
+    public boolean isIndexed() {
+        return indexed;
+    }
+
+    public void setIndexed(boolean indexed) {
+        this.indexed = indexed;
+    }
+
+    public void setCardinality(Cardinality cardinality) {
+        this.cardinality = cardinality;
+    }
+
+    private static List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
         Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
 
         for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) {
@@ -74,7 +94,7 @@
 
         typeMirrors.add(nodeData.getTypeSystem().getGenericType());
 
-        return typeMirrors.toArray(new TypeMirror[typeMirrors.size()]);
+        return new ArrayList<>(typeMirrors);
     }
 
     public final String getName() {
@@ -89,13 +109,12 @@
         return cardinality;
     }
 
-    public TypeMirror[] getAllowedTypes() {
+    public List<TypeMirror> getAllowedTypes() {
         return allowedTypes;
     }
 
     public boolean matches(TypeMirror actualType) {
-        for (int i = 0; i < allowedTypes.length; i++) {
-            TypeMirror mirror = allowedTypes[i];
+        for (TypeMirror mirror : allowedTypes) {
             if (Utils.typeEquals(actualType, mirror)) {
                 return true;
             }
@@ -103,7 +122,4 @@
         return false;
     }
 
-    public TypeMirror getValueType() {
-        return valueType;
-    }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java	Thu Mar 21 14:11:13 2013 +0100
@@ -29,18 +29,34 @@
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.api.element.*;
 
-public abstract class Template {
+public abstract class Template extends MessageContainer {
 
     private final TypeElement templateType;
+    private final String templateMethodName;
     private final AnnotationMirror annotation;
 
     private List<? extends WritableElement> extensionElements;
 
-    public Template(TypeElement templateType, AnnotationMirror annotation) {
+    public Template(TypeElement templateType, String templateMethodName, AnnotationMirror annotation) {
         this.templateType = templateType;
+        this.templateMethodName = templateMethodName;
         this.annotation = annotation;
     }
 
+    @Override
+    public Element getMessageElement() {
+        return templateType;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public String getTemplateMethodName() {
+        return templateMethodName;
+    }
+
     public TypeElement getTemplateType() {
         return templateType;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Thu Mar 21 14:11:13 2013 +0100
@@ -22,33 +22,66 @@
  */
 package com.oracle.truffle.codegen.processor.template;
 
+import java.util.*;
+
 import javax.lang.model.element.*;
+import javax.lang.model.type.*;
 
-public class TemplateMethod {
+import com.oracle.truffle.codegen.processor.*;
 
+public class TemplateMethod extends MessageContainer {
+
+    private String id;
     private final Template template;
     private final MethodSpec specification;
     private final ExecutableElement method;
     private final AnnotationMirror markerAnnotation;
     private final ActualParameter returnType;
-    private final ActualParameter[] parameters;
+    private final List<ActualParameter> parameters;
 
-    public TemplateMethod(Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, ActualParameter[] parameters) {
+    public TemplateMethod(String id, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType,
+                    List<ActualParameter> parameters) {
         this.template = template;
         this.specification = specification;
         this.method = method;
         this.markerAnnotation = markerAnnotation;
         this.returnType = returnType;
         this.parameters = parameters;
+        this.id = id;
+
+        if (parameters != null) {
+            for (ActualParameter param : parameters) {
+                param.setMethod(this);
+            }
+        }
     }
 
     public TemplateMethod(TemplateMethod method) {
-        this.template = method.template;
-        this.specification = method.specification;
-        this.method = method.method;
-        this.markerAnnotation = method.markerAnnotation;
-        this.returnType = method.returnType;
-        this.parameters = method.parameters;
+        this(method.id, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters);
+        getMessages().addAll(method.getMessages());
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return method;
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return markerAnnotation;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getId() {
+        return id;
     }
 
     public Template getTemplate() {
@@ -63,34 +96,50 @@
         return returnType;
     }
 
-    public ActualParameter[] getParameters() {
+    public List<ActualParameter> getParameters() {
         return parameters;
     }
 
     public ActualParameter findParameter(String valueName) {
         for (ActualParameter param : getParameters()) {
-            if (param.getSpecification().getName().equals(valueName)) {
+            if (param.getLocalName().equals(valueName)) {
                 return param;
             }
         }
         return null;
     }
 
+    public List<ActualParameter> getReturnTypeAndParameters() {
+        List<ActualParameter> allParameters = new ArrayList<>(getParameters().size() + 1);
+        allParameters.add(getReturnType());
+        allParameters.addAll(getParameters());
+        return Collections.unmodifiableList(allParameters);
+    }
+
     public ActualParameter findParameter(ParameterSpec spec) {
         for (ActualParameter param : getParameters()) {
-            if (param.getSpecification() == spec) {
+            if (param.getSpecification().getName().equals(spec.getName())) {
                 return param;
             }
         }
         return null;
     }
 
+    public boolean canBeAccessedByInstanceOf(TypeMirror type) {
+        TypeMirror methodType = Utils.findNearestEnclosingType(getMethod()).asType();
+        return Utils.isAssignable(type, methodType) || Utils.isAssignable(methodType, type);
+    }
+
     public ExecutableElement getMethod() {
         return method;
     }
 
     public String getMethodName() {
-        return getMethod().getSimpleName().toString();
+        if (getMethod() != null) {
+            return getMethod().getSimpleName().toString();
+        } else {
+            return "$synthetic";
+        }
     }
 
     public AnnotationMirror getMarkerAnnotation() {
@@ -99,6 +148,17 @@
 
     @Override
     public String toString() {
-        return getClass().getSimpleName() + " [method = " + method + "]";
+        return "id = " + getId() + ", " + getClass().getSimpleName() + " [method = " + getMethod() + "]";
+    }
+
+    public ActualParameter getPreviousParam(ActualParameter searchParam) {
+        ActualParameter prev = null;
+        for (ActualParameter param : getParameters()) {
+            if (param == searchParam) {
+                return prev;
+            }
+            prev = param;
+        }
+        return prev;
     }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -31,6 +31,7 @@
 import javax.lang.model.type.*;
 import javax.lang.model.util.*;
 
+import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
 
@@ -95,19 +96,28 @@
                 mirror = Utils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType);
             }
 
-            if (method.getModifiers().contains(Modifier.PRIVATE)) {
-                getContext().getLog().error(method, "Method must not be private.");
+            E parsedMethod = parse(method, mirror);
+
+            if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) {
+                parsedMethod.addError("Method must not be private.");
                 valid = false;
                 continue;
             }
 
-            E parsedMethod = parse(method, mirror);
             if (parsedMethod != null) {
                 parsedMethods.add(parsedMethod);
             } else {
                 valid = false;
             }
         }
+        Collections.sort(parsedMethods, new Comparator<TemplateMethod>() {
+
+            @Override
+            public int compare(TemplateMethod o1, TemplateMethod o2) {
+                return o1.getMethodName().compareTo(o2.getMethodName());
+            }
+        });
+
         if (!valid && parseNullOnError) {
             return null;
         }
@@ -120,108 +130,140 @@
             return null;
         }
 
+        String id = method.getSimpleName().toString();
+        AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class);
+        if (idAnnotation != null) {
+            id = Utils.getAnnotationValue(String.class, idAnnotation, "value");
+        }
+
         List<TypeDef> typeDefs = createTypeDefinitions(methodSpecification.getReturnType(), methodSpecification.getParameters());
 
         ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
         List<ParameterSpec> parameterSpecs = new ArrayList<>();
         parameterSpecs.addAll(methodSpecification.getParameters());
 
-        ActualParameter returnTypeMirror = resolveTypeMirror(returnTypeSpec, method.getReturnType(), template);
+        ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false);
         if (returnTypeMirror == null) {
-            if (isEmitErrors()) {
+            if (emitErrors) {
+                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
                 String expectedReturnType = createTypeSignature(returnTypeSpec, typeDefs, true);
                 String actualReturnType = Utils.getSimpleName(method.getReturnType());
 
                 String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
                                 createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+                invalidMethod.addError(message);
+                return invalidMethod;
+            } else {
+                return null;
+            }
+        }
 
-                context.getLog().error(method, annotation, message);
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        for (VariableElement var : method.getParameters()) {
+            parameterTypes.add(var.asType());
+        }
+
+        List<ActualParameter> parameters = parseParameters(parameterTypes, methodSpecification.getImplicitTypes(), parameterSpecs);
+        if (parameters == null) {
+            if (isEmitErrors()) {
+                E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
+                String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method),
+                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+                invalidMethod.addError(message);
+                return invalidMethod;
+            } else {
+                return null;
             }
-            return null;
         }
 
-        Iterator<? extends VariableElement> variableIterator = method.getParameters().iterator();
+        return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters));
+    }
+
+    private static String createActualSignature(MethodSpec spec, ExecutableElement method) {
+        List<String> types = new ArrayList<>();
+        for (TypeMirror implicitType : spec.getImplicitTypes()) {
+            types.add("implicit " + Utils.getSimpleName(implicitType));
+        }
+        for (VariableElement var : method.getParameters()) {
+            types.add(Utils.getSimpleName(var.asType()));
+        }
+
+        StringBuilder b = new StringBuilder("(");
+        for (Iterator<String> iterator = types.iterator(); iterator.hasNext();) {
+            b.append(iterator.next());
+            if (iterator.hasNext()) {
+                b.append(", ");
+            }
+        }
+        b.append(")");
+        return b.toString();
+    }
+
+    private List<ActualParameter> parseParameters(List<TypeMirror> types, List<TypeMirror> implicitTypes, List<ParameterSpec> parameterSpecs) {
+        Iterator<? extends TypeMirror> parameterIterator = types.iterator();
+        Iterator<? extends TypeMirror> implicitParametersIterator = implicitTypes.iterator();
         Iterator<? extends ParameterSpec> specificationIterator = parameterSpecs.iterator();
 
-        List<ActualParameter> resolvedMirrors = new ArrayList<>();
-        VariableElement parameter = null;
-        ParameterSpec specification = null;
-        while (specificationIterator.hasNext() || specification != null) {
-            if (specification == null) {
-                specification = specificationIterator.next();
-            }
-
-            if (parameter == null && variableIterator.hasNext()) {
-                parameter = variableIterator.next();
-            }
-
-            if (parameter == null) {
-                if (specification.getCardinality() == Cardinality.MULTIPLE) {
-                    specification = null;
-                    continue;
-                } else if (!specification.isOptional()) {
-                    if (isEmitErrors()) {
-                        // non option type specification found -> argument missing
-                        String expectedType = createTypeSignature(specification, typeDefs, false);
-
-                        String message = String.format("Missing argument \"%s\".\nExpected signature: \n %s", expectedType,
-                                        createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+        TypeMirror parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
+        TypeMirror implicitParameter = implicitParametersIterator.hasNext() ? implicitParametersIterator.next() : null;
+        ParameterSpec specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
 
-                        context.getLog().error(method, message);
-                    }
-                    return null;
-                } else {
-                    // specification is optional -> continue
-                    specification = null;
+        int specificationParameterIndex = 0;
+        List<ActualParameter> resolvedParameters = new ArrayList<>();
+        while (parameter != null || specification != null || implicitParameter != null) {
+            if (parameter == null || specification == null) {
+                if (specification != null && (specification.isOptional() || specification.getCardinality() == Cardinality.MULTIPLE)) {
+                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+                    specificationParameterIndex = 0;
                     continue;
                 }
-            }
-
-            ActualParameter resolvedMirror = resolveTypeMirror(specification, parameter.asType(), template);
-
-            if (resolvedMirror == null) {
-                if (specification.isOptional()) {
-                    specification = null;
-                    continue;
-                }
-
-                if (isEmitErrors()) {
-                    String expectedReturnType = createTypeSignature(specification, typeDefs, false);
-                    String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
-
-                    String message = String.format("The provided argument type \"%s\" does not match expected type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
-                                    createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
-
-                    context.getLog().error(parameter, message);
-                }
                 return null;
             }
 
-            resolvedMirrors.add(resolvedMirror);
-            parameter = null; // consume parameter
+            ActualParameter resolvedParameter = null;
+
+            boolean implicit = false;
+            if (implicitParameter != null) {
+                resolvedParameter = matchParameter(specification, implicitParameter, template, specificationParameterIndex, true);
+                if (resolvedParameter != null) {
+                    implicit = true;
+                }
+            }
+
+            if (resolvedParameter == null) {
+                resolvedParameter = matchParameter(specification, parameter, template, specificationParameterIndex, false);
+            }
 
-            if (specification.getCardinality() != Cardinality.MULTIPLE) {
-                specification = null;
+            if (resolvedParameter == null) {
+                // mismatch
+                if (specification.isOptional()) {
+                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+                    specificationParameterIndex = 0;
+                } else {
+                    return null;
+                }
+            } else {
+                resolvedParameters.add(resolvedParameter);
+
+                // match
+                if (implicit) {
+                    implicitParameter = implicitParametersIterator.hasNext() ? implicitParametersIterator.next() : null;
+                } else {
+                    parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
+                }
+
+                if (specification.getCardinality() == Cardinality.ONE) {
+                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+                    specificationParameterIndex = 0;
+                } else if (specification.getCardinality() == Cardinality.MULTIPLE) {
+                    specificationParameterIndex++;
+                }
             }
         }
-
-        if (variableIterator.hasNext()) {
-            parameter = variableIterator.next();
-            if (isEmitErrors()) {
-                String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
-                String message = String.format("No argument expected but found \"%s\".\nExpected signature: \n %s", actualReturnType,
-                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
-
-                context.getLog().error(parameter, message);
-            }
-            return null;
-        }
-
-        ActualParameter[] paramMirrors = resolvedMirrors.toArray(new ActualParameter[resolvedMirrors.size()]);
-        return create(new TemplateMethod(template, methodSpecification, method, annotation, returnTypeMirror, paramMirrors));
+        return resolvedParameters;
     }
 
-    private ActualParameter resolveTypeMirror(ParameterSpec specification, TypeMirror mirror, Template typeSystem) {
+    private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index, boolean implicit) {
         TypeMirror resolvedType = mirror;
         if (hasError(resolvedType)) {
             resolvedType = context.resolveNotYetCompiledType(mirror, typeSystem);
@@ -230,7 +272,7 @@
         if (!specification.matches(resolvedType)) {
             return null;
         }
-        return new ActualParameter(specification, resolvedType);
+        return new ActualParameter(specification, resolvedType, index, implicit);
     }
 
     protected List<TypeDef> createTypeDefinitions(ParameterSpec returnType, List<? extends ParameterSpec> parameters) {
@@ -242,12 +284,12 @@
 
         int defIndex = 0;
         for (ParameterSpec spec : allParams) {
-            TypeMirror[] allowedTypes = spec.getAllowedTypes();
-            TypeMirror[] types = spec.getAllowedTypes();
-            if (types != null && allowedTypes.length > 1) {
+            List<TypeMirror> allowedTypes = spec.getAllowedTypes();
+            List<TypeMirror> types = spec.getAllowedTypes();
+            if (types != null && allowedTypes.size() > 1) {
                 TypeDef foundDef = null;
                 for (TypeDef def : typeDefs) {
-                    if (Arrays.equals(allowedTypes, def.getTypes())) {
+                    if (allowedTypes.equals(def.getTypes())) {
                         foundDef = def;
                         break;
                     }
@@ -267,11 +309,11 @@
 
     protected static class TypeDef {
 
-        private final TypeMirror[] types;
+        private final List<TypeMirror> types;
         private final String name;
         private final List<ParameterSpec> parameters = new ArrayList<>();
 
-        public TypeDef(TypeMirror[] types, String name) {
+        public TypeDef(List<TypeMirror> types, String name) {
             this.types = types;
             this.name = name;
         }
@@ -280,7 +322,7 @@
             return parameters;
         }
 
-        public TypeMirror[] getTypes() {
+        public List<TypeMirror> getTypes() {
             return types;
         }
 
@@ -349,7 +391,7 @@
 
     private static String createTypeSignature(ParameterSpec spec, List<TypeDef> typeDefs, boolean typeOnly) {
         StringBuilder builder = new StringBuilder();
-        if (spec.getAllowedTypes().length > 1) {
+        if (spec.getAllowedTypes().size() > 1) {
             TypeDef foundTypeDef = null;
             for (TypeDef typeDef : typeDefs) {
                 if (typeDef.getParameters().contains(spec)) {
@@ -360,8 +402,8 @@
             if (foundTypeDef != null) {
                 builder.append("<" + foundTypeDef.getName() + ">");
             }
-        } else if (spec.getAllowedTypes().length == 1) {
-            builder.append(Utils.getSimpleName(spec.getAllowedTypes()[0]));
+        } else if (spec.getAllowedTypes().size() == 1) {
+            builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0)));
         } else {
             builder.append("void");
         }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -43,9 +43,8 @@
         return extensionParser;
     }
 
-    protected boolean verifyExclusiveMethodAnnotation(TypeElement type, Class<?>... annotationTypes) {
-        boolean valid = true;
-        List<ExecutableElement> methods = ElementFilter.methodsIn(type.getEnclosedElements());
+    protected void verifyExclusiveMethodAnnotation(Template template, Class<?>... annotationTypes) {
+        List<ExecutableElement> methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements());
         for (ExecutableElement method : methods) {
             List<AnnotationMirror> foundAnnotations = new ArrayList<>();
             for (int i = 0; i < annotationTypes.length; i++) {
@@ -61,34 +60,9 @@
                     annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType()));
                 }
 
-                for (AnnotationMirror mirror : foundAnnotations) {
-                    context.getLog().error(method, mirror, "Non exclusive usage of annotations %s.", annotationNames);
-                }
-                valid = false;
+                template.addError("Non exclusive usage of annotations %s.", annotationNames);
             }
         }
-        return valid;
-    }
-
-    protected boolean verifyTemplateType(TypeElement template, AnnotationMirror annotation) {
-        // annotation type on class path!?
-        boolean valid = true;
-        TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
-        if (annotationTypeElement == null) {
-            log.error(template, annotation, "Required class " + getAnnotationType().getName() + " is not on the classpath.");
-            valid = false;
-        }
-        if (template.getModifiers().contains(Modifier.PRIVATE)) {
-            log.error(template, annotation, "The annotated class must have at least package protected visibility.");
-            valid = false;
-        }
-
-        if (template.getModifiers().contains(Modifier.FINAL)) {
-            log.error(template, annotation, "The annotated class must not be final.");
-            valid = false;
-        }
-
-        return valid;
     }
 
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,15 +26,8 @@
 
 public class GuardData extends TemplateMethod {
 
-    private final Template origin;
-
-    public GuardData(TemplateMethod method, Template origin) {
+    public GuardData(TemplateMethod method) {
         super(method);
-        this.origin = origin;
-    }
-
-    public Template getOrigin() {
-        return origin;
     }
 
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,8 +26,8 @@
 import java.util.*;
 
 import javax.lang.model.element.*;
+import javax.lang.model.type.*;
 
-import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.template.*;
 import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
@@ -39,30 +39,31 @@
     public GuardParser(ProcessorContext context, Template template, TypeSystemData typeSystem) {
         super(context, template);
         this.typeSystem = typeSystem;
+        setEmitErrors(false);
+        setParseNullOnError(false);
     }
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         List<ParameterSpec> specs = new ArrayList<>();
-        specs.add(new ParameterSpec("value1", typeSystem, false, Cardinality.ONE));
         specs.add(new ParameterSpec("valueN", typeSystem, false, Cardinality.MULTIPLE));
         ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), false);
-        return new MethodSpec(returnTypeSpec, specs);
+        return new MethodSpec(Collections.<TypeMirror> emptyList(), returnTypeSpec, specs);
     }
 
     @Override
     public boolean isParsable(ExecutableElement method) {
-        return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
+        return true;
     }
 
     @Override
     public GuardData create(TemplateMethod method) {
-        return new GuardData(method, template);
+        return new GuardData(method);
     }
 
     @Override
     public Class<? extends Annotation> getAnnotationType() {
-        return GuardCheck.class;
+        return null;
     }
 
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,6 +26,7 @@
 import java.util.*;
 
 import javax.lang.model.element.*;
+import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.codegen.processor.*;
@@ -40,21 +41,21 @@
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        TypeData targetType = findTypeByMethodName(method, mirror, "as");
+        TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as");
         if (targetType == null) {
             return null;
         }
         List<ParameterSpec> specs = new ArrayList<>();
         specs.add(new ParameterSpec("value", getTypeSystem(), false, Cardinality.ONE));
         ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetType.getPrimitiveType(), false);
-        MethodSpec spec = new MethodSpec(returnTypeSpec, specs);
+        MethodSpec spec = new MethodSpec(Collections.<TypeMirror> emptyList(), returnTypeSpec, specs);
         return spec;
     }
 
     @Override
     public TypeCastData create(TemplateMethod method) {
-        TypeData targetType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "as");
-        ActualParameter parameter = method.findParameter("value");
+        TypeData targetType = findTypeByMethodName(method, "as");
+        ActualParameter parameter = method.findParameter("valueValue");
         return new TypeCastData(method, parameter.getActualTypeData(getTypeSystem()), targetType);
     }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -26,6 +26,7 @@
 import java.util.*;
 
 import javax.lang.model.element.*;
+import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.codegen.processor.*;
@@ -40,22 +41,22 @@
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        TypeData targetType = findTypeByMethodName(method, mirror, "is");
+        TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is");
         if (targetType == null) {
             return null;
         }
         List<ParameterSpec> specs = new ArrayList<>();
         specs.add(new ParameterSpec("value", getTypeSystem(), false, Cardinality.ONE));
         ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), false);
-        MethodSpec spec = new MethodSpec(returnTypeSpec, specs);
+        MethodSpec spec = new MethodSpec(Collections.<TypeMirror> emptyList(), returnTypeSpec, specs);
         return spec;
     }
 
     @Override
     public TypeCheckData create(TemplateMethod method) {
-        TypeData checkedType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "is");
+        TypeData checkedType = findTypeByMethodName(method, "is");
         assert checkedType != null;
-        ActualParameter parameter = method.findParameter("value");
+        ActualParameter parameter = method.findParameter("valueValue");
         assert parameter != null;
         return new TypeCheckData(method, checkedType, parameter.getActualTypeData(getTypeSystem()));
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -30,21 +30,38 @@
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.template.*;
 
-public class TypeData extends Template {
+public class TypeData extends MessageContainer {
 
-    protected TypeSystemData typeSystem;
+    private final TypeSystemData typeSystem;
+    private final AnnotationValue annotationValue;
     private final TypeMirror primitiveType;
     private final TypeMirror boxedType;
 
     private final List<TypeCastData> typeCasts = new ArrayList<>();
     private final List<TypeCheckData> typeChecks = new ArrayList<>();
 
-    public TypeData(TypeElement templateType, AnnotationMirror annotation, TypeMirror primitiveType, TypeMirror boxedType) {
-        super(templateType, annotation);
+    public TypeData(TypeSystemData typeSystem, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) {
+        this.typeSystem = typeSystem;
+        this.annotationValue = value;
         this.primitiveType = primitiveType;
         this.boxedType = boxedType;
     }
 
+    @Override
+    public Element getMessageElement() {
+        return typeSystem.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return typeSystem.getMessageAnnotation();
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return annotationValue;
+    }
+
     void addTypeCast(TypeCastData typeCast) {
         this.typeCasts.add(typeCast);
     }
@@ -89,4 +106,8 @@
         return getClass().getSimpleName() + "[" + Utils.getSimpleName(primitiveType) + "]";
     }
 
+    public boolean equalsType(TypeData actualTypeData) {
+        return Utils.typeEquals(boxedType, actualTypeData.boxedType);
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java	Thu Mar 21 14:11:13 2013 +0100
@@ -41,15 +41,15 @@
     }
 
     public static String isTypeMethodName(TypeData type) {
-        return "is" + Utils.getSimpleName(type.getBoxedType());
+        return "is" + Utils.getTypeId(type.getBoxedType());
     }
 
     public static String asTypeMethodName(TypeData type) {
-        return "as" + Utils.getSimpleName(type.getBoxedType());
+        return "as" + Utils.getTypeId(type.getBoxedType());
     }
 
     public static String expectTypeMethodName(TypeData type) {
-        return "expect" + Utils.getSimpleName(type.getBoxedType());
+        return "expect" + Utils.getTypeId(type.getBoxedType());
     }
 
     /**
@@ -167,8 +167,8 @@
 
             CodeTreeBuilder builder = method.createBuilder();
             builder.startReturn();
-            if (typeSystem.getTypes().length > 0) {
-                builder.typeLiteral(typeSystem.getTypes()[0].getBoxedType());
+            if (!typeSystem.getTypes().isEmpty()) {
+                builder.typeLiteral(typeSystem.getTypes().get(0).getBoxedType());
             } else {
                 builder.null_();
             }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java	Thu Mar 21 14:11:13 2013 +0100
@@ -32,35 +32,42 @@
 
 public class TypeSystemData extends Template {
 
-    private final TypeData[] types;
-    private final TypeMirror[] primitiveTypeMirrors;
-    private final TypeMirror[] boxedTypeMirrors;
+    private List<TypeData> types;
+    private List<TypeMirror> primitiveTypeMirrors = new ArrayList<>();
+    private List<TypeMirror> boxedTypeMirrors = new ArrayList<>();
 
-    private final TypeMirror genericType;
+    private TypeMirror genericType;
+    private TypeData voidType;
+
+    public TypeSystemData(TypeElement templateType, AnnotationMirror annotation) {
+        super(templateType, null, annotation);
+    }
 
-    private final TypeData voidType;
+    void setTypes(List<TypeData> types) {
+        this.types = types;
+        if (types != null) {
+            for (TypeData typeData : types) {
+                primitiveTypeMirrors.add(typeData.getPrimitiveType());
+                boxedTypeMirrors.add(typeData.getBoxedType());
+            }
+        }
+    }
 
-    public TypeSystemData(TypeElement templateType, AnnotationMirror annotation, TypeData[] types, TypeMirror genericType, TypeData voidType) {
-        super(templateType, annotation);
-        this.types = types;
+    void setGenericType(TypeMirror genericType) {
         this.genericType = genericType;
+    }
+
+    void setVoidType(TypeData voidType) {
         this.voidType = voidType;
-        this.primitiveTypeMirrors = new TypeMirror[types.length];
-        for (int i = 0; i < types.length; i++) {
-            primitiveTypeMirrors[i] = types[i].getPrimitiveType();
-        }
+    }
 
-        this.boxedTypeMirrors = new TypeMirror[types.length];
-        for (int i = 0; i < types.length; i++) {
-            boxedTypeMirrors[i] = types[i].getBoxedType();
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> sinks = new ArrayList<>();
+        if (types != null) {
+            sinks.addAll(types);
         }
-
-        for (TypeData type : types) {
-            type.typeSystem = this;
-        }
-        if (voidType != null) {
-            voidType.typeSystem = this;
-        }
+        return sinks;
     }
 
     public boolean isGeneric(TypeMirror type) {
@@ -71,16 +78,16 @@
         return voidType;
     }
 
-    public TypeData[] getTypes() {
-        return types;
+    public List<TypeMirror> getBoxedTypeMirrors() {
+        return boxedTypeMirrors;
     }
 
-    public TypeMirror[] getPrimitiveTypeMirrors() {
+    public List<TypeMirror> getPrimitiveTypeMirrors() {
         return primitiveTypeMirrors;
     }
 
-    public TypeMirror[] getBoxedTypeMirrors() {
-        return boxedTypeMirrors;
+    public List<TypeData> getTypes() {
+        return types;
     }
 
     public TypeMirror getGenericType() {
@@ -88,7 +95,7 @@
     }
 
     public TypeData getGenericTypeData() {
-        TypeData result = types[types.length - 1];
+        TypeData result = types.get(types.size() - 1);
         assert result.getBoxedType() == genericType;
         return result;
     }
@@ -111,7 +118,7 @@
         if (index == -1) {
             return null;
         }
-        return types[index];
+        return types.get(index);
     }
 
     public int findType(TypeData typeData) {
@@ -119,8 +126,8 @@
     }
 
     public int findType(TypeMirror type) {
-        for (int i = 0; i < types.length; i++) {
-            if (Utils.typeEquals(types[i].getPrimitiveType(), type)) {
+        for (int i = 0; i < types.size(); i++) {
+            if (Utils.typeEquals(types.get(i).getPrimitiveType(), type)) {
                 return i;
             }
         }
@@ -129,7 +136,7 @@
 
     @Override
     public String toString() {
-        return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + Arrays.toString(types) + "]";
+        return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + types + "]";
     }
 
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -43,18 +43,24 @@
         return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
     }
 
-    protected TypeData findTypeByMethodName(ExecutableElement method, AnnotationMirror annotationMirror, String prefix) {
-        String methodName = method.getSimpleName().toString();
+    protected TypeData findTypeByMethodName(String methodName, String prefix) {
+        String typeName = methodName.substring(prefix.length(), methodName.length());
+        TypeData type = getTypeSystem().findType(typeName);
+        return type;
+    }
+
+    protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) {
+        String methodName = method.getMethodName();
         if (!methodName.startsWith(prefix)) {
-            String annotationName = Utils.getSimpleName(annotationMirror.getAnnotationType());
-            getContext().getLog().error(method, "Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix));
+            String annotationName = Utils.getSimpleName(method.getMessageAnnotation().getAnnotationType());
+            method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix));
             return null;
         }
         String typeName = methodName.substring(prefix.length(), methodName.length());
         TypeData type = getTypeSystem().findType(typeName);
         if (type == null) {
             String annotationName = TypeSystem.class.getSimpleName();
-            getContext().getLog().error(method, "Type '%s' is not declared in this @%s.", typeName, annotationName);
+            method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName);
             return null;
         }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -52,27 +52,39 @@
     protected TypeSystemData parse(Element element, AnnotationMirror mirror) {
         TypeElement templateType = (TypeElement) element;
         AnnotationMirror templateTypeAnnotation = mirror;
+        TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation);
 
-        if (!verifyTemplateType(templateType, templateTypeAnnotation)) {
-            return null;
+        // annotation type on class path!?
+        TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
+        if (annotationTypeElement == null) {
+            typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName());
+        }
+        if (templateType.getModifiers().contains(Modifier.PRIVATE)) {
+            typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName());
         }
 
-        TypeData[] types = parseTypes(templateType, templateTypeAnnotation);
-        if (types == null) {
-            return null;
+        if (templateType.getModifiers().contains(Modifier.FINAL)) {
+            typeSystem.addError("The @%s must not be final.", getAnnotationType().getName());
+        }
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+
+        typeSystem.setTypes(parseTypes(typeSystem));
+        if (typeSystem.getTypes() == null) {
+            return typeSystem;
         }
 
         TypeMirror genericType = context.getType(Object.class);
-        TypeData voidType = new TypeData(templateType, templateTypeAnnotation, context.getType(void.class), context.getType(Void.class));
-
-        TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation, types, genericType, voidType);
+        TypeData voidType = new TypeData(typeSystem, null, context.getType(void.class), context.getType(Void.class));
 
-        if (!verifyExclusiveMethodAnnotation(templateType, TypeCast.class, TypeCheck.class)) {
-            return null;
-        }
+        typeSystem.setGenericType(genericType);
+        typeSystem.setVoidType(voidType);
+
+        verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
 
         List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
-        typeSystem.setExtensionElements(getExtensionParser().parseAll(templateType, elements));
+        typeSystem.setExtensionElements(getExtensionParser().parseAll(typeSystem, elements));
         if (typeSystem.getExtensionElements() != null) {
             elements.addAll(typeSystem.getExtensionElements());
         }
@@ -81,7 +93,7 @@
         List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
 
         if (casts == null || checks == null) {
-            return null;
+            return typeSystem;
         }
 
         for (TypeCheckData check : checks) {
@@ -92,24 +104,15 @@
             cast.getTargetType().addTypeCast(cast);
         }
 
-        if (!verifyGenericTypeChecksAndCasts(types)) {
-            return null;
-        }
-
-        if (!verifyMethodSignatures(element, types)) {
-            return null;
-        }
-
-        if (!verifyNamesUnique(templateType, templateTypeAnnotation, types)) {
-            return null;
-        }
+        verifyGenericTypeChecksAndCasts(typeSystem);
+        verifyMethodSignatures(typeSystem);
+        verifyNamesUnique(typeSystem);
 
         return typeSystem;
     }
 
-    private boolean verifyGenericTypeChecksAndCasts(TypeData[] types) {
-        boolean valid = true;
-        for (TypeData type : types) {
+    private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) {
+        for (TypeData type : typeSystem.getTypes()) {
             if (!type.getTypeChecks().isEmpty()) {
                 boolean hasGeneric = false;
                 for (TypeCheckData typeCheck : type.getTypeChecks()) {
@@ -119,10 +122,9 @@
                     }
                 }
                 if (!hasGeneric) {
-                    log.error(type.getTypeSystem().getTemplateType(), "No generic but specific @%s method %s for type %s specified. "
-                                    + "Specify a generic @%s method with parameter type %s to resolve this.", TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type),
-                                    Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(), Object.class.getSimpleName());
-                    valid = false;
+                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
+                                    TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(),
+                                    Object.class.getSimpleName());
                 }
             }
             if (!type.getTypeCasts().isEmpty()) {
@@ -134,63 +136,55 @@
                     }
                 }
                 if (!hasGeneric) {
-                    log.error(type.getTypeSystem().getTemplateType(), "No generic but specific @%s method %s for type %s specified. "
-                                    + "Specify a generic @%s method with parameter type %s to resolve this.", TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type),
-                                    Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(), Object.class.getSimpleName());
-                    valid = false;
+                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
+                                    TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(),
+                                    Object.class.getSimpleName());
                 }
             }
         }
-        return valid;
     }
 
-    private TypeData[] parseTypes(TypeElement templateType, AnnotationMirror templateTypeAnnotation) {
-        List<TypeMirror> typeMirrors = Utils.getAnnotationValueList(templateTypeAnnotation, "value");
-        if (typeMirrors.size() == 0) {
-            log.error(templateType, templateTypeAnnotation, "At least one type must be defined.");
-            return null;
+    private List<TypeData> parseTypes(TypeSystemData typeSystem) {
+        List<TypeData> types = new ArrayList<>();
+        List<TypeMirror> typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value");
+        if (typeMirrors.isEmpty()) {
+            typeSystem.addError("At least one type must be defined.");
+            return types;
         }
 
-        final AnnotationValue annotationValue = Utils.getAnnotationValue(templateTypeAnnotation, "value");
+        final AnnotationValue annotationValue = Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value");
         final TypeMirror objectType = context.getType(Object.class);
 
-        List<TypeData> types = new ArrayList<>();
         for (TypeMirror primitiveType : typeMirrors) {
+            TypeMirror boxedType = Utils.boxType(context, primitiveType);
+            TypeData typeData = new TypeData(typeSystem, annotationValue, primitiveType, boxedType);
 
             if (isPrimitiveWrapper(primitiveType)) {
-                log.error(templateType, templateTypeAnnotation, annotationValue, "Types must not contain primitive wrapper types.");
-                continue;
-            }
-
-            TypeMirror boxedType = primitiveType;
-            if (boxedType.getKind().isPrimitive()) {
-                boxedType = processingEnv.getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
+                typeData.addError("Types must not contain primitive wrapper types.");
             }
 
             if (Utils.typeEquals(boxedType, objectType)) {
-                log.error(templateType, templateTypeAnnotation, annotationValue, "Types must not contain the generic type java.lang.Object.");
-                continue;
+                typeData.addError("Types must not contain the generic type java.lang.Object.");
             }
 
-            types.add(new TypeData(templateType, templateTypeAnnotation, primitiveType, boxedType));
+            types.add(typeData);
         }
 
-        verifyTypeOrder(templateType, templateTypeAnnotation, annotationValue, types);
+        verifyTypeOrder(types);
 
-        types.add(new TypeData(templateType, templateTypeAnnotation, objectType, objectType));
+        types.add(new TypeData(typeSystem, annotationValue, objectType, objectType));
 
-        return types.toArray(new TypeData[types.size()]);
+        return types;
     }
 
-    private void verifyTypeOrder(TypeElement templateType, AnnotationMirror templateTypeAnnotation, AnnotationValue annotationValue, List<TypeData> types) {
+    private static void verifyTypeOrder(List<TypeData> types) {
         Map<String, List<String>> invalidTypes = new HashMap<>();
 
         for (int i = types.size() - 1; i >= 0; i--) {
             TypeData typeData = types.get(i);
             TypeMirror type = typeData.getBoxedType();
             if (invalidTypes.containsKey(Utils.getQualifiedName(type))) {
-                log.error(templateType, templateTypeAnnotation, annotationValue, "Invalid type order. The type(s) %s are inherited from a earlier defined type %s.",
-                                invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type));
+                typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type));
             }
             List<String> nextInvalidTypes = Utils.getQualifiedSuperTypeNames(Utils.fromTypeMirror(type));
             nextInvalidTypes.add(getQualifiedName(type));
@@ -219,19 +213,18 @@
         return false;
     }
 
-    private boolean verifyMethodSignatures(Element element, TypeData[] types) {
+    private void verifyMethodSignatures(TypeSystemData typeSystem) {
         Set<String> generatedIsMethodNames = new HashSet<>();
         Set<String> generatedAsMethodNames = new HashSet<>();
         Set<String> generatedExpectMethodNames = new HashSet<>();
 
-        for (TypeData typeData : types) {
+        for (TypeData typeData : typeSystem.getTypes()) {
             generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData));
             generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData));
             generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData));
         }
 
-        boolean valid = true;
-        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
+        List<ExecutableElement> methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements());
         for (ExecutableElement method : methods) {
             if (method.getModifiers().contains(Modifier.PRIVATE)) {
                 // will not conflict overridden methods
@@ -241,51 +234,48 @@
             }
             String methodName = method.getSimpleName().toString();
             if (generatedIsMethodNames.contains(methodName)) {
-                valid &= verifyIsMethod(method);
+                verifyIsMethod(typeSystem, method);
             } else if (generatedAsMethodNames.contains(methodName)) {
-                valid &= verifyAsMethod(method);
+                verifyAsMethod(typeSystem, method);
             } else if (generatedExpectMethodNames.contains(methodName)) {
-                valid &= verifyExpectMethod(method);
+                verifyExpectMethod(typeSystem);
             }
         }
-        return valid;
     }
 
-    private boolean verifyIsMethod(ExecutableElement method) {
+    private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) {
         AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class);
         if (mirror == null) {
-            log.error(method, "Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName());
+            typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName());
             return false;
         }
         return true;
     }
 
-    private boolean verifyAsMethod(ExecutableElement method) {
+    private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) {
         AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class);
         if (mirror == null) {
-            log.error(method, "Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName());
+            typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName());
             return false;
         }
         return true;
     }
 
-    private boolean verifyExpectMethod(ExecutableElement method) {
-        log.error(method, "Method starting with the pattern expect${typeName} must not be declared manually.");
+    private static boolean verifyExpectMethod(TypeSystemData typeSystem) {
+        typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually.");
         return false;
     }
 
-    private boolean verifyNamesUnique(TypeElement templateType, AnnotationMirror templateTypeAnnotation, TypeData[] types) {
-        boolean valid = true;
-        for (int i = 0; i < types.length; i++) {
-            for (int j = i + 1; j < types.length; j++) {
-                String name1 = Utils.getSimpleName(types[i].getBoxedType());
-                String name2 = Utils.getSimpleName(types[j].getBoxedType());
+    private static void verifyNamesUnique(TypeSystemData typeSystem) {
+        List<TypeData> types = typeSystem.getTypes();
+        for (int i = 0; i < types.size(); i++) {
+            for (int j = i + 1; j < types.size(); j++) {
+                String name1 = Utils.getSimpleName(types.get(i).getBoxedType());
+                String name2 = Utils.getSimpleName(types.get(j).getBoxedType());
                 if (name1.equalsIgnoreCase(name2)) {
-                    log.error(templateType, templateTypeAnnotation, "Two types result in the same name: %s, %s.", name1, name2);
-                    valid = false;
+                    typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2);
                 }
             }
         }
-        return valid;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/TernaryTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test;
+
+import org.junit.*;
+
+// @formatter:off
+public class TernaryTest extends AbstractTest {
+
+    private static String[] INPUT = new String[] {
+"function main {  " +
+"  print #(1 < 2) ? 1 : 2;" +
+"  print #(2 < 1) ? 100000000000000 : 1;  ",
+"  print #(1 < 2) ? 100000000000000 : 1;  ",
+"  print #(2 < 1) ? \"wrong\" : \"true\";",
+"  print #(2 < 1) ? \"wrong\" : 1;",
+"}  ",
+    };
+
+    private static String[] OUTPUT = new String[] {
+        "1",
+        "1",
+        "100000000000000",
+        "true",
+        "1",
+    };
+
+    @Test
+    public void test() {
+        executeSL(INPUT, OUTPUT, true);
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java	Thu Mar 21 14:11:13 2013 +0100
@@ -27,8 +27,11 @@
 import java.util.*;
 
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.AddNodeFactory;
+import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.DivNodeFactory;
+import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.MulNodeFactory;
+import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.SubNodeFactory;
 import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.*;
 
 public class NodeFactory {
 
@@ -127,4 +130,8 @@
         StatementNode write = WriteLocalNodeFactory.create(slot, value);
         return new ReturnNode(write);
     }
+
+    public TypedNode createTernary(TypedNode condition, TypedNode thenPart, TypedNode elsePart) {
+        return TernaryNodeFactory.create(condition, thenPart, elsePart);
+    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java	Thu Mar 21 14:11:13 2013 +0100
@@ -41,7 +41,7 @@
             return (int) value;
         } else {
             int result = ((BigInteger) value).intValue();
-            assert BigInteger.valueOf(result).equals(value) : "Loosing precision";
+            assert BigInteger.valueOf(result).equals(value) : "Losing precision";
             return result;
         }
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -37,11 +37,6 @@
         super(node);
     }
 
-    @Generic
-    public Object doGeneric(Object left, Object right) {
-        throw new RuntimeException("Arithmetic not defined for types " + left.getClass().getSimpleName() + ", " + right.getClass().getSimpleName());
-    }
-
     public abstract static class AddNode extends ArithmeticNode {
 
         public AddNode(TypedNode left, TypedNode right) {
@@ -52,9 +47,8 @@
             super(node);
         }
 
-        @Specialization
-        @SpecializationThrows(javaClass = ArithmeticException.class, transitionTo = "doBigInteger")
-        int doInteger(int left, int right) {
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int doInt(int left, int right) {
             return ExactMath.addExact(left, right);
         }
 
@@ -64,13 +58,12 @@
         }
 
         @Specialization
-        String doStringDirect(String left, String right) {
+        String doString(String left, String right) {
             return left + right;
         }
 
-        @Specialization
-        @SpecializationGuard(methodName = "isString")
-        String doString(Object left, Object right) {
+        @Specialization(guards = "isString")
+        String add(Object left, Object right) {
             return left.toString() + right.toString();
         }
     }
@@ -85,16 +78,16 @@
             super(node);
         }
 
-        @Specialization
-        @SpecializationThrows(javaClass = ArithmeticException.class, transitionTo = "doBigInteger")
-        int doInteger(int left, int right) {
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int sub(int left, int right) {
             return ExactMath.subtractExact(left, right);
         }
 
         @Specialization
-        BigInteger doBigInteger(BigInteger left, BigInteger right) {
+        BigInteger sub(BigInteger left, BigInteger right) {
             return left.subtract(right);
         }
+
     }
 
     public abstract static class DivNode extends ArithmeticNode {
@@ -107,14 +100,13 @@
             super(node);
         }
 
-        @Specialization
-        @SpecializationThrows(javaClass = ArithmeticException.class, transitionTo = "doBigInteger")
-        int doInteger(int left, int right) {
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int div(int left, int right) {
             return left / right;
         }
 
         @Specialization
-        BigInteger doBigInteger(BigInteger left, BigInteger right) {
+        BigInteger div(BigInteger left, BigInteger right) {
             return left.divide(right);
         }
     }
@@ -129,16 +121,16 @@
             super(node);
         }
 
-        @Specialization
-        @SpecializationThrows(javaClass = ArithmeticException.class, transitionTo = "doBigInteger")
-        int doInteger(int left, int right) {
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int mul(int left, int right) {
             return ExactMath.multiplyExact(left, right);
         }
 
         @Specialization
-        BigInteger doBigInteger(BigInteger left, BigInteger right) {
+        BigInteger mul(BigInteger left, BigInteger right) {
             return left.multiply(right);
         }
+
     }
 
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionalNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes;
-
-import java.math.*;
-
-import com.oracle.truffle.api.codegen.*;
-
-@SuppressWarnings("unused")
-@ExecuteChildren({"conditionNode", "ifPartNode", "elsePartNode"})
-public abstract class ConditionalNode extends TypedNode {
-
-    @Child protected ConditionNode conditionNode;
-
-    @Child protected TypedNode ifPartNode;
-
-    @Child protected TypedNode elsePartNode;
-
-    public ConditionalNode(ConditionNode condition, TypedNode ifPart, TypedNode elsePart) {
-        this.conditionNode = adoptChild(condition);
-        this.ifPartNode = adoptChild(ifPart);
-        this.elsePartNode = adoptChild(elsePart);
-    }
-
-    public ConditionalNode(ConditionalNode condition) {
-        this(condition.conditionNode, condition.ifPartNode, condition.elsePartNode);
-    }
-
-    @ShortCircuit("ifPartNode")
-    public boolean needsIfPart(boolean condition) {
-        return condition;
-    }
-
-    @ShortCircuit("ifPartNode")
-    public boolean needsIfPart(Object condition) {
-        throw new RuntimeException("operation not defined for type " + condition.getClass().getSimpleName());
-    }
-
-    @ShortCircuit("elsePartNode")
-    public boolean needsElsePart(Object condition, boolean hasIfPart, Object ifPart) {
-        return !hasIfPart;
-    }
-
-    @ShortCircuit("elsePartNode")
-    public boolean needsElsePart(boolean condition, boolean hasIfPart, int ifPart) {
-        return !hasIfPart;
-    }
-
-    @ShortCircuit("elsePartNode")
-    public boolean needsElsePart(boolean condition, boolean hasIfPart, BigInteger ifPart) {
-        return !hasIfPart;
-    }
-
-    @Specialization
-    public int doInteger(boolean condition, boolean hasIfPart, int ifPart, boolean hasElsePart, int elsePart) {
-        return hasIfPart ? ifPart : elsePart;
-    }
-
-    @Specialization
-    public BigInteger doBigInteger(boolean condition, boolean hasIfPart, BigInteger ifPart, boolean hasElsePart, BigInteger elsePart) {
-        return hasIfPart ? ifPart : elsePart;
-    }
-
-    @Generic
-    public Object doGeneric(boolean condition, boolean hasIfPart, Object ifPart, boolean hasElsePart, Object elsePart) {
-        return hasIfPart ? ifPart : elsePart;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -46,8 +46,7 @@
         return left.compareTo(right) < 0;
     }
 
-    @Specialization
-    @SpecializationGuard(methodName = "isString")
+    @Specialization(guards = "isString")
     public boolean doString(Object left, Object right) {
         return left.toString().compareTo(right.toString()) < 0;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import java.math.*;
+
+import com.oracle.truffle.api.codegen.*;
+
+@SuppressWarnings("unused")
+@ExecuteChildren({"conditionNode", "ifPartNode", "elsePartNode"})
+public abstract class TernaryNode extends TypedNode {
+
+    @Child protected ConditionNode conditionNode;
+
+    @Child protected TypedNode ifPartNode;
+
+    @Child protected TypedNode elsePartNode;
+
+    public TernaryNode(ConditionNode condition, TypedNode ifPart, TypedNode elsePart) {
+        this.conditionNode = adoptChild(condition);
+        this.ifPartNode = adoptChild(ifPart);
+        this.elsePartNode = adoptChild(elsePart);
+    }
+
+    public TernaryNode(TernaryNode condition) {
+        this(condition.conditionNode, condition.ifPartNode, condition.elsePartNode);
+    }
+
+    @ShortCircuit("ifPartNode")
+    public boolean needsIfPart(boolean condition) {
+        return condition;
+    }
+
+    @ShortCircuit("elsePartNode")
+    public boolean needsElsePart(boolean condition, boolean hasIfPart, Object ifPart) {
+        return !hasIfPart;
+    }
+
+    @Specialization
+    public int doInteger(boolean condition, boolean hasIfPart, int ifPart, boolean hasElsePart, int elsePart) {
+        return hasIfPart ? ifPart : elsePart;
+    }
+
+    @Specialization
+    public BigInteger doBigInteger(boolean condition, boolean hasIfPart, BigInteger ifPart, boolean hasElsePart, BigInteger elsePart) {
+        return hasIfPart ? ifPart : elsePart;
+    }
+
+    @Generic
+    public Object doGeneric(boolean condition, boolean hasIfPart, Object ifPart, boolean hasElsePart, Object elsePart) {
+        return hasIfPart ? ifPart : elsePart;
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,7 +24,6 @@
 
 import java.math.*;
 
-import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
@@ -49,7 +48,6 @@
 
     public abstract Object executeGeneric(VirtualFrame frame);
 
-    @GuardCheck
     public boolean isString(Object a, Object b) {
         return a instanceof String || b instanceof String;
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -41,31 +41,31 @@
     }
 
     @Specialization
-    public int doInteger(VirtualFrame frame, int right) {
+    public int write(VirtualFrame frame, int right) {
         frame.setInt(slot, right);
         return right;
     }
 
     @Specialization
-    public BigInteger doBigInteger(VirtualFrame frame, BigInteger right) {
+    public BigInteger write(VirtualFrame frame, BigInteger right) {
         frame.setObject(slot, right);
         return right;
     }
 
     @Specialization
-    public boolean doBoolean(VirtualFrame frame, boolean right) {
+    public boolean write(VirtualFrame frame, boolean right) {
         frame.setBoolean(slot, right);
         return right;
     }
 
     @Specialization
-    public String doString(VirtualFrame frame, String right) {
+    public String write(VirtualFrame frame, String right) {
         frame.setObject(slot, right);
         return right;
     }
 
-    @Generic
-    public Object doGeneric(VirtualFrame frame, Object right) {
+    @Generic(useSpecializations = false)
+    public Object writeGeneric(VirtualFrame frame, Object right) {
         frame.setObject(slot, right);
         return right;
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Thu Mar 21 14:11:13 2013 +0100
@@ -21,10 +21,9 @@
  * questions.
  */
 
-// The content of this file is automatically generated. DO NOT EDIT.
+ // The content of this file is automatically generated. DO NOT EDIT.
 
 package com.oracle.truffle.sl.parser;
-
 import java.util.*;
 
 import com.oracle.truffle.sl.*;
@@ -33,11 +32,11 @@
 // Checkstyle: stop
 // @formatter:off
 public class Parser {
-	public static final int _EOF = 0;
-	public static final int _identifier = 1;
-	public static final int _stringLiteral = 2;
-	public static final int _numericLiteral = 3;
-	public static final int maxT = 25;
+	public static final int _EOF = 0;
+	public static final int _identifier = 1;
+	public static final int _stringLiteral = 2;
+	public static final int _numericLiteral = 3;
+	public static final int maxT = 28;
 
     static final boolean T = true;
     static final boolean x = false;
@@ -50,7 +49,7 @@
     public final Scanner scanner;
     public final Errors errors;
     private final NodeFactory factory;
-
+    
     public Parser(Scanner scanner, NodeFactory factory) {
         this.scanner = scanner;
         this.factory = factory;
@@ -121,226 +120,255 @@
         }
     }
 
-	void SimpleLanguage() {
-		Function();
-		while (la.kind == 4) {
-			Function();
-		}
-	}
-
-	void Function() {
-		Expect(4);
-		factory.startFunction();
-		Expect(1);
-		String name = t.val;
-		StatementNode body = Block();
-		factory.createFunction(body, name);
-	}
-
-	StatementNode  Block() {
-		StatementNode  result;
-		List<StatementNode> statements = new ArrayList<>();
-		Expect(5);
-		while (StartOf(1)) {
-			StatementNode statement = Statement();
-			statements.add(statement);
-		}
-		Expect(6);
-		result = factory.createBlock(statements);
-		return result;
-	}
-
-	StatementNode  Statement() {
-		StatementNode  result;
-		result = null;
-		if (la.kind == 7) {
-			result = WhileStatement();
-		} else if (la.kind == 1) {
-			result = AssignmentStatement();
-		} else if (la.kind == 12) {
-			result = OutputStatement();
-		} else if (la.kind == 13) {
-			result = ReturnStatement();
-		} else SynErr(26);
-		return result;
-	}
-
-	StatementNode  WhileStatement() {
-		StatementNode  result;
-		Expect(7);
-		Expect(8);
-		ConditionNode condition = Expression();
-		Expect(9);
-		StatementNode body = Block();
-		result = factory.createWhile(condition, body);
-		return result;
-	}
-
-	StatementNode  AssignmentStatement() {
-		StatementNode  result;
-		Expect(1);
-		String name = t.val;
-		Expect(10);
-		TypedNode rvalue = Expression();
-		Expect(11);
-		result = factory.createAssignment(name, rvalue);
-		return result;
-	}
-
-	StatementNode  OutputStatement() {
-		StatementNode  result;
-		List<TypedNode> expressions = new ArrayList<>();
-		Expect(12);
-		while (StartOf(2)) {
-			TypedNode value = Expression();
-			expressions.add(value);
-		}
-		Expect(11);
-		result = factory.createPrint(expressions);
-		return result;
-	}
-
-	StatementNode  ReturnStatement() {
-		StatementNode  result;
-		Expect(13);
-		TypedNode value = Expression();
-		Expect(11);
-		result = factory.createReturn(value);
-		return result;
-	}
-
-	TypedNode  Expression() {
-		TypedNode  result;
-		result = ValueExpression();
-		if (StartOf(3)) {
-			switch (la.kind) {
-			case 14: {
-				Get();
-				break;
-			}
-			case 15: {
-				Get();
-				break;
-			}
-			case 16: {
-				Get();
-				break;
-			}
-			case 17: {
-				Get();
-				break;
-			}
-			case 18: {
-				Get();
-				break;
-			}
-			case 19: {
-				Get();
-				break;
-			}
-			}
-			String op = t.val;
-			TypedNode right = ValueExpression();
-			result = factory.createBinary(op, result, right);
-		}
-		return result;
-	}
-
-	TypedNode  ValueExpression() {
-		TypedNode  result;
-		result = Term();
-		while (la.kind == 20 || la.kind == 21) {
-			if (la.kind == 20) {
-				Get();
-			} else {
-				Get();
-			}
-			String op = t.val;
-			TypedNode right = Term();
-			result = factory.createBinary(op, result, right);
-		}
-		return result;
-	}
-
-	TypedNode  Term() {
-		TypedNode  result;
-		result = Factor();
-		while (la.kind == 22 || la.kind == 23) {
-			if (la.kind == 22) {
-				Get();
-			} else {
-				Get();
-			}
-			String op = t.val;
-			TypedNode right = Factor();
-			result = factory.createBinary(op, result, right);
-		}
-		return result;
-	}
-
-	TypedNode  Factor() {
-		TypedNode  result;
-		result = null;
-		if (la.kind == 24) {
-			result = TimeRef();
-		} else if (la.kind == 1) {
-			result = VariableRef();
-		} else if (la.kind == 2) {
-			result = StringLiteral();
-		} else if (la.kind == 3) {
-			result = NumericLiteral();
-		} else if (la.kind == 8) {
-			Get();
-			result = Expression();
-			Expect(9);
-		} else SynErr(27);
-		return result;
-	}
-
-	TypedNode  TimeRef() {
-		TypedNode  result;
-		Expect(24);
-		result = factory.createTime();
-		return result;
-	}
-
-	TypedNode  VariableRef() {
-		TypedNode  result;
-		Expect(1);
-		result = factory.createLocal(t.val);
-		return result;
-	}
-
-	TypedNode  StringLiteral() {
-		TypedNode  result;
-		Expect(2);
-		result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1));
-		return result;
-	}
-
-	TypedNode  NumericLiteral() {
-		TypedNode  result;
-		Expect(3);
-		result = factory.createNumericLiteral(t.val);
-		return result;
-	}
-
+	void SimpleLanguage() {
+		Function();
+		while (la.kind == 4) {
+			Function();
+		}
+	}
+
+	void Function() {
+		Expect(4);
+		factory.startFunction(); 
+		Expect(1);
+		String name = t.val; 
+		StatementNode body = Block();
+		factory.createFunction(body, name); 
+	}
+
+	StatementNode  Block() {
+		StatementNode  result;
+		List<StatementNode> statements = new ArrayList<>(); 
+		Expect(5);
+		while (StartOf(1)) {
+			StatementNode statement = Statement();
+			statements.add(statement); 
+		}
+		Expect(6);
+		result = factory.createBlock(statements); 
+		return result;
+	}
+
+	StatementNode  Statement() {
+		StatementNode  result;
+		result = null; 
+		if (la.kind == 7) {
+			result = WhileStatement();
+		} else if (la.kind == 1) {
+			result = AssignmentStatement();
+		} else if (la.kind == 12) {
+			result = OutputStatement();
+		} else if (la.kind == 13) {
+			result = ReturnStatement();
+		} else SynErr(29);
+		return result;
+	}
+
+	StatementNode  WhileStatement() {
+		StatementNode  result;
+		Expect(7);
+		Expect(8);
+		ConditionNode condition = Expression();
+		Expect(9);
+		StatementNode body = Block();
+		result = factory.createWhile(condition, body); 
+		return result;
+	}
+
+	StatementNode  AssignmentStatement() {
+		StatementNode  result;
+		Expect(1);
+		String name = t.val; 
+		Expect(10);
+		TypedNode rvalue = Expression();
+		Expect(11);
+		result = factory.createAssignment(name, rvalue); 
+		return result;
+	}
+
+	StatementNode  OutputStatement() {
+		StatementNode  result;
+		List<TypedNode> expressions = new ArrayList<>(); 
+		Expect(12);
+		while (StartOf(2)) {
+			TypedNode value = Expression();
+			expressions.add(value); 
+		}
+		Expect(11);
+		result = factory.createPrint(expressions); 
+		return result;
+	}
+
+	StatementNode  ReturnStatement() {
+		StatementNode  result;
+		Expect(13);
+		TypedNode value = Expression();
+		Expect(11);
+		result = factory.createReturn(value); 
+		return result;
+	}
+
+	TypedNode  Expression() {
+		TypedNode  result;
+		result = ValueExpression();
+		if (StartOf(3)) {
+			switch (la.kind) {
+			case 14: {
+				Get();
+				break;
+			}
+			case 15: {
+				Get();
+				break;
+			}
+			case 16: {
+				Get();
+				break;
+			}
+			case 17: {
+				Get();
+				break;
+			}
+			case 18: {
+				Get();
+				break;
+			}
+			case 19: {
+				Get();
+				break;
+			}
+			}
+			String op = t.val; 
+			TypedNode right = ValueExpression();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  ValueExpression() {
+		TypedNode  result;
+		result = Term();
+		while (la.kind == 20 || la.kind == 21) {
+			if (la.kind == 20) {
+				Get();
+			} else {
+				Get();
+			}
+			String op = t.val; 
+			TypedNode right = Term();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  Term() {
+		TypedNode  result;
+		result = Factor();
+		while (la.kind == 22 || la.kind == 23) {
+			if (la.kind == 22) {
+				Get();
+			} else {
+				Get();
+			}
+			String op = t.val; 
+			TypedNode right = Factor();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  Factor() {
+		TypedNode  result;
+		result = null; 
+		switch (la.kind) {
+		case 27: {
+			result = TimeRef();
+			break;
+		}
+		case 1: {
+			result = VariableRef();
+			break;
+		}
+		case 2: {
+			result = StringLiteral();
+			break;
+		}
+		case 3: {
+			result = NumericLiteral();
+			break;
+		}
+		case 24: {
+			result = Ternary();
+			break;
+		}
+		case 8: {
+			Get();
+			result = Expression();
+			Expect(9);
+			break;
+		}
+		default: SynErr(30); break;
+		}
+		return result;
+	}
+
+	TypedNode  TimeRef() {
+		TypedNode  result;
+		Expect(27);
+		result = factory.createTime(); 
+		return result;
+	}
+
+	TypedNode  VariableRef() {
+		TypedNode  result;
+		Expect(1);
+		result = factory.createLocal(t.val); 
+		return result;
+	}
+
+	TypedNode  StringLiteral() {
+		TypedNode  result;
+		Expect(2);
+		result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); 
+		return result;
+	}
+
+	TypedNode  NumericLiteral() {
+		TypedNode  result;
+		Expect(3);
+		result = factory.createNumericLiteral(t.val); 
+		return result;
+	}
+
+	TypedNode  Ternary() {
+		TypedNode  result;
+		TypedNode condition, thenPart, elsePart; 
+		Expect(24);
+		condition = Expression();
+		Expect(25);
+		thenPart = Expression();
+		Expect(26);
+		elsePart = Expression();
+		result = factory.createTernary(condition, thenPart, elsePart); 
+		return result;
+	}
+
 
 
     public void Parse() {
         la = new Token();
         la.val = "";
         Get();
-		SimpleLanguage();
-		Expect(0);
+		SimpleLanguage();
+		Expect(0);
 
     }
 
     private static final boolean[][] set = {
-		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
-		{x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x},
-		{x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x},
-		{x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x}
+		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+		{x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
+		{x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,T, x,x},
+		{x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x}
 
     };
 
@@ -388,35 +416,38 @@
 
     public void SynErr(int line, int col, int n) {
         String s;
-        switch (n) {
-			case 0: s = "EOF expected"; break;
-			case 1: s = "identifier expected"; break;
-			case 2: s = "stringLiteral expected"; break;
-			case 3: s = "numericLiteral expected"; break;
-			case 4: s = "\"function\" expected"; break;
-			case 5: s = "\"{\" expected"; break;
-			case 6: s = "\"}\" expected"; break;
-			case 7: s = "\"while\" expected"; break;
-			case 8: s = "\"(\" expected"; break;
-			case 9: s = "\")\" expected"; break;
-			case 10: s = "\"=\" expected"; break;
-			case 11: s = "\";\" expected"; break;
-			case 12: s = "\"print\" expected"; break;
-			case 13: s = "\"return\" expected"; break;
-			case 14: s = "\"<\" expected"; break;
-			case 15: s = "\">\" expected"; break;
-			case 16: s = "\"<=\" expected"; break;
-			case 17: s = "\">=\" expected"; break;
-			case 18: s = "\"==\" expected"; break;
-			case 19: s = "\"!=\" expected"; break;
-			case 20: s = "\"+\" expected"; break;
-			case 21: s = "\"-\" expected"; break;
-			case 22: s = "\"*\" expected"; break;
-			case 23: s = "\"/\" expected"; break;
-			case 24: s = "\"time\" expected"; break;
-			case 25: s = "??? expected"; break;
-			case 26: s = "invalid Statement"; break;
-			case 27: s = "invalid Factor"; break;
+        switch (n) {
+			case 0: s = "EOF expected"; break;
+			case 1: s = "identifier expected"; break;
+			case 2: s = "stringLiteral expected"; break;
+			case 3: s = "numericLiteral expected"; break;
+			case 4: s = "\"function\" expected"; break;
+			case 5: s = "\"{\" expected"; break;
+			case 6: s = "\"}\" expected"; break;
+			case 7: s = "\"while\" expected"; break;
+			case 8: s = "\"(\" expected"; break;
+			case 9: s = "\")\" expected"; break;
+			case 10: s = "\"=\" expected"; break;
+			case 11: s = "\";\" expected"; break;
+			case 12: s = "\"print\" expected"; break;
+			case 13: s = "\"return\" expected"; break;
+			case 14: s = "\"<\" expected"; break;
+			case 15: s = "\">\" expected"; break;
+			case 16: s = "\"<=\" expected"; break;
+			case 17: s = "\">=\" expected"; break;
+			case 18: s = "\"==\" expected"; break;
+			case 19: s = "\"!=\" expected"; break;
+			case 20: s = "\"+\" expected"; break;
+			case 21: s = "\"-\" expected"; break;
+			case 22: s = "\"*\" expected"; break;
+			case 23: s = "\"/\" expected"; break;
+			case 24: s = "\"#\" expected"; break;
+			case 25: s = "\"?\" expected"; break;
+			case 26: s = "\":\" expected"; break;
+			case 27: s = "\"time\" expected"; break;
+			case 28: s = "??? expected"; break;
+			case 29: s = "invalid Statement"; break;
+			case 30: s = "invalid Factor"; break;
             default:
                 s = "error " + n;
                 break;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Thu Mar 21 14:11:13 2013 +0100
@@ -311,8 +311,8 @@
 
     static final char EOL = '\n';
     static final int eofSym = 0;
-	static final int maxT = 25;
-	static final int noSym = 25;
+	static final int maxT = 28;
+	static final int noSym = 28;
 
 
     public Buffer buffer; // scanner buffer
@@ -339,27 +339,30 @@
 		for (int i = 65; i <= 90; ++i) start.set(i, 1);
 		for (int i = 97; i <= 122; ++i) start.set(i, 1);
 		for (int i = 49; i <= 57; ++i) start.set(i, 4);
-		start.set(34, 2);
-		start.set(48, 5);
-		start.set(123, 6);
-		start.set(125, 7);
-		start.set(40, 8);
-		start.set(41, 9);
-		start.set(61, 20);
-		start.set(59, 10);
-		start.set(60, 21);
-		start.set(62, 22);
-		start.set(33, 14);
-		start.set(43, 16);
-		start.set(45, 17);
-		start.set(42, 18);
-		start.set(47, 19);
+		start.set(34, 2); 
+		start.set(48, 5); 
+		start.set(123, 6); 
+		start.set(125, 7); 
+		start.set(40, 8); 
+		start.set(41, 9); 
+		start.set(61, 23); 
+		start.set(59, 10); 
+		start.set(60, 24); 
+		start.set(62, 25); 
+		start.set(33, 14); 
+		start.set(43, 16); 
+		start.set(45, 17); 
+		start.set(42, 18); 
+		start.set(47, 19); 
+		start.set(35, 20); 
+		start.set(63, 21); 
+		start.set(58, 22); 
 		start.set(Buffer.EOF, -1);
 		literals.put("function", new Integer(4));
 		literals.put("while", new Integer(7));
 		literals.put("print", new Integer(12));
 		literals.put("return", new Integer(13));
-		literals.put("time", new Integer(24));
+		literals.put("time", new Integer(27));
 
     }
 
@@ -425,7 +428,7 @@
             tval = newBuf;
         }
         if (ch != Buffer.EOF) {
-			tval[tlen++] = (char)ch;
+			tval[tlen++] = (char)ch; 
 
             NextCh();
         }
@@ -484,9 +487,9 @@
     }
 
     Token NextToken() {
-        while (ch == ' ' ||
+        while (ch == ' ' || 
 			ch >= 9 && ch <= 10 || ch == 13
-		) NextCh();
+        ) NextCh();
 		if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken();
         int recKind = noSym;
         int recEnd = pos;
@@ -515,60 +518,66 @@
                 } // NextCh already done
 				case 1:
 					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
+					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
 					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
 				case 2:
-					if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;}
-					else if (ch == '"') {AddCh(); state = 3; break;}
+					if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;}
+					else if (ch == '"') {AddCh(); state = 3; break;}
 					else {state = 0; break;}
-				case 3:
+				case 3:
 					{t.kind = 2; break loop;}
 				case 4:
 					recEnd = pos; recKind = 3;
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
+					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
 					else {t.kind = 3; break loop;}
-				case 5:
+				case 5:
 					{t.kind = 3; break loop;}
-				case 6:
+				case 6:
 					{t.kind = 5; break loop;}
-				case 7:
+				case 7:
 					{t.kind = 6; break loop;}
-				case 8:
+				case 8:
 					{t.kind = 8; break loop;}
-				case 9:
+				case 9:
 					{t.kind = 9; break loop;}
-				case 10:
+				case 10:
 					{t.kind = 11; break loop;}
-				case 11:
+				case 11:
 					{t.kind = 16; break loop;}
-				case 12:
+				case 12:
 					{t.kind = 17; break loop;}
-				case 13:
+				case 13:
 					{t.kind = 18; break loop;}
 				case 14:
-					if (ch == '=') {AddCh(); state = 15; break;}
+					if (ch == '=') {AddCh(); state = 15; break;}
 					else {state = 0; break;}
-				case 15:
+				case 15:
 					{t.kind = 19; break loop;}
-				case 16:
+				case 16:
 					{t.kind = 20; break loop;}
-				case 17:
+				case 17:
 					{t.kind = 21; break loop;}
-				case 18:
+				case 18:
 					{t.kind = 22; break loop;}
-				case 19:
+				case 19:
 					{t.kind = 23; break loop;}
-				case 20:
+				case 20:
+					{t.kind = 24; break loop;}
+				case 21:
+					{t.kind = 25; break loop;}
+				case 22:
+					{t.kind = 26; break loop;}
+				case 23:
 					recEnd = pos; recKind = 10;
-					if (ch == '=') {AddCh(); state = 13; break;}
+					if (ch == '=') {AddCh(); state = 13; break;}
 					else {t.kind = 10; break loop;}
-				case 21:
+				case 24:
 					recEnd = pos; recKind = 14;
-					if (ch == '=') {AddCh(); state = 11; break;}
+					if (ch == '=') {AddCh(); state = 11; break;}
 					else {t.kind = 14; break loop;}
-				case 22:
+				case 25:
 					recEnd = pos; recKind = 15;
-					if (ch == '=') {AddCh(); state = 12; break;}
+					if (ch == '=') {AddCh(); state = 12; break;}
 					else {t.kind = 15; break loop;}
 
             }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Thu Mar 21 11:30:38 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Thu Mar 21 14:11:13 2013 +0100
@@ -131,11 +131,19 @@
 |
     NumericLiteral<out result>
 |
+    Ternary<out result>  
+|
     "(" Expression<out result> ")"
-)
+) 
 .
 
-TimeRef<out TypedNode result>
+Ternary<out TypedNode result>                   (. TypedNode condition, thenPart, elsePart; .)
+=
+"#" Expression<out condition> "?" Expression<out thenPart> ":" Expression<out elsePart>
+                                                (. result = factory.createTernary(condition, thenPart, elsePart); .)
+.
+
+TimeRef<out TypedNode result> 
 =
 "time"                                          (. result = factory.createTime(); .)
 .
--- a/make/Makefile	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/Makefile	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -84,10 +84,12 @@
   ALT_OUT=
 endif
 
+# Directory for shared code (e.g. graal.jar)
+SHARED_DIR=$(OUTPUTDIR)/shared
+
 # Typical C1/C2 targets made available with this Makefile
 C1_VM_TARGETS=product1 fastdebug1 optimized1 jvmg1
 C2_VM_TARGETS=product  fastdebug  optimized  jvmg
-KERNEL_VM_TARGETS=productkernel fastdebugkernel optimizedkernel jvmgkernel
 ZERO_VM_TARGETS=productzero fastdebugzero optimizedzero jvmgzero
 SHARK_VM_TARGETS=productshark fastdebugshark optimizedshark jvmgshark
 MINIMAL1_VM_TARGETS=productminimal1 fastdebugminimal1 jvmgminimal1
@@ -168,11 +170,6 @@
 	$(CD) $(GAMMADIR)/make; \
 	$(MAKE) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT)
 
-$(KERNEL_VM_TARGETS):
-	$(CD) $(GAMMADIR)/make; \
-	$(MAKE) BUILD_FLAVOR=$(@:%kernel=%) VM_TARGET=$@ \
-	  generic_buildkernel $(ALT_OUT)
-
 $(ZERO_VM_TARGETS):
 	$(CD) $(GAMMADIR)/make; \
 	$(MAKE) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ \
@@ -193,7 +190,7 @@
 	$(MAKE) VM_TARGET=$@ generic_buildgraal $(ALT_OUT)
 
 # Build compiler1 (client) rule, different for platforms
-generic_build1:
+generic_build1: buildshared
 	$(MKDIR) -p $(OUTPUTDIR)
 ifeq ($(OSNAME),windows)
   ifeq ($(ARCH_DATA_MODEL), 32)
@@ -214,7 +211,7 @@
 endif
 
 # Build compiler2 (server) rule, different for platforms
-generic_build2:
+generic_build2: buildshared
 	$(MKDIR) -p $(OUTPUTDIR)
 ifeq ($(OSNAME),windows)
 	$(CD) $(OUTPUTDIR); \
@@ -230,24 +227,6 @@
 		      $(MAKE_ARGS) $(VM_TARGET)
 endif
 
-generic_buildkernel:
-	$(MKDIR) -p $(OUTPUTDIR)
-ifeq ($(OSNAME),windows)
-  ifeq ($(ARCH_DATA_MODEL), 32)
-	$(CD) $(OUTPUTDIR); \
-	    $(NMAKE) -f $(ABS_OS_MAKEFILE) \
-		      Variant=kernel \
-                      WorkSpace=$(ABS_GAMMADIR) \
-		      BootStrapDir=$(ABS_BOOTDIR) \
-                      BuildUser=$(USERNAME) \
-		      $(MAKE_ARGS) $(VM_TARGET:%kernel=%)
-  else
-	@$(ECHO) "No kernel ($(VM_TARGET)) for ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)"
-  endif
-else
-	@$(ECHO) "No kernel ($(VM_TARGET)) for OS_NAME=$(OSNAME)"
-endif
-
 generic_buildzero:
 	$(MKDIR) -p $(OUTPUTDIR)
 	$(CD) $(OUTPUTDIR); \
@@ -281,12 +260,16 @@
 	@$(ECHO) "Error: trying to build a minimal target but JVM_VARIANT_MINIMAL1 is not true."
 endif
 
-generic_buildgraal:
+generic_buildgraal: buildshared
 	$(MKDIR) -p $(OUTPUTDIR)
 	$(CD) $(OUTPUTDIR); \
 		$(MAKE) -f $(ABS_OS_MAKEFILE) \
 			$(MAKE_ARGS) $(VM_TARGET) 
 
+# Builds code that can be shared among different build flavors
+buildshared:
+	$(REMOTE) $(ANT) -f $(GAMMADIR)/make/build-graal.xml -Dgamma.dir=$(GAMMADIR) -Dshared.dir=$(SHARED_DIR)
+
 # Export file rule
 generic_export: $(EXPORT_LIST)
 export_product:
@@ -327,13 +310,11 @@
 DOCS_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_docs
 C1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1
 C2_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2
-KERNEL_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_kernel
 ZERO_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_zero
 SHARK_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_shark
 GRAAL_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_graal
 C1_DIR=$(C1_BASE_DIR)/$(VM_SUBDIR)
 C2_DIR=$(C2_BASE_DIR)/$(VM_SUBDIR)
-KERNEL_DIR=$(KERNEL_BASE_DIR)/$(VM_SUBDIR)
 ZERO_DIR=$(ZERO_BASE_DIR)/$(VM_SUBDIR)
 SHARK_DIR=$(SHARK_BASE_DIR)/$(VM_SUBDIR)
 MINIMAL1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1
@@ -348,10 +329,6 @@
     MISC_DIR=$(C1_DIR)
     GEN_DIR=$(C1_BASE_DIR)/generated
 endif
-ifeq ($(JVM_VARIANT_KERNEL), true)
-    MISC_DIR=$(C2_DIR)
-    GEN_DIR=$(C2_BASE_DIR)/generated
-endif
 ifeq ($(JVM_VARIANT_ZEROSHARK), true)
     MISC_DIR=$(SHARK_DIR)
     GEN_DIR=$(SHARK_BASE_DIR)/generated
@@ -401,16 +378,6 @@
 	$(install-file)
 $(EXPORT_SERVER_DIR)/%.map:  $(C2_DIR)/%.map
 	$(install-file)
-
-# Kernel files always come from kernel area
-$(EXPORT_KERNEL_DIR)/%.diz:  $(KERNEL_DIR)/%.diz
-	$(install-file)
-$(EXPORT_KERNEL_DIR)/%.dll:  $(KERNEL_DIR)/%.dll
-	$(install-file)
-$(EXPORT_KERNEL_DIR)/%.pdb:  $(KERNEL_DIR)/%.pdb
-	$(install-file)
-$(EXPORT_KERNEL_DIR)/%.map:  $(KERNEL_DIR)/%.map
-	$(install-file)
 endif
 
 # Minimal JVM files always come from minimal area
@@ -426,6 +393,7 @@
 # Shared Library
 ifneq ($(OSNAME),windows)
     ifeq ($(JVM_VARIANT_SERVER), true)
+	# C2
         $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
 		$(install-file)
         $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(C2_DIR)/%.$(LIBRARY_SUFFIX)
@@ -444,7 +412,27 @@
 		$(install-file)
         $(EXPORT_SERVER_DIR)/64/%.diz:    			$(C2_DIR)/%.diz
 		$(install-file)
-    endif
+
+	# Graal
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(GRAAL_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(GRAAL_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX):    $(GRAAL_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: 		$(GRAAL_DIR)/%.debuginfo
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/%.debuginfo:       		$(GRAAL_DIR)/%.debuginfo
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/64/%.debuginfo:    		$(GRAAL_DIR)/%.debuginfo
+		$(install-file)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: 			$(GRAAL_DIR)/%.diz
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/%.diz:       			$(GRAAL_DIR)/%.diz
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/64/%.diz:    			$(GRAAL_DIR)/%.diz
+		$(install-file)
+     endif
     ifeq ($(JVM_VARIANT_CLIENT), true)
         $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
 		$(install-file)
@@ -519,7 +507,8 @@
 $(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar
 	$(install-file)
 
-$(EXPORT_JRE_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar
+# Shared jar files
+$(EXPORT_JRE_LIB_DIR)/%.jar: $(SHARED_DIR)/%.jar
 	$(install-file)
 
 # Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h)
@@ -553,7 +542,7 @@
 	$(install-file)
 
 # Xusage file
-$(EXPORT_SERVER_DIR)/Xusage.txt $(EXPORT_CLIENT_DIR)/Xusage.txt $(EXPORT_KERNEL_DIR)/Xusage.txt $(EXPORT_MINIMAL_DIR)/Xusage.txt: $(XUSAGE)
+$(EXPORT_SERVER_DIR)/Xusage.txt $(EXPORT_CLIENT_DIR)/Xusage.txt $(EXPORT_MINIMAL_DIR)/Xusage.txt: $(XUSAGE)
 	$(prep-target)
 	$(RM) $@.temp
 	$(SED) 's/\(separated by \)[;:]/\1$(PATH_SEP)/g' $< > $@.temp
@@ -564,9 +553,9 @@
 #
 clobber clean: clean_build clean_export clean_jdk
 clean_build:
+	$(RM) -r $(SHARED_DIR)
 	$(RM) -r $(C1_DIR)
 	$(RM) -r $(C2_DIR)
-	$(RM) -r $(KERNEL_DIR)
 	$(RM) -r $(ZERO_DIR)
 	$(RM) -r $(SHARK_DIR)
 	$(RM) -r $(MINIMAL1_DIR)
@@ -602,10 +591,6 @@
 	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -Xinternalversion
 	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -version
   endif
-  ifeq ($(JVM_VARIANT_KERNEL), true)
-	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -Xinternalversion
-	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -version
-  endif
 
 copy_product_jdk::
 	$(RM) -r $(JDK_IMAGE_DIR)
@@ -681,7 +666,6 @@
 	@$(ECHO) "Other targets are:"
 	@$(ECHO) "   $(C1_VM_TARGETS)"
 	@$(ECHO) "   $(C2_VM_TARGETS)"
-	@$(ECHO) "   $(KERNEL_VM_TARGETS)"
 	@$(ECHO) "   $(MINIMAL1_VM_TARGETS)"
 
 # Variable help (only common ones used by this workspace)
@@ -777,8 +761,8 @@
 include $(GAMMADIR)/make/jprt.gmk
 
 .PHONY: all world clobber clean help $(C1_VM_TARGETS) $(C2_VM_TARGETS) \
-        $(KERNEL_VM_TARGETS) $(MINIMAL1_VM_TARGETS) \
-	generic_build1 generic_build2 generic_buildkernel generic_buildminimal1 generic_export \
+        $(MINIMAL1_VM_TARGETS) \
+	generic_build1 generic_build2 generic_buildminimal1 generic_export \
 	export_product export_fastdebug export_debug export_optimized \
 	export_jdk_product export_jdk_fastdebug export_jdk_debug \
 	create_jdk copy_jdk update_jdk test_jdk \
--- a/make/bsd/makefiles/buildtree.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/bsd/makefiles/buildtree.make	Thu Mar 21 14:11:13 2013 +0100
@@ -354,7 +354,7 @@
 	$(BUILDTREE_COMMENT); \
 	[ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \
 	{ \
-	echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \
+	echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:$(OUTPUTDIR)/shared/graal.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \
 	} | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \
 	echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \
 	echo "export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER"; \
--- a/make/bsd/makefiles/defs.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/bsd/makefiles/defs.make	Thu Mar 21 14:11:13 2013 +0100
@@ -157,8 +157,6 @@
 EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
 EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal
 
-EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
-
 ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
--- a/make/bsd/makefiles/dtrace.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/bsd/makefiles/dtrace.make	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,9 @@
 # Rules to build jvm_db/dtrace, used by vm.make
 
 # We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2
-# but not for CORE or KERNEL configurations.
+# but not for CORE configuration.
 
 ifneq ("${TYPE}", "CORE")
-ifneq ("${TYPE}", "KERNEL")
 
 ifeq ($(OS_VENDOR), Darwin)
 # we build dtrace for macosx using USDT2 probes
@@ -280,13 +279,6 @@
 endif # ifeq ($(OS_VENDOR), Darwin)
 
 
-else # KERNEL build
-
-dtraceCheck:
-	$(QUIETLY) echo "**NOTICE** Dtrace support disabled for KERNEL builds"
-
-endif # ifneq ("${TYPE}", "KERNEL")
-
 else # CORE build
 
 dtraceCheck:
--- a/make/bsd/makefiles/mapfile-vers-debug	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/bsd/makefiles/mapfile-vers-debug	Thu Mar 21 14:11:13 2013 +0100
@@ -188,6 +188,7 @@
                 JVM_IsSilentCompiler;
                 JVM_IsSupportedJNIVersion;
                 JVM_IsThreadAlive;
+                JVM_IsVMGeneratedMethodIx;
                 JVM_LatestUserDefinedLoader;
                 JVM_Listen;
                 JVM_LoadClass0;
--- a/make/bsd/makefiles/mapfile-vers-product	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/bsd/makefiles/mapfile-vers-product	Thu Mar 21 14:11:13 2013 +0100
@@ -188,6 +188,7 @@
                 JVM_IsSilentCompiler;
                 JVM_IsSupportedJNIVersion;
                 JVM_IsThreadAlive;
+                JVM_IsVMGeneratedMethodIx;
                 JVM_LatestUserDefinedLoader;
                 JVM_Listen;
                 JVM_LoadClass0;
--- a/make/bsd/makefiles/minimal1.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/bsd/makefiles/minimal1.make	Thu Mar 21 14:11:13 2013 +0100
@@ -30,7 +30,7 @@
 INCLUDE_JNI_CHECK ?= false
 INCLUDE_SERVICES ?= false
 INCLUDE_MANAGEMENT ?= false
-INCLUDE_ALTERNATE_GCS ?= false
+INCLUDE_ALL_GCS ?= false
 INCLUDE_NMT ?= false
 INCLUDE_CDS ?= false
 
--- a/make/bsd/makefiles/vm.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/bsd/makefiles/vm.make	Thu Mar 21 14:11:13 2013 +0100
@@ -94,7 +94,12 @@
 # This is VERY important! The version define must only be supplied to vm_version.o
 # If not, ccache will not re-use the cache at all, since the version string might contain
 # a time and date. 
-vm_version.o: CXXFLAGS += ${JRE_VERSION} 
+CXXFLAGS/vm_version.o += ${JRE_VERSION}
+
+CXXFLAGS/BYFILE = $(CXXFLAGS/$@)
+
+# File specific flags
+CXXFLAGS += $(CXXFLAGS/BYFILE)
 
 ifdef DEFAULT_LIBPATH
 CXXFLAGS += -DDEFAULT_LIBPATH="\"$(DEFAULT_LIBPATH)\""
@@ -343,9 +348,6 @@
 # Serviceability agent
 include $(MAKEFILES_DIR)/saproc.make
 
-# Whitebox testing API
-include $(MAKEFILES_DIR)/wb.make
-
 #----------------------------------------------------------------------
 
 ifeq ($(OS_VENDOR), Darwin)
@@ -353,10 +355,10 @@
 	dsymutil $(LIBJVM)
 
 # no libjvm_db for macosx
-build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM $(WB_JAR)
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM
 	echo "Doing vm.make build:"
 else
-build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) $(WB_JAR)
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC)
 endif
 
 install: install_jvm install_jsig install_saproc
--- a/make/bsd/makefiles/wb.make	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-#
-# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#  
-#
-
-# Rules to build whitebox testing library, used by vm.make
-WB = wb
-
-WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox
-
-WB_JAR = $(GENERATED)/$(WB).jar
-
-WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java')
-WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes
-
-WB_JAVA_CLASSES  = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
-	$(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
-
-$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
-	$(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
-
-$(WB_JAR): $(WB_JAVA_CLASSES)
-	$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
-
-$(WB_JAVA_CLASSDIR):
-	$(QUIETLY) mkdir -p $@
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/build-graal.xml	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+-->
+<project basedir="." default="main" name="graal">
+  <property name="src.dir" value="${gamma.dir}/graal"/>
+  <property name="classes.dir" value="${shared.dir}/graal"/>
+  <property name="jar.dir" value="${shared.dir}"/>
+  <property name="jar.file" value="${jar.dir}/graal.jar"/>
+  <target depends="jar" name="main"/>
+  <target name="compile">
+    <mkdir dir="${classes.dir}"/>
+    <javac debug="on" destdir="${classes.dir}" includeantruntime="false">
+      <src path="${src.dir}/com.oracle.graal.api.meta"/>
+      <src path="${src.dir}/com.oracle.graal.api.code"/>
+      <src path="${src.dir}/com.oracle.graal.graph"/>
+      <src path="${src.dir}/com.oracle.graal.debug"/>
+      <src path="${src.dir}/com.oracle.graal.nodes"/>
+      <src path="${src.dir}/com.oracle.graal.phases"/>
+      <src path="${src.dir}/com.oracle.graal.phases.common"/>
+      <src path="${src.dir}/com.oracle.graal.virtual"/>
+      <src path="${src.dir}/com.oracle.graal.loop"/>
+      <src path="${src.dir}/com.oracle.graal.alloc"/>
+      <src path="${src.dir}/com.oracle.graal.asm"/>
+      <src path="${src.dir}/com.oracle.graal.lir"/>
+      <src path="${src.dir}/com.oracle.graal.compiler"/>
+      <src path="${src.dir}/com.oracle.graal.bytecode"/>
+      <src path="${src.dir}/com.oracle.graal.java"/>
+      <src path="${src.dir}/com.oracle.graal.word"/>
+      <src path="${src.dir}/com.oracle.graal.snippets"/>
+      <src path="${src.dir}/com.oracle.graal.api.runtime"/>
+      <src path="${src.dir}/com.oracle.graal.printer"/>
+      <src path="${src.dir}/com.oracle.graal.hotspot"/>
+      <src path="${src.dir}/com.oracle.graal.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.asm.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.lir.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.compiler.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.snippets.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.hotspot.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.sparc"/>
+      <src path="${src.dir}/com.oracle.graal.asm.sparc"/>
+      <src path="${src.dir}/com.oracle.graal.lir.sparc"/>
+      <src path="${src.dir}/com.oracle.graal.compiler.sparc"/>
+      <src path="${src.dir}/com.oracle.graal.hotspot.sparc"/>
+      <compilerarg value="-XDignore.symbol.file"/>
+      <classpath>
+        <fileset dir="${java.home}/../lib">
+          <include name="tools.jar"/>
+        </fileset>
+      </classpath>
+    </javac>
+  </target>
+  <target depends="compile" name="jar">
+    <mkdir dir="${jar.dir}"/>
+    <jar basedir="${classes.dir}" destfile="${jar.file}"/>
+  </target>
+  <target name="clean">
+    <delete dir="${classes.dir}"/>
+    <delete file="${jar.filr}"/>
+  </target>
+</project>
--- a/make/defs.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/defs.make	Thu Mar 21 14:11:13 2013 +0100
@@ -236,6 +236,33 @@
   JDK_IMAGE_DIR=$(ALT_JDK_IMAGE_DIR)
 endif
 
+# Utilities ant
+ifeq ($(PLATFORM), windows)
+  ifeq ($(ANT_HOME),)
+    ANT_HOME := $(call DirExists,$(JDK_DEVTOOLS_DIR)/share/ant/latest,,)
+  endif
+endif
+
+# There are few problems with ant we need to workaround:
+#  1) ant is using temporary directory java.io.tmpdir
+#     However, this directory is not unique enough and two separate ant processes
+#     can easily end up using the exact same temp directory. This may lead to weird build failures
+#     To workaround this we will define tmp dir explicitly
+#  2) ant attempts to detect JDK location based on java.exe location
+#     This is fragile as developer may have JRE first on the PATH.
+#     To workaround this we will specify JAVA_HOME explicitly
+#  3) Sometimes we need to run ant with the boot jdk, sometimes with the import
+#     jdk, sometimes with the jdk we are building (see deploy repo).
+
+ANT_TMPDIR = $(OUTPUTDIR)/tmp
+ANT_WORKAROUNDS = ANT_OPTS=-Djava.io.tmpdir='$(ANT_TMPDIR)'
+
+ifeq ($(ANT_HOME),)
+  ANT = $(ANT_WORKAROUNDS) JAVA_HOME='$(BOOTDIR)' ant
+else
+  ANT = $(ANT_WORKAROUNDS) JAVA_HOME='$(BOOTDIR)' $(ANT_HOME)/bin/ant
+endif
+
 # The platform dependent defs.make defines platform specific variable such 
 # as ARCH, EXPORT_LIST etc. We must place the include here after BOOTDIR is defined.
 include $(GAMMADIR)/make/$(OSNAME)/makefiles/defs.make
@@ -336,6 +363,7 @@
 EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jni.h
 EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h
 EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h
+EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/graal.jar
 
 # By default, run Queens test after building
 TEST_IN_BUILD ?= true
--- a/make/excludeSrc.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/excludeSrc.make	Thu Mar 21 14:11:13 2013 +0100
@@ -72,15 +72,13 @@
       Src_Files_EXCLUDE += metaspaceShared.cpp
 endif
 
-ifeq ($(INCLUDE_ALTERNATE_GCS), false)
-      CXXFLAGS += -DINCLUDE_ALTERNATE_GCS=0
-      CFLAGS += -DINCLUDE_ALTERNATE_GCS=0
+ifeq ($(INCLUDE_ALL_GCS), false)
+      CXXFLAGS += -DINCLUDE_ALL_GCS=0
+      CFLAGS += -DINCLUDE_ALL_GCS=0
 
-      CXXFLAGS += -DSERIALGC
-      CFLAGS += -DSERIALGC
       Src_Files_EXCLUDE += \
 	cmsAdaptiveSizePolicy.cpp cmsCollectorPolicy.cpp \
-	cmsGCAdaptivePolicyCounters.cpp cmsLockVerifier.cpp cmsPermGen.cpp compactibleFreeListSpace.cpp \
+	cmsGCAdaptivePolicyCounters.cpp cmsLockVerifier.cpp compactibleFreeListSpace.cpp \
 	concurrentMarkSweepGeneration.cpp concurrentMarkSweepThread.cpp \
 	freeChunk.cpp adaptiveFreeList.cpp promotionInfo.cpp vmCMSOperations.cpp collectionSetChooser.cpp \
 	concurrentG1Refine.cpp concurrentG1RefineThread.cpp concurrentMark.cpp concurrentMarkThread.cpp \
@@ -93,11 +91,11 @@
 	gcTaskManager.cpp gcTaskThread.cpp objectStartArray.cpp parallelScavengeHeap.cpp parMarkBitMap.cpp \
 	pcTasks.cpp psAdaptiveSizePolicy.cpp psCompactionManager.cpp psGCAdaptivePolicyCounters.cpp \
 	psGenerationCounters.cpp psMarkSweep.cpp psMarkSweepDecorator.cpp psOldGen.cpp psParallelCompact.cpp \
-	psPermGen.cpp psPromotionLAB.cpp psPromotionManager.cpp psScavenge.cpp psTasks.cpp psVirtualspace.cpp \
+	psPromotionLAB.cpp psPromotionManager.cpp psScavenge.cpp psTasks.cpp psVirtualspace.cpp \
 	psYoungGen.cpp vmPSOperations.cpp asParNewGeneration.cpp parCardTableModRefBS.cpp \
 	parGCAllocBuffer.cpp parNewGeneration.cpp mutableSpace.cpp gSpaceCounters.cpp allocationStats.cpp \
 	spaceCounters.cpp gcAdaptivePolicyCounters.cpp mutableNUMASpace.cpp immutableSpace.cpp \
-	immutableSpace.cpp g1MemoryPool.cpp psMemoryPool.cpp yieldWorkingGroup.cpp g1Log.cpp
+	immutableSpace.cpp g1MemoryPool.cpp psMemoryPool.cpp yieldingWorkGroup.cpp g1Log.cpp
 endif 
 
 ifeq ($(INCLUDE_NMT), false)
--- a/make/hotspot_version	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/hotspot_version	Thu Mar 21 14:11:13 2013 +0100
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=25
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=17
+HS_BUILD_NUMBER=21
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/make/linux/makefiles/buildtree.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/linux/makefiles/buildtree.make	Thu Mar 21 14:11:13 2013 +0100
@@ -347,7 +347,7 @@
 	$(BUILDTREE_COMMENT); \
 	[ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \
 	{ \
-	echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \
+	echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:$(OUTPUTDIR)/shared/graal.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \
 	} | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \
 	echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \
 	echo "export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER"; \
--- a/make/linux/makefiles/defs.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/linux/makefiles/defs.make	Thu Mar 21 14:11:13 2013 +0100
@@ -258,8 +258,6 @@
 EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
 EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal
 
-EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
-
 ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
--- a/make/linux/makefiles/mapfile-vers-debug	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/linux/makefiles/mapfile-vers-debug	Thu Mar 21 14:11:13 2013 +0100
@@ -184,6 +184,7 @@
                 JVM_IsSilentCompiler;
                 JVM_IsSupportedJNIVersion;
                 JVM_IsThreadAlive;
+                JVM_IsVMGeneratedMethodIx;
                 JVM_LatestUserDefinedLoader;
                 JVM_Listen;
                 JVM_LoadClass0;
--- a/make/linux/makefiles/mapfile-vers-product	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/linux/makefiles/mapfile-vers-product	Thu Mar 21 14:11:13 2013 +0100
@@ -184,6 +184,7 @@
                 JVM_IsSilentCompiler;
                 JVM_IsSupportedJNIVersion;
                 JVM_IsThreadAlive;
+                JVM_IsVMGeneratedMethodIx;
                 JVM_LatestUserDefinedLoader;
                 JVM_Listen;
                 JVM_LoadClass0;
--- a/make/linux/makefiles/minimal1.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/linux/makefiles/minimal1.make	Thu Mar 21 14:11:13 2013 +0100
@@ -30,7 +30,7 @@
 INCLUDE_JNI_CHECK ?= false
 INCLUDE_SERVICES ?= false
 INCLUDE_MANAGEMENT ?= false
-INCLUDE_ALTERNATE_GCS ?= false
+INCLUDE_ALL_GCS ?= false
 INCLUDE_NMT ?= false
 INCLUDE_CDS ?= false
 
--- a/make/linux/makefiles/vm.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/linux/makefiles/vm.make	Thu Mar 21 14:11:13 2013 +0100
@@ -100,7 +100,13 @@
 # This is VERY important! The version define must only be supplied to vm_version.o
 # If not, ccache will not re-use the cache at all, since the version string might contain
 # a time and date. 
-vm_version.o: CXXFLAGS += ${JRE_VERSION}
+CXXFLAGS/vm_version.o += ${JRE_VERSION}
+
+CXXFLAGS/BYFILE = $(CXXFLAGS/$@)
+
+# File specific flags
+CXXFLAGS += $(CXXFLAGS/BYFILE)
+
 
 ifndef JAVASE_EMBEDDED 
 ifneq (${ARCH},arm)
@@ -386,12 +392,9 @@
 # Serviceability agent
 include $(MAKEFILES_DIR)/saproc.make
 
-# Whitebox testing API
-include $(MAKEFILES_DIR)/wb.make
-
 #----------------------------------------------------------------------
 
-build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) dtraceCheck $(WB_JAR)
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) dtraceCheck
 
 install: install_jvm install_jsig install_saproc
 
--- a/make/linux/makefiles/wb.make	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-#
-# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#  
-#
-
-# Rules to build whitebox testing library, used by vm.make
-WB = wb
-
-WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox
-
-WB_JAR = $(GENERATED)/$(WB).jar
-
-WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java')
-WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes
-
-WB_JAVA_CLASSES  = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
-	$(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
-
-$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
-	$(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
-
-$(WB_JAR): $(WB_JAVA_CLASSES)
-	$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
-
-$(WB_JAVA_CLASSDIR):
-	$(QUIETLY) mkdir -p $@
-
--- a/make/sa.files	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/sa.files	Thu Mar 21 14:11:13 2013 +0100
@@ -24,10 +24,7 @@
 
 # This filelist macro is included in platform specific sa.make
 # included all packages/*.java. package list can be generated by
-# $(GAMMADIR)/agent/make/build-pkglist. Then manually removed all 
-# classes in sun.jvm.hotspot.ui (and subpackages),  all ui classes 
-# in sun.jvm.hotspot.bugspot/hotspot and SPARC and x86 disassembler 
-# classes and sun.jvm.hotspot.utilities.soql.
+# $(GAMMADIR)/agent/make/build-pkglist. 
 
 # define AGENT_DIR before including this file in sa.make
 
@@ -40,8 +37,6 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/sparc/*.java \
-$(AGENT_SRC_DIR)/sun/jvm/hotspot/bugspot/*.java \
-$(AGENT_SRC_DIR)/sun/jvm/hotspot/bugspot/tree/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/c1/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/ci/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \
@@ -82,7 +77,6 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_interface/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/interpreter/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/jdi/*.java \
-$(AGENT_SRC_DIR)/sun/jvm/hotspot/livejvm/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/memory/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/oops/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/opto/*.java \
--- a/make/solaris/Makefile	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/solaris/Makefile	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -157,14 +157,12 @@
 SUBDIRS_C2        = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler2/,$(TARGETS))
 SUBDIRS_TIERED    = $(addprefix $(OSNAME)_$(BUILDARCH)_tiered/,$(TARGETS))
 SUBDIRS_CORE      = $(addprefix $(OSNAME)_$(BUILDARCH)_core/,$(TARGETS))
-SUBDIRS_KERNEL    = $(addprefix $(OSNAME)_$(BUILDARCH)_kernel/,$(TARGETS))
 SUBDIRS_GRAAL     = $(addprefix $(OSNAME)_$(BUILDARCH)_graal/,$(TARGETS))
 
 TARGETS_C2        = $(TARGETS)
 TARGETS_C1        = $(addsuffix 1,$(TARGETS))
 TARGETS_TIERED    = $(addsuffix tiered,$(TARGETS))
 TARGETS_CORE      = $(addsuffix core,$(TARGETS))
-TARGETS_KERNEL    = $(addsuffix kernel,$(TARGETS))
 TARGETS_GRAAL     = $(addsuffix graal,$(TARGETS))
 
 BUILDTREE_MAKE    = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make
@@ -232,10 +230,6 @@
 	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
 	$(BUILDTREE) VARIANT=core
 
-$(SUBDIRS_KERNEL): $(BUILDTREE_MAKE)
-	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
-	$(BUILDTREE) VARIANT=kernel
-
 $(SUBDIRS_GRAAL): $(BUILDTREE_MAKE)
 	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
 	$(BUILDTREE) VARIANT=graal
@@ -278,15 +272,6 @@
 	cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install
 endif
 
-$(TARGETS_KERNEL):  $(SUBDIRS_KERNEL)
-	cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && $(MAKE) $(MFLAGS)
-ifeq ($(TEST_IN_BUILD),true)
-	cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && ./test_gamma
-endif
-ifdef INSTALL
-	cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && $(MAKE) $(MFLAGS) install
-endif
-
 $(TARGETS_GRAAL):  $(SUBDIRS_GRAAL)
 	cd $(OSNAME)_$(BUILDARCH)_graal/$(patsubst %graal,%,$@) && $(MAKE) $(MFLAGS)
 ifdef INSTALL
@@ -297,7 +282,6 @@
 tree:      $(SUBDIRS_C2)
 tree1:     $(SUBDIRS_C1)
 treecore:  $(SUBDIRS_CORE)
-treekernel:  $(SUBDIRS_KERNEL)
 treegraal: $(SUBDIRS_GRAAL)
 
 # Doc target.  This is the same for all build options.
@@ -318,10 +302,10 @@
 clean_docs:
 	rm -rf $(SUBDIR_DOCS)
 
-clean_compiler1 clean_compiler2 clean_core clean_kernel clean_graal:
+clean_compiler1 clean_compiler2 clean_core clean_graal:
 	rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@)
 
-clean:  clean_compiler2 clean_compiler1 clean_core clean_docs clean_kernel clean_graal
+clean:  clean_compiler2 clean_compiler1 clean_core clean_docs clean_graal
 
 include $(GAMMADIR)/make/cscope.make
 
--- a/make/solaris/makefiles/buildtree.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/solaris/makefiles/buildtree.make	Thu Mar 21 14:11:13 2013 +0100
@@ -336,7 +336,7 @@
 	$(BUILDTREE_COMMENT); \
 	[ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \
 	{ \
-	echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \
+	echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:$(OUTPUTDIR)/shared/graal.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \
 	} | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \
 	echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \
 	echo "export JAVA_HOME LD_LIBRARY_PATH CLASSPATH HOTSPOT_BUILD_USER"; \
--- a/make/solaris/makefiles/defs.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/solaris/makefiles/defs.make	Thu Mar 21 14:11:13 2013 +0100
@@ -187,8 +187,6 @@
   endif
 endif
 
-EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
-
 EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
 EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
 
--- a/make/solaris/makefiles/dtrace.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/solaris/makefiles/dtrace.make	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,9 @@
 # Rules to build jvm_db/dtrace, used by vm.make
 
 # We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2
-# but not for CORE or KERNEL configurations.
+# but not for CORE configuration.
 
 ifneq ("${TYPE}", "CORE")
-ifneq ("${TYPE}", "KERNEL")
 
 ifdef USE_GCC
 
@@ -362,13 +361,6 @@
 
 endif # ifdef USE_GCC
 
-else # KERNEL build
-
-dtraceCheck:
-	$(QUIETLY) echo "**NOTICE** Dtrace support disabled for KERNEL builds"
-
-endif # ifneq ("${TYPE}", "KERNEL")
-
 else # CORE build
 
 dtraceCheck:
--- a/make/solaris/makefiles/kernel.make	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#
-# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#   
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#   
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#  
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#   
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#  
-#
-# 
-# Sets make macros for making kernel version of VM.
-# This target on solaris is just tempoarily for debugging the kernel build.
-
-TYPE=KERNEL
-
-VM_SUBDIR = client
-
-CFLAGS += -DKERNEL
--- a/make/solaris/makefiles/mapfile-vers	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/solaris/makefiles/mapfile-vers	Thu Mar 21 14:11:13 2013 +0100
@@ -184,6 +184,7 @@
                 JVM_IsSilentCompiler;
                 JVM_IsSupportedJNIVersion;
                 JVM_IsThreadAlive;
+                JVM_IsVMGeneratedMethodIx;
                 JVM_LatestUserDefinedLoader;
                 JVM_Listen;
                 JVM_LoadClass0;
--- a/make/solaris/makefiles/vm.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/solaris/makefiles/vm.make	Thu Mar 21 14:11:13 2013 +0100
@@ -88,7 +88,13 @@
 # This is VERY important! The version define must only be supplied to vm_version.o
 # If not, ccache will not re-use the cache at all, since the version string might contain
 # a time and date. 
-vm_version.o: CXXFLAGS += ${JRE_VERSION} 
+CXXFLAGS/vm_version.o += ${JRE_VERSION}
+
+CXXFLAGS/BYFILE = $(CXXFLAGS/$@)
+
+# File specific flags
+CXXFLAGS += $(CXXFLAGS/BYFILE)
+
 
 # CFLAGS_WARN holds compiler options to suppress/enable warnings.
 CFLAGS += $(CFLAGS_WARN)
@@ -347,12 +353,9 @@
 # Serviceability agent
 include $(MAKEFILES_DIR)/saproc.make
 
-# Whitebox testing API
-include $(MAKEFILES_DIR)/wb.make
-
 #----------------------------------------------------------------------
 
-build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(LIBJVM_DTRACE) $(BUILDLIBSAPROC) dtraceCheck $(WB_JAR)
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(LIBJVM_DTRACE) $(BUILDLIBSAPROC) dtraceCheck
 
 install: install_jvm install_jsig install_saproc
 
--- a/make/solaris/makefiles/wb.make	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-#
-# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# Rules to build whitebox testing library, used by vm.make
-
-WB = wb
-
-WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox
-
-WB_JAR = $(GENERATED)/$(WB).jar
-
-WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java')
-WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes
-
-WB_JAVA_CLASSES  = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
-	$(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
-
-$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
-	$(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
-
-$(WB_JAR): $(WB_JAVA_CLASSES)
-	$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
-
-$(WB_JAVA_CLASSDIR):
-	$(QUIETLY) mkdir -p $@
-
--- a/make/windows/build.bat	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/windows/build.bat	Thu Mar 21 14:11:13 2013 +0100
@@ -1,6 +1,6 @@
 @echo off
 REM
-REM Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+REM Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 REM
 REM This code is free software; you can redistribute it and/or modify it
@@ -67,7 +67,6 @@
 
 :test1
 if "%2" == "core"      goto test2
-if "%2" == "kernel"    goto test2
 if "%2" == "compiler1" goto test2
 if "%2" == "compiler2" goto test2
 if "%2" == "tiered"    goto test2
@@ -109,7 +108,7 @@
 echo.
 echo where:
 echo flavor is "product", "debug" or "fastdebug",
-echo version is "core", "kernel", "compiler1", "compiler2", or "tiered",
+echo version is "core", "compiler1", "compiler2", or "tiered",
 echo workspace is source directory without trailing slash, 
 echo bootstrap_dir is a full path to a JDK in which bin/java 
 echo   and bin/javac are present and working, and build_id is an 
--- a/make/windows/create_obj_files.sh	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/windows/create_obj_files.sh	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -107,7 +107,6 @@
 # Include dirs per type.
 case "${TYPE}" in
     "core")      Src_Dirs="${CORE_PATHS}" ;;
-    "kernel")    Src_Dirs="${BASE_PATHS} ${COMPILER1_PATHS}" ;;
     "compiler1") Src_Dirs="${CORE_PATHS} ${COMPILER1_PATHS}" ;;
     "compiler2") Src_Dirs="${CORE_PATHS} ${COMPILER2_PATHS}" ;;
     "tiered")    Src_Dirs="${CORE_PATHS} ${COMPILER1_PATHS} ${COMPILER2_PATHS}" ;;
@@ -120,16 +119,12 @@
 SHARK_SPECIFIC_FILES="shark"
 ZERO_SPECIFIC_FILES="zero"
 
-# These files need to be excluded when building the kernel target.
-KERNEL_EXCLUDED_FILES="attachListener.cpp attachListener_windows.cpp metaspaceShared_${Platform_arch_model}.cpp forte.cpp fprofiler.cpp heapDumper.cpp heapInspection.cpp jniCheck.cpp jvmtiCodeBlobEvents.cpp jvmtiExtensions.cpp jvmtiImpl.cpp jvmtiRawMonitor.cpp jvmtiTagMap.cpp jvmtiTrace.cpp vmStructs.cpp g1MemoryPool.cpp psMemoryPool.cpp gcAdaptivePolicyCounters.cpp concurrentGCThread.cpp metaspaceShared.cpp mutableNUMASpace.cpp allocationStats.cpp gSpaceCounters.cpp immutableSpace.cpp mutableSpace.cpp spaceCounters.cpp yieldingWorkgroup.cpp"
-
 # Always exclude these.
 Src_Files_EXCLUDE="jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp"
 
 # Exclude per type.
 case "${TYPE}" in
     "core")      Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;;
-    "kernel")    Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ${KERNEL_EXCLUDED_FILES} ciTypeFlow.cpp" ;;
     "compiler1") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;;
     "compiler2") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;;
     "tiered")    Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;;
--- a/make/windows/makefiles/debug.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/windows/makefiles/debug.make	Thu Mar 21 14:11:13 2013 +0100
@@ -33,7 +33,7 @@
 BUILD_PCH_FILE=_build_pch_file.obj
 !endif
 
-default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb
+default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
 
 !include ../local.make
 !include compile.make
@@ -72,4 +72,3 @@
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
 !include $(WorkSpace)/make/windows/makefiles/launcher.make
-!include $(WorkSpace)/make/windows/makefiles/wb.make
--- a/make/windows/makefiles/defs.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/windows/makefiles/defs.make	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -157,7 +157,7 @@
 MAKE_ARGS += RM="$(RM)"
 MAKE_ARGS += ZIPEXE=$(ZIPEXE)
 
-# On 32 bit windows we build server, client and kernel, on 64 bit just server.
+# On 32 bit windows we build server and client, on 64 bit just server.
 ifeq ($(JVM_VARIANTS),)
   ifeq ($(ARCH_DATA_MODEL), 32)
     JVM_VARIANTS:=client,server
@@ -250,7 +250,6 @@
 
 EXPORT_SERVER_DIR = $(EXPORT_JRE_BIN_DIR)/server
 EXPORT_CLIENT_DIR = $(EXPORT_JRE_BIN_DIR)/client
-EXPORT_KERNEL_DIR = $(EXPORT_JRE_BIN_DIR)/kernel
 
 ifeq ($(JVM_VARIANT_SERVER),true)
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
@@ -277,20 +276,6 @@
     endif
   endif
 endif
-ifeq ($(JVM_VARIANT_KERNEL),true)
-  EXPORT_LIST += $(EXPORT_KERNEL_DIR)/Xusage.txt
-  EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.$(LIBRARY_SUFFIX)
-  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
-    ifeq ($(ZIP_DEBUGINFO_FILES),1)
-      EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.diz
-    else
-      EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.pdb
-      EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.map
-    endif
-  endif
-endif
-
-EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
 
 ifeq ($(BUILD_WIN_SA), 1)
   EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX)
--- a/make/windows/makefiles/fastdebug.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/windows/makefiles/fastdebug.make	Thu Mar 21 14:11:13 2013 +0100
@@ -33,7 +33,7 @@
 BUILD_PCH_FILE=_build_pch_file.obj
 !endif
 
-default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb
+default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
 
 !include ../local.make
 !include compile.make
@@ -71,4 +71,3 @@
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
 !include $(WorkSpace)/make/windows/makefiles/launcher.make
-!include $(WorkSpace)/make/windows/makefiles/wb.make
--- a/make/windows/makefiles/product.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/windows/makefiles/product.make	Thu Mar 21 14:11:13 2013 +0100
@@ -32,7 +32,7 @@
 BUILD_PCH_FILE=_build_pch_file.obj
 !endif
 
-default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb
+default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
 
 !include ../local.make
 !include compile.make
@@ -82,4 +82,3 @@
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
 !include $(WorkSpace)/make/windows/makefiles/launcher.make
-!include $(WorkSpace)/make/windows/makefiles/wb.make
--- a/make/windows/makefiles/projectcreator.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/windows/makefiles/projectcreator.make	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -145,8 +145,10 @@
  -ignorePath_TARGET c1_
 
 ProjectCreatorIDEOptionsIgnoreGraal=\
- -ignorePath_TARGET graal
- 
+ -ignorePath_TARGET src/share/vm/graal \
+ -ignorePath_TARGET graal/generated \
+ -ignorePath_TARGET vm/graal
+
 ProjectCreatorIDEOptionsIgnoreCompiler2=\
  -ignorePath_TARGET compiler2 \
  -ignorePath_TARGET tiered \
@@ -170,70 +172,13 @@
 $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=core)
 
 ##################################################
-# JKERNEL specific options
-##################################################
-ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
- -define_kernel KERNEL \
-$(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=kernel) \
- -ignorePath_kernel src/share/vm/gc_implementation/parallelScavenge \
- -ignorePath_kernel src/share/vm/gc_implementation/parNew \
- -ignorePath_kernel src/share/vm/gc_implementation/concurrentMarkSweep \
- -ignorePath_kernel src/share/vm/gc_implementation/g1 \
- -ignoreFile_kernel attachListener.cpp \
- -ignoreFile_kernel attachListener_windows.cpp \
- -ignoreFile_kernel dump.cpp \
- -ignoreFile_kernel dump_$(Platform_arch_model).cpp \
- -ignoreFile_kernel forte.cpp \
- -ignoreFile_kernel fprofiler.cpp \
- -ignoreFile_kernel heapDumper.cpp \
- -ignoreFile_kernel heapInspection.cpp \
- -ignoreFile_kernel jniCheck.cpp \
- -ignoreFile_kernel jvmtiCodeBlobEvents.cpp \
- -ignoreFile_kernel jvmtiExtensions.cpp \
- -ignoreFile_kernel jvmtiImpl.cpp \
- -ignoreFile_kernel jvmtiRawMonitor.cpp \
- -ignoreFile_kernel jvmtiTagMap.cpp \
- -ignoreFile_kernel jvmtiTrace.cpp \
- -ignoreFile_kernel jvmtiTrace.hpp \
- -ignoreFile_kernel restore.cpp \
- -ignoreFile_kernel serialize.cpp \
- -ignoreFile_kernel vmStructs.cpp \
- -ignoreFile_kernel g1MemoryPool.cpp \
- -ignoreFile_kernel g1MemoryPool.hpp \
- -ignoreFile_kernel psMemoryPool.cpp \
- -ignoreFile_kernel psMemoryPool.hpp \
- -ignoreFile_kernel gcAdaptivePolicyCounters.cpp \
- -ignoreFile_kernel concurrentGCThread.cpp \
- -ignoreFile_kernel mutableNUMASpace.cpp \
- -ignoreFile_kernel ciTypeFlow.cpp \
- -ignoreFile_kernel ciTypeFlow.hpp \
- -ignoreFile_kernel oop.pcgc.inline.hpp \
- -ignoreFile_kernel oop.psgc.inline.hpp \
- -ignoreFile_kernel allocationStats.cpp \
- -ignoreFile_kernel allocationStats.hpp \
- -ignoreFile_kernel concurrentGCThread.hpp \
- -ignoreFile_kernel gSpaceCounters.cpp \
- -ignoreFile_kernel gSpaceCounters.hpp \
- -ignoreFile_kernel gcAdaptivePolicyCounters.hpp \
- -ignoreFile_kernel immutableSpace.cpp \
- -ignoreFile_kernel mutableNUMASpace.hpp \
- -ignoreFile_kernel mutableSpace.cpp \
- -ignoreFile_kernel spaceCounters.cpp \
- -ignoreFile_kernel spaceCounters.hpp \
- -ignoreFile_kernel yieldingWorkgroup.cpp \
- -ignoreFile_kernel yieldingWorkgroup.hpp \
- -ignorePath_kernel vmStructs_ \
- -ignoreFile_kernel $(Platform_arch_model).ad \
- -additionalFile_kernel gcTaskManager.hpp
-
-##################################################
 # Client(C1) compiler specific options
 ##################################################
 ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
  -define_compiler1 COMPILER1 \
+ -define_compiler1 GRAAL \
  -ignorePath_compiler1 core \
- -ignorePath_compiler1 src/share/vm/graal \
- $(ProjectCreatorIDEOptionsIgnoreGraal:TARGET=compiler1) \
+ -ignorePath_compiler1 graal/generated \
  $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=compiler1)
 
 ##################################################
@@ -242,7 +187,6 @@
 ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
  -define_graal GRAAL \
  -ignorePath_graal core \
- -ignorePath_graal src/share/vm/c1 \
  $(ProjectCreatorIDEOptionsIgnoreCompiler1:TARGET=graal) \
  $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=graal)
 
@@ -252,8 +196,10 @@
 #NOTE! This list must be kept in sync with GENERATED_NAMES in adlc.make.
 ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
  -define_compiler2 COMPILER2 \
+ -define_compiler2 GRAAL \
+ -define_compiler2 TIERED \
  -ignorePath_compiler2 core \
- -ignorePath_compiler2 src/share/vm/graal \
+ -ignorePath_compiler2 graal/generated \
  -additionalFile_compiler2 $(Platform_arch_model).ad \
  -additionalFile_compiler2 ad_$(Platform_arch_model).cpp \
  -additionalFile_compiler2 ad_$(Platform_arch_model).hpp \
@@ -266,7 +212,6 @@
  -additionalFile_compiler2 ad_$(Platform_arch_model)_pipeline.cpp \
  -additionalFile_compiler2 adGlobals_$(Platform_arch_model).hpp \
  -additionalFile_compiler2 dfa_$(Platform_arch_model).cpp \
- $(ProjectCreatorIDEOptionsIgnoreGraal:TARGET=compiler2) \
  $(ProjectCreatorIDEOptionsIgnoreCompiler1:TARGET=compiler2)
 
 # Add in the jvmti (JSR-163) options
--- a/make/windows/makefiles/vm.make	Thu Mar 21 11:30:38 2013 +0100
+++ b/make/windows/makefiles/vm.make	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -44,10 +44,6 @@
 # No need to define anything, CORE is defined as !COMPILER1 && !COMPILER2
 !endif
 
-!if "$(Variant)" == "kernel"
-CXX_FLAGS=$(CXX_FLAGS) /D "KERNEL"
-!endif
-
 !if "$(Variant)" == "compiler1"
 CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1"
 !endif
--- a/make/windows/makefiles/wb.make	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-#
-# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#  
-#
-
-# This makefile is used to build the whitebox testing lib
-# and compile the tests which use it
-
-!include $(WorkSpace)/make/windows/makefiles/rules.make
-
-WBSRCDIR = $(WorkSpace)/src/share/tools/whitebox
-
-# turn GENERATED into a windows path to get sane dependencies
-WB_CLASSES=$(GENERATED:/=\)\wb\classes
-WB_JAR=$(GENERATED:/=\)\wb.jar
-
-# call recursive make to do wildcard expansion
-.SUFFIXES : .java .class
-wb_java_srcs: $(WorkSpace)\src\share\tools\whitebox\sun\hotspot\*.java $(WB_CLASSES)
-	$(MAKE) -f $(WorkSpace)\make\windows\makefiles\$(BUILD_FLAVOR).make $(**:.java=.class)
-
-
-{$(WorkSpace)\src\share\tools\whitebox\sun\hotspot}.java.class::
-	$(COMPILE_JAVAC) -sourcepath $(WBSRCDIR) -d $(WB_CLASSES) $<
-
-$(WB_JAR): wb_java_srcs
-	$(RUN_JAR) cf $@ -C $(WB_CLASSES) .
-
-# turn $@ to a unix path because mkdir in PATH is cygwin/mks mkdir
-$(WB_CLASSES):
-	mkdir -p $(@:\=/)
-
-# main target to build wb
-wb: $(WB_JAR)
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mx/JUnitWrapper.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/* Execute testcases by reading names from a given file, due to limits of
+ * the operating system regarding command line size (windows: 32k,
+ * linux [depending on the settings]: ~2097k)
+ * see http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx
+ */
+
+import org.junit.runner.*;
+import java.io.*;
+import java.util.*;
+
+public class JUnitWrapper {
+
+    /**
+     * @param args
+     *            args[0] is the path where to read the names of the testclasses.
+     */
+    public static void main(String[] args) {
+        if (args.length == 0) {
+            System.err.printf("wrong usage. provide a filename\n");
+            System.exit(1);
+        }
+        ArrayList<String> tests = new ArrayList<String>(1000);
+        BufferedReader br = null;
+        try {
+            br = new BufferedReader(new FileReader(args[0]));
+
+            String buf;
+            while ((buf = br.readLine()) != null) {
+                tests.add(buf);
+            }
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            System.exit(2);
+        } finally {
+            try {
+                if (br != null) {
+                    br.close();
+                }
+            } catch (IOException ioe) {
+                ioe.printStackTrace();
+                System.exit(3);
+            }
+        }
+
+        String[] strargs = tests.toArray(new String[tests.size()]);
+        System.out.printf("executing junit tests now... (%d testclasses)\n", strargs.length);
+        JUnitCore.main(strargs);
+    }
+}
--- a/mx/commands.py	Thu Mar 21 11:30:38 2013 +0100
+++ b/mx/commands.py	Thu Mar 21 14:11:13 2013 +0100
@@ -27,7 +27,7 @@
 # ----------------------------------------------------------------------------------------------------
 
 import os, sys, shutil, zipfile, tempfile, re, time, datetime, platform, subprocess, multiprocessing
-from os.path import join, exists, dirname, basename
+from os.path import join, exists, dirname, basename, getmtime
 from argparse import ArgumentParser, REMAINDER
 import mx
 import sanitycheck
@@ -52,30 +52,7 @@
 
 _make_eclipse_launch = False
 
-_copyrightTemplate = """/*
- * Copyright (c) {0}, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-"""
+_minVersion = mx.JavaVersion('1.7.0_04')
 
 def _chmodDir(chmodFlags, dirname, fnames):
     os.chmod(dirname, chmodFlags)
@@ -91,7 +68,7 @@
     if opts.native:
         os.environ.update(ARCH_DATA_MODEL='64', LANG='C', HOTSPOT_BUILD_JOBS='16')
         mx.run([mx.gmake_cmd(), 'clean'], cwd=join(_graal_home, 'make'))
-        jdks = join(_graal_home, 'jdk' + mx.java().version)
+        jdks = join(_graal_home, 'jdk' + str(mx.java().version))
         if exists(jdks):
             shutil.rmtree(jdks)
 
@@ -314,11 +291,11 @@
         return join(jdk, 'jre', 'lib', _arch(), 'jvm.cfg')
     return join(_vmLibDirInJdk(jdk), 'jvm.cfg')
 
-def _jdk(build='product', create=False):
+def _jdk(build='product', vmToCheck=None, create=False):
     """
     Get the JDK into which Graal is installed, creating it first if necessary.
     """
-    jdk = join(_graal_home, 'jdk' + mx.java().version, build)
+    jdk = join(_graal_home, 'jdk' + str(mx.java().version), build)
     jdkContents = ['bin', 'include', 'jre', 'lib']
     if (exists(join(jdk, 'db'))):
         jdkContents.append('db')
@@ -342,7 +319,6 @@
             if not exists(jvmCfg):
                 mx.abort(jvmCfg + ' does not exist')
 
-            lines = []
             defaultVM = None
             with open(jvmCfg) as f:
                 for line in f:
@@ -351,17 +327,14 @@
                         assert len(parts) == 2, parts
                         assert parts[1] == 'KNOWN', parts[1]
                         defaultVM = parts[0][1:]
-                        lines.append('-' + defaultVM + '0 KNOWN\n')
-                    lines.append(line)
 
             assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg
             if mx.get_os() != 'windows':
                 chmodRecursive(jdk, 0755)
             shutil.copytree(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), defaultVM + '0'))
 
-            with open(jvmCfg, 'w') as f:
-                for line in lines:
-                    f.write(line)
+            with open(jvmCfg, 'w') as fp:
+                print >> fp, '-' + defaultVM + '0 KNOWN'
 
             # Install a copy of the disassembler library
             try:
@@ -370,9 +343,36 @@
                 pass
     else:
         if not exists(jdk):
-            mx.abort('The ' + build + ' VM has not been created - run \'mx clean; mx build ' + build + '\'')
+            mx.abort('The ' + build + ' VM has not been created - run "mx build ' + build + '"')
+            
+    _installGraalJarInJdks(mx.distribution('GRAAL'))
+    
+    if vmToCheck is not None:
+        jvmCfg = _vmCfgInJdk(jdk)
+        found = False
+        with open(jvmCfg) as f:
+            for line in f:
+                if line.strip() == '-' + vmToCheck + ' KNOWN':
+                    found = True
+                    break
+        if not found:
+            mx.abort('The ' + build + ' ' + vmToCheck + ' VM has not been created - run "mx --vm ' + vmToCheck + ' build ' + build + '"')
+        
     return jdk
 
+def _installGraalJarInJdks(graalDist):
+    graalJar = graalDist.path
+    jdks = join(_graal_home, 'jdk' + str(mx.java().version))
+    if exists(jdks):
+        for e in os.listdir(jdks):
+            jreLibDir = join(jdks, e, 'jre', 'lib')
+            if exists(jreLibDir):
+                # do a copy and then a move to get atomic updating (on Unix) of graal.jar in the JRE
+                fd, tmp = tempfile.mkstemp(suffix='', prefix='graal.jar', dir=jreLibDir)
+                shutil.copyfile(graalJar, tmp)
+                os.close(fd)
+                shutil.move(tmp, join(jreLibDir, 'graal.jar'))
+
 # run a command in the windows SDK Debug Shell
 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo={}):
     newLine = os.linesep
@@ -435,7 +435,79 @@
     """print the JDK directory selected for the 'vm' command"""
 
     build = _vmbuild if _vmSourcesAvailable else 'product'
-    print join(_graal_home, 'jdk' + mx.java().version, build)
+    print join(_graal_home, 'jdk' + str(mx.java().version), build)
+
+def initantbuild(args):
+    """(re)generates an ant build file for producing graal.jar"""
+    parser=ArgumentParser(prog='mx initantbuild')
+    parser.add_argument('-f', '--buildfile', help='file to generate', default=join(_graal_home, 'make', 'build-graal.xml'))
+
+    args = parser.parse_args(args)
+    
+    out = mx.XMLDoc()
+    
+    out.comment("""
+ Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+""")
+    
+    out.open('project', {'name' : 'graal', 'default' : 'main', 'basedir' : '.'})
+    out.element('property', {'name' : 'src.dir', 'value' : '${gamma.dir}/graal'})
+    out.element('property', {'name' : 'classes.dir', 'value' : '${shared.dir}/graal'})
+    out.element('property', {'name' : 'jar.dir', 'value' : '${shared.dir}'})
+    out.element('property', {'name' : 'jar.file', 'value' : '${jar.dir}/graal.jar'})
+    
+    out.element('target', {'name' : 'main', 'depends' : 'jar'})
+
+    out.open('target', {'name' : 'compile'})
+    out.element('mkdir', {'dir' : '${classes.dir}'})
+    out.open('javac', {'destdir' : '${classes.dir}', 'debug' : 'on', 'includeantruntime' : 'false', })
+    for p in mx.sorted_deps(mx.distribution('GRAAL').deps):
+        out.element('src', {'path' : '${src.dir}/' + p.name})
+    out.element('compilerarg', {'value' : '-XDignore.symbol.file'})
+    
+    out.open('classpath')
+    out.open('fileset', {'dir' : '${java.home}/../lib'})
+    out.element('include', {'name' : 'tools.jar'})
+    out.close('fileset')
+    out.close('classpath')
+    
+    out.close('javac')
+    out.close('target')
+
+    out.open('target', {'name' : 'jar', 'depends' : 'compile'})
+    out.element('mkdir', {'dir' : '${jar.dir}'})
+    out.element('jar', {'destfile' : '${jar.file}', 'basedir' : '${classes.dir}'})
+    out.close('target')
+    
+    out.open('target', {'name' : 'clean'})
+    out.element('delete', {'dir' : '${classes.dir}'})
+    out.element('delete', {'file' : '${jar.filr}'})
+    out.close('target')
+
+    out.close('project')
+    
+    mx.update_file(args.buildfile, out.xml(indent='  ', newl='\n'))
 
 def build(args, vm=None):
     """build the VM binary
@@ -465,6 +537,8 @@
     else:
         assert vm == 'graal', vm
         buildSuffix = 'graal'
+        
+    initantbuild([])
 
     for build in builds:
         if build == 'ide-build-target':
@@ -486,25 +560,6 @@
             if not 'Xusage.txt' in line:
                 sys.stderr.write(line + os.linesep)
 
-        # Check that the declaration of graal_projects in arguments.cpp is up to date
-        argumentsCpp = join(_graal_home, 'src', 'share', 'vm', 'runtime', 'arguments.cpp')
-        assert exists(argumentsCpp), 'File does not exist: ' + argumentsCpp
-        with open(argumentsCpp) as fp:
-            source = fp.read();
-            decl = 'const char* graal_projects[] = {'
-            start = source.find(decl)
-            assert start != -1, 'Could not find "' + decl + '" in ' + fp.name
-            end = source.find('};', start)
-            assert end != -1, 'Could not find "' + decl + '" ... "};" in ' + fp.name
-            actual = frozenset(re.findall(r'"([^"]+)"', source[start + len(decl):end]))
-            expected = frozenset([p.name for p in mx.project('com.oracle.graal.hotspot.' + _arch()).all_deps([], False)])
-            missing = expected - actual
-            extra = actual - expected
-            if len(missing) != 0:
-                mx.abort(fp.name + ':' + str(source[:start].count('\n') + 1) + ': add missing project(s) to declaration:\n    ' + '\n    '.join(missing))
-            if len(extra) != 0:
-                mx.abort(fp.name + ':' + str(source[:start].count('\n') + 1) + ': remove project(s) from declaration:\n    ' + '\n    '.join(extra))
-
         # Check if a build really needs to be done
         timestampFile = join(vmDir, '.build-timestamp')
         if opts2.force or not exists(timestampFile):
@@ -589,23 +644,18 @@
             mx.abort(jvmCfg + ' does not exist')
 
         prefix = '-' + vm
-        vmKnown = prefix + ' KNOWN\n'
-        lines = []
+        vmKnown = prefix + ' KNOWN'
         with open(jvmCfg) as f:
             for line in f:
-                if vmKnown in line:
+                if vmKnown == line.strip():
                     found = True
                     break
-                if not line.startswith(prefix):
-                    lines.append(line)
         if not found:
             mx.log('Appending "' + prefix + ' KNOWN" to ' + jvmCfg)
-            lines.append(vmKnown)
             if mx.get_os() != 'windows':
                 os.chmod(jvmCfg, 0755)
-            with open(jvmCfg, 'w') as f:
-                for line in lines:
-                    f.write(line)
+            with open(jvmCfg, 'a') as f:
+                print >> f, vmKnown
 
         if exists(timestampFile):
             os.utime(timestampFile, None)
@@ -627,7 +677,7 @@
         vm = _vm
 
     build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product'
-    jdk = _jdk(build)
+    jdk = _jdk(build, vmToCheck=vm)
     mx.expand_project_in_args(args)
     if _make_eclipse_launch:
         mx.make_eclipse_launch(args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True))
@@ -654,6 +704,7 @@
         args = ['-javaagent:' + jacocoagent.get_path(True) + '=' + ','.join([k + '=' + v for k, v in agentOptions.items()])] + args
     if '-d64' not in args:
         args = ['-d64'] + args
+
     exe = join(jdk, 'bin', mx.exe_suffix('java'))
     dbg = _native_dbg.split() if _native_dbg is not None else []
     return mx.run(dbg + [exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
@@ -668,7 +719,7 @@
     matches = lambda line : len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0
     return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses)
 
-def _run_tests(args, harness):
+def _run_tests(args, harness, annotations, testfile):
     pos = [a for a in args if a[0] != '-' and a[0] != '@' ]
     neg = [a[1:] for a in args if a[0] == '-']
     vmArgs = [a[1:] for a in args if a[0] == '@']
@@ -679,29 +730,66 @@
                 return True
         return False
 
+    classes = []
     for p in mx.projects():
-        classes = _find_classes_with_annotations(p, None, ['@Test'])
+        classes += _find_classes_with_annotations(p, None, annotations)
 
         if len(pos) != 0:
             classes = [c for c in classes if containsAny(c, pos)]
         if len(neg) != 0:
             classes = [c for c in classes if not containsAny(c, neg)]
 
-        if len(classes) != 0:
-            mx.log('running tests in ' + p.name)
-            harness(p, vmArgs, classes)
+    projectscp = mx.classpath([pcp.name for pcp in mx.projects()])
+
+    if len(classes) != 0:
+        f_testfile = open(testfile, 'w')
+        for c in classes:
+            f_testfile.write(c + '\n')
+        f_testfile.close()
+        harness(projectscp, vmArgs)
+
+def _unittest(args, annotations):
+    mxdir = dirname(__file__)
+    name = 'JUnitWrapper'
+    javaSource = join(mxdir, name + '.java')
+    javaClass = join(mxdir, name + '.class')
+    (_, testfile) = tempfile.mkstemp(".testclasses", "graal")
+
+    def harness(projectscp, vmArgs):
+        if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
+            subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource])
+        prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea']
+        vm(prefixArgs + vmArgs + ['-cp', projectscp + ':' + mxdir, name] + [testfile])
+
+    _run_tests(args, harness, annotations, testfile)
+    os.remove(testfile)
 
 def unittest(args):
-    """run the JUnit tests
+    """run the JUnit tests (all testcases)
 
     If filters are supplied, only tests whose fully qualified name
     include a filter as a substring are run. Negative filters are
     those with a '-' prefix. VM args should have a @ prefix."""
 
-    def harness(p, vmArgs, classes):
-        prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea']
-        vm(prefixArgs + vmArgs + ['-cp', mx.classpath(p.name), 'org.junit.runner.JUnitCore'] + classes)
-    _run_tests(args, harness)
+    _unittest(args, ['@Test', '@LongTest'])
+
+def shortunittest(args):
+    """run the JUnit tests (short testcases only)
+
+    If filters are supplied, only tests whose fully qualified name
+    include a filter as a substring are run. Negative filters are
+    those with a '-' prefix. VM args should have a @ prefix."""
+
+    _unittest(args, ['@Test'])
+
+def longunittest(args):
+    """run the JUnit tests (long testcases only)
+
+    If filters are supplied, only tests whose fully qualified name
+    include a filter as a substring are run. Negative filters are
+    those with a '-' prefix. VM args should have a @ prefix."""
+
+    _unittest(args, ['@LongTest'])
 
 def buildvms(args):
     """build one or more VMs in various configurations"""
@@ -784,11 +872,22 @@
             if mx.eclipseformat(['-e', eclipse_exe]) != 0:
                 t.abort('Formatter modified files - run "mx eclipseformat", check in changes and repush')
             tasks.append(t.stop())
+
+        t = Task('Canonicalization Check')
+        mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...'))
+        if mx.canonicalizeprojects([]) != 0:
+            t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.')
+        tasks.append(t.stop())
         
         t = Task('BuildJava')
         build(['--no-native', '--jdt-warning-as-error'])
         tasks.append(t.stop())
         
+        t = Task('Checkstyle')
+        if mx.checkstyle([]) != 0:
+            t.abort('Checkstyle warnings were found')
+        tasks.append(t.stop())
+        
         if exists('jacoco.exec'):
             os.unlink('jacoco.exec')
         
@@ -796,10 +895,9 @@
             _jacoco = 'append'
         else:
             _jacoco = 'off'
-        
 
         t = Task('BuildHotSpotGraal: fastdebug,product')
-        buildvms(['--vms', 'graal', '--builds', 'fastdebug,product'])
+        buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product'])
         tasks.append(t.stop())
 
         _vmbuild = 'fastdebug'
@@ -808,9 +906,16 @@
         tasks.append(t.stop())
 
         _vmbuild = 'product'
-        t = Task('UnitTests:product')
+        t = Task('BootstrapWithRegisterPressure:product')
+        vm(['-G:RegisterPressure=rbx,r11,r14,xmm3,xmm11,xmm14', '-esa', '-version'])
+        tasks.append(t.stop())
+
+        originalVm = _vm
+        _vm = 'server' # hosted mode
+        t = Task('UnitTests:hosted-product')
         unittest([])
         tasks.append(t.stop())
+        _vm = originalVm
 
         for vmbuild in ['fastdebug', 'product']:
             for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild):
@@ -824,17 +929,6 @@
             
         _jacoco = 'off'
 
-        t = Task('Checkstyle')
-        if mx.checkstyle([]) != 0:
-            t.abort('Checkstyle warnings were found')
-        tasks.append(t.stop())
-
-        t = Task('Canonicalization Check')
-        mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...'))
-        if mx.canonicalizeprojects([]) != 0:
-            t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.')
-        tasks.append(t.stop())
-
         t = Task('CleanAndBuildGraalVisualizer')
         mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-q', 'clean', 'build'])
         tasks.append(t.stop())
@@ -1016,6 +1110,24 @@
         benchArgs.remove(args[itIdx+1])
     vm = _vm;
     sanitycheck.getSPECjvm2008(benchArgs, skipCheck, skipValid, wt, it).bench(vm, opts=vmArgs)
+    
+def specjbb2013(args):
+    """runs the composite SPECjbb2013 benchmark
+
+    All options begining with - will be passed to the vm"""
+    benchArgs = [a for a in args if a[0] != '-']
+    vmArgs = [a for a in args if a[0] == '-']
+    vm = _vm;
+    sanitycheck.getSPECjbb2013(benchArgs).bench(vm, opts=vmArgs)
+
+def specjbb2005(args):
+    """runs the composite SPECjbb2005 benchmark
+        
+        All options begining with - will be passed to the vm"""
+    benchArgs = [a for a in args if a[0] != '-']
+    vmArgs = [a for a in args if a[0] == '-']
+    vm = _vm;
+    sanitycheck.getSPECjbb2005(benchArgs).bench(vm, opts=vmArgs)
 
 def hsdis(args, copyToDir=None):
     """download the hsdis library
@@ -1094,20 +1206,6 @@
         mx.abort('jacocoreport takes only one argument : an output directory')
     mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out])
 
-def jar(args):
-    parser = ArgumentParser(prog='mx jar');
-    parser.add_argument('projects', nargs=REMAINDER, metavar='projects...')
-    args = parser.parse_args(args)
-    
-    if not args.projects:
-        mx.abort('Please specify at least one project to jar.')
-    
-    for pname in args.projects:
-        p = mx.project(pname, fatalIfMissing=True)
-        outputDir = p.output_dir()
-        targetJar = join(p.dir, p.name + '.jar')
-        mx.jar(targetJar, [outputDir])
-
 def site(args):
     """create a website containing javadoc and the project dependency graph"""
 
@@ -1129,17 +1227,21 @@
         'clean': [clean, ''],
         'hsdis': [hsdis, '[att]'],
         'hcfdis': [hcfdis, ''],
+        'initantbuild' : [initantbuild, '[-options]'],
         'igv' : [igv, ''],
         'jdkhome': [jdkhome, ''],
         'dacapo': [dacapo, '[[n] benchmark] [VM options|@DaCapo options]'],
         'scaladacapo': [scaladacapo, '[[n] benchmark] [VM options|@Scala DaCapo options]'],
-        'specjvm2008': [specjvm2008, '[VM options|@specjvm2008 options]'],
-        'jar': [jar, '[-options]'],
+        'specjvm2008': [specjvm2008, '[VM options|specjvm2008 options (-v, -ikv, -ict, -wt, -it)]'],
+        'specjbb2013': [specjbb2013, '[VM options]'],
+        'specjbb2005': [specjbb2005, '[VM options]'],
         #'example': [example, '[-v] example names...'],
         'gate' : [gate, '[-options]'],
         'gv' : [gv, ''],
         'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
         'unittest' : [unittest, '[filters...]'],
+        'longunittest' : [longunittest, '[filters...]'],
+        'shortunittest' : [shortunittest, '[filters...]'],
         'jacocoreport' : [jacocoreport, '[output directory]'],
         'site' : [site, '[-options]'],
         'vm': [vm, '[-options] class [args...]'],
@@ -1168,23 +1270,10 @@
 
     mx.commands.update(commands)
 
-def mx_post_parse_cmd_line(opts):
-    version = mx.java().version.split('-')[0]
-    parts = version.split('.')
-    assert len(parts) >= 2
-    assert parts[0] == '1'
-    major = int(parts[1])
-    minor = 0
-    update = 0
-    if len(parts) >= 3:
-        minorParts = parts[2].split('_')
-        if len(minorParts) >= 1:
-            minor = int(minorParts[0])
-        if len(minorParts) >= 2:
-            update = int(minorParts[1])
-    
-    if (not major >= 7) or (major == 7 and minor == 0 and not update >= 4) :
-        mx.abort('Requires Java version 1.7.0_04 or greater, got version ' + version)
+def mx_post_parse_cmd_line(opts):#
+    # TODO _minVersion check could probably be part of a Suite in mx?
+    if (mx.java().version < _minVersion) :
+        mx.abort('Requires Java version ' + str(_minVersion) + ' or greater, got version ' + str(mx.java().version))
 
     if (_vmSourcesAvailable):
         if hasattr(opts, 'vm') and opts.vm is not None:
@@ -1199,3 +1288,5 @@
     _jacoco = opts.jacoco
     global _native_dbg
     _native_dbg = opts.native_dbg
+
+    mx.distribution('GRAAL').add_update_listener(_installGraalJarInJdks)
--- a/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Thu Mar 21 11:30:38 2013 +0100
+++ b/mx/eclipse-settings/org.eclipse.jdt.core.prefs	Thu Mar 21 14:11:13 2013 +0100
@@ -132,7 +132,7 @@
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=48
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
@@ -140,7 +140,7 @@
 org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
-org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=48
 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
 org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
@@ -149,7 +149,7 @@
 org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0
 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=48
 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
--- a/mx/projects	Thu Mar 21 11:30:38 2013 +0100
+++ b/mx/projects	Thu Mar 21 14:11:13 2013 +0100
@@ -22,6 +22,9 @@
 library@DACAPO_SCALA@path=lib/dacapo-scala-0.1.0-20120216.jar
 library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar
 
+distribution@GRAAL@path=graal.jar
+distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.sparc
+
 # graal.api.runtime
 project@com.oracle.graal.api.runtime@subDir=graal
 project@com.oracle.graal.api.runtime@sourceDirs=src
@@ -62,6 +65,13 @@
 project@com.oracle.graal.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.amd64@javaCompliance=1.7
 
+# graal.ptx
+project@com.oracle.graal.ptx@subDir=graal
+project@com.oracle.graal.ptx@sourceDirs=src
+project@com.oracle.graal.ptx@dependencies=com.oracle.graal.api.code
+project@com.oracle.graal.ptx@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.ptx@javaCompliance=1.7
+
 # graal.sparc
 project@com.oracle.graal.sparc@subDir=graal
 project@com.oracle.graal.sparc@sourceDirs=src
@@ -79,7 +89,7 @@
 # graal.hotspot.amd64
 project@com.oracle.graal.hotspot.amd64@subDir=graal
 project@com.oracle.graal.hotspot.amd64@sourceDirs=src
-project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.hotspot,com.oracle.graal.compiler.amd64
+project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.hotspot,com.oracle.graal.compiler.amd64,com.oracle.graal.snippets.amd64
 project@com.oracle.graal.hotspot.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.amd64@javaCompliance=1.7
 
@@ -104,6 +114,13 @@
 project@com.oracle.graal.hotspot.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.test@javaCompliance=1.7
 
+# graal.hotspot.amd64.test
+project@com.oracle.graal.hotspot.amd64.test@subDir=graal
+project@com.oracle.graal.hotspot.amd64.test@sourceDirs=src
+project@com.oracle.graal.hotspot.amd64.test@dependencies=com.oracle.graal.asm.amd64,com.oracle.graal.compiler.test
+project@com.oracle.graal.hotspot.amd64.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.hotspot.amd64.test@javaCompliance=1.7
+
 # graal.graph
 project@com.oracle.graal.graph@subDir=graal
 project@com.oracle.graal.graph@sourceDirs=src
@@ -137,6 +154,13 @@
 project@com.oracle.graal.lir.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir.amd64@javaCompliance=1.7
 
+# graal.lir.ptx
+project@com.oracle.graal.lir.ptx@subDir=graal
+project@com.oracle.graal.lir.ptx@sourceDirs=src
+project@com.oracle.graal.lir.ptx@dependencies=com.oracle.graal.asm.ptx,com.oracle.graal.lir
+project@com.oracle.graal.lir.ptx@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.lir.ptx@javaCompliance=1.7
+
 # graal.lir.sparc
 project@com.oracle.graal.lir.sparc@subDir=graal
 project@com.oracle.graal.lir.sparc@sourceDirs=src
@@ -165,6 +189,13 @@
 project@com.oracle.graal.snippets@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.snippets@javaCompliance=1.7
 
+# graal.snippets.amd64
+project@com.oracle.graal.snippets.amd64@subDir=graal
+project@com.oracle.graal.snippets.amd64@sourceDirs=src
+project@com.oracle.graal.snippets.amd64@dependencies=com.oracle.graal.snippets
+project@com.oracle.graal.snippets.amd64@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.snippets.amd64@javaCompliance=1.7
+
 # graal.snippets.test
 project@com.oracle.graal.snippets.test@subDir=graal
 project@com.oracle.graal.snippets.test@sourceDirs=src
@@ -221,6 +252,27 @@
 project@com.oracle.graal.compiler.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.amd64@javaCompliance=1.7
 
+# graal.compiler.amd64.test
+project@com.oracle.graal.compiler.amd64.test@subDir=graal
+project@com.oracle.graal.compiler.amd64.test@sourceDirs=src
+project@com.oracle.graal.compiler.amd64.test@dependencies=com.oracle.graal.compiler.test
+project@com.oracle.graal.compiler.amd64.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.compiler.amd64.test@javaCompliance=1.7
+
+# graal.compiler.ptx
+project@com.oracle.graal.compiler.ptx@subDir=graal
+project@com.oracle.graal.compiler.ptx@sourceDirs=src
+project@com.oracle.graal.compiler.ptx@dependencies=com.oracle.graal.compiler,com.oracle.graal.lir.ptx
+project@com.oracle.graal.compiler.ptx@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.compiler.ptx@javaCompliance=1.7
+
+# graal.compiler.ptx.test
+project@com.oracle.graal.compiler.ptx.test@subDir=graal
+project@com.oracle.graal.compiler.ptx.test@sourceDirs=src
+project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test,com.oracle.graal.ptx
+project@com.oracle.graal.compiler.ptx.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.compiler.ptx.test@javaCompliance=1.7
+
 # graal.compiler.sparc
 project@com.oracle.graal.compiler.sparc@subDir=graal
 project@com.oracle.graal.compiler.sparc@sourceDirs=src
@@ -297,6 +349,13 @@
 project@com.oracle.graal.asm.amd64.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.asm.amd64.test@javaCompliance=1.7
 
+# graal.asm.ptx
+project@com.oracle.graal.asm.ptx@subDir=graal
+project@com.oracle.graal.asm.ptx@sourceDirs=src
+project@com.oracle.graal.asm.ptx@dependencies=com.oracle.graal.asm
+project@com.oracle.graal.asm.ptx@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.asm.ptx@javaCompliance=1.7
+
 # graal.asm.sparc
 project@com.oracle.graal.asm.sparc@subDir=graal
 project@com.oracle.graal.asm.sparc@sourceDirs=src
@@ -321,21 +380,29 @@
 # truffle.api.codegen
 project@com.oracle.truffle.api.codegen@subDir=graal
 project@com.oracle.truffle.api.codegen@sourceDirs=src
-project@com.oracle.truffle.api.codegen@dependencies=
+project@com.oracle.truffle.api.codegen@dependencies=com.oracle.truffle.api
 project@com.oracle.truffle.api.codegen@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.api.codegen@javaCompliance=1.7
 
+# truffle.api.codegen.test
+project@com.oracle.truffle.api.codegen.test@subDir=graal
+project@com.oracle.truffle.api.codegen.test@sourceDirs=src
+project@com.oracle.truffle.api.codegen.test@dependencies=com.oracle.truffle.api.codegen,JUNIT
+project@com.oracle.truffle.api.codegen.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.truffle.api.codegen.test@javaCompliance=1.7
+project@com.oracle.truffle.api.codegen.test@annotationProcessors=com.oracle.truffle.codegen.processor
+
 # truffle.codegen.processor
 project@com.oracle.truffle.codegen.processor@subDir=graal
 project@com.oracle.truffle.codegen.processor@sourceDirs=src
-project@com.oracle.truffle.codegen.processor@dependencies=com.oracle.truffle.api.codegen,com.oracle.truffle.api
+project@com.oracle.truffle.codegen.processor@dependencies=com.oracle.truffle.api.codegen
 project@com.oracle.truffle.codegen.processor@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.codegen.processor@javaCompliance=1.7
 
 # truffle.sl
 project@com.oracle.truffle.sl@subDir=graal
 project@com.oracle.truffle.sl@sourceDirs=src
-project@com.oracle.truffle.sl@dependencies=com.oracle.truffle.api.codegen,com.oracle.truffle.api
+project@com.oracle.truffle.sl@dependencies=com.oracle.truffle.api.codegen
 project@com.oracle.truffle.sl@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.sl@javaCompliance=1.7
 project@com.oracle.truffle.sl@annotationProcessors=com.oracle.truffle.codegen.processor
--- a/mx/sanitycheck.py	Thu Mar 21 11:30:38 2013 +0100
+++ b/mx/sanitycheck.py	Thu Mar 21 14:11:13 2013 +0100
@@ -49,7 +49,7 @@
 dacapoScalaSanityWarmup = {
     'actors':     [0, 0, 2,  8, 10],
 # (lstadler) apparat was disabled due to a deadlock which I think is the benchmarks fault.
-#    'apparat':    [0, 0, 1,  2,  3],
+    'apparat':    [0, 0, 0,  0,  0],
     'factorie':   [0, 0, 2,  5,  5],
     'kiama':      [0, 0, 3, 13, 15],
     'scalac':     [0, 0, 5, 15, 20],
@@ -58,7 +58,8 @@
     'scalariform':[0, 0, 6, 15, 20],
     'scalatest':  [0, 0, 2, 10, 12],
     'scalaxb':    [0, 0, 5, 15, 25],
-    'specs':      [0, 0, 3, 13, 18],
+#(gdub) specs sometimes returns a non-zero value event though there is no apparent failure
+    'specs':      [0, 0, 0,  0,  0],
     'tmt':        [0, 0, 3, 10, 12]
 }
 
@@ -121,7 +122,7 @@
     success = re.compile(r"org.spec.jbb.controller: Run finished", re.MULTILINE)
     matcherMax = ValuesMatcher(jops, {'group' : 'SPECjbb2013', 'name' : 'max', 'score' : '<max>'})
     matcherCritical = ValuesMatcher(jops, {'group' : 'SPECjbb2013', 'name' : 'critical', 'score' : '<critical>'})
-    return Test("SPECjbb2013", ['-jar', 'specjbb2013.jar', '-m', 'composite'] + benchArgs, [success], [], [matcherCritical, matcherMax], vmOpts=['-Xms7g', '-XX:+'+gc, '-XX:-UseCompressedOops'], defaultCwd=specjbb2013)
+    return Test("SPECjbb2013", ['-jar', 'specjbb2013.jar', '-m', 'composite'] + benchArgs, [success], [], [matcherCritical, matcherMax], vmOpts=['-Xmx6g', '-Xms6g', '-Xmn3g', '-XX:+UseParallelOldGC', '-XX:-UseAdaptiveSizePolicy', '-XX:-UseBiasedLocking', '-XX:-UseCompressedOops'], defaultCwd=specjbb2013)
     
 def getSPECjvm2008(benchArgs = [], skipCheck=False, skipKitValidation=False, warmupTime=None, iterationTime=None):
     
@@ -272,9 +273,12 @@
         if len(valueMaps) == 0:
             return False
         
-        assert len(valueMaps) == 1, 'Test matchers should not return more than one record'
-        
-        record = valueMaps[0]
+        record = {}
+        for valueMap in valueMaps:
+            for key, value in valueMap.items():
+                if record.has_key(key) and record[key] != value:
+                    mx.abort('Inconsistant values returned by test machers : ' + str(valueMaps))
+                record[key] = value
         
         jvmErrorFile = record.get('jvmError')
         if jvmErrorFile:
--- a/mxtool/mx.py	Thu Mar 21 11:30:38 2013 +0100
+++ b/mxtool/mx.py	Thu Mar 21 14:11:13 2013 +0100
@@ -143,12 +143,36 @@
 
 _projects = dict()
 _libs = dict()
+_dists = dict()
 _suites = dict()
 _mainSuite = None
 _opts = None
 _java = None
 
 """
+A distribution is a jar or zip file containing the output from one or more Java projects.
+"""
+class Distribution:
+    def __init__(self, suite, name, path, deps):
+        self.suite = suite
+        self.name = name
+        self.path = path.replace('/', os.sep)
+        if not isabs(self.path):
+            self.path = join(suite.dir, self.path)
+        self.deps = deps
+        self.update_listeners = set()
+        
+    def __str__(self):
+        return self.name
+    
+    def add_update_listener(self, listener):
+        self.update_listeners.add(listener)
+        
+    def notify_updated(self):
+        for l in self.update_listeners:
+            l(self)
+    
+"""
 A dependency is a library or project specified in a suite.
 """
 class Dependency:
@@ -416,6 +440,7 @@
         self.dir = d
         self.projects = []
         self.libs = []
+        self.dists = []
         self.includes = []
         self.commands = None
         self.primary = primary
@@ -427,6 +452,7 @@
     def _load_projects(self, mxDir):
         libsMap = dict()
         projsMap = dict()
+        distsMap = dict()
         projectsFile = join(mxDir, 'projects')
         if not exists(projectsFile):
             return
@@ -447,8 +473,10 @@
                         m = projsMap
                     elif kind == 'library':
                         m = libsMap
+                    elif kind == 'distribution':
+                        m = distsMap
                     else:
-                        abort('Property name does not start with "project@" or "library@": ' + key)
+                        abort('Property name does not start with "project@", "library@" or "distribution@": ' + key)
 
                     attrs = m.get(name)
                     if attrs is None:
@@ -494,6 +522,13 @@
             l.__dict__.update(attrs)
             self.libs.append(l)
 
+        for name, attrs in distsMap.iteritems():
+            path = attrs.pop('path')
+            deps = pop_list(attrs, 'dependencies')
+            d = Distribution(self, name, path, deps)
+            d.__dict__.update(attrs)
+            self.dists.append(d)
+
     def _load_commands(self, mxDir):
         commands = join(mxDir, 'commands.py')
         if exists(commands):
@@ -536,8 +571,6 @@
     def _post_init(self, opts):
         mxDir = join(self.dir, 'mx')
         self._load_projects(mxDir)
-        if hasattr(self, 'mx_post_parse_cmd_line'):
-            self.mx_post_parse_cmd_line(opts)
         for p in self.projects:
             existing = _projects.get(p.name)
             if existing is not None:
@@ -549,6 +582,13 @@
             if existing is not None:
                 abort('cannot redefine library  ' + l.name)
             _libs[l.name] = l
+        for d in self.dists:
+            existing = _dists.get(l.name)
+            if existing is not None:
+                abort('cannot redefine distribution  ' + d.name)
+            _dists[d.name] = d
+        if hasattr(self, 'mx_post_parse_cmd_line'):
+            self.mx_post_parse_cmd_line(opts)
 
 class XMLElement(xml.dom.minidom.Element):
     def writexml(self, writer, indent="", addindent="", newl=""):
@@ -590,6 +630,9 @@
         e.ownerDocument = self
         return e
 
+    def comment(self, txt):
+        self.current.appendChild(self.createComment(txt))
+
     def open(self, tag, attributes={}, data=None):
         element = self.createElement(tag)
         for key, value in attributes.items():
@@ -653,6 +696,16 @@
     """
     return _projects.values()
 
+def distribution(name, fatalIfMissing=True):
+    """
+    Get the distribution for a given name. This will abort if the named distribution does
+    not exist and 'fatalIfMissing' is true.
+    """
+    d = _dists.get(name)
+    if d is None and fatalIfMissing:
+        abort('distribution named ' + name + ' not found')
+    return d
+
 def project(name, fatalIfMissing=True):
     """
     Get the project for a given name. This will abort if the named project does
@@ -1001,6 +1054,24 @@
             other = JavaCompliance(other)
 
         return cmp(self.value, other.value)
+    
+"""
+A Java version as defined in JSR-56
+"""
+class JavaVersion:
+    def __init__(self, versionString):
+        validChar = '[\x21-\x25\x27-\x29\x2c\x2f-\x5e\x60-\x7f]'
+        separator = '[.\-_]'
+        m = re.match(validChar + '+(' + separator + validChar + '+)*', versionString)
+        assert m is not None, 'not a recognized version string: ' + versionString
+        self.versionString = versionString;
+        self.parts = [int(f) if f.isdigit() else f for f in re.split(separator, versionString)]
+        
+    def __str__(self):
+        return self.versionString
+    
+    def __cmp__(self, other):
+        return cmp(self.parts, other.parts)
 
 """
 A JavaConfig object encapsulates info on how Java commands are run.
@@ -1039,8 +1110,8 @@
 
         output = output.split()
         assert output[1] == 'version'
-        self.version = output[2].strip('"')
-        self.javaCompliance = JavaCompliance(self.version)
+        self.version = JavaVersion(output[2].strip('"'))
+        self.javaCompliance = JavaCompliance(self.version.versionString)
 
         if self.debug_port is not None:
             self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(self.debug_port)]
@@ -1459,6 +1530,9 @@
         finally:
             for n in toBeDeleted:
                 os.remove(n)
+                
+    for dist in _dists.values():
+        archive(['@' + dist.name])
 
     if suppliedParser:
         return args
@@ -1557,59 +1631,59 @@
     return 0
 
 def processorjars():
-    projects = set([])
+    projects = set()
     
     for p in sorted_deps():
-        if _needsEclipseJarBuild(p):
+        if _isAnnotationProcessorDependency(p):
             projects.add(p)
             
     if len(projects) <= 0:
         return
     
-    build(['--projects', ",".join(map(lambda p: p.name, projects))])
-
-    for p in projects:
-        targetJar = join(p.dir, p.name + '.jar')
-        jar(targetJar, [p.output_dir()])
-            
-
-def jar(destFileName, dirs):
-    latestMod = _latestModification(dirs)
-    
-    if exists(destFileName):
-        mod = os.path.getmtime(destFileName)
-        if int(round(latestMod*1000)) == int(round(mod*1000)):
-            # nothing todo
-            return
-        
-    if latestMod is None and exists(destFileName):
-        return
-
-    jarCmd = [java().jar, 'cf', destFileName]
+    pnames = [p.name for p in projects]
+    build(['--projects', ",".join(pnames)])
+    archive(pnames)
+
+def archive(args):
+    """create jar files for projects and distributions"""
+    parser = ArgumentParser(prog='mx archive');
+    parser.add_argument('names', nargs=REMAINDER, metavar='[<project>|@<distribution>]...')
+    args = parser.parse_args(args)
     
-    for directory in dirs:
-        jarCmd += ['-C', directory, '.']
-    
-    subprocess.check_call(jarCmd)
-    log('Written jar file {0}'.format(destFileName))
-    
-    atime = os.path.getatime(destFileName)
-    os.utime(destFileName, (atime, latestMod))
-
-def _latestModification(directories):
-    latestMod = None
-    for directory in directories:
-        if not os.path.exists (directory):
-            continue
-        for root, _, files in os.walk(directory):
-                for names in files:
-                    filepath = os.path.join(root, names)
-                    mod = os.path.getmtime(filepath)
-                    if latestMod is None:
-                        latestMod = mod
-                    elif mod > latestMod:
-                        latestMod = mod
-    return latestMod
+    for name in args.names:
+        if name.startswith('@'):
+            dname = name[1:]
+            d = distribution(dname)
+            fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(d.path) + '.', dir=dirname(d.path))
+            zf = zipfile.ZipFile(tmp, 'w')
+            for p in sorted_deps(d.deps):
+                outputDir = p.output_dir()
+                for root, _, files in os.walk(outputDir):
+                    for f in files:
+                        relpath = root[len(outputDir) + 1:]
+                        arcname = join(relpath, f).replace(os.sep, '/')
+                        zf.write(join(root, f), arcname)
+            zf.close()
+            os.close(fd)
+            # Atomic on Unix
+            shutil.move(tmp, d.path)
+            #print time.time(), 'move:', tmp, '->', d.path
+            d.notify_updated()
+
+        else:
+            p = project(name)
+            outputDir = p.output_dir()
+            fd, tmp = tempfile.mkstemp(suffix='', prefix=p.name, dir=p.dir)
+            zf = zipfile.ZipFile(tmp, 'w')
+            for root, _, files in os.walk(outputDir):
+                for f in files:
+                    relpath = root[len(outputDir) + 1:]
+                    arcname = join(relpath, f).replace(os.sep, '/')
+                    zf.write(join(root, f), arcname)
+            zf.close()
+            os.close(fd)
+            # Atomic on Unix
+            shutil.move(tmp, join(p.dir, p.name + '.jar'))
 
 def canonicalizeprojects(args):
     """process all project files to canonicalize the dependencies
@@ -1989,6 +2063,12 @@
     if buildProcessorJars:
         processorjars()
 
+    projToDist = dict()
+    for dist in _dists.values():
+        distDeps = sorted_deps(dist.deps)
+        for p in distDeps:
+            projToDist[p.name] = (dist, [dep.name for dep in distDeps])
+
     for p in projects():
         if p.native:
             continue
@@ -2103,24 +2183,14 @@
                 out.element('arguments', data='')
                 out.close('buildCommand')
 
-        if (_needsEclipseJarBuild(p)):
-            targetValues = _genEclipseJarBuild(p);
-            for value in targetValues:
-                out.open('buildCommand')
-                out.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder')
-                out.element('triggers', data='auto,full,incremental,')
-                out.open('arguments')
-                out.open('dictionary')
-                out.element('key', data = 'LaunchConfigHandle')
-                out.element('value', data = value)
-                out.close('dictionary')
-                out.open('dictionary')
-                out.element('key', data = 'incclean')
-                out.element('value', data = 'true')
-                out.close('dictionary')
-                out.close('arguments')
-                out.close('buildCommand')       
-                    
+        if _isAnnotationProcessorDependency(p):
+            _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh = False, async = False)
+            _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh = True, async = True)
+                       
+        if projToDist.has_key(p.name):
+            dist, distDeps = projToDist[p.name]
+            _genEclipseBuilder(out, p, 'Create' + dist.name + 'Dist.launch', 'archive @' + dist.name, refresh=False, async=True)
+        
         out.close('buildSpec')
         out.open('natures')
         out.element('nature', data='org.eclipse.jdt.core.javanature')
@@ -2175,8 +2245,11 @@
     make_eclipse_attach('localhost', '8000', deps=projects())
 
 
-def _needsEclipseJarBuild(p):
-    processors = set([])
+def _isAnnotationProcessorDependency(p):
+    """
+    Determines if a given project is part of an annotation processor.
+    """
+    processors = set()
     
     for otherProject in projects():
         if hasattr(otherProject, 'annotationProcessors') and len(otherProject.annotationProcessors) > 0:
@@ -2193,19 +2266,18 @@
     
     return False
 
-def _genEclipseJarBuild(p):
-    builders = []
-    builders.append(_genEclipseLaunch(p, 'Jar.launch', ''.join(['jar ', p.name]), refresh = False, async = False))
-    builders.append(_genEclipseLaunch(p, 'Refresh.launch', '', refresh = True, async = True))
-    return builders
-
-def _genEclipseLaunch(p, name, mxCommand, refresh=True, async=False):
+def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False):
     launchOut = XMLDoc();
+    consoleOn = 'true' if logToConsole else 'false'
     launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'})
+    launchOut.open('mapAttribute', {'key' : 'org.eclipse.debug.core.environmentVariables'})
+    launchOut.element('mapEntry', {'key' : 'JAVA_HOME',	'value' : java().jdk})
+    launchOut.close('mapAttribute')
+    
     if refresh:
         launchOut.element('stringAttribute',  {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE',            'value': '${project}'})
-    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output',                'value': 'false'})
-    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON',          'value': 'false'})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON',          'value': consoleOn})
+    launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output',                'value': consoleOn})
     if async:
         launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND',       'value': 'true'})
     
@@ -2229,9 +2301,21 @@
         os.makedirs(externalToolDir)
     update_file(join(externalToolDir, name), launchOut.xml(indent='\t', newl='\n'))
     
-    return ''.join(["<project>/.externalToolBuilders/", name])
-
-
+    dotProjectDoc.open('buildCommand')
+    dotProjectDoc.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder')
+    dotProjectDoc.element('triggers', data='auto,full,incremental,')
+    dotProjectDoc.open('arguments')
+    dotProjectDoc.open('dictionary')
+    dotProjectDoc.element('key', data = 'LaunchConfigHandle')
+    dotProjectDoc.element('value', data = '<project>/.externalToolBuilders/' + name)
+    dotProjectDoc.close('dictionary')
+    dotProjectDoc.open('dictionary')
+    dotProjectDoc.element('key', data = 'incclean')
+    dotProjectDoc.element('value', data = 'true')
+    dotProjectDoc.close('dictionary')
+    dotProjectDoc.close('arguments')
+    dotProjectDoc.close('buildCommand')
+    
 def netbeansinit(args, suite=None):
     """(re)generate NetBeans project configurations"""
 
@@ -2256,6 +2340,14 @@
         out.open('project', {'name' : p.name, 'default' : 'default', 'basedir' : '.'})
         out.element('description', data='Builds, tests, and runs the project ' + p.name + '.')
         out.element('import', {'file' : 'nbproject/build-impl.xml'})
+        out.open('target', {'name' : '-post-compile'})
+        out.open('exec', { 'executable' : sys.executable})
+        out.element('env', {'key' : 'JAVA_HOME', 'value' : java().jdk})
+        out.element('arg', {'value' : os.path.abspath(__file__)})
+        out.element('arg', {'value' : 'archive'})
+        out.element('arg', {'value' : '@GRAAL'})
+        out.close('exec')
+        out.close('target')
         out.close('project')
         updated = update_file(join(p.dir, 'build.xml'), out.xml(indent='\t', newl='\n')) or updated
 
@@ -2303,7 +2395,7 @@
         updated = update_file(join(p.dir, 'nbproject', 'project.xml'), out.xml(indent='    ', newl='\n')) or updated
 
         out = StringIO.StringIO()
-        jdkPlatform = 'JDK_' + java().version
+        jdkPlatform = 'JDK_' + str(java().version)
 
         annotationProcessorEnabled = "false"
         annotationProcessorReferences = ""
@@ -2444,7 +2536,7 @@
 
     if updated:
         log('If using NetBeans:')
-        log('  1. Ensure that a platform named "JDK ' + java().version + '" is defined (Tools -> Java Platforms)')
+        log('  1. Ensure that a platform named "JDK_' + str(java().version) + '" is defined (Tools -> Java Platforms)')
         log('  2. Open/create a Project Group for the directory containing the projects (File -> Project Group -> New Group... -> Folder of Projects)')
 
 def ideclean(args, suite=None):
@@ -2474,6 +2566,24 @@
     """(re)generate Eclipse and NetBeans project configurations"""
     eclipseinit(args, suite)
     netbeansinit(args, suite)
+    fsckprojects([])
+
+def fsckprojects(args):
+    """find directories corresponding to deleted Java projects and delete them"""
+    for suite in suites():
+        projectDirs = [p.dir for p in suite.projects]
+        for root, dirnames, files in os.walk(suite.dir):
+            currentDir = join(suite.dir, root)
+            if currentDir in projectDirs:
+                # don't traverse subdirs of an existing project
+                dirnames[:] = []
+            else:
+                projectConfigFiles = frozenset(['.classpath', 'nbproject'])
+                indicators = projectConfigFiles.intersection(files)
+                if len(indicators) != 0:
+                    if not sys.stdout.isatty() or raw_input(currentDir + ' looks like a removed project -- delete it? [yn]: ') == 'y':
+                        shutil.rmtree(currentDir)
+                        log('Deleted ' + currentDir)
 
 def javadoc(args, parser=None, docDir='javadoc', includeDeps=True):
     """generate javadoc for some/all Java projects"""
@@ -2926,9 +3036,11 @@
     'eclipseinit': [eclipseinit, ''],
     'eclipseformat': [eclipseformat, ''],
     'findclass': [findclass, ''],
+    'fsckprojects': [fsckprojects, ''],
     'help': [help_, '[command]'],
     'ideclean': [ideclean, ''],
     'ideinit': [ideinit, ''],
+    'archive': [archive, '[options]'],
     'projectgraph': [projectgraph, ''],
     'javap': [javap, ''],
     'javadoc': [javadoc, '[options]'],
--- a/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -30,10 +30,11 @@
 #include "c1/c1_Runtime1.hpp"
 #include "nativeInst_sparc.hpp"
 #include "runtime/sharedRuntime.hpp"
+#include "utilities/macros.hpp"
 #include "vmreg_sparc.inline.hpp"
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 #define __ ce->masm()->
 
@@ -420,7 +421,7 @@
 
 
 ///////////////////////////////////////////////////////////////////////////////////
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
 void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
   // At this point we know that marking is in progress.
@@ -483,7 +484,7 @@
   __ delayed()->nop();
 }
 
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 ///////////////////////////////////////////////////////////////////////////////////
 
 #undef __
--- a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -35,6 +35,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/vframeArray.hpp"
+#include "utilities/macros.hpp"
 #include "vmreg_sparc.inline.hpp"
 
 // Implementation of StubAssembler
@@ -822,7 +823,7 @@
       }
       break;
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case g1_pre_barrier_slow_id:
       { // G4: previous value of memory
         BarrierSet* bs = Universe::heap()->barrier_set();
@@ -984,7 +985,7 @@
         __ delayed()->restore();
       }
       break;
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
     default:
       { __ set_info("unimplemented entry", dont_gc_arguments);
--- a/src/cpu/sparc/vm/c2_globals_sparc.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -43,7 +43,7 @@
 #else
 define_pd_global(bool, ProfileInterpreter,           true);
 #endif // CC_INTERP
-define_pd_global(bool, TieredCompilation,            trueInTiered);
+define_pd_global(bool, TieredCompilation,            false);
 define_pd_global(intx, CompileThreshold,             10000);
 define_pd_global(intx, BackEdgeThreshold,            140000);
 
--- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -45,6 +45,7 @@
 #include "runtime/timer.hpp"
 #include "runtime/vframeArray.hpp"
 #include "utilities/debug.hpp"
+#include "utilities/macros.hpp"
 #ifdef SHARK
 #include "shark/shark_globals.hpp"
 #endif
@@ -551,7 +552,7 @@
 }
 
 address InterpreterGenerator::generate_Reference_get_entry(void) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   if (UseG1GC) {
     // We need to generate have a routine that generates code to:
     //   * load the value in the referent field
@@ -563,7 +564,7 @@
     // field as live.
     Unimplemented();
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // If G1 is not enabled then attempt to go through the accessor entry point
   // Reference.get is an accessor
--- a/src/cpu/sparc/vm/frame_sparc.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/frame_sparc.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -216,6 +216,11 @@
       }
     }
 
+    // Could just be some random pointer within the codeBlob
+    if (!_cb->code_contains(_pc)) {
+      return false;
+    }
+
     // Entry frame checks
     if (is_entry_frame()) {
       // an entry frame must have a valid fp.
--- a/src/cpu/sparc/vm/frame_sparc.inline.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/frame_sparc.inline.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -74,8 +74,7 @@
 
 // return address:
 
-inline address* frame::sender_pc_addr()   const { return (address*) (I7_addr() + pc_return_offset); }
-inline address  frame::sender_pc()        const { return *sender_pc_addr(); }
+inline address  frame::sender_pc()        const    { return *I7_addr() + pc_return_offset; }
 
 inline address* frame::I7_addr() const  { return (address*) &sp()[ I7->sp_offset_in_saved_window()]; }
 inline address* frame::I0_addr() const  { return (address*) &sp()[ I0->sp_offset_in_saved_window()]; }
--- a/src/cpu/sparc/vm/jniTypes_sparc.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/jniTypes_sparc.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -112,25 +112,6 @@
                                                           return *(jdouble *)&jl; }
 #endif
 
-  static inline jint    get_int   (intptr_t *from, int& pos) {
-    return get_int(from + pos++);
-  }
-  static inline jlong   get_long  (intptr_t *from, int& pos) {
-    jlong result = get_long(from + pos);
-    pos += 2;
-    return result;
-  }
-  static inline oop     get_obj   (intptr_t *from, int& pos) {
-    return get_obj(from + pos++);
-  }
-  static inline jfloat  get_float (intptr_t *from, int& pos) {
-    return get_float(from + pos++);
-  }
-  static inline jdouble get_double(intptr_t *from, int& pos) {
-    jdouble result = get_double(from + pos);
-    pos += 2;
-    return result;
-  }
 };
 
 #endif // CPU_SPARC_VM_JNITYPES_SPARC_HPP
--- a/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -36,11 +36,12 @@
 #include "runtime/os.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 #ifdef PRODUCT
 #define BLOCK_COMMENT(str) /* nothing */
@@ -3867,7 +3868,7 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////////
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
 static address satb_log_enqueue_with_frame = NULL;
 static u_char* satb_log_enqueue_with_frame_end = NULL;
@@ -4231,7 +4232,7 @@
   bind(filtered);
 }
 
-#endif  // SERIALGC
+#endif // INCLUDE_ALL_GCS
 ///////////////////////////////////////////////////////////////////////////////////
 
 void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_val, Register tmp) {
--- a/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -26,6 +26,7 @@
 #define CPU_SPARC_VM_MACROASSEMBLER_SPARC_HPP
 
 #include "asm/assembler.hpp"
+#include "utilities/macros.hpp"
 
 // <sys/trap.h> promises that the system will not use traps 16-31
 #define ST_RESERVED_FOR_USER_0 0x10
@@ -1181,13 +1182,13 @@
 
   void card_write_barrier_post(Register store_addr, Register new_val, Register tmp);
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // General G1 pre-barrier generator.
   void g1_write_barrier_pre(Register obj, Register index, int offset, Register pre_val, Register tmp, bool preserve_o_regs);
 
   // General G1 post-barrier generator
   void g1_write_barrier_post(Register store_addr, Register new_val, Register tmp);
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack
   void push_fTOS();
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -44,6 +44,7 @@
 #include "runtime/timer.hpp"
 #include "runtime/vframeArray.hpp"
 #include "utilities/debug.hpp"
+#include "utilities/macros.hpp"
 
 #ifndef CC_INTERP
 #ifndef FAST_DISPATCH
@@ -734,7 +735,7 @@
 
 // Method entry for java.lang.ref.Reference.get.
 address InterpreterGenerator::generate_Reference_get_entry(void) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // Code: _aload_0, _getfield, _areturn
   // parameter size = 1
   //
@@ -805,7 +806,7 @@
     (void) generate_normal_entry(false);
     return entry;
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // If G1 is not enabled then attempt to go through the accessor entry point
   // Reference.get is an accessor
--- a/src/cpu/sparc/vm/templateTable_sparc.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/sparc/vm/templateTable_sparc.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/synchronizer.hpp"
+#include "utilities/macros.hpp"
 
 #ifndef CC_INTERP
 #define __ _masm->
@@ -53,7 +54,7 @@
   assert(tmp != val && tmp != base && tmp != index, "register collision");
   assert(index == noreg || offset == 0, "only one offset");
   switch (barrier) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case BarrierSet::G1SATBCT:
     case BarrierSet::G1SATBCTLogging:
       {
@@ -82,7 +83,7 @@
         }
       }
       break;
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
     case BarrierSet::CardTableModRef:
     case BarrierSet::CardTableExtension:
       {
@@ -339,8 +340,6 @@
 
   __ bind(notInt);
  // __ cmp(O2, JVM_CONSTANT_String);
-  __ brx(Assembler::equal, true, Assembler::pt, isString);
-  __ delayed()->cmp(O2, JVM_CONSTANT_Object);
   __ brx(Assembler::notEqual, true, Assembler::pt, notString);
   __ delayed()->ldf(FloatRegisterImpl::S, O0, O1, Ftos_f);
   __ bind(isString);
--- a/src/cpu/x86/vm/assembler_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -36,11 +36,12 @@
 #include "runtime/os.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 #ifdef PRODUCT
 #define BLOCK_COMMENT(str) /* nothing */
@@ -2269,10 +2270,11 @@
 }
 
 void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256) {
-    int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector256);
-    emit_int8(0x00);
-    emit_int8(0xC0 | encode);
-    emit_int8(imm8);
+  assert(VM_Version::supports_avx2(), "");
+  int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector256);
+  emit_int8(0x00);
+  emit_int8(0xC0 | encode);
+  emit_int8(imm8);
 }
 
 void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) {
--- a/src/cpu/x86/vm/assembler_x86.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/assembler_x86.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -543,7 +543,7 @@
   // of instructions are freely declared without the need for wrapping them an ifdef.
   // (Some dangerous instructions are ifdef's out of inappropriate jvm's.)
   // In the .cpp file the implementations are wrapped so that they are dropped out
-  // of the resulting jvm. This is done mostly to keep the footprint of KERNEL
+  // of the resulting jvm. This is done mostly to keep the footprint of MINIMAL
   // to the size it was prior to merging up the 32bit and 64bit assemblers.
   //
   // This does mean you'll get a linker/runtime error if you use a 64bit only instruction
--- a/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -30,10 +30,11 @@
 #include "c1/c1_Runtime1.hpp"
 #include "nativeInst_x86.hpp"
 #include "runtime/sharedRuntime.hpp"
+#include "utilities/macros.hpp"
 #include "vmreg_x86.inline.hpp"
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 
 #define __ ce->masm()->
@@ -482,7 +483,7 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
 void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
   // At this point we know that marking is in progress.
@@ -528,7 +529,7 @@
   __ jmp(_continuation);
 }
 
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 /////////////////////////////////////////////////////////////////////////////
 
 #undef __
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -36,6 +36,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/vframeArray.hpp"
+#include "utilities/macros.hpp"
 #include "vmreg_x86.inline.hpp"
 
 
@@ -1607,7 +1608,7 @@
       }
       break;
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case g1_pre_barrier_slow_id:
       {
         StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments);
@@ -1804,7 +1805,7 @@
 
       }
       break;
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
     default:
       { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments);
--- a/src/cpu/x86/vm/c2_globals_x86.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/c2_globals_x86.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -45,7 +45,7 @@
 #else
 define_pd_global(bool, ProfileInterpreter,           true);
 #endif // CC_INTERP
-define_pd_global(bool, TieredCompilation,            trueInTiered);
+define_pd_global(bool, TieredCompilation,            false);
 define_pd_global(intx, CompileThreshold,             10000);
 define_pd_global(intx, BackEdgeThreshold,            100000);
 
--- a/src/cpu/x86/vm/cppInterpreter_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -45,6 +45,7 @@
 #include "runtime/timer.hpp"
 #include "runtime/vframeArray.hpp"
 #include "utilities/debug.hpp"
+#include "utilities/macros.hpp"
 #ifdef SHARK
 #include "shark/shark_globals.hpp"
 #endif
@@ -938,7 +939,7 @@
 }
 
 address InterpreterGenerator::generate_Reference_get_entry(void) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   if (UseG1GC) {
     // We need to generate have a routine that generates code to:
     //   * load the value in the referent field
@@ -950,7 +951,7 @@
     // field as live.
     Unimplemented();
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // If G1 is not enabled then attempt to go through the accessor entry point
   // Reference.get is an accessor
--- a/src/cpu/x86/vm/frame_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/frame_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -91,6 +91,12 @@
         return false;
       }
     }
+
+    // Could just be some random pointer within the codeBlob
+    if (!_cb->code_contains(_pc)) {
+      return false;
+    }
+
     // Entry frame checks
     if (is_entry_frame()) {
       // an entry frame must have a valid fp.
@@ -302,11 +308,6 @@
   ptr_at_put(interpreter_frame_sender_sp_offset, (intptr_t) sender_sp);
 }
 
-intptr_t** frame::interpreter_frame_sender_sp_addr() const {
-  assert(is_interpreted_frame(), "interpreted frame expected");
-  return (intptr_t**) addr_at(interpreter_frame_sender_sp_offset);
-}
-
 
 // monitor elements
 
--- a/src/cpu/x86/vm/frame_x86.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/frame_x86.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -191,12 +191,13 @@
   // Note: not necessarily the real 'frame pointer' (see real_fp)
   intptr_t*   fp() const { return _fp; }
 
+  inline address* sender_pc_addr() const;
+
   // return address of param, zero origin index.
   inline address* native_param_addr(int idx) const;
 
   // expression stack tos if we are nested in a java call
   intptr_t* interpreter_frame_last_sp() const;
-  intptr_t** interpreter_frame_last_sp_addr() const;
 
   // helper to update a map with callee-saved RBP
   static void update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr);
--- a/src/cpu/x86/vm/frame_x86.inline.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/frame_x86.inline.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -133,9 +133,8 @@
 
 
 
-inline intptr_t*  frame::link() const              { return (intptr_t*) *(intptr_t **)addr_at(link_offset); }
-inline intptr_t** frame::link_addr() const         { return (intptr_t **)addr_at(link_offset); }
-inline void       frame::set_link(intptr_t* addr)  { *(intptr_t **)addr_at(link_offset) = addr; }
+inline intptr_t* frame::link() const              { return (intptr_t*) *(intptr_t **)addr_at(link_offset); }
+inline void      frame::set_link(intptr_t* addr)  { *(intptr_t **)addr_at(link_offset) = addr; }
 
 
 inline intptr_t* frame::unextended_sp() const     { return _unextended_sp; }
@@ -211,10 +210,6 @@
   return *(intptr_t**)addr_at(interpreter_frame_last_sp_offset);
 }
 
-inline intptr_t** frame::interpreter_frame_last_sp_addr() const {
-  return (intptr_t**)addr_at(interpreter_frame_last_sp_offset);
-}
-
 inline intptr_t* frame::interpreter_frame_bcx_addr() const {
   return (intptr_t*)addr_at(interpreter_frame_bcx_offset);
 }
--- a/src/cpu/x86/vm/graalRuntime_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/graalRuntime_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -46,12 +46,6 @@
   assert(!(oop_result1->is_valid() || metadata_result->is_valid()) || oop_result1 != metadata_result, "registers must be different");
   assert(oop_result1 != thread && metadata_result != thread, "registers must be different");
   assert(args_size >= 0, "illegal args_size");
-  bool align_stack = false;
-#ifdef _LP64
-  // At a method handle call, the stack may not be properly aligned
-  // when returning with an exception.
-  align_stack = (stub_id() == false /*GraalRuntime::handle_exception_from_callee_id*/);
-#endif
 
 #ifdef _LP64
   mov(c_rarg0, thread);
@@ -65,20 +59,11 @@
 #endif // _LP64
 
   int call_offset;
-  if (!align_stack) {
-    set_last_Java_frame(thread, noreg, rbp, NULL);
-  } else {
-    address the_pc = pc();
-    call_offset = offset();
-    set_last_Java_frame(thread, noreg, rbp, the_pc);
-    andptr(rsp, -(StackAlignmentInBytes));    // Align stack
-  }
+  set_last_Java_frame(thread, rsp, noreg, NULL);
 
   // do the call
   call(RuntimeAddress(entry));
-  if (!align_stack) {
-    call_offset = offset();
-  }
+  call_offset = offset();
   // verify callee-saved register
 #ifdef ASSERT
   guarantee(thread != rax, "change this code");
@@ -93,7 +78,7 @@
   }
   pop(rax);
 #endif
-  reset_last_Java_frame(thread, true, align_stack);
+  reset_last_Java_frame(thread, true, false);
 
   // discard thread and arguments
   NOT_LP64(addptr(rsp, num_rt_args()*BytesPerWord));
@@ -115,7 +100,7 @@
     restore_live_registers(this, false);
     movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD);
     leave();
-    movl(rscratch1, Deoptimization::make_trap_request(Deoptimization::Reason_constraint, Deoptimization::Action_reinterpret));
+    movl(Address(thread, ThreadShadow::pending_deoptimization_offset()), Deoptimization::make_trap_request(Deoptimization::Reason_constraint, Deoptimization::Action_reinterpret));
     jump(RuntimeAddress(SharedRuntime::deopt_blob()->uncommon_trap()));
     bind(L);
   }
@@ -356,6 +341,7 @@
   map->set_callee_saved(VMRegImpl::stack2reg(rcx_off + num_rt_args), rcx->as_VMReg());
   map->set_callee_saved(VMRegImpl::stack2reg(rdx_off + num_rt_args), rdx->as_VMReg());
   map->set_callee_saved(VMRegImpl::stack2reg(rbx_off + num_rt_args), rbx->as_VMReg());
+  map->set_callee_saved(VMRegImpl::stack2reg(rbp_off + num_rt_args), rbp->as_VMReg());
   map->set_callee_saved(VMRegImpl::stack2reg(rsi_off + num_rt_args), rsi->as_VMReg());
   map->set_callee_saved(VMRegImpl::stack2reg(rdi_off + num_rt_args), rdi->as_VMReg());
 #ifdef _LP64
@@ -373,6 +359,7 @@
   map->set_callee_saved(VMRegImpl::stack2reg(rcxH_off + num_rt_args), rcx->as_VMReg()->next());
   map->set_callee_saved(VMRegImpl::stack2reg(rdxH_off + num_rt_args), rdx->as_VMReg()->next());
   map->set_callee_saved(VMRegImpl::stack2reg(rbxH_off + num_rt_args), rbx->as_VMReg()->next());
+  map->set_callee_saved(VMRegImpl::stack2reg(rbpH_off + num_rt_args), rbp->as_VMReg()->next());
   map->set_callee_saved(VMRegImpl::stack2reg(rsiH_off + num_rt_args), rsi->as_VMReg()->next());
   map->set_callee_saved(VMRegImpl::stack2reg(rdiH_off + num_rt_args), rdi->as_VMReg()->next());
 
@@ -638,9 +625,9 @@
   OopMapSet* oop_maps = new OopMapSet();
   OopMap* oop_map = NULL;
   switch (id) {
-    case graal_handle_exception_nofpu_id:
+    case handle_exception_nofpu_id:
       // At this point all registers MAY be live.
-      oop_map = save_live_registers(sasm, 1 /*thread*/, id == graal_handle_exception_nofpu_id);
+      oop_map = save_live_registers(sasm, 1 /*thread*/, id == handle_exception_nofpu_id);
       break;
     default:  ShouldNotReachHere();
   }
@@ -712,9 +699,9 @@
   __ movptr(Address(rbp, 1*BytesPerWord), rax);
 
   switch (id) {
-    case graal_handle_exception_nofpu_id:
+    case handle_exception_nofpu_id:
       // Restore the registers that were saved at the beginning.
-      restore_live_registers(sasm, id == graal_handle_exception_nofpu_id);
+      restore_live_registers(sasm, id == handle_exception_nofpu_id);
       break;
     default:  ShouldNotReachHere();
   }
@@ -824,7 +811,7 @@
   OopMapSet* oop_maps = NULL;
   switch (id) {
 
-    case graal_new_instance_id:
+    case new_instance_id:
       {
         Register klass = rdx; // Incoming
         Register obj   = rax; // Result
@@ -844,7 +831,7 @@
 
       break;
 
-    case graal_new_array_id:
+    case new_array_id:
       {
         Register length   = rbx; // Incoming
         Register klass    = rdx; // Incoming
@@ -869,7 +856,7 @@
       }
       break;
 
-    case graal_new_multi_array_id:
+    case new_multi_array_id:
       { GraalStubFrame f(sasm, "new_multi_array", dont_gc_arguments);
         // rax,: klass
         // rbx,: rank
@@ -886,7 +873,7 @@
       }
       break;
 
-    case graal_register_finalizer_id:
+    case register_finalizer_id:
       {
         __ set_info("register_finalizer", dont_gc_arguments);
 
@@ -927,88 +914,16 @@
       }
       break;
 
-    case graal_handle_exception_nofpu_id:
+    case handle_exception_nofpu_id:
       { GraalStubFrame f(sasm, "handle_exception", dont_gc_arguments);
         oop_maps = generate_handle_exception(id, sasm);
       }
       break;
 
-    case graal_slow_subtype_check_id:
-      {
-        // Typical calling sequence:
-        // __ push(klass_RInfo);  // object klass or other subclass
-        // __ push(sup_k_RInfo);  // array element klass or other superclass
-        // __ call(slow_subtype_check);
-        // Note that the subclass is pushed first, and is therefore deepest.
-        // Previous versions of this code reversed the names 'sub' and 'super'.
-        // This was operationally harmless but made the code unreadable.
-        enum layout {
-          rax_off, SLOT2(raxH_off)
-          rcx_off, SLOT2(rcxH_off)
-          rsi_off, SLOT2(rsiH_off)
-          rdi_off, SLOT2(rdiH_off)
-          // saved_rbp_off, SLOT2(saved_rbpH_off)
-          return_off, SLOT2(returnH_off)
-          sup_k_off, SLOT2(sup_kH_off)
-          klass_off, SLOT2(superH_off)
-          framesize,
-          result_off = klass_off  // deepest argument is also the return value
-        };
-
-        __ set_info("slow_subtype_check", dont_gc_arguments);
-        __ push(rdi);
-        __ push(rsi);
-        __ push(rcx);
-        __ push(rax);
-
-        // This is called by pushing args and not with C abi
-        __ movptr(rsi, Address(rsp, (klass_off) * VMRegImpl::stack_slot_size)); // subclass
-        __ movptr(rax, Address(rsp, (sup_k_off) * VMRegImpl::stack_slot_size)); // superclass
-
-        Label miss;
-        Label success;
-        __ check_klass_subtype_fast_path(rsi, rax, rcx, &success, &miss, NULL);
-
-        __ check_klass_subtype_slow_path(rsi, rax, rcx, rdi, NULL, &miss);
-
-        // fallthrough on success:
-        __ bind(success);
-        __ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), 1); // result
-        __ pop(rax);
-        __ pop(rcx);
-        __ pop(rsi);
-        __ pop(rdi);
-        __ ret(0);
-
-        __ bind(miss);
-        __ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), NULL_WORD); // result
-        __ pop(rax);
-        __ pop(rcx);
-        __ pop(rsi);
-        __ pop(rdi);
-        __ ret(0);
-      }
-      break;
-
-    case graal_unwind_exception_call_id: {
+    case unwind_exception_call_id: {
       // remove the frame from the stack
       __ movptr(rsp, rbp);
       __ pop(rbp);
-      // exception_oop is passed using ordinary java calling conventions
-      __ movptr(rax, j_rarg0);
-
-      Label nonNullExceptionOop;
-      __ testptr(rax, rax);
-      __ jcc(Assembler::notZero, nonNullExceptionOop);
-      {
-        __ enter();
-        oop_maps = new OopMapSet();
-        OopMap* oop_map = save_live_registers(sasm, 0);
-        int call_offset = __ call_RT(rax, noreg, (address)graal_create_null_exception, 0);
-        oop_maps->add_gc_map(call_offset, oop_map);
-        __ leave();
-      }
-      __ bind(nonNullExceptionOop);
 
       __ set_info("unwind_exception", dont_gc_arguments);
       // note: no stubframe since we are about to leave the current
@@ -1018,7 +933,7 @@
       break;
     }
 
-    case graal_OSR_migration_end_id: {
+    case OSR_migration_end_id: {
     __ enter();
     save_live_registers(sasm, 0);
     __ movptr(c_rarg0, j_rarg0);
@@ -1029,39 +944,33 @@
       break;
     }
 
-    case graal_set_deopt_info_id: {
-    __ movptr(Address(r15_thread, JavaThread::graal_deopt_info_offset()), rscratch1);
-    __ ret(0);
-      break;
-    }
-
-    case graal_create_null_pointer_exception_id: {
+    case create_null_pointer_exception_id: {
 		__ enter();
 		oop_maps = new OopMapSet();
 		OopMap* oop_map = save_live_registers(sasm, 0);
-		int call_offset = __ call_RT(rax, noreg, (address)graal_create_null_exception, 0);
+		int call_offset = __ call_RT(rax, noreg, (address)create_null_exception, 0);
 		oop_maps->add_gc_map(call_offset, oop_map);
 		__ leave();
 		__ ret(0);
       break;
     }
 
-    case graal_create_out_of_bounds_exception_id: {
+    case create_out_of_bounds_exception_id: {
 		__ enter();
 		oop_maps = new OopMapSet();
 		OopMap* oop_map = save_live_registers(sasm, 0);
-		int call_offset = __ call_RT(rax, noreg, (address)graal_create_out_of_bounds_exception, j_rarg0);
+		int call_offset = __ call_RT(rax, noreg, (address)create_out_of_bounds_exception, j_rarg0);
 		oop_maps->add_gc_map(call_offset, oop_map);
 		__ leave();
 		__ ret(0);
       break;
     }
 
-    case graal_vm_error_id: {
+    case vm_error_id: {
       __ enter();
       oop_maps = new OopMapSet();
       OopMap* oop_map = save_live_registers(sasm, 0);
-      int call_offset = __ call_RT(noreg, noreg, (address)graal_vm_error, j_rarg0, j_rarg1, j_rarg2);
+      int call_offset = __ call_RT(noreg, noreg, (address)vm_error, j_rarg0, j_rarg1, j_rarg2);
       oop_maps->add_gc_map(call_offset, oop_map);
       restore_live_registers(sasm);
       __ leave();
@@ -1069,11 +978,11 @@
       break;
     }
 
-    case graal_log_printf_id: {
+    case log_printf_id: {
       __ enter();
       oop_maps = new OopMapSet();
       OopMap* oop_map = save_live_registers(sasm, 0);
-      int call_offset = __ call_RT(noreg, noreg, (address)graal_log_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3);
+      int call_offset = __ call_RT(noreg, noreg, (address)log_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3);
       oop_maps->add_gc_map(call_offset, oop_map);
       restore_live_registers(sasm);
       __ leave();
@@ -1081,11 +990,11 @@
       break;
     }
 
-    case graal_log_primitive_id: {
+    case log_primitive_id: {
       __ enter();
       oop_maps = new OopMapSet();
       OopMap* oop_map = save_live_registers(sasm, 0);
-      int call_offset = __ call_RT(noreg, noreg, (address)graal_log_primitive, j_rarg0, j_rarg1, j_rarg2);
+      int call_offset = __ call_RT(noreg, noreg, (address)log_primitive, j_rarg0, j_rarg1, j_rarg2);
       oop_maps->add_gc_map(call_offset, oop_map);
       restore_live_registers(sasm);
       __ leave();
@@ -1093,11 +1002,11 @@
       break;
     }
 
-    case graal_log_object_id: {
+    case log_object_id: {
       __ enter();
       oop_maps = new OopMapSet();
       OopMap* oop_map = save_live_registers(sasm, 0);
-      int call_offset = __ call_RT(noreg, noreg, (address)graal_log_object, j_rarg0, j_rarg1);
+      int call_offset = __ call_RT(noreg, noreg, (address)log_object, j_rarg0, j_rarg1);
       oop_maps->add_gc_map(call_offset, oop_map);
       restore_live_registers(sasm);
       __ leave();
@@ -1105,7 +1014,7 @@
       break;
     }
 
-    case graal_verify_oop_id: {
+    case verify_oop_id: {
       // We use enter & leave so that a better stack trace is produced in the hs_err file
       __ enter();
       __ verify_oop(r13, "Graal verify oop");
@@ -1114,7 +1023,7 @@
       break;
     }
 
-    case graal_arithmetic_frem_id: {
+    case arithmetic_frem_id: {
       __ subptr(rsp, 8);
       __ movflt(Address(rsp, 0), xmm1);
       __ fld_s(Address(rsp, 0));
@@ -1135,7 +1044,7 @@
       __ ret(0);
       break;
     }
-    case graal_arithmetic_drem_id: {
+    case arithmetic_drem_id: {
       __ subptr(rsp, 8);
       __ movdbl(Address(rsp, 0), xmm1);
       __ fld_d(Address(rsp, 0));
@@ -1156,15 +1065,15 @@
       __ ret(0);
       break;
     }
-    case graal_monitorenter_id: {
+    case monitorenter_id: {
       Register obj = j_rarg0;
       Register lock = j_rarg1;
       {
-        GraalStubFrame f(sasm, "graal_monitorenter", dont_gc_arguments);
+        GraalStubFrame f(sasm, "monitorenter", dont_gc_arguments);
         OopMap* map = save_live_registers(sasm, 2, save_fpu_registers);
 
         // Called with store_parameter and not C abi
-        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_monitorenter), obj, lock);
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), obj, lock);
 
         oop_maps = new OopMapSet();
         oop_maps->add_gc_map(call_offset, map);
@@ -1173,17 +1082,17 @@
       __ ret(0);
       break;
     }
-    case graal_monitorexit_id: {
+    case monitorexit_id: {
       Register obj = j_rarg0;
       Register lock = j_rarg1;
       {
-        GraalStubFrame f(sasm, "graal_monitorexit", dont_gc_arguments);
+        GraalStubFrame f(sasm, "monitorexit", dont_gc_arguments);
         OopMap* map = save_live_registers(sasm, 2, save_fpu_registers);
 
         // note: really a leaf routine but must setup last java sp
         //       => use call_RT for now (speed can be improved by
         //       doing last java sp setup manually)
-        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_monitorexit), obj, lock);
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), obj, lock);
 
         oop_maps = new OopMapSet();
         oop_maps->add_gc_map(call_offset, map);
@@ -1192,7 +1101,7 @@
       __ ret(0);
       break;
    }
-   case graal_wb_pre_call_id: {
+   case wb_pre_call_id: {
       Register obj = j_rarg0;
       {
         GraalStubFrame f(sasm, "graal_wb_pre_call", dont_gc_arguments);
@@ -1201,7 +1110,7 @@
         // note: really a leaf routine but must setup last java sp
         //       => use call_RT for now (speed can be improved by
         //       doing last java sp setup manually)
-        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_wb_pre_call), obj);
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, wb_pre_call), obj);
 
         oop_maps = new OopMapSet();
         oop_maps->add_gc_map(call_offset, map);
@@ -1210,7 +1119,7 @@
       __ ret(0);
       break;
    }
-   case graal_wb_post_call_id: {
+   case wb_post_call_id: {
       Register obj = j_rarg0;
       Register caddr = j_rarg1;
       {
@@ -1220,7 +1129,7 @@
         // note: really a leaf routine but must setup last java sp
         //       => use call_RT for now (speed can be improved by
         //       doing last java sp setup manually)
-        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_wb_post_call), obj, caddr);
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, wb_post_call), obj, caddr);
 
         oop_maps = new OopMapSet();
         oop_maps->add_gc_map(call_offset, map);
@@ -1230,12 +1139,13 @@
       break;
    }
 
-   case graal_identity_hash_code_id: {
+
+    case identity_hash_code_id: {
       Register obj = j_rarg0; // Incoming
       __ set_info("identity_hash_code", dont_gc_arguments);
       __ enter();
       OopMap* map = save_live_registers(sasm, 1);
-      int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_identity_hash_code), obj);
+      int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, identity_hash_code), obj);
       oop_maps = new OopMapSet();
       oop_maps->add_gc_map(call_offset, map);
       restore_live_registers_except_rax(sasm);
@@ -1243,14 +1153,14 @@
       __ ret(0);
       break;
     }
-    case graal_thread_is_interrupted_id: {
+    case thread_is_interrupted_id: {
       Register thread = j_rarg0;
       Register clear_interrupted = j_rarg1;
 
       __ set_info("identity_hash_code", dont_gc_arguments);
       __ enter();
       OopMap* map = save_live_registers(sasm, 1);
-      int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_thread_is_interrupted), thread, clear_interrupted);
+      int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, thread_is_interrupted), thread, clear_interrupted);
       oop_maps = new OopMapSet();
       oop_maps->add_gc_map(call_offset, map);
       restore_live_registers_except_rax(sasm);
--- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -30,6 +30,8 @@
 //
   friend class AbstractInterpreterGenerator;
 
+  address generate_deopt_entry_for(TosState state, int step);
+
  private:
 
   address generate_normal_entry(bool synchronized);
--- a/src/cpu/x86/vm/jniTypes_x86.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/jniTypes_x86.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -127,26 +127,6 @@
   static inline oop     get_obj   (intptr_t *from) { return *(oop *)    from; }
   static inline jfloat  get_float (intptr_t *from) { return *(jfloat *) from; }
   static inline jdouble get_double(intptr_t *from) { return *(jdouble *)(from + _JNI_SLOT_OFFSET); }
-
-  static inline jint    get_int   (intptr_t *from, int& pos) {
-    return get_int(from + pos++);
-  }
-  static inline jlong   get_long  (intptr_t *from, int& pos) {
-    jlong result = get_long(from + pos);
-    pos += 2;
-    return result;
-  }
-  static inline oop     get_obj   (intptr_t *from, int& pos) {
-    return get_obj(from + pos++);
-  }
-  static inline jfloat  get_float (intptr_t *from, int& pos) {
-    return get_float(from + pos++);
-  }
-  static inline jdouble get_double(intptr_t *from, int& pos) {
-    jdouble result = get_double(from + pos);
-    pos += 2;
-    return result;
-  }
 #undef _JNI_SLOT_OFFSET
 };
 
--- a/src/cpu/x86/vm/macroAssembler_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/macroAssembler_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -37,11 +37,12 @@
 #include "runtime/os.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 #ifdef PRODUCT
 #define BLOCK_COMMENT(str) /* nothing */
@@ -2057,7 +2058,7 @@
 }
 
 // !defined(COMPILER2) is because of stupid core builds
-#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2)
+#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) || defined(GRAAL)
 void MacroAssembler::empty_FPU_stack() {
   if (VM_Version::supports_mmx()) {
     emms();
@@ -3207,7 +3208,7 @@
 
 
 //////////////////////////////////////////////////////////////////////////////////
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
 void MacroAssembler::g1_write_barrier_pre(Register obj,
                                           Register pre_val,
@@ -3417,7 +3418,7 @@
   bind(done);
 }
 
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 //////////////////////////////////////////////////////////////////////////////////
 
 
@@ -5690,7 +5691,7 @@
   Address::ScaleFactor scale = Address::times_2;
   int stride = 8;
 
-  if (UseAVX >= 2) {
+  if (UseAVX >= 2 && UseSSE42Intrinsics) {
     Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR;
     Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR;
     Label COMPARE_TAIL_LONG;
--- a/src/cpu/x86/vm/macroAssembler_x86.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/macroAssembler_x86.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -26,6 +26,7 @@
 #define CPU_X86_VM_MACROASSEMBLER_X86_HPP
 
 #include "asm/assembler.hpp"
+#include "utilities/macros.hpp"
 
 
 // MacroAssembler extends Assembler by frequently used macros.
@@ -294,7 +295,7 @@
   void store_check(Register obj);                // store check for obj - register is destroyed afterwards
   void store_check(Register obj, Address dst);   // same as above, dst is exact store location (reg. is destroyed)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
   void g1_write_barrier_pre(Register obj,
                             Register pre_val,
@@ -309,7 +310,7 @@
                              Register tmp,
                              Register tmp2);
 
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // split store_check(Register obj) to enhance instruction interleaving
   void store_check_part_1(Register obj);
--- a/src/cpu/x86/vm/nativeInst_x86.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/nativeInst_x86.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -574,15 +574,18 @@
       return false;
     }
   } else {
-    if (ubyte_at(0) == Assembler::REX_WR && ubyte_at(1) == NativeMovRegMem::instruction_code_mem2reg && ubyte_at(2) == 0x15) { // mov r10, rip[...]
-      address fault = addr_at(7) + int_at(3);
-      return os::is_poll_address(fault);
-    } else if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && ubyte_at(1) == 0x05) { // 00 rax 101
+#ifdef GRAAL
+    // Graal may allocate an arbitrary register for storing the polling address.
+    return true;
+#else
+    if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+        ubyte_at(1) == 0x05) { // 00 rax 101
       address fault = addr_at(6) + int_at(2);
       return os::is_poll_address(fault);
     } else {
       return false;
     }
+#endif
   }
 #else
   return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1763,8 +1763,7 @@
 
   int vep_offset = ((intptr_t)__ pc()) - start;
 
-#if defined(COMPILER1) || defined(GRAAL)
-
+#ifdef COMPILER1
   if (InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) {
     // Object.hashCode can pull the hashCode from the header word
     // instead of doing a full VM transition once it's been computed.
@@ -1793,7 +1792,7 @@
     __ ret(0);
     __ bind (slowCase);
   }
-#endif // COMPILER1 || GRAAL
+#endif // COMPILER1
 
   // The instruction at the verified entry point must be 5 bytes or longer
   // because it can be patched on the fly by make_non_entrant. The stack bang
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1996,50 +1996,6 @@
 
   int vep_offset = ((intptr_t)__ pc()) - start;
 
-#ifdef GRAALVM
-  if (InlineObjectHash && (method->intrinsic_id() == vmIntrinsics::_hashCode || method->intrinsic_id() == vmIntrinsics::_identityHashCode)) {
-    // Object.hashCode can pull the hashCode from the header word
-    // instead of doing a full VM transition once it's been computed.
-    // Since hashCode is usually polymorphic at call sites we can't do
-    // this optimization at the call site without a lot of work.
-    Label slowCase;
-    Label nullCase;
-    Register result = rax;
-
-    if (method->intrinsic_id() == vmIntrinsics::_identityHashCode) {
-      __ cmpptr(receiver, 0);
-      __ jcc(Assembler::equal, nullCase);
-    }
-
-    __ movptr(result, Address(receiver, oopDesc::mark_offset_in_bytes()));
-
-    // check if locked
-    __ testptr(result, markOopDesc::unlocked_value);
-    __ jcc (Assembler::zero, slowCase);
-
-    if (UseBiasedLocking) {
-      // Check if biased and fall through to runtime if so
-      __ testptr(result, markOopDesc::biased_lock_bit_in_place);
-      __ jcc (Assembler::notZero, slowCase);
-    }
-
-    // get hash
-    __ shrptr(result, markOopDesc::hash_shift);
-    __ andptr(result, markOopDesc::hash_mask);
-    // test if hashCode exists
-    __ jcc  (Assembler::zero, slowCase);
-    __ ret(0);
-
-    if (method->intrinsic_id() == vmIntrinsics::_identityHashCode) {
-      __ bind(nullCase);
-      __ movl(result, 0);
-      __ ret(0);
-    }
-
-    __ bind (slowCase);
-  }
-#endif // GRAALVM
-
   // The instruction at the verified entry point must be 5 bytes or longer
   // because it can be patched on the fly by make_non_entrant. The stack bang
   // instruction fits that requirement.
@@ -3452,8 +3408,8 @@
   __ jmp(cont);
 
   int implicit_exception_uncommon_trap_offset = __ pc() - start;
+  // pc where the exception happened is in ScratchA
   __ pushptr(Address(r15_thread, in_bytes(JavaThread::ScratchA_offset())));
-  __ movptr(rscratch1, Address(r15_thread, in_bytes(JavaThread::ScratchB_offset())));
 
   int uncommon_trap_offset = __ pc() - start;
 
@@ -3462,8 +3418,8 @@
   // fetch_unroll_info needs to call last_java_frame()
   __ set_last_Java_frame(noreg, noreg, NULL);
 
-  assert(r10 == rscratch1, "scratch register should be r10");
-  __ movl(c_rarg1, Address(rsp, RegisterSaver::r10_offset_in_bytes()));
+  __ movl(c_rarg1, Address(r15_thread, in_bytes(ThreadShadow::pending_deoptimization_offset())));
+  __ movl(Address(r15_thread, in_bytes(ThreadShadow::pending_deoptimization_offset())), -1);
 
   __ movl(r14, (int32_t)Deoptimization::Unpack_reexecute);
   __ mov(c_rarg0, r15_thread);
--- a/src/cpu/x86/vm/templateInterpreter_x86.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/templateInterpreter_x86.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -34,7 +34,7 @@
   // Run with +PrintInterpreter to get the VM to print out the size.
   // Max size with JVMTI
 #ifdef AMD64
-  const static int InterpreterCodeSize = 200 * 1024;
+  const static int InterpreterCodeSize = 220 * 1024;
 #else
   const static int InterpreterCodeSize = 168 * 1024;
 #endif // AMD64
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -44,6 +44,7 @@
 #include "runtime/timer.hpp"
 #include "runtime/vframeArray.hpp"
 #include "utilities/debug.hpp"
+#include "utilities/macros.hpp"
 
 #define __ _masm->
 
@@ -761,7 +762,7 @@
 
 // Method entry for java.lang.ref.Reference.get.
 address InterpreterGenerator::generate_Reference_get_entry(void) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // Code: _aload_0, _getfield, _areturn
   // parameter size = 1
   //
@@ -844,7 +845,7 @@
 
     return entry;
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // If G1 is not enabled then attempt to go through the accessor entry point
   // Reference.get is an accessor
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -45,6 +45,7 @@
 #include "runtime/timer.hpp"
 #include "runtime/vframeArray.hpp"
 #include "utilities/debug.hpp"
+#include "utilities/macros.hpp"
 
 #define __ _masm->
 
@@ -203,13 +204,26 @@
 }
 
 
-address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
+address InterpreterGenerator::generate_deopt_entry_for(TosState state,
                                                                int step) {
   address entry = __ pc();
   // NULL last_sp until next java call
   __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
   __ restore_bcp();
   __ restore_locals();
+  // Check if we need to take lock at entry of synchronized method.
+  {
+    Label L;
+    __ cmpb(Address(r15_thread, Thread::pending_monitorenter_offset()), 0);
+    __ jcc(Assembler::zero, L);
+    // Clear flag.
+    __ movb(Address(r15_thread, Thread::pending_monitorenter_offset()), 0);
+    // Satisfy calling convention for lock_method().
+    __ get_method(rbx);
+    // Take lock.
+    lock_method();
+    __ bind(L);
+  }
   // handle exceptions
   {
     Label L;
@@ -773,7 +787,7 @@
 
 // Method entry for java.lang.ref.Reference.get.
 address InterpreterGenerator::generate_Reference_get_entry(void) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // Code: _aload_0, _getfield, _areturn
   // parameter size = 1
   //
@@ -852,7 +866,7 @@
 
     return entry;
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // If G1 is not enabled then attempt to go through the accessor entry point
   // Reference.get is an accessor
--- a/src/cpu/x86/vm/templateTable_x86_32.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/templateTable_x86_32.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -35,6 +35,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/synchronizer.hpp"
+#include "utilities/macros.hpp"
 
 #ifndef CC_INTERP
 #define __ _masm->
@@ -125,7 +126,7 @@
                          bool precise) {
   assert(val == noreg || val == rax, "parameter is just for looks");
   switch (barrier) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case BarrierSet::G1SATBCT:
     case BarrierSet::G1SATBCTLogging:
       {
@@ -164,7 +165,7 @@
 
       }
       break;
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
     case BarrierSet::CardTableModRef:
     case BarrierSet::CardTableExtension:
       {
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -35,6 +35,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/synchronizer.hpp"
+#include "utilities/macros.hpp"
 
 #ifndef CC_INTERP
 
@@ -136,7 +137,7 @@
                          bool precise) {
   assert(val == noreg || val == rax, "parameter is just for looks");
   switch (barrier) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case BarrierSet::G1SATBCT:
     case BarrierSet::G1SATBCTLogging:
       {
@@ -167,7 +168,7 @@
 
       }
       break;
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
     case BarrierSet::CardTableModRef:
     case BarrierSet::CardTableExtension:
       {
--- a/src/cpu/zero/vm/assembler_zero.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/zero/vm/assembler_zero.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -36,11 +36,12 @@
 #include "runtime/os.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 int AbstractAssembler::code_fill_byte() {
   return 0;
--- a/src/cpu/zero/vm/cppInterpreter_zero.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -47,6 +47,7 @@
 #include "runtime/vframeArray.hpp"
 #include "stack_zero.inline.hpp"
 #include "utilities/debug.hpp"
+#include "utilities/macros.hpp"
 #ifdef SHARK
 #include "shark/shark_globals.hpp"
 #endif
@@ -791,7 +792,7 @@
 }
 
 address InterpreterGenerator::generate_Reference_get_entry(void) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   if (UseG1GC) {
     // We need to generate have a routine that generates code to:
     //   * load the value in the referent field
@@ -803,7 +804,7 @@
     // field as live.
     Unimplemented();
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // If G1 is not enabled then attempt to go through the accessor entry point
   // Reference.get is an accessor
--- a/src/cpu/zero/vm/shark_globals_zero.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/cpu/zero/vm/shark_globals_zero.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2008, 2009, 2010 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -51,7 +51,7 @@
 define_pd_global(intx,     OnStackReplacePercentage,     933  );
 define_pd_global(intx,     FreqInlineSize,               325  );
 define_pd_global(intx,     InlineSmallCode,              1000 );
-define_pd_global(intx,     NewRatio,                     12   );
+define_pd_global(uintx,    NewRatio,                     12   );
 define_pd_global(intx,     NewSizeThreadIncrease,        4*K  );
 define_pd_global(intx,     InitialCodeCacheSize,         160*K);
 define_pd_global(intx,     ReservedCodeCacheSize,        32*M );
--- a/src/os/bsd/vm/osThread_bsd.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os/bsd/vm/osThread_bsd.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -49,6 +49,11 @@
   // (e.g. pthread_kill).
   pthread_t _pthread_id;
 
+  // This is the "thread_id" from struct thread_identifier_info. According to a
+  // comment in thread_info.h, this is a "system-wide unique 64-bit thread id".
+  // The value is used by SA to correlate threads.
+  uint64_t _unique_thread_id;
+
   sigset_t _caller_sigmask; // Caller's signal mask
 
  public:
@@ -77,6 +82,10 @@
     _pthread_id = tid;
   }
 
+  void set_unique_thread_id(uint64_t id) {
+    _unique_thread_id = id;
+  }
+
   // ***************************************************************
   // suspension support.
   // ***************************************************************
--- a/src/os/bsd/vm/os_bsd.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os/bsd/vm/os_bsd.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -657,6 +657,18 @@
 objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL;
 #endif
 
+#ifdef __APPLE__
+static uint64_t locate_unique_thread_id() {
+  // Additional thread_id used to correlate threads in SA
+  thread_identifier_info_data_t     m_ident_info;
+  mach_msg_type_number_t            count = THREAD_IDENTIFIER_INFO_COUNT;
+
+  thread_info(::mach_thread_self(), THREAD_IDENTIFIER_INFO,
+              (thread_info_t) &m_ident_info, &count);
+  return m_ident_info.thread_id;
+}
+#endif
+
 // Thread start routine for all newly created threads
 static void *java_start(Thread *thread) {
   // Try to randomize the cache line index of hot stack frames.
@@ -685,6 +697,7 @@
 #ifdef __APPLE__
   // thread_id is mach thread on macos
   osthread->set_thread_id(::mach_thread_self());
+  osthread->set_unique_thread_id(locate_unique_thread_id());
 #else
   // thread_id is pthread_id on BSD
   osthread->set_thread_id(::pthread_self());
@@ -847,6 +860,7 @@
   // Store pthread info into the OSThread
 #ifdef __APPLE__
   osthread->set_thread_id(::mach_thread_self());
+  osthread->set_unique_thread_id(locate_unique_thread_id());
 #else
   osthread->set_thread_id(::pthread_self());
 #endif
@@ -2873,7 +2887,9 @@
 
 void signalHandler(int sig, siginfo_t* info, void* uc) {
   assert(info != NULL && uc != NULL, "it must be old kernel");
+  int orig_errno = errno;  // Preserve errno value over signal handler.
   JVM_handle_bsd_signal(sig, info, uc, true);
+  errno = orig_errno;
 }
 
 
@@ -3619,9 +3635,9 @@
 // able to use structured exception handling (thread-local exception filters)
 // on, e.g., Win32.
 void
-os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm,
+os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method,
                          JavaCallArguments* args, Thread* thread) {
-  f(value, method, nm, args, thread);
+  f(value, method, args, thread);
 }
 
 void os::print_statistics() {
--- a/src/os/linux/vm/os_linux.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os/linux/vm/os_linux.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1155,13 +1155,9 @@
   //   for initial thread if its stack size exceeds 6M. Cap it at 2M,
   //   in case other parts in glibc still assumes 2M max stack size.
   // FIXME: alt signal stack is gone, maybe we can relax this constraint?
-#ifndef IA64
-  if (stack_size > 2 * K * K) stack_size = 2 * K * K;
-#else
   // Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small
-  if (stack_size > 4 * K * K) stack_size = 4 * K * K;
-#endif
-
+  if (stack_size > 2 * K * K IA64_ONLY(*2))
+      stack_size = 2 * K * K IA64_ONLY(*2);
   // Try to figure out where the stack base (top) is. This is harder.
   //
   // When an application is started, glibc saves the initial stack pointer in
@@ -3657,14 +3653,9 @@
 
 void signalHandler(int sig, siginfo_t* info, void* uc) {
   assert(info != NULL && uc != NULL, "it must be old kernel");
-  ResourceMark rm;
-  if (TraceSignals) {
-    tty->print_cr(err_msg("signal received: code=%d errno=%d signo=%d thread=%s address=%x", info->si_code, info->si_errno, info->si_signo, Thread::current()->name(), info->si_addr));
-  }
+  int orig_errno = errno;  // Preserve errno value over signal handler.
   JVM_handle_linux_signal(sig, info, uc, true);
-  if (TraceSignals) {
-    tty->print_cr("signal handled");
-  }
+  errno = orig_errno;
 }
 
 
@@ -4374,16 +4365,12 @@
    if (is_NPTL()) {
       return pthread_cond_timedwait(_cond, _mutex, _abstime);
    } else {
-#ifndef IA64
       // 6292965: LinuxThreads pthread_cond_timedwait() resets FPU control
       // word back to default 64bit precision if condvar is signaled. Java
       // wants 53bit precision.  Save and restore current value.
       int fpu = get_fpu_control_word();
-#endif // IA64
       int status = pthread_cond_timedwait(_cond, _mutex, _abstime);
-#ifndef IA64
       set_fpu_control_word(fpu);
-#endif // IA64
       return status;
    }
 }
@@ -4447,9 +4434,9 @@
 // able to use structured exception handling (thread-local exception filters)
 // on, e.g., Win32.
 void
-os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm,
+os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method,
                          JavaCallArguments* args, Thread* thread) {
-  f(value, method, nm, args, thread);
+  f(value, method, args, thread);
 }
 
 void os::print_statistics() {
@@ -4756,49 +4743,26 @@
 //
 
 static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
-  static bool proc_pid_cpu_avail = true;
   static bool proc_task_unchecked = true;
   static const char *proc_stat_path = "/proc/%d/stat";
   pid_t  tid = thread->osthread()->thread_id();
-  int i;
   char *s;
   char stat[2048];
   int statlen;
   char proc_name[64];
   int count;
   long sys_time, user_time;
-  char string[64];
   char cdummy;
   int idummy;
   long ldummy;
   FILE *fp;
 
-  // We first try accessing /proc/<pid>/cpu since this is faster to
-  // process.  If this file is not present (linux kernels 2.5 and above)
-  // then we open /proc/<pid>/stat.
-  if ( proc_pid_cpu_avail ) {
-    sprintf(proc_name, "/proc/%d/cpu", tid);
-    fp =  fopen(proc_name, "r");
-    if ( fp != NULL ) {
-      count = fscanf( fp, "%s %lu %lu\n", string, &user_time, &sys_time);
-      fclose(fp);
-      if ( count != 3 ) return -1;
-
-      if (user_sys_cpu_time) {
-        return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec);
-      } else {
-        return (jlong)user_time * (1000000000 / clock_tics_per_sec);
-      }
-    }
-    else proc_pid_cpu_avail = false;
-  }
-
   // The /proc/<tid>/stat aggregates per-process usage on
   // new Linux kernels 2.6+ where NPTL is supported.
   // The /proc/self/task/<tid>/stat still has the per-thread usage.
   // See bug 6328462.
-  // There can be no directory /proc/self/task on kernels 2.4 with NPTL
-  // and possibly in some other cases, so we check its availability.
+  // There possibly can be cases where there is no directory
+  // /proc/self/task, so we check its availability.
   if (proc_task_unchecked && os::Linux::is_NPTL()) {
     // This is executed only once
     proc_task_unchecked = false;
@@ -4823,7 +4787,6 @@
   // We don't really need to know the command string, just find the last
   // occurrence of ")" and then start parsing from there. See bug 4726580.
   s = strrchr(stat, ')');
-  i = 0;
   if (s == NULL ) return -1;
 
   // Skip blank chars
--- a/src/os/solaris/vm/os_solaris.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os/solaris/vm/os_solaris.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1865,7 +1865,7 @@
 
 // Die immediately, no exit hook, no abort hook, no cleanup.
 void os::die() {
-  _exit(-1);
+  ::abort(); // dump core (for debugging)
 }
 
 // unused
@@ -4280,8 +4280,8 @@
 
 // This does not do anything on Solaris. This is basically a hook for being
 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
-void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread) {
-  f(value, method, nm, args, thread);
+void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) {
+  f(value, method, args, thread);
 }
 
 // This routine may be used by user applications as a "hook" to catch signals.
@@ -4317,7 +4317,9 @@
 
 
 void signalHandler(int sig, siginfo_t* info, void* ucVoid) {
+  int orig_errno = errno;  // Preserve errno value over signal handler.
   JVM_handle_solaris_signal(sig, info, ucVoid, true);
+  errno = orig_errno;
 }
 
 /* Do not delete - if guarantee is ever removed,  a signal handler (even empty)
--- a/src/os/windows/vm/os_windows.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os/windows/vm/os_windows.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -349,6 +349,33 @@
 
 #ifdef _M_IA64
   // IA64 has memory and register stacks
+  //
+  // This is the stack layout you get on NT/IA64 if you specify 1MB stack limit
+  // at thread creation (1MB backing store growing upwards, 1MB memory stack
+  // growing downwards, 2MB summed up)
+  //
+  // ...
+  // ------- top of stack (high address) -----
+  // |
+  // |      1MB
+  // |      Backing Store (Register Stack)
+  // |
+  // |         / \
+  // |          |
+  // |          |
+  // |          |
+  // ------------------------ stack base -----
+  // |      1MB
+  // |      Memory Stack
+  // |
+  // |          |
+  // |          |
+  // |          |
+  // |         \ /
+  // |
+  // ----- bottom of stack (low address) -----
+  // ...
+
   stack_size = stack_size / 2;
 #endif
   return stack_bottom + stack_size;
@@ -1913,7 +1940,7 @@
 
 // a counter for each possible signal value, including signal_thread exit signal
 static volatile jint pending_signals[NSIG+1] = { 0 };
-static HANDLE sig_sem;
+static HANDLE sig_sem = NULL;
 
 void os::signal_init_pd() {
   // Initialize signal structures
@@ -1943,10 +1970,11 @@
 
 void os::signal_notify(int signal_number) {
   BOOL ret;
-
-  Atomic::inc(&pending_signals[signal_number]);
-  ret = ::ReleaseSemaphore(sig_sem, 1, NULL);
-  assert(ret != 0, "ReleaseSemaphore() failed");
+  if (sig_sem != NULL) {
+    Atomic::inc(&pending_signals[signal_number]);
+    ret = ::ReleaseSemaphore(sig_sem, 1, NULL);
+    assert(ret != 0, "ReleaseSemaphore() failed");
+  }
 }
 
 static int check_pending_signals(bool wait_for_signal) {
@@ -2005,17 +2033,34 @@
   JavaThread* thread = JavaThread::current();
   // Save pc in thread
 #ifdef _M_IA64
-  thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->StIIP);
+  // Do not blow up if no thread info available.
+  if (thread) {
+    // Saving PRECISE pc (with slot information) in thread.
+    uint64_t precise_pc = (uint64_t) exceptionInfo->ExceptionRecord->ExceptionAddress;
+    // Convert precise PC into "Unix" format
+    precise_pc = (precise_pc & 0xFFFFFFFFFFFFFFF0) | ((precise_pc & 0xF) >> 2);
+    thread->set_saved_exception_pc((address)precise_pc);
+  }
   // Set pc to handler
   exceptionInfo->ContextRecord->StIIP = (DWORD64)handler;
+  // Clear out psr.ri (= Restart Instruction) in order to continue
+  // at the beginning of the target bundle.
+  exceptionInfo->ContextRecord->StIPSR &= 0xFFFFF9FFFFFFFFFF;
+  assert(((DWORD64)handler & 0xF) == 0, "Target address must point to the beginning of a bundle!");
 #elif _M_AMD64
-  thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->Rip);
+  // Do not blow up if no thread info available.
+  if (thread) {
+    thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Rip);
+  }
   // Set pc to handler
   exceptionInfo->ContextRecord->Rip = (DWORD64)handler;
 #else
-  thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->Eip);
+  // Do not blow up if no thread info available.
+  if (thread) {
+    thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Eip);
+  }
   // Set pc to handler
-  exceptionInfo->ContextRecord->Eip = (LONG)handler;
+  exceptionInfo->ContextRecord->Eip = (DWORD)(DWORD_PTR)handler;
 #endif
 
   // Continue the execution
@@ -2040,6 +2085,14 @@
 // included or copied here.
 #define EXCEPTION_INFO_EXEC_VIOLATION 0x08
 
+// Handle NAT Bit consumption on IA64.
+#ifdef _M_IA64
+#define EXCEPTION_REG_NAT_CONSUMPTION    STATUS_REG_NAT_CONSUMPTION
+#endif
+
+// Windows Vista/2008 heap corruption check
+#define EXCEPTION_HEAP_CORRUPTION        0xC0000374
+
 #define def_excpt(val) #val, val
 
 struct siglabel {
@@ -2082,6 +2135,10 @@
     def_excpt(EXCEPTION_GUARD_PAGE),
     def_excpt(EXCEPTION_INVALID_HANDLE),
     def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION),
+    def_excpt(EXCEPTION_HEAP_CORRUPTION),
+#ifdef _M_IA64
+    def_excpt(EXCEPTION_REG_NAT_CONSUMPTION),
+#endif
     NULL, 0
 };
 
@@ -2222,7 +2279,14 @@
   if (InterceptOSException) return EXCEPTION_CONTINUE_SEARCH;
   DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode;
 #ifdef _M_IA64
-  address pc = (address) exceptionInfo->ContextRecord->StIIP;
+  // On Itanium, we need the "precise pc", which has the slot number coded
+  // into the least 4 bits: 0000=slot0, 0100=slot1, 1000=slot2 (Windows format).
+  address pc = (address) exceptionInfo->ExceptionRecord->ExceptionAddress;
+  // Convert the pc to "Unix format", which has the slot number coded
+  // into the least 2 bits: 0000=slot0, 0001=slot1, 0010=slot2
+  // This is needed for IA64 because "relocation" / "implicit null check" / "poll instruction"
+  // information is saved in the Unix format.
+  address pc_unix_format = (address) ((((uint64_t)pc) & 0xFFFFFFFFFFFFFFF0) | ((((uint64_t)pc) & 0xF) >> 2));
 #elif _M_AMD64
   address pc = (address) exceptionInfo->ContextRecord->Rip;
 #else
@@ -2337,29 +2401,40 @@
     if (exception_code == EXCEPTION_STACK_OVERFLOW) {
       if (os::uses_stack_guard_pages()) {
 #ifdef _M_IA64
-        //
-        // If it's a legal stack address continue, Windows will map it in.
-        //
+        // Use guard page for register stack.
         PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
         address addr = (address) exceptionRecord->ExceptionInformation[1];
-        if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() )
-          return EXCEPTION_CONTINUE_EXECUTION;
-
-        // The register save area is the same size as the memory stack
-        // and starts at the page just above the start of the memory stack.
-        // If we get a fault in this area, we've run out of register
-        // stack.  If we are in java, try throwing a stack overflow exception.
-        if (addr > thread->stack_base() &&
-                      addr <= (thread->stack_base()+thread->stack_size()) ) {
-          char buf[256];
-          jio_snprintf(buf, sizeof(buf),
-                       "Register stack overflow, addr:%p, stack_base:%p\n",
-                       addr, thread->stack_base() );
-          tty->print_raw_cr(buf);
-          // If not in java code, return and hope for the best.
-          return in_java ? Handle_Exception(exceptionInfo,
-            SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW))
-            :  EXCEPTION_CONTINUE_EXECUTION;
+        // Check for a register stack overflow on Itanium
+        if (thread->addr_inside_register_stack_red_zone(addr)) {
+          // Fatal red zone violation happens if the Java program
+          // catches a StackOverflow error and does so much processing
+          // that it runs beyond the unprotected yellow guard zone. As
+          // a result, we are out of here.
+          fatal("ERROR: Unrecoverable stack overflow happened. JVM will exit.");
+        } else if(thread->addr_inside_register_stack(addr)) {
+          // Disable the yellow zone which sets the state that
+          // we've got a stack overflow problem.
+          if (thread->stack_yellow_zone_enabled()) {
+            thread->disable_stack_yellow_zone();
+          }
+          // Give us some room to process the exception.
+          thread->disable_register_stack_guard();
+          // Tracing with +Verbose.
+          if (Verbose) {
+            tty->print_cr("SOF Compiled Register Stack overflow at " INTPTR_FORMAT " (SIGSEGV)", pc);
+            tty->print_cr("Register Stack access at " INTPTR_FORMAT, addr);
+            tty->print_cr("Register Stack base " INTPTR_FORMAT, thread->register_stack_base());
+            tty->print_cr("Register Stack [" INTPTR_FORMAT "," INTPTR_FORMAT "]",
+                          thread->register_stack_base(),
+                          thread->register_stack_base() + thread->stack_size());
+          }
+
+          // Reguard the permanent register stack red zone just to be sure.
+          // We saw Windows silently disabling this without telling us.
+          thread->enable_register_stack_red_zone();
+
+          return Handle_Exception(exceptionInfo,
+            SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW));
         }
 #endif
         if (thread->stack_yellow_zone_enabled()) {
@@ -2434,50 +2509,33 @@
           {
             // Null pointer exception.
 #ifdef _M_IA64
-            // We catch register stack overflows in compiled code by doing
-            // an explicit compare and executing a st8(G0, G0) if the
-            // BSP enters into our guard area.  We test for the overflow
-            // condition and fall into the normal null pointer exception
-            // code if BSP hasn't overflowed.
-            if ( in_java ) {
-              if(thread->register_stack_overflow()) {
-                assert((address)exceptionInfo->ContextRecord->IntS3 ==
-                                thread->register_stack_limit(),
-                               "GR7 doesn't contain register_stack_limit");
-                // Disable the yellow zone which sets the state that
-                // we've got a stack overflow problem.
-                if (thread->stack_yellow_zone_enabled()) {
-                  thread->disable_stack_yellow_zone();
+            // Process implicit null checks in compiled code. Note: Implicit null checks
+            // can happen even if "ImplicitNullChecks" is disabled, e.g. in vtable stubs.
+            if (CodeCache::contains((void*) pc_unix_format) && !MacroAssembler::needs_explicit_null_check((intptr_t) addr)) {
+              CodeBlob *cb = CodeCache::find_blob_unsafe(pc_unix_format);
+              // Handle implicit null check in UEP method entry
+              if (cb && (cb->is_frame_complete_at(pc) ||
+                         (cb->is_nmethod() && ((nmethod *)cb)->inlinecache_check_contains(pc)))) {
+                if (Verbose) {
+                  intptr_t *bundle_start = (intptr_t*) ((intptr_t) pc_unix_format & 0xFFFFFFFFFFFFFFF0);
+                  tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc_unix_format);
+                  tty->print_cr("      to addr " INTPTR_FORMAT, addr);
+                  tty->print_cr("      bundle is " INTPTR_FORMAT " (high), " INTPTR_FORMAT " (low)",
+                                *(bundle_start + 1), *bundle_start);
                 }
-                // Give us some room to process the exception
-                thread->disable_register_stack_guard();
-                // Update GR7 with the new limit so we can continue running
-                // compiled code.
-                exceptionInfo->ContextRecord->IntS3 =
-                               (ULONGLONG)thread->register_stack_limit();
                 return Handle_Exception(exceptionInfo,
-                       SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW));
-              } else {
-                //
-                // Check for implicit null
-                // We only expect null pointers in the stubs (vtable)
-                // the rest are checked explicitly now.
-                //
-                if (((uintptr_t)addr) < os::vm_page_size() ) {
-                  // an access to the first page of VM--assume it is a null pointer
-                  address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
-                  if (stub != NULL) return Handle_Exception(exceptionInfo, stub);
-                }
+                  SharedRuntime::continuation_for_implicit_exception(thread, pc_unix_format, SharedRuntime::IMPLICIT_NULL));
               }
-            } // in_java
-
-            // IA64 doesn't use implicit null checking yet. So we shouldn't
-            // get here.
-            tty->print_raw_cr("Access violation, possible null pointer exception");
+            }
+
+            // Implicit null checks were processed above.  Hence, we should not reach
+            // here in the usual case => die!
+            if (Verbose) tty->print_raw_cr("Access violation, possible null pointer exception");
             report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,
                          exceptionInfo->ContextRecord);
             return EXCEPTION_CONTINUE_SEARCH;
-#else /* !IA64 */
+
+#else // !IA64
 
             // Windows 98 reports faulting addresses incorrectly
             if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) ||
@@ -2509,7 +2567,24 @@
       report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,
                    exceptionInfo->ContextRecord);
       return EXCEPTION_CONTINUE_SEARCH;
-    }
+    } // /EXCEPTION_ACCESS_VIOLATION
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#if defined _M_IA64
+    else if ((exception_code == EXCEPTION_ILLEGAL_INSTRUCTION ||
+              exception_code == EXCEPTION_ILLEGAL_INSTRUCTION_2)) {
+      M37 handle_wrong_method_break(0, NativeJump::HANDLE_WRONG_METHOD, PR0);
+
+      // Compiled method patched to be non entrant? Following conditions must apply:
+      // 1. must be first instruction in bundle
+      // 2. must be a break instruction with appropriate code
+      if((((uint64_t) pc & 0x0F) == 0) &&
+         (((IPF_Bundle*) pc)->get_slot0() == handle_wrong_method_break.bits())) {
+        return Handle_Exception(exceptionInfo,
+                                (address)SharedRuntime::get_handle_wrong_method_stub());
+      }
+    } // /EXCEPTION_ILLEGAL_INSTRUCTION
+#endif
+
 
     if (in_java) {
       switch (exception_code) {
--- a/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
 #endif // AMD64
 
 define_pd_global(intx, CompilerThreadStackSize,  0);
-define_pd_global(intx, SurvivorRatio,            8);
+define_pd_global(uintx, SurvivorRatio,           8);
 
 define_pd_global(uintx, JVMInvokeMethodSlack,    8192);
 
--- a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -372,7 +372,7 @@
                 CAST_FROM_FN_PTR(address, os::current_frame));
   if (os::is_first_C_frame(&myframe)) {
     // stack is not walkable
-    return frame(NULL, NULL, NULL);
+    return frame();
   } else {
     return os::get_sender_for_C_frame(&myframe);
   }
--- a/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -35,17 +35,16 @@
   /* Threads (NOTE: incomplete) */                                                                                                   \
   /******************************/                                                                                                   \
   nonstatic_field(OSThread,                      _thread_id,                                      OSThread::thread_id_t)             \
-  nonstatic_field(OSThread,                      _pthread_id,                                     pthread_t)
+  nonstatic_field(OSThread,                      _unique_thread_id,                               uint64_t)
 
 
 #define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
                                                                           \
   /**********************/                                                \
-  /* Posix Thread IDs   */                                                \
+  /* Thread IDs         */                                                \
   /**********************/                                                \
                                                                           \
-  declare_unsigned_integer_type(OSThread::thread_id_t)                    \
-  declare_unsigned_integer_type(pthread_t)
+  declare_unsigned_integer_type(OSThread::thread_id_t)
 
 #define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
 
--- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -189,7 +189,7 @@
                 CAST_FROM_FN_PTR(address, os::current_frame));
   if (os::is_first_C_frame(&myframe)) {
     // stack is not walkable
-    return frame(NULL, NULL, NULL);
+    return frame();
   } else {
     return os::get_sender_for_C_frame(&myframe);
   }
@@ -282,17 +282,6 @@
     }
 #endif // AMD64
 
-    if (TraceSignals) {
-    CodeBlob* cb = CodeCache::find_blob(pc);
-      if (cb != NULL && cb->is_nmethod()) {
-        nmethod* nm = (nmethod*)cb;
-        int rel = pc - nm->code_begin();
-        tty->print_cr(err_msg("Implicit exception at %d of method %s", rel, nm->method()->name()->as_C_string()));
-      } else {
-        tty->print_cr("No code blob found for %x", pc);
-      }
-    }
-
     // Handle ALL stack overflow variations here
     if (sig == SIGSEGV) {
       address addr = (address) info->si_addr;
@@ -306,7 +295,6 @@
           if (thread->thread_state() == _thread_in_Java) {
             // Throw a stack overflow exception.  Guard pages will be reenabled
             // while unwinding the stack.
-            if (WizardMode) tty->print("implicit: %08x%08x\n", ((long long)pc) >> 32, pc);
             stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
           } else {
             // Thread was in the vm or native code.  Return and try to finish.
@@ -392,15 +380,8 @@
 #endif // AMD64
       } else if (sig == SIGSEGV &&
                !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
-          if (TraceSignals) {
-            tty->print_cr("Implicit exception continuation");
-          }
           // Determination of interpreter/vtable stub/compiled code null exception
           stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
-      } else if (sig == SIGSEGV) {
-        if (TraceSignals) {
-          tty->print_cr("would have needed explicit null check %d", (intptr_t)info->si_addr);
-        }
       }
     } else if (thread->thread_state() == _thread_in_vm &&
                sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
--- a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -70,7 +70,7 @@
 extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* );
 
 // Install a win32 structured exception handler around thread.
-void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread) {
+void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) {
   __try {
 
 #ifndef AMD64
@@ -110,7 +110,7 @@
 #endif // ASSERT
 #endif // !AMD64
 
-    f(value, method, nm, args, thread);
+    f(value, method, args, thread);
   } __except(topLevelExceptionFilter((_EXCEPTION_POINTERS*)_exception_info())) {
       // Nothing to do.
   }
@@ -399,7 +399,7 @@
   typedef intptr_t*      get_fp_func           ();
   get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*,
                                      StubRoutines::x86::get_previous_fp_entry());
-  if (func == NULL) return frame(NULL, NULL, NULL);
+  if (func == NULL) return frame();
   intptr_t* fp = (*func)();
 #else
   intptr_t* fp = _get_previous_fp();
@@ -410,7 +410,7 @@
                 CAST_FROM_FN_PTR(address, os::current_frame));
   if (os::is_first_C_frame(&myframe)) {
     // stack is not walkable
-    return frame(NULL, NULL, NULL);
+    return frame();
   } else {
     return os::get_sender_for_C_frame(&myframe);
   }
--- a/src/os_cpu/windows_x86/vm/threadLS_windows_x86.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/os_cpu/windows_x86/vm/threadLS_windows_x86.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -39,7 +39,7 @@
 // up the offset from FS of the thread pointer.
 void ThreadLocalStorage::generate_code_for_get_thread() {
       os::os_exception_wrapper( (java_call_t)call_wrapper_dummy,
-                                NULL, NULL, NULL, NULL, NULL);
+                                NULL, NULL, NULL, NULL);
 }
 
 void ThreadLocalStorage::pd_init() { }
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/GraphNode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -23,8 +23,10 @@
  */
 package com.sun.hotspot.igv.coordinator;
 
+import com.sun.hotspot.igv.coordinator.actions.CloneGraphAction;
 import com.sun.hotspot.igv.coordinator.actions.DiffGraphAction;
 import com.sun.hotspot.igv.coordinator.actions.DiffGraphCookie;
+import com.sun.hotspot.igv.coordinator.actions.GraphCloneCookie;
 import com.sun.hotspot.igv.coordinator.actions.GraphOpenCookie;
 import com.sun.hotspot.igv.coordinator.actions.GraphRemoveCookie;
 import com.sun.hotspot.igv.data.InputGraph;
@@ -72,6 +74,9 @@
 
         // Action for diffing to the current graph
         content.add(new DiffGraphCookie(graph));
+
+        // Action for cloning to the current graph
+        content.add(new GraphCloneCookie(viewer, graph));
     }
 
     @Override
@@ -97,7 +102,7 @@
 
     @Override
     public Action[] getActions(boolean b) {
-        return new Action[]{(Action) DiffGraphAction.findObject(DiffGraphAction.class, true), (Action) OpenAction.findObject(OpenAction.class, true)};
+        return new Action[]{(Action) DiffGraphAction.findObject(DiffGraphAction.class, true), (Action) CloneGraphAction.findObject(CloneGraphAction.class, true), (Action) OpenAction.findObject(OpenAction.class, true)};
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/CloneGraphAction.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.sun.hotspot.igv.coordinator.actions;
+
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.actions.CookieAction;
+
+/**
+ *
+ * @author Thomas Wuerthinger
+ */
+public final class CloneGraphAction extends CookieAction {
+
+    @Override
+    protected void performAction(Node[] activatedNodes) {
+        GraphCloneCookie c = activatedNodes[0].getCookie(GraphCloneCookie.class);
+        assert c != null;
+        c.openClone();
+    }
+
+    @Override
+    protected int mode() {
+        return CookieAction.MODE_EXACTLY_ONE;
+    }
+
+    @Override
+    protected boolean enable(Node[] activatedNodes) {
+        boolean b = super.enable(activatedNodes);
+        if (b) {
+            assert activatedNodes.length == 1;
+            GraphCloneCookie c = activatedNodes[0].getCookie(GraphCloneCookie.class);
+            assert c != null;
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public String getName() {
+        return "Open clone";
+    }
+
+    @Override
+    protected Class<?>[] cookieClasses() {
+        return new Class<?>[]{
+            GraphCloneCookie.class
+        };
+    }
+
+    @Override
+    protected String iconResource() {
+        return "com/sun/hotspot/igv/coordinator/images/graph.png";
+    }
+
+    @Override
+    public HelpCtx getHelpCtx() {
+        return HelpCtx.DEFAULT_HELP;
+    }
+
+    @Override
+    protected boolean asynchronous() {
+        return false;
+    }
+}
+
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphCookie.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/DiffGraphCookie.java	Thu Mar 21 14:11:13 2013 +0100
@@ -60,7 +60,7 @@
         final GraphViewer viewer = Lookup.getDefault().lookup(GraphViewer.class);
         if (viewer != null) {
             InputGraph diffGraph = Difference.createDiffGraph(other, graph);
-            viewer.view(diffGraph);
+            viewer.view(diffGraph, true);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphCloneCookie.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package com.sun.hotspot.igv.coordinator.actions;
+
+import com.sun.hotspot.igv.data.InputGraph;
+import com.sun.hotspot.igv.data.services.GraphViewer;
+import org.openide.nodes.Node;
+
+public class GraphCloneCookie implements Node.Cookie {
+
+    private final GraphViewer viewer;
+    private final InputGraph graph;
+
+    public GraphCloneCookie(GraphViewer viewer, InputGraph graph) {
+        this.viewer = viewer;
+        this.graph = graph;
+    }
+
+    public void openClone() {
+        viewer.view(graph, true);
+    }
+}
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphOpenCookie.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphOpenCookie.java	Thu Mar 21 14:11:13 2013 +0100
@@ -39,6 +39,6 @@
 
     @Override
     public void open() {
-        viewer.view(graph);
+        viewer.view(graph, false);
     }
 }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GraphViewer.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/services/GraphViewer.java	Thu Mar 21 14:11:13 2013 +0100
@@ -31,5 +31,5 @@
  */
 public interface GraphViewer {
 
-    public void view(InputGraph graph);
+    public void view(InputGraph graph, boolean clone);
 }
--- a/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java	Thu Mar 21 14:11:13 2013 +0100
@@ -207,12 +207,16 @@
             InputNode nodeTo = inputNodeMap.get(a.getNode(to));
             char fromIndex = e.getFromIndex();
             char toIndex = e.getToIndex();
-
-            InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId());
-            if (!newEdges.contains(newEdge)) {
-                markAsDeleted(newEdge);
-                newEdges.add(newEdge);
-                graph.addEdge(newEdge);
+            
+            if (nodeFrom == null || nodeTo == null) {
+                System.out.println("Unexpected edge : " + from + " -> " + to);
+            } else {
+                InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId());
+                if (!newEdges.contains(newEdge)) {
+                    markAsDeleted(newEdge);
+                    newEdges.add(newEdge);
+                    graph.addEdge(newEdge);
+                }
             }
         }
 
@@ -224,17 +228,21 @@
             char fromIndex = e.getFromIndex();
             char toIndex = e.getToIndex();
 
-            InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId());
-            if (!newEdges.contains(newEdge)) {
-                markAsNew(newEdge);
-                newEdges.add(newEdge);
-                graph.addEdge(newEdge);
+            if (nodeFrom == null || nodeTo == null) {
+                System.out.println("Unexpected edge : " + from + " -> " + to);
             } else {
-                newEdges.remove(newEdge);
-                graph.removeEdge(newEdge);
-                markAsSame(newEdge);
-                newEdges.add(newEdge);
-                graph.addEdge(newEdge);
+                InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId());
+                if (!newEdges.contains(newEdge)) {
+                    markAsNew(newEdge);
+                    newEdges.add(newEdge);
+                    graph.addEdge(newEdge);
+                } else {
+                    newEdges.remove(newEdge);
+                    graph.removeEdge(newEdge);
+                    markAsSame(newEdge);
+                    newEdges.add(newEdge);
+                    graph.addEdge(newEdge);
+                }
             }
         }
 
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java	Thu Mar 21 14:11:13 2013 +0100
@@ -45,7 +45,6 @@
         Set<Connection> connectionsToRemove = new HashSet<>();
         for (Figure f : d.getFigures()) {
             final String prop = f.getProperties().get("probability");
-            
             if (prop == null) {
                 figuresToRemove.add(f);
             }
@@ -54,7 +53,15 @@
         
         for (Figure f : d.getFigures()) {
             Properties p = f.getProperties();
-            int predCount = Integer.parseInt(p.get("predecessorCount"));
+            int predCount;
+            String predCountString = p.get("predecessorCount");
+            if (predCountString != null) {
+                predCount = Integer.parseInt(predCountString);
+            } else if (Boolean.parseBoolean(p.get("hasPredecessor"))) {
+                predCount = 1;
+            } else {
+                predCount = 0;
+            }
             for (InputSlot is : f.getInputSlots()) {
                 if (is.getPosition() >= predCount && !"EndNode".equals(is.getProperties().get("class"))) {
                     for (Connection c : is.getConnections()) {
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Thu Mar 21 14:11:13 2013 +0100
@@ -58,7 +58,10 @@
         for (Figure f : figures) {
             Properties p = f.getProperties();
             int predCount;
-            if (Boolean.parseBoolean(p.get("hasPredecessor"))) {
+            String predCountString = p.get("predecessorCount");
+            if (predCountString != null) {
+                predCount = Integer.parseInt(predCountString);
+            } else if (Boolean.parseBoolean(p.get("hasPredecessor"))) {
                 predCount = 1;
             } else {
                 predCount = 0;
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramViewModel.java	Thu Mar 21 14:11:13 2013 +0100
@@ -70,6 +70,10 @@
         result.setData(this);
         return result;
     }
+    
+    public Group getGroup() {
+        return group;
+    }
 
     public void setData(DiagramViewModel newModel) {
         super.setData(newModel);
--- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/GraphViewerImplementation.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/GraphViewerImplementation.java	Thu Mar 21 14:11:13 2013 +0100
@@ -27,6 +27,9 @@
 import com.sun.hotspot.igv.data.services.GraphViewer;
 import com.sun.hotspot.igv.graph.Diagram;
 import com.sun.hotspot.igv.settings.Settings;
+import org.openide.windows.Mode;
+import org.openide.windows.TopComponent;
+import org.openide.windows.WindowManager;
 
 /**
  *
@@ -35,7 +38,24 @@
 public class GraphViewerImplementation implements GraphViewer {
 
     @Override
-    public void view(InputGraph graph) {
+    public void view(InputGraph graph, boolean clone) {
+        
+        if (!clone) {
+            WindowManager manager = WindowManager.getDefault();
+            for (Mode m : manager.getModes()) {
+                for (TopComponent t : manager.getOpenedTopComponents(m)) {
+                    if (t instanceof EditorTopComponent) {
+                        EditorTopComponent etc = (EditorTopComponent) t;
+                        if (etc.getModel().getGroup().getGraphs().contains(graph)) {
+                            etc.getModel().selectGraph(graph);
+                            t.requestActive();
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+        
         Diagram diagram = Diagram.createDiagram(graph, Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT));
         EditorTopComponent tc = new EditorTopComponent(diagram);
         tc.open();
--- a/src/share/tools/ProjectCreator/FileTreeCreatorVC10.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/tools/ProjectCreator/FileTreeCreatorVC10.java	Thu Mar 21 14:11:13 2013 +0100
@@ -50,7 +50,8 @@
                if (addFile.equals(fileName)) {
                   // supress any ignore
                   // TODO - may need some adjustments
-                  if (file.toAbsolutePath().toString().contains(cfg.get("Flavour"))) {
+                  String relativePath = startDir.toUri().relativize(file.toUri()).getPath();
+                  if (relativePath.contains(cfg.get("Flavour"))) {
                      currentFileAttr.removeFromIgnored(cfg);
                   }
                }
--- a/src/share/tools/whitebox/sun/hotspot/WhiteBox.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.hotspot;
-import java.security.BasicPermission;
-import sun.hotspot.parser.DiagnosticCommand;
-
-public class WhiteBox {
-
-  @SuppressWarnings("serial")
-  public static class WhiteBoxPermission extends BasicPermission {
-    public WhiteBoxPermission(String s) {
-      super(s);
-    }
-  }
-
-  private WhiteBox() {}
-  private static final WhiteBox instance = new WhiteBox();
-  private static native void registerNatives();
-
-  /**
-   * Returns the singleton WhiteBox instance.
-   *
-   * The returned WhiteBox object should be carefully guarded
-   * by the caller, since it can be used to read and write data
-   * at arbitrary memory addresses. It must never be passed to
-   * untrusted code.
-   */
-  public synchronized static WhiteBox getWhiteBox() {
-    SecurityManager sm = System.getSecurityManager();
-    if (sm != null) {
-      sm.checkPermission(new WhiteBoxPermission("getInstance"));
-    }
-    return instance;
-  }
-
-  static {
-    registerNatives();
-  }
-
-  // Memory
-  public native long getObjectAddress(Object o);
-  public native int  getHeapOopSize();
-
-  // Runtime
-  // Make sure class name is in the correct format
-  public boolean isClassAlive(String name) {
-    return isClassAlive0(name.replace('.', '/'));
-  }
-  private native boolean isClassAlive0(String name);
-
-  // G1
-  public native boolean g1InConcurrentMark();
-  public native boolean g1IsHumongous(Object o);
-  public native long    g1NumFreeRegions();
-  public native int     g1RegionSize();
-  public native Object[]    parseCommandLine(String commandline, DiagnosticCommand[] args);
-}
--- a/src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-package sun.hotspot.parser;
-
-public class DiagnosticCommand {
-
-    public enum DiagnosticArgumentType {
-        JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE
-    }
-
-    private String name;
-    private String desc;
-    private DiagnosticArgumentType type;
-    private boolean mandatory;
-    private String defaultValue;
-
-    public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type,
-            boolean mandatory, String defaultValue) {
-        this.name = name;
-        this.desc = desc;
-        this.type = type;
-        this.mandatory = mandatory;
-        this.defaultValue = defaultValue;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public String getDesc() {
-        return desc;
-    }
-
-    public DiagnosticArgumentType getType() {
-        return type;
-    }
-
-    public boolean isMandatory() {
-        return mandatory;
-    }
-
-    public String getDefaultValue() {
-        return defaultValue;
-    }
-}
--- a/src/share/vm/adlc/adlparse.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/adlc/adlparse.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -168,7 +168,7 @@
   // Check for block delimiter
   if ( (_curchar != '%')
        || ( next_char(),  (_curchar != '{')) ) {
-    parse_err(SYNERR, "missing '%{' in instruction definition\n");
+    parse_err(SYNERR, "missing '%%{' in instruction definition\n");
     return;
   }
   next_char();                     // Maintain the invariant
@@ -253,7 +253,7 @@
   } while(_curchar != '%');
   next_char();
   if (_curchar != '}') {
-    parse_err(SYNERR, "missing '%}' in instruction definition\n");
+    parse_err(SYNERR, "missing '%%}' in instruction definition\n");
     return;
   }
   // Check for "Set" form of chain rule
@@ -423,7 +423,7 @@
   skipws();
   // Check for block delimiter
   if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block
-    parse_err(SYNERR, "missing '%c{' in operand definition\n","%");
+    parse_err(SYNERR, "missing '%%{' in operand definition\n");
     return;
   }
   next_char(); next_char();        // Skip over "%{" symbol
@@ -483,7 +483,7 @@
   } while(_curchar != '%');
   next_char();
   if (_curchar != '}') {
-    parse_err(SYNERR, "missing '%}' in operand definition\n");
+    parse_err(SYNERR, "missing '%%}' in operand definition\n");
     return;
   }
   // Add operand to tail of operand list
@@ -1324,7 +1324,7 @@
   // Check for block delimiter
   if ( (_curchar != '%')
        || ( next_char(),  (_curchar != '{')) ) {
-    parse_err(SYNERR, "missing '%{' in pipeline definition\n");
+    parse_err(SYNERR, "missing '%%{' in pipeline definition\n");
     return;
   }
   next_char();                     // Maintain the invariant
@@ -1341,7 +1341,7 @@
       skipws();
       if ( (_curchar != '%')
            || ( next_char(),  (_curchar != '{')) ) {
-        parse_err(SYNERR, "expected '%{'\n");
+        parse_err(SYNERR, "expected '%%{'\n");
         return;
       }
       next_char(); skipws();
@@ -1397,7 +1397,7 @@
       skipws();
       if ( (_curchar != '%')
            || ( next_char(),  (_curchar != '{')) ) {
-        parse_err(SYNERR, "expected '%{'\n");
+        parse_err(SYNERR, "expected '%%{'\n");
         return;
       }
       next_char(); skipws();
@@ -1586,7 +1586,7 @@
 
       if ( (_curchar != '%')
            || ( next_char(),  (_curchar != '}')) ) {
-        parse_err(SYNERR, "expected '%}', found \"%c\"\n", _curchar);
+        parse_err(SYNERR, "expected '%%}', found \"%c\"\n", _curchar);
       }
       next_char(); skipws();
 
@@ -1612,7 +1612,7 @@
 
   next_char();
   if (_curchar != '}') {
-    parse_err(SYNERR, "missing \"%}\" in pipeline definition\n");
+    parse_err(SYNERR, "missing \"%%}\" in pipeline definition\n");
     return;
   }
 
@@ -1775,7 +1775,7 @@
   // Check for block delimiter
   if ( (_curchar != '%')
        || ( next_char(),  (_curchar != '{')) ) {
-    parse_err(SYNERR, "missing \"%{\" in pipe_class definition\n");
+    parse_err(SYNERR, "missing \"%%{\" in pipe_class definition\n");
     return;
   }
   next_char();
@@ -2062,7 +2062,7 @@
 
   next_char();
   if (_curchar != '}') {
-    parse_err(SYNERR, "missing \"%}\" in pipe_class definition\n");
+    parse_err(SYNERR, "missing \"%%}\" in pipe_class definition\n");
     return;
   }
 
@@ -3341,12 +3341,12 @@
   char *disp        = NULL;
 
   if (_curchar != '%') {
-    parse_err(SYNERR, "Missing '%{' for 'interface' block.\n");
+    parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n");
     return NULL;
   }
   next_char();                  // Skip '%'
   if (_curchar != '{') {
-    parse_err(SYNERR, "Missing '%{' for 'interface' block.\n");
+    parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n");
     return NULL;
   }
   next_char();                  // Skip '{'
@@ -3354,7 +3354,7 @@
   do {
     char *field = get_ident();
     if (field == NULL) {
-      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%}' ending interface.\n");
+      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%%}' ending interface.\n");
       return NULL;
     }
     if ( strcmp(field,"base") == 0 ) {
@@ -3370,13 +3370,13 @@
       disp  = interface_field_parse();
     }
     else {
-      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%}' ending interface.\n");
+      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%%}' ending interface.\n");
       return NULL;
     }
   } while( _curchar != '%' );
   next_char();                  // Skip '%'
   if ( _curchar != '}' ) {
-    parse_err(SYNERR, "Missing '%}' for 'interface' block.\n");
+    parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n");
     return NULL;
   }
   next_char();                  // Skip '}'
@@ -3403,12 +3403,12 @@
   const char *greater_format = "gt";
 
   if (_curchar != '%') {
-    parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n");
+    parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n");
     return NULL;
   }
   next_char();                  // Skip '%'
   if (_curchar != '{') {
-    parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n");
+    parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n");
     return NULL;
   }
   next_char();                  // Skip '{'
@@ -3416,7 +3416,7 @@
   do {
     char *field = get_ident();
     if (field == NULL) {
-      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%}' ending interface.\n");
+      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%%}' ending interface.\n");
       return NULL;
     }
     if ( strcmp(field,"equal") == 0 ) {
@@ -3438,13 +3438,13 @@
       greater = interface_field_parse(&greater_format);
     }
     else {
-      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%}' ending interface.\n");
+      parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%%}' ending interface.\n");
       return NULL;
     }
   } while( _curchar != '%' );
   next_char();                  // Skip '%'
   if ( _curchar != '}' ) {
-    parse_err(SYNERR, "Missing '%}' for 'interface' block.\n");
+    parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n");
     return NULL;
   }
   next_char();                  // Skip '}'
@@ -3543,7 +3543,7 @@
   }
   else if ((cnstr = find_cpp_block("match constructor")) == NULL ) {
     parse_err(SYNERR, "invalid construction of match rule\n"
-              "Missing ';' or invalid '%{' and '%}' constructor\n");
+              "Missing ';' or invalid '%%{' and '%%}' constructor\n");
     return NULL;                  // No MatchRule to return
   }
   if (_AD._adl_debug > 1)
@@ -3646,7 +3646,7 @@
       // Check for closing '"' and '%}' in format description
       skipws();                   // Move to closing '%}'
       if ( _curchar != '%' ) {
-        parse_err(SYNERR, "non-blank characters between closing '\"' and '%' in format");
+        parse_err(SYNERR, "non-blank characters between closing '\"' and '%%' in format");
         return NULL;
       }
     } // Done with format description inside
@@ -3654,7 +3654,7 @@
     skipws();
     // Past format description, at '%'
     if ( _curchar != '%' || *(_ptr+1) != '}' ) {
-      parse_err(SYNERR, "missing '%}' at end of format block");
+      parse_err(SYNERR, "missing '%%}' at end of format block");
       return NULL;
     }
     next_char();                  // Move past the '%'
@@ -3785,7 +3785,7 @@
   skipws();
   // Past format description, at '%'
   if ( _curchar != '%' || *(_ptr+1) != '}' ) {
-    parse_err(SYNERR, "missing '%}' at end of format block");
+    parse_err(SYNERR, "missing '%%}' at end of format block");
     return NULL;
   }
   next_char();                  // Move past the '%'
@@ -3834,7 +3834,7 @@
   skipws();                        // Skip leading whitespace
   if ((_curchar != '%')
       || (next_char(), (_curchar != '{')) ) { // If not open block
-    parse_err(SYNERR, "missing '%{' in expand definition\n");
+    parse_err(SYNERR, "missing '%%{' in expand definition\n");
     return(NULL);
   }
   next_char();                     // Maintain the invariant
@@ -3933,7 +3933,7 @@
   } while(_curchar != '%');
   next_char();
   if (_curchar != '}') {
-    parse_err(SYNERR, "missing '%}' in expand rule definition\n");
+    parse_err(SYNERR, "missing '%%}' in expand rule definition\n");
     return(NULL);
   }
   next_char();
--- a/src/share/vm/adlc/formssel.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/adlc/formssel.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -753,10 +753,11 @@
         !strcmp(_matrule->_rChild->_opType,"DecodeNKlass") ||
         !strcmp(_matrule->_rChild->_opType,"EncodePKlass") ||
         !strcmp(_matrule->_rChild->_opType,"LoadN")        ||
-        !strcmp(_matrule->_rChild->_opType,"GetAndSetN")   ||
         !strcmp(_matrule->_rChild->_opType,"LoadNKlass")   ||
         !strcmp(_matrule->_rChild->_opType,"CreateEx")     ||  // type of exception
-        !strcmp(_matrule->_rChild->_opType,"CheckCastPP")) ) return true;
+        !strcmp(_matrule->_rChild->_opType,"CheckCastPP")  ||
+        !strcmp(_matrule->_rChild->_opType,"GetAndSetP")   ||
+        !strcmp(_matrule->_rChild->_opType,"GetAndSetN")) )  return true;
   else if ( is_ideal_load() == Form::idealP )                return true;
   else if ( is_ideal_store() != Form::none  )                return true;
 
--- a/src/share/vm/asm/macroAssembler.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/asm/macroAssembler.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -37,10 +37,10 @@
 # include "assembler_zero.hpp"
 #endif
 #ifdef TARGET_ARCH_arm
-# include "assembler_arm.hpp"
+# include "macroAssembler_arm.hpp"
 #endif
 #ifdef TARGET_ARCH_ppc
-# include "assembler_ppc.hpp"
+# include "macroAssembler_ppc.hpp"
 #endif
 
 #endif // SHARE_VM_ASM_MACROASSEMBLER_HPP
--- a/src/share/vm/asm/macroAssembler.inline.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/asm/macroAssembler.inline.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -37,10 +37,10 @@
 # include "assembler_zero.inline.hpp"
 #endif
 #ifdef TARGET_ARCH_arm
-# include "assembler_arm.inline.hpp"
+# include "macroAssembler_arm.inline.hpp"
 #endif
 #ifdef TARGET_ARCH_ppc
-# include "assembler_ppc.inline.hpp"
+# include "macroAssembler_ppc.inline.hpp"
 #endif
 
 #endif // SHARE_VM_ASM_MACROASSEMBLER_INLINE_HPP
--- a/src/share/vm/c1/c1_CodeStubs.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/c1/c1_CodeStubs.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -31,6 +31,7 @@
 #include "c1/c1_LIR.hpp"
 #include "c1/c1_Runtime1.hpp"
 #include "utilities/array.hpp"
+#include "utilities/macros.hpp"
 
 class CodeEmitInfo;
 class LIR_Assembler;
@@ -515,7 +516,7 @@
 };
 
 //////////////////////////////////////////////////////////////////////////////////////////
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
 // Code stubs for Garbage-First barriers.
 class G1PreBarrierStub: public CodeStub {
@@ -608,7 +609,7 @@
 #endif // PRODUCT
 };
 
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 //////////////////////////////////////////////////////////////////////////////////////////
 
 #endif // SHARE_VM_C1_C1_CODESTUBS_HPP
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -3667,11 +3667,12 @@
   }
 
   // now perform tests that are based on flag settings
-  if (callee->force_inline() || callee->should_inline()) {
-    // ignore heuristic controls on inlining
-    if (callee->force_inline())
-      print_inlining(callee, "force inline by annotation");
+  if (callee->force_inline()) {
+    print_inlining(callee, "force inline by annotation");
+  } else if (callee->should_inline()) {
+    print_inlining(callee, "force inline by CompileOracle");
   } else {
+    // use heuristic controls on inlining
     if (inline_level() > MaxInlineLevel                         ) INLINE_BAILOUT("inlining too deep");
     if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep");
     if (callee->code_size_for_inlining() > max_inline_size()    ) INLINE_BAILOUT("callee is too large");
--- a/src/share/vm/c1/c1_IR.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/c1/c1_IR.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -240,8 +240,8 @@
     // reexecute allowed only for the topmost frame
     bool reexecute = topmost ? should_reexecute() : false;
     bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis.
-    methodHandle null_mh;
-    recorder->describe_scope(pc_offset, null_mh, scope()->method(), bci(), reexecute, false, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
+    bool rethrow_exception = false;
+    recorder->describe_scope(pc_offset, methodHandle(), scope()->method(), bci(), reexecute, rethrow_exception, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
   }
 };
 
--- a/src/share/vm/c1/c1_Instruction.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/c1/c1_Instruction.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -188,7 +188,7 @@
 
 ciType* LoadIndexed::declared_type() const {
   ciType* array_type = array()->declared_type();
-  if (array_type == NULL) {
+  if (array_type == NULL || !array_type->is_loaded()) {
     return NULL;
   }
   assert(array_type->is_array_klass(), "what else?");
--- a/src/share/vm/c1/c1_LIR.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/c1/c1_LIR.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -814,7 +814,7 @@
 
       // only visit register parameters
       int n = opJavaCall->_arguments->length();
-      for (int i = 0; i < n; i++) {
+      for (int i = opJavaCall->_receiver->is_valid() ? 1 : 0; i < n; i++) {
         if (!opJavaCall->_arguments->at(i)->is_pointer()) {
           do_input(*opJavaCall->_arguments->adr_at(i));
         }
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -35,9 +35,10 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "utilities/bitMap.inline.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/heapRegion.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 #ifdef ASSERT
 #define __ gen()->lir(__FILE__, __LINE__)->
@@ -1417,12 +1418,12 @@
                                bool do_load, bool patch, CodeEmitInfo* info) {
   // Do the pre-write barrier, if any.
   switch (_bs->kind()) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case BarrierSet::G1SATBCT:
     case BarrierSet::G1SATBCTLogging:
       G1SATBCardTableModRef_pre_barrier(addr_opr, pre_val, do_load, patch, info);
       break;
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
     case BarrierSet::CardTableModRef:
     case BarrierSet::CardTableExtension:
       // No pre barriers
@@ -1439,12 +1440,12 @@
 
 void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) {
   switch (_bs->kind()) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case BarrierSet::G1SATBCT:
     case BarrierSet::G1SATBCTLogging:
       G1SATBCardTableModRef_post_barrier(addr,  new_val);
       break;
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
     case BarrierSet::CardTableModRef:
     case BarrierSet::CardTableExtension:
       CardTableModRef_post_barrier(addr,  new_val);
@@ -1459,7 +1460,7 @@
 }
 
 ////////////////////////////////////////////////////////////////////////
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
 void LIRGenerator::G1SATBCardTableModRef_pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val,
                                                      bool do_load, bool patch, CodeEmitInfo* info) {
@@ -1575,7 +1576,7 @@
   __ branch_destination(slow->continuation());
 }
 
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 ////////////////////////////////////////////////////////////////////////
 
 void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) {
@@ -2181,7 +2182,7 @@
 
   get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile());
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // We might be reading the value of the referent field of a
   // Reference object in order to attach it back to the live
   // object graph. If G1 is enabled then we need to record
@@ -2311,7 +2312,7 @@
       __ branch_destination(Lcont->label());
     }
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   if (x->is_volatile() && os::is_MP()) __ membar_acquire();
 }
--- a/src/share/vm/ci/ciCallProfile.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/ci/ciCallProfile.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -61,7 +61,6 @@
   // Note:  The following predicates return false for invalid profiles:
   bool      has_receiver(int i) const { return _limit > i; }
   int       morphism() const          { return _morphism; }
-  int       limit() const             { return _limit; }
 
   int       count() const             { return _count; }
   int       receiver_count(int i)  {
--- a/src/share/vm/ci/ciEnv.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/ci/ciEnv.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,6 +52,7 @@
 #include "runtime/reflection.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/dtrace.hpp"
+#include "utilities/macros.hpp"
 #ifdef COMPILER1
 #include "c1/c1_Runtime1.hpp"
 #endif
@@ -596,10 +597,6 @@
     assert (klass->is_instance_klass() || klass->is_array_klass(),
             "must be an instance or array klass ");
     return ciConstant(T_OBJECT, klass->java_mirror());
-  } else if (tag.is_object()) {
-    oop obj = cpool->object_at(index);
-    ciObject* ciobj = get_object(obj);
-    return ciConstant(T_OBJECT, ciobj);
   } else if (tag.is_method_type()) {
     // must execute Java code to link this CP entry into cache[i].f1
     ciSymbol* signature = get_symbol(cpool->method_type_signature_at(index));
@@ -1168,7 +1165,7 @@
 
 void ciEnv::dump_replay_data(outputStream* out) {
   ASSERT_IN_VM;
-
+  ResourceMark rm;
 #if INCLUDE_JVMTI
   out->print_cr("JvmtiExport can_access_local_variables %d",     _jvmti_can_access_local_variables);
   out->print_cr("JvmtiExport can_hotswap_or_post_breakpoint %d", _jvmti_can_hotswap_or_post_breakpoint);
--- a/src/share/vm/ci/ciField.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/ci/ciField.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -166,8 +166,6 @@
   // at each point of access.
   bool will_link(ciInstanceKlass* accessing_klass,
                  Bytecodes::Code bc);
-  bool will_link_from_vm(ciInstanceKlass* accessing_klass,
-                 Bytecodes::Code bc);
 
   // Java access flags
   bool is_public      () { return flags().is_public(); }
--- a/src/share/vm/ci/ciInstanceKlass.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/ci/ciInstanceKlass.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -580,6 +580,7 @@
   }
   void do_field(fieldDescriptor* fd) {
     if (fd->is_final() && !fd->has_initial_value()) {
+      ResourceMark rm;
       oop mirror = fd->field_holder()->java_mirror();
       _out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii());
       switch (fd->field_type()) {
@@ -643,6 +644,8 @@
 
 void ciInstanceKlass::dump_replay_data(outputStream* out) {
   ASSERT_IN_VM;
+  ResourceMark rm;
+
   InstanceKlass* ik = get_instanceKlass();
   ConstantPool*  cp = ik->constants();
 
--- a/src/share/vm/ci/ciMethod.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/ci/ciMethod.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -977,7 +977,7 @@
 // ciMethod::set_not_compilable
 //
 // Tell the VM that this method cannot be compiled at all.
-void ciMethod::set_not_compilable() {
+void ciMethod::set_not_compilable(const char* reason) {
   check_is_loaded();
   VM_ENTRY_MARK;
   ciEnv* env = CURRENT_ENV;
@@ -986,7 +986,7 @@
   } else {
     _is_c2_compilable = false;
   }
-  get_Method()->set_not_compilable(env->comp_level());
+  get_Method()->set_not_compilable(env->comp_level(), true, reason);
 }
 
 // ------------------------------------------------------------------
@@ -1178,6 +1178,7 @@
 
 void ciMethod::dump_replay_data(outputStream* st) {
   ASSERT_IN_VM;
+  ResourceMark rm;
   Method* method = get_Method();
   Klass*  holder = method->method_holder();
   st->print_cr("ciMethod %s %s %s %d %d %d %d %d",
--- a/src/share/vm/ci/ciMethod.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/ci/ciMethod.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -252,7 +252,7 @@
   bool has_option(const char *option);
   bool can_be_compiled();
   bool can_be_osr_compiled(int entry_bci);
-  void set_not_compilable();
+  void set_not_compilable(const char* reason = NULL);
   bool has_compiled_code();
   void log_nmethod_identity(xmlStream* log);
   bool is_not_reached(int bci);
--- a/src/share/vm/ci/ciMethodData.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/ci/ciMethodData.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -374,6 +374,7 @@
 
 void ciMethodData::dump_replay_data(outputStream* out) {
   ASSERT_IN_VM;
+  ResourceMark rm;
   MethodData* mdo = get_MethodData();
   Method* method = mdo->method();
   Klass* holder = method->method_holder();
--- a/src/share/vm/ci/ciObject.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/ci/ciObject.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -65,14 +65,12 @@
   ciObject(Handle h);
   ciObject(ciKlass* klass);
 
-public:
   jobject      handle()  const { return _handle; }
   // Get the VM oop that this object holds.
   oop get_oop() const {
     assert(_handle != NULL, "null oop");
     return JNIHandles::resolve_non_null(_handle);
   }
-protected:
 
   void init_flags_from(oop x);
 
--- a/src/share/vm/ci/ciReplay.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/ci/ciReplay.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -30,6 +30,7 @@
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
 #include "utilities/copy.hpp"
+#include "utilities/macros.hpp"
 
 #ifndef PRODUCT
 
--- a/src/share/vm/ci/ciSymbol.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/ci/ciSymbol.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -48,7 +48,7 @@
 
 private:
   const vmSymbols::SID _sid;
-  DEBUG_ONLY( bool sid_ok() { return true;/*vmSymbols::find_sid(get_symbol()) == _sid;*/ } )
+  DEBUG_ONLY( bool sid_ok() { return vmSymbols::find_sid(get_symbol()) == _sid; } )
 
   ciSymbol(Symbol* s);  // normal case, for symbols not mentioned in vmSymbols
   ciSymbol(Symbol* s, vmSymbols::SID sid);   // for use with vmSymbols
--- a/src/share/vm/classfile/classFileParser.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/classFileParser.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1856,6 +1856,154 @@
 #define MAX_CODE_SIZE 65535
 #define INITIAL_MAX_LVT_NUMBER 256
 
+/* Copy class file LVT's/LVTT's into the HotSpot internal LVT.
+ *
+ * Rules for LVT's and LVTT's are:
+ *   - There can be any number of LVT's and LVTT's.
+ *   - If there are n LVT's, it is the same as if there was just
+ *     one LVT containing all the entries from the n LVT's.
+ *   - There may be no more than one LVT entry per local variable.
+ *     Two LVT entries are 'equal' if these fields are the same:
+ *        start_pc, length, name, slot
+ *   - There may be no more than one LVTT entry per each LVT entry.
+ *     Each LVTT entry has to match some LVT entry.
+ *   - HotSpot internal LVT keeps natural ordering of class file LVT entries.
+ */
+void ClassFileParser::copy_localvariable_table(ConstMethod* cm,
+                                               int lvt_cnt,
+                                               u2* localvariable_table_length,
+                                               u2** localvariable_table_start,
+                                               int lvtt_cnt,
+                                               u2* localvariable_type_table_length,
+                                               u2** localvariable_type_table_start,
+                                               TRAPS) {
+
+  LVT_Hash** lvt_Hash = NEW_RESOURCE_ARRAY(LVT_Hash*, HASH_ROW_SIZE);
+  initialize_hashtable(lvt_Hash);
+
+  // To fill LocalVariableTable in
+  Classfile_LVT_Element*  cf_lvt;
+  LocalVariableTableElement* lvt = cm->localvariable_table_start();
+
+  for (int tbl_no = 0; tbl_no < lvt_cnt; tbl_no++) {
+    cf_lvt = (Classfile_LVT_Element *) localvariable_table_start[tbl_no];
+    for (int idx = 0; idx < localvariable_table_length[tbl_no]; idx++, lvt++) {
+      copy_lvt_element(&cf_lvt[idx], lvt);
+      // If no duplicates, add LVT elem in hashtable lvt_Hash.
+      if (LVT_put_after_lookup(lvt, lvt_Hash) == false
+          && _need_verify
+          && _major_version >= JAVA_1_5_VERSION) {
+        clear_hashtable(lvt_Hash);
+        ConstantPool* cp = cm->constants();
+        classfile_parse_error("Duplicated LocalVariableTable attribute "
+                              "entry for '%s' in class file %s",
+                               cp->symbol_at(lvt->name_cp_index)->as_utf8(),
+                               CHECK);
+      }
+    }
+  }
+
+  // To merge LocalVariableTable and LocalVariableTypeTable
+  Classfile_LVT_Element* cf_lvtt;
+  LocalVariableTableElement lvtt_elem;
+
+  for (int tbl_no = 0; tbl_no < lvtt_cnt; tbl_no++) {
+    cf_lvtt = (Classfile_LVT_Element *) localvariable_type_table_start[tbl_no];
+    for (int idx = 0; idx < localvariable_type_table_length[tbl_no]; idx++) {
+      copy_lvt_element(&cf_lvtt[idx], &lvtt_elem);
+      int index = hash(&lvtt_elem);
+      LVT_Hash* entry = LVT_lookup(&lvtt_elem, index, lvt_Hash);
+      if (entry == NULL) {
+        if (_need_verify) {
+          clear_hashtable(lvt_Hash);
+          ConstantPool* cp = cm->constants();
+          classfile_parse_error("LVTT entry for '%s' in class file %s "
+                                "does not match any LVT entry",
+                                 cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
+                                 CHECK);
+        }
+      } else if (entry->_elem->signature_cp_index != 0 && _need_verify) {
+        clear_hashtable(lvt_Hash);
+        ConstantPool* cp = cm->constants();
+        classfile_parse_error("Duplicated LocalVariableTypeTable attribute "
+                              "entry for '%s' in class file %s",
+                               cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
+                               CHECK);
+      } else {
+        // to add generic signatures into LocalVariableTable
+        entry->_elem->signature_cp_index = lvtt_elem.descriptor_cp_index;
+      }
+    }
+  }
+  clear_hashtable(lvt_Hash);
+}
+
+
+void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
+                                       ConstMethod* cm,
+                                       u1* runtime_visible_annotations,
+                                       int runtime_visible_annotations_length,
+                                       u1* runtime_invisible_annotations,
+                                       int runtime_invisible_annotations_length,
+                                       u1* runtime_visible_parameter_annotations,
+                                       int runtime_visible_parameter_annotations_length,
+                                       u1* runtime_invisible_parameter_annotations,
+                                       int runtime_invisible_parameter_annotations_length,
+                                       u1* runtime_visible_type_annotations,
+                                       int runtime_visible_type_annotations_length,
+                                       u1* runtime_invisible_type_annotations,
+                                       int runtime_invisible_type_annotations_length,
+                                       u1* annotation_default,
+                                       int annotation_default_length,
+                                       TRAPS) {
+
+  AnnotationArray* a;
+
+  if (runtime_visible_annotations_length +
+      runtime_invisible_annotations_length > 0) {
+     a = assemble_annotations(loader_data,
+                              runtime_visible_annotations,
+                              runtime_visible_annotations_length,
+                              runtime_invisible_annotations,
+                              runtime_invisible_annotations_length,
+                              CHECK);
+     cm->set_method_annotations(a);
+  }
+
+  if (runtime_visible_parameter_annotations_length +
+      runtime_invisible_parameter_annotations_length > 0) {
+    a = assemble_annotations(loader_data,
+                             runtime_visible_parameter_annotations,
+                             runtime_visible_parameter_annotations_length,
+                             runtime_invisible_parameter_annotations,
+                             runtime_invisible_parameter_annotations_length,
+                             CHECK);
+    cm->set_parameter_annotations(a);
+  }
+
+  if (annotation_default_length > 0) {
+    a = assemble_annotations(loader_data,
+                             annotation_default,
+                             annotation_default_length,
+                             NULL,
+                             0,
+                             CHECK);
+    cm->set_default_annotations(a);
+  }
+
+  if (runtime_visible_type_annotations_length +
+      runtime_invisible_type_annotations_length > 0) {
+    a = assemble_annotations(loader_data,
+                             runtime_visible_type_annotations,
+                             runtime_visible_type_annotations_length,
+                             runtime_invisible_type_annotations,
+                             runtime_invisible_type_annotations_length,
+                             CHECK);
+    cm->set_type_annotations(a);
+  }
+}
+
+
 // Note: the parse_method below is big and clunky because all parsing of the code and exceptions
 // attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the
 // Method* to save footprint, so we only know the size of the resulting Method* when the
@@ -1869,10 +2017,6 @@
                                            constantPoolHandle cp,
                                            bool is_interface,
                                            AccessFlags *promoted_flags,
-                                           AnnotationArray** method_annotations,
-                                           AnnotationArray** method_parameter_annotations,
-                                           AnnotationArray** method_default_annotations,
-                                           AnnotationArray** method_type_annotations,
                                            TRAPS) {
   ClassFileStream* cfs = stream();
   methodHandle nullHandle;
@@ -1947,6 +2091,8 @@
   u2** localvariable_type_table_start;
   u2 method_parameters_length = 0;
   u1* method_parameters_data = NULL;
+  bool method_parameters_seen = false;
+  bool method_parameters_four_byte_flags;
   bool parsed_code_attribute = false;
   bool parsed_checked_exceptions_attribute = false;
   bool parsed_stackmap_attribute = false;
@@ -2157,21 +2303,31 @@
                                      method_attribute_length,
                                      cp, CHECK_(nullHandle));
     } else if (method_attribute_name == vmSymbols::tag_method_parameters()) {
+      // reject multiple method parameters
+      if (method_parameters_seen) {
+        classfile_parse_error("Multiple MethodParameters attributes in class file %s", CHECK_(nullHandle));
+      }
+      method_parameters_seen = true;
       method_parameters_length = cfs->get_u1_fast();
       // Track the actual size (note: this is written for clarity; a
       // decent compiler will CSE and constant-fold this into a single
       // expression)
-      u2 actual_size = 1;
+      // Use the attribute length to figure out the size of flags
+      if (method_attribute_length == (method_parameters_length * 6u) + 1u) {
+        method_parameters_four_byte_flags = true;
+      } else if (method_attribute_length == (method_parameters_length * 4u) + 1u) {
+        method_parameters_four_byte_flags = false;
+      } else {
+        classfile_parse_error(
+          "Invalid MethodParameters method attribute length %u in class file",
+          method_attribute_length, CHECK_(nullHandle));
+      }
       method_parameters_data = cfs->get_u1_buffer();
-      actual_size += 2 * method_parameters_length;
       cfs->skip_u2_fast(method_parameters_length);
-      actual_size += 4 * method_parameters_length;
-      cfs->skip_u4_fast(method_parameters_length);
-      // Enforce attribute length
-      if (method_attribute_length != actual_size) {
-        classfile_parse_error(
-          "Invalid MethodParameters method attribute length %u in class file %s",
-          method_attribute_length, CHECK_(nullHandle));
+      if (method_parameters_four_byte_flags) {
+        cfs->skip_u4_fast(method_parameters_length);
+      } else {
+        cfs->skip_u2_fast(method_parameters_length);
       }
       // ignore this attribute if it cannot be reflected
       if (!SystemDictionary::Parameter_klass_loaded())
@@ -2261,10 +2417,24 @@
   }
 
   // All sizing information for a Method* is finally available, now create it
+  InlineTableSizes sizes(
+      total_lvt_length,
+      linenumber_table_length,
+      exception_table_length,
+      checked_exceptions_length,
+      method_parameters_length,
+      generic_signature_index,
+      runtime_visible_annotations_length +
+           runtime_invisible_annotations_length,
+      runtime_visible_parameter_annotations_length +
+           runtime_invisible_parameter_annotations_length,
+      runtime_visible_type_annotations_length +
+           runtime_invisible_type_annotations_length,
+      annotation_default_length,
+      0);
+
   Method* m = Method::allocate(
-      loader_data, code_length, access_flags, linenumber_table_length,
-      total_lvt_length, exception_table_length, checked_exceptions_length,
-      method_parameters_length, generic_signature_index,
+      loader_data, code_length, access_flags, &sizes,
       ConstMethod::NORMAL, CHECK_(nullHandle));
 
   ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
@@ -2316,15 +2486,16 @@
   // Copy method parameters
   if (method_parameters_length > 0) {
     MethodParametersElement* elem = m->constMethod()->method_parameters_start();
-    for(int i = 0; i < method_parameters_length; i++) {
-      elem[i].name_cp_index =
-        Bytes::get_Java_u2(method_parameters_data);
+    for (int i = 0; i < method_parameters_length; i++) {
+      elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data);
       method_parameters_data += 2;
-      u4 flags = Bytes::get_Java_u4(method_parameters_data);
-      // This caused an alignment fault on Sparc, if flags was a u4
-      elem[i].flags_lo = extract_low_short_from_int(flags);
-      elem[i].flags_hi = extract_high_short_from_int(flags);
-      method_parameters_data += 4;
+      if (method_parameters_four_byte_flags) {
+        elem[i].flags = Bytes::get_Java_u4(method_parameters_data);
+        method_parameters_data += 4;
+      } else {
+        elem[i].flags = Bytes::get_Java_u2(method_parameters_data);
+        method_parameters_data += 2;
+      }
     }
   }
 
@@ -2334,107 +2505,37 @@
     copy_u2_with_conversion((u2*) m->checked_exceptions_start(), checked_exceptions_start, size);
   }
 
-  /* Copy class file LVT's/LVTT's into the HotSpot internal LVT.
-   *
-   * Rules for LVT's and LVTT's are:
-   *   - There can be any number of LVT's and LVTT's.
-   *   - If there are n LVT's, it is the same as if there was just
-   *     one LVT containing all the entries from the n LVT's.
-   *   - There may be no more than one LVT entry per local variable.
-   *     Two LVT entries are 'equal' if these fields are the same:
-   *        start_pc, length, name, slot
-   *   - There may be no more than one LVTT entry per each LVT entry.
-   *     Each LVTT entry has to match some LVT entry.
-   *   - HotSpot internal LVT keeps natural ordering of class file LVT entries.
-   */
+  // Copy class file LVT's/LVTT's into the HotSpot internal LVT.
   if (total_lvt_length > 0) {
-    int tbl_no, idx;
-
     promoted_flags->set_has_localvariable_table();
-
-    LVT_Hash** lvt_Hash = NEW_RESOURCE_ARRAY(LVT_Hash*, HASH_ROW_SIZE);
-    initialize_hashtable(lvt_Hash);
-
-    // To fill LocalVariableTable in
-    Classfile_LVT_Element*  cf_lvt;
-    LocalVariableTableElement* lvt = m->localvariable_table_start();
-
-    for (tbl_no = 0; tbl_no < lvt_cnt; tbl_no++) {
-      cf_lvt = (Classfile_LVT_Element *) localvariable_table_start[tbl_no];
-      for (idx = 0; idx < localvariable_table_length[tbl_no]; idx++, lvt++) {
-        copy_lvt_element(&cf_lvt[idx], lvt);
-        // If no duplicates, add LVT elem in hashtable lvt_Hash.
-        if (LVT_put_after_lookup(lvt, lvt_Hash) == false
-          && _need_verify
-          && _major_version >= JAVA_1_5_VERSION ) {
-          clear_hashtable(lvt_Hash);
-          classfile_parse_error("Duplicated LocalVariableTable attribute "
-                                "entry for '%s' in class file %s",
-                                 cp->symbol_at(lvt->name_cp_index)->as_utf8(),
-                                 CHECK_(nullHandle));
-        }
-      }
-    }
-
-    // To merge LocalVariableTable and LocalVariableTypeTable
-    Classfile_LVT_Element* cf_lvtt;
-    LocalVariableTableElement lvtt_elem;
-
-    for (tbl_no = 0; tbl_no < lvtt_cnt; tbl_no++) {
-      cf_lvtt = (Classfile_LVT_Element *) localvariable_type_table_start[tbl_no];
-      for (idx = 0; idx < localvariable_type_table_length[tbl_no]; idx++) {
-        copy_lvt_element(&cf_lvtt[idx], &lvtt_elem);
-        int index = hash(&lvtt_elem);
-        LVT_Hash* entry = LVT_lookup(&lvtt_elem, index, lvt_Hash);
-        if (entry == NULL) {
-          if (_need_verify) {
-            clear_hashtable(lvt_Hash);
-            classfile_parse_error("LVTT entry for '%s' in class file %s "
-                                  "does not match any LVT entry",
-                                   cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
-                                   CHECK_(nullHandle));
-          }
-        } else if (entry->_elem->signature_cp_index != 0 && _need_verify) {
-          clear_hashtable(lvt_Hash);
-          classfile_parse_error("Duplicated LocalVariableTypeTable attribute "
-                                "entry for '%s' in class file %s",
-                                 cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
-                                 CHECK_(nullHandle));
-        } else {
-          // to add generic signatures into LocalVariableTable
-          entry->_elem->signature_cp_index = lvtt_elem.descriptor_cp_index;
-        }
-      }
-    }
-    clear_hashtable(lvt_Hash);
+    copy_localvariable_table(m->constMethod(), lvt_cnt,
+                             localvariable_table_length,
+                             localvariable_table_start,
+                             lvtt_cnt,
+                             localvariable_type_table_length,
+                             localvariable_type_table_start, CHECK_NULL);
   }
 
   if (parsed_annotations.has_any_annotations())
     parsed_annotations.apply_to(m);
-  *method_annotations = assemble_annotations(loader_data,
-                                             runtime_visible_annotations,
-                                             runtime_visible_annotations_length,
-                                             runtime_invisible_annotations,
-                                             runtime_invisible_annotations_length,
-                                             CHECK_(nullHandle));
-  *method_parameter_annotations = assemble_annotations(loader_data,
-                                                       runtime_visible_parameter_annotations,
-                                                       runtime_visible_parameter_annotations_length,
-                                                       runtime_invisible_parameter_annotations,
-                                                       runtime_invisible_parameter_annotations_length,
-                                                       CHECK_(nullHandle));
-  *method_default_annotations = assemble_annotations(loader_data,
-                                                     annotation_default,
-                                                     annotation_default_length,
-                                                     NULL,
-                                                     0,
-                                                     CHECK_(nullHandle));
-  *method_type_annotations = assemble_annotations(loader_data,
-                                                  runtime_visible_type_annotations,
-                                                  runtime_visible_type_annotations_length,
-                                                  runtime_invisible_type_annotations,
-                                                  runtime_invisible_type_annotations_length,
-                                                  CHECK_(nullHandle));
+
+  // Copy annotations
+  copy_method_annotations(loader_data, m->constMethod(),
+                          runtime_visible_annotations,
+                          runtime_visible_annotations_length,
+                          runtime_invisible_annotations,
+                          runtime_invisible_annotations_length,
+                          runtime_visible_parameter_annotations,
+                          runtime_visible_parameter_annotations_length,
+                          runtime_invisible_parameter_annotations,
+                          runtime_invisible_parameter_annotations_length,
+                          runtime_visible_type_annotations,
+                          runtime_visible_type_annotations_length,
+                          runtime_invisible_type_annotations,
+                          runtime_invisible_type_annotations_length,
+                          annotation_default,
+                          annotation_default_length,
+                          CHECK_NULL);
 
   if (name == vmSymbols::finalize_method_name() &&
       signature == vmSymbols::void_method_signature()) {
@@ -2450,6 +2551,7 @@
     _has_vanilla_constructor = true;
   }
 
+  NOT_PRODUCT(m->verify());
   return m;
 }
 
@@ -2463,17 +2565,9 @@
                                                bool is_interface,
                                                AccessFlags* promoted_flags,
                                                bool* has_final_method,
-                                               Array<AnnotationArray*>** methods_annotations,
-                                               Array<AnnotationArray*>** methods_parameter_annotations,
-                                               Array<AnnotationArray*>** methods_default_annotations,
-                                               Array<AnnotationArray*>** methods_type_annotations,
                                                bool* has_default_methods,
                                                TRAPS) {
   ClassFileStream* cfs = stream();
-  AnnotationArray* method_annotations = NULL;
-  AnnotationArray* method_parameter_annotations = NULL;
-  AnnotationArray* method_default_annotations = NULL;
-  AnnotationArray* method_type_annotations = NULL;
   cfs->guarantee_more(2, CHECK_NULL);  // length
   u2 length = cfs->get_u2_fast();
   if (length == 0) {
@@ -2487,10 +2581,6 @@
       methodHandle method = parse_method(loader_data,
                                          cp, is_interface,
                                          promoted_flags,
-                                         &method_annotations,
-                                         &method_parameter_annotations,
-                                         &method_default_annotations,
-                                         &method_type_annotations,
                                          CHECK_NULL);
 
       if (method->is_final()) {
@@ -2501,38 +2591,6 @@
         *has_default_methods = true;
       }
       methods->at_put(index, method());
-
-      if (method_annotations != NULL) {
-        if (*methods_annotations == NULL) {
-          *methods_annotations =
-              MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
-        }
-        (*methods_annotations)->at_put(index, method_annotations);
-      }
-
-      if (method_parameter_annotations != NULL) {
-        if (*methods_parameter_annotations == NULL) {
-          *methods_parameter_annotations =
-              MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
-        }
-        (*methods_parameter_annotations)->at_put(index, method_parameter_annotations);
-      }
-
-      if (method_default_annotations != NULL) {
-        if (*methods_default_annotations == NULL) {
-          *methods_default_annotations =
-              MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
-        }
-        (*methods_default_annotations)->at_put(index, method_default_annotations);
-      }
-
-      if (method_type_annotations != NULL) {
-        if (*methods_type_annotations == NULL) {
-          *methods_type_annotations =
-              MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
-        }
-        (*methods_type_annotations)->at_put(index, method_type_annotations);
-      }
     }
 
     if (_need_verify && length > 1) {
@@ -2565,11 +2623,7 @@
 
 Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
                                           Array<Method*>* methods,
-                                          Array<AnnotationArray*>* methods_annotations,
-                                          Array<AnnotationArray*>* methods_parameter_annotations,
-                                          Array<AnnotationArray*>* methods_default_annotations,
-                                          Array<AnnotationArray*>* methods_type_annotations,
-                                              TRAPS) {
+                                          TRAPS) {
   int length = methods->length();
   // If JVMTI original method ordering or sharing is enabled we have to
   // remember the original class file ordering.
@@ -2585,10 +2639,7 @@
   }
   // Sort method array by ascending method name (for faster lookups & vtable construction)
   // Note that the ordering is not alphabetical, see Symbol::fast_compare
-  Method::sort_methods(methods, methods_annotations,
-                       methods_parameter_annotations,
-                       methods_default_annotations,
-                       methods_type_annotations);
+  Method::sort_methods(methods);
 
   // If JVMTI original method ordering or sharing is enabled construct int
   // array remembering the original ordering
@@ -3035,9 +3086,6 @@
     k->set_source_debug_extension(_sde_buffer, _sde_length);
   }
   k->set_inner_classes(_inner_classes);
-  if (_annotations != NULL) {
-    k->annotations()->set_class_annotations(_annotations);
-  }
 }
 
 AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_data,
@@ -3348,19 +3396,10 @@
     bool has_final_method = false;
     AccessFlags promoted_flags;
     promoted_flags.set_flags(0);
-
-    Array<AnnotationArray*>* methods_annotations = NULL;
-    Array<AnnotationArray*>* methods_parameter_annotations = NULL;
-    Array<AnnotationArray*>* methods_default_annotations = NULL;
-    Array<AnnotationArray*>* methods_type_annotations = NULL;
     Array<Method*>* methods = parse_methods(loader_data,
                                             cp, access_flags.is_interface(),
                                             &promoted_flags,
                                             &has_final_method,
-                                            &methods_annotations,
-                                            &methods_parameter_annotations,
-                                            &methods_default_annotations,
-                                            &methods_type_annotations,
                                             &has_default_methods,
                                             CHECK_(nullHandle));
 
@@ -3419,10 +3458,6 @@
     // sort methods
     Array<int>* method_ordering = sort_methods(loader_data,
                                                methods,
-                                               methods_annotations,
-                                               methods_parameter_annotations,
-                                               methods_default_annotations,
-                                               methods_type_annotations,
                                                CHECK_(nullHandle));
 
     // promote flags from parse_methods() to the klass' flags
@@ -4022,7 +4057,6 @@
     const unsigned int total_oop_map_count =
       compute_oop_map_count(super_klass, nonstatic_oop_map_count,
                             first_nonstatic_oop_offset);
-
     // Compute reference type
     ReferenceType rt;
     if (super_klass() == NULL) {
@@ -4044,7 +4078,7 @@
                                                        access_flags,
                                                        name,
                                                        super_klass(),
-                                                       host_klass,
+                                                       !host_klass.is_null(),
                                                        CHECK_(nullHandle));
 
     // Add all classes to our internal class loader list here,
@@ -4090,31 +4124,15 @@
     if (is_anonymous())  // I am well known to myself
       cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
 
-    // Allocate an annotation type if needed.
-    if (fields_annotations != NULL ||
-        methods_annotations != NULL ||
-        methods_parameter_annotations != NULL ||
-        methods_default_annotations != NULL ||
-        fields_type_annotations != NULL ||
-        methods_type_annotations != NULL) {
-      Annotations* anno = Annotations::allocate(loader_data,
-                            fields_annotations, methods_annotations,
-                            methods_parameter_annotations,
-                            methods_default_annotations, CHECK_(nullHandle));
-      this_klass->set_annotations(anno);
-    } else {
-      this_klass->set_annotations(NULL);
-    }
-
-    if (fields_type_annotations != NULL ||
-        methods_type_annotations != NULL) {
-      assert(this_klass->annotations() != NULL, "annotations should have been allocated");
-      Annotations* anno = Annotations::allocate(loader_data,
-                                                fields_type_annotations,
-                                                methods_type_annotations,
-                                                NULL,
-                                                NULL, CHECK_(nullHandle));
-      this_klass->annotations()->set_type_annotations(anno);
+    // Assign allocations if needed
+    if (_annotations != NULL || _type_annotations != NULL ||
+        fields_annotations != NULL || fields_type_annotations != NULL) {
+      Annotations* annotations = Annotations::allocate(loader_data, CHECK_NULL);
+      annotations->set_class_annotations(_annotations);
+      annotations->set_class_type_annotations(_type_annotations);
+      annotations->set_fields_annotations(fields_annotations);
+      annotations->set_fields_type_annotations(fields_type_annotations);
+      this_klass->set_annotations(annotations);
     }
 
     this_klass->set_minor_version(minor_version);
@@ -4140,27 +4158,8 @@
     // Fill in field values obtained by parse_classfile_attributes
     if (parsed_annotations.has_any_annotations())
       parsed_annotations.apply_to(this_klass);
-
-    // Create annotations
-    if (_annotations != NULL && this_klass->annotations() == NULL) {
-      Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
-      this_klass->set_annotations(anno);
-    }
     apply_parsed_class_attributes(this_klass);
 
-    // Create type annotations
-    if (_type_annotations != NULL) {
-      if (this_klass->annotations() == NULL) {
-        Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
-        this_klass->set_annotations(anno);
-      }
-      if (this_klass->annotations()->type_annotations() == NULL) {
-        Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
-        this_klass->annotations()->set_type_annotations(anno);
-      }
-      this_klass->annotations()->type_annotations()->set_class_annotations(_type_annotations);
-    }
-
     // Miranda methods
     if ((num_miranda_methods > 0) ||
         // if this class introduced new miranda methods or
--- a/src/share/vm/classfile/classFileParser.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/classFileParser.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -199,29 +199,17 @@
                             constantPoolHandle cp,
                             bool is_interface,
                             AccessFlags* promoted_flags,
-                            AnnotationArray** method_annotations,
-                            AnnotationArray** method_parameter_annotations,
-                            AnnotationArray** method_default_annotations,
-                            AnnotationArray** method_type_annotations,
                             TRAPS);
   Array<Method*>* parse_methods(ClassLoaderData* loader_data,
                                 constantPoolHandle cp,
                                 bool is_interface,
                                 AccessFlags* promoted_flags,
                                 bool* has_final_method,
-                                Array<AnnotationArray*>** methods_annotations,
-                                Array<AnnotationArray*>** methods_parameter_annotations,
-                                Array<AnnotationArray*>** methods_default_annotations,
-                                Array<AnnotationArray*>** methods_type_annotations,
                                 bool* has_default_method,
                                 TRAPS);
   Array<int>* sort_methods(ClassLoaderData* loader_data,
                            Array<Method*>* methods,
-                           Array<AnnotationArray*>* methods_annotations,
-                           Array<AnnotationArray*>* methods_parameter_annotations,
-                           Array<AnnotationArray*>* methods_default_annotations,
-                           Array<AnnotationArray*>* methods_type_annotations,
-                                TRAPS);
+                           TRAPS);
   u2* parse_exception_table(ClassLoaderData* loader_data,
                             u4 code_length, u4 exception_table_length,
                             constantPoolHandle cp, TRAPS);
@@ -377,6 +365,32 @@
             : cp->tag_at(index).is_klass_reference());
   }
 
+  void copy_localvariable_table(ConstMethod* cm, int lvt_cnt,
+                                u2* localvariable_table_length,
+                                u2** localvariable_table_start,
+                                int lvtt_cnt,
+                                u2* localvariable_type_table_length,
+                                u2** localvariable_type_table_start,
+                                TRAPS);
+
+  void copy_method_annotations(ClassLoaderData* loader_data,
+                               ConstMethod* cm,
+                               u1* runtime_visible_annotations,
+                               int runtime_visible_annotations_length,
+                               u1* runtime_invisible_annotations,
+                               int runtime_invisible_annotations_length,
+                               u1* runtime_visible_parameter_annotations,
+                               int runtime_visible_parameter_annotations_length,
+                               u1* runtime_invisible_parameter_annotations,
+                               int runtime_invisible_parameter_annotations_length,
+                               u1* runtime_visible_type_annotations,
+                               int runtime_visible_type_annotations_length,
+                               u1* runtime_invisible_type_annotations,
+                               int runtime_invisible_type_annotations_length,
+                               u1* annotation_default,
+                               int annotation_default_length,
+                               TRAPS);
+
  public:
   // Constructor
   ClassFileParser(ClassFileStream* st) { set_stream(st); }
--- a/src/share/vm/classfile/classLoader.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/classLoader.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -442,23 +442,10 @@
 void ClassLoader::setup_bootstrap_search_path() {
   assert(_first_entry == NULL, "should not setup bootstrap class search path twice");
   char* sys_class_path = os::strdup(Arguments::get_sysclasspath());
-#ifdef GRAAL
-  char* compiler_class_path = os::strdup(Arguments::get_compilerclasspath());
-#endif
   if (TraceClassLoading && Verbose) {
     tty->print_cr("[Bootstrap loader class path=%s]", sys_class_path);
-#ifdef GRAAL
-    tty->print_cr("[Compiler loader class path=%s]", compiler_class_path);
-#endif
   }
 
-  setup_bootstrap_search_path(sys_class_path);
-#ifdef GRAAL
-  setup_bootstrap_search_path(compiler_class_path);
-#endif
-}
-
-void ClassLoader::setup_bootstrap_search_path(char* sys_class_path) {
   int len = (int)strlen(sys_class_path);
   int end = 0;
 
@@ -908,23 +895,7 @@
     PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
                                ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
                                PerfClassTraceTime::CLASS_LOAD);
-    ClassPathEntry* e = _first_entry; 
-    while (e != NULL) {
-      stream = e->open_stream(name);
-      if (stream != NULL) {
-        break;
-      }
-      e = e->next();
-      ++classpath_index;
-    }
-  }
-
-  if (stream == NULL && !(THREAD->is_Compiler_thread())) {  
-	  classpath_index = 0;
-    PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
-                               ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
-                               PerfClassTraceTime::CLASS_LOAD);
-    ClassPathEntry* e = _first_entry; 
+    ClassPathEntry* e = _first_entry;
     while (e != NULL) {
       stream = e->open_stream(name);
       if (stream != NULL) {
--- a/src/share/vm/classfile/classLoader.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/classLoader.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -206,7 +206,6 @@
   // Initialization
   static void setup_meta_index();
   static void setup_bootstrap_search_path();
-  static void setup_bootstrap_search_path(char* sys_class_path);
   static void load_zip_library();
   static void create_class_path_entry(char *path, struct stat st, ClassPathEntry **new_entry, bool lazy);
 
--- a/src/share/vm/classfile/classLoaderData.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/classLoaderData.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,11 +50,12 @@
 #include "classfile/classLoaderData.hpp"
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaClasses.hpp"
+#include "classfile/metadataOnStackMark.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceShared.hpp"
-#include "prims/jvmtiRedefineClasses.hpp"
+#include "memory/oopFactory.hpp"
 #include "runtime/jniHandles.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/safepoint.hpp"
@@ -723,13 +724,13 @@
   }
   MetaspaceAux::dump(out);
 }
+#endif // PRODUCT
 
 void ClassLoaderData::print_value_on(outputStream* out) const {
   if (class_loader() == NULL) {
-    out->print_cr("NULL class_loader");
+    out->print("NULL class_loader");
   } else {
     out->print("class loader "PTR_FORMAT, this);
     class_loader()->print_value_on(out);
   }
 }
-#endif // PRODUCT
--- a/src/share/vm/classfile/classLoaderData.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/classLoaderData.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -220,7 +220,7 @@
   void set_jmethod_ids(JNIMethodBlock* new_block)  { _jmethod_ids = new_block; }
 
   void print_value() { print_value_on(tty); }
-  void print_value_on(outputStream* out) const PRODUCT_RETURN;
+  void print_value_on(outputStream* out) const;
   void dump(outputStream * const out) PRODUCT_RETURN;
   void verify();
   const char* loader_name();
--- a/src/share/vm/classfile/defaultMethods.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/defaultMethods.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1146,9 +1146,10 @@
 
   address code_start = static_cast<address>(bytecodes->adr_at(0));
   int code_length = bytecodes->length();
+  InlineTableSizes sizes;
 
   Method* m = Method::allocate(cp->pool_holder()->class_loader_data(),
-                               code_length, flags, 0, 0, 0, 0, 0, 0,
+                               code_length, flags, &sizes,
                                mt, CHECK_NULL);
 
   m->set_constants(NULL); // This will get filled in later
@@ -1285,33 +1286,15 @@
 
   enum { ANNOTATIONS, PARAMETERS, DEFAULTS, NUM_ARRAYS };
 
-  Array<AnnotationArray*>* original_annots[NUM_ARRAYS] = { NULL };
-
   Array<Method*>* original_methods = klass->methods();
-  Annotations* annots = klass->annotations();
-  if (annots != NULL) {
-    original_annots[ANNOTATIONS] = annots->methods_annotations();
-    original_annots[PARAMETERS]  = annots->methods_parameter_annotations();
-    original_annots[DEFAULTS]    = annots->methods_default_annotations();
-  }
-
   Array<int>* original_ordering = klass->method_ordering();
   Array<int>* merged_ordering = Universe::the_empty_int_array();
 
   int new_size = klass->methods()->length() + new_methods->length();
 
-  Array<AnnotationArray*>* merged_annots[NUM_ARRAYS];
-
   Array<Method*>* merged_methods = MetadataFactory::new_array<Method*>(
       klass->class_loader_data(), new_size, NULL, CHECK);
-  for (int i = 0; i < NUM_ARRAYS; ++i) {
-    if (original_annots[i] != NULL) {
-      merged_annots[i] = MetadataFactory::new_array<AnnotationArray*>(
-          klass->class_loader_data(), new_size, CHECK);
-    } else {
-      merged_annots[i] = NULL;
-    }
-  }
+
   if (original_ordering != NULL && original_ordering->length() > 0) {
     merged_ordering = MetadataFactory::new_array<int>(
         klass->class_loader_data(), new_size, CHECK);
@@ -1338,12 +1321,6 @@
         (new_method == NULL || orig_method->name() < new_method->name())) {
       merged_methods->at_put(i, orig_method);
       original_methods->at_put(orig_idx, NULL);
-      for (int j = 0; j < NUM_ARRAYS; ++j) {
-        if (merged_annots[j] != NULL) {
-          merged_annots[j]->at_put(i, original_annots[j]->at(orig_idx));
-          original_annots[j]->at_put(orig_idx, NULL);
-        }
-      }
       if (merged_ordering->length() > 0) {
         merged_ordering->at_put(i, original_ordering->at(orig_idx));
       }
@@ -1372,21 +1349,9 @@
 
   // Replace klass methods with new merged lists
   klass->set_methods(merged_methods);
-  if (annots != NULL) {
-    annots->set_methods_annotations(merged_annots[ANNOTATIONS]);
-    annots->set_methods_parameter_annotations(merged_annots[PARAMETERS]);
-    annots->set_methods_default_annotations(merged_annots[DEFAULTS]);
-  } else {
-    assert(merged_annots[ANNOTATIONS] == NULL, "Must be");
-    assert(merged_annots[PARAMETERS] == NULL, "Must be");
-    assert(merged_annots[DEFAULTS] == NULL, "Must be");
-  }
 
   ClassLoaderData* cld = klass->class_loader_data();
   MetadataFactory::free_array(cld, original_methods);
-  for (int i = 0; i < NUM_ARRAYS; ++i) {
-    MetadataFactory::free_array(cld, original_annots[i]);
-  }
   if (original_ordering->length() > 0) {
     klass->set_method_ordering(merged_ordering);
     MetadataFactory::free_array(cld, original_ordering);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/metadataOnStackMark.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/metadataOnStackMark.hpp"
+#include "code/codeCache.hpp"
+#include "compiler/compileBroker.hpp"
+#include "oops/metadata.hpp"
+#include "runtime/synchronizer.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/growableArray.hpp"
+
+
+// Keep track of marked on-stack metadata so it can be cleared.
+GrowableArray<Metadata*>* _marked_objects = NULL;
+NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
+
+// Walk metadata on the stack and mark it so that redefinition doesn't delete
+// it.  Class unloading also walks the previous versions and might try to
+// delete it, so this class is used by class unloading also.
+MetadataOnStackMark::MetadataOnStackMark() {
+  assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
+  NOT_PRODUCT(_is_active = true;)
+  if (_marked_objects == NULL) {
+    _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(1000, true);
+  }
+  Threads::metadata_do(Metadata::mark_on_stack);
+  CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
+  CompileBroker::mark_on_stack();
+}
+
+MetadataOnStackMark::~MetadataOnStackMark() {
+  assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
+  // Unmark everything that was marked.   Can't do the same walk because
+  // redefine classes messes up the code cache so the set of methods
+  // might not be the same.
+  for (int i = 0; i< _marked_objects->length(); i++) {
+    _marked_objects->at(i)->set_on_stack(false);
+  }
+  _marked_objects->clear();   // reuse growable array for next time.
+  NOT_PRODUCT(_is_active = false;)
+}
+
+// Record which objects are marked so we can unmark the same objects.
+void MetadataOnStackMark::record(Metadata* m) {
+  assert(_is_active, "metadata on stack marking is active");
+  _marked_objects->push(m);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/metadataOnStackMark.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP
+#define SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP
+
+#include "memory/allocation.hpp"
+
+class Metadata;
+
+// Helper class to mark and unmark metadata used on the stack as either handles
+// or executing methods, so that it can't be deleted during class redefinition
+// and class unloading.
+// This is also used for other things that can be deallocated, like class
+// metadata during parsing, relocated methods, and methods in backtraces.
+class MetadataOnStackMark : public StackObj {
+  NOT_PRODUCT(static bool _is_active;)
+ public:
+  MetadataOnStackMark();
+  ~MetadataOnStackMark();
+  static void record(Metadata* m);
+};
+
+#endif // SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP
--- a/src/share/vm/classfile/stackMapFrame.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/stackMapFrame.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -178,7 +178,7 @@
 #ifdef DEBUG
     // Put bogus type to indicate it's no longer valid.
     if (_stack_mark != -1) {
-      for (int i = _stack_mark; i >= _stack_size; --i) {
+      for (int i = _stack_mark - 1; i >= _stack_size; --i) {
         _stack[i] = VerificationType::bogus_type();
       }
     }
--- a/src/share/vm/classfile/systemDictionary.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/systemDictionary.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1199,66 +1199,6 @@
   return ik;
 }
 
-#ifdef KERNEL
-// Some classes on the bootstrap class path haven't been installed on the
-// system yet.  Call the DownloadManager method to make them appear in the
-// bootstrap class path and try again to load the named class.
-// Note that with delegation class loaders all classes in another loader will
-// first try to call this so it'd better be fast!!
-static instanceKlassHandle download_and_retry_class_load(
-                                                    Symbol* class_name,
-                                                    TRAPS) {
-
-  Klass* dlm = SystemDictionary::DownloadManager_klass();
-  instanceKlassHandle nk;
-
-  // If download manager class isn't loaded just return.
-  if (dlm == NULL) return nk;
-
-  { HandleMark hm(THREAD);
-    ResourceMark rm(THREAD);
-    Handle s = java_lang_String::create_from_symbol(class_name, CHECK_(nk));
-    Handle class_string = java_lang_String::externalize_classname(s, CHECK_(nk));
-
-    // return value
-    JavaValue result(T_OBJECT);
-
-    // Call the DownloadManager.  We assume that it has a lock because
-    // multiple classes could be not found and downloaded at the same time.
-    // class sun.misc.DownloadManager;
-    // public static String getBootClassPathEntryForClass(String className);
-    JavaCalls::call_static(&result,
-                       KlassHandle(THREAD, dlm),
-                       vmSymbols::getBootClassPathEntryForClass_name(),
-                       vmSymbols::string_string_signature(),
-                       class_string,
-                       CHECK_(nk));
-
-    // Get result.string and add to bootclasspath
-    assert(result.get_type() == T_OBJECT, "just checking");
-    oop obj = (oop) result.get_jobject();
-    if (obj == NULL) { return nk; }
-
-    Handle h_obj(THREAD, obj);
-    char* new_class_name = java_lang_String::as_platform_dependent_str(h_obj,
-                                                                  CHECK_(nk));
-
-    // lock the loader
-    // we use this lock because JVMTI does.
-    Handle loader_lock(THREAD, SystemDictionary::system_loader_lock());
-
-    ObjectLocker ol(loader_lock, THREAD);
-    // add the file to the bootclasspath
-    ClassLoader::update_class_path_entry_list(new_class_name, true);
-  } // end HandleMark
-
-  if (TraceClassLoading) {
-    ClassLoader::print_bootclasspath();
-  }
-  return ClassLoader::load_classfile(class_name, CHECK_(nk));
-}
-#endif // KERNEL
-
 
 instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
@@ -1278,15 +1218,6 @@
       k = ClassLoader::load_classfile(class_name, CHECK_(nh));
     }
 
-#ifdef KERNEL
-    // If the VM class loader has failed to load the class, call the
-    // DownloadManager class to make it magically appear on the classpath
-    // and try again.  This is only configured with the Kernel VM.
-    if (k.is_null()) {
-      k = download_and_retry_class_load(class_name, CHECK_(nh));
-    }
-#endif // KERNEL
-
     // find_or_define_instance_class may return a different InstanceKlass
     if (!k.is_null()) {
       k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh));
@@ -1822,13 +1753,7 @@
   Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
   Klass**    klassp = &_well_known_klasses[id];
   bool must_load = (init_opt < SystemDictionary::Opt);
-  bool try_load  = true;
-  if (init_opt == SystemDictionary::Opt_Kernel) {
-#ifndef KERNEL
-    try_load = false;
-#endif //KERNEL
-  }
-  if ((*klassp) == NULL && try_load) {
+  if ((*klassp) == NULL) {
     if (must_load) {
       (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class
     } else {
@@ -1918,12 +1843,6 @@
   //_box_klasses[T_OBJECT]  = WK_KLASS(object_klass);
   //_box_klasses[T_ARRAY]   = WK_KLASS(object_klass);
 
-#ifdef KERNEL
-  if (DownloadManager_klass() == NULL) {
-    warning("Cannot find sun/jkernel/DownloadManager");
-  }
-#endif // KERNEL
-
   { // Compute whether we should use loadClass or loadClassInternal when loading classes.
     Method* method = InstanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature());
     _has_loadClassInternal = (method != NULL);
--- a/src/share/vm/classfile/systemDictionary.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -168,8 +168,6 @@
   /* It's okay if this turns out to be NULL in non-1.4 JDKs. */                                                          \
   do_klass(nio_Buffer_klass,                            java_nio_Buffer,                           Opt                 ) \
                                                                                                                          \
-  do_klass(DownloadManager_klass,                       sun_jkernel_DownloadManager,               Opt_Kernel          ) \
-                                                                                                                         \
   do_klass(PostVMInitHook_klass,                        sun_misc_PostVMInitHook,                   Opt                 ) \
                                                                                                                          \
   /* Preload boxing klasses */                                                                                           \
@@ -186,6 +184,7 @@
   do_klass(GraalBitMap_klass,                     java_util_BitSet,                                             Opt) \
   /* graal.hotspot */                                                                                                \
   do_klass(HotSpotCompilationResult_klass,        com_oracle_graal_hotspot_HotSpotCompilationResult,            Opt) \
+  do_klass(HotSpotRuntimeCallTarget_klass,        com_oracle_graal_hotspot_HotSpotRuntimeCallTarget,            Opt) \
   do_klass(HotSpotCodeInfo_klass,                 com_oracle_graal_hotspot_meta_HotSpotCodeInfo,                Opt) \
   do_klass(HotSpotInstalledCode_klass,            com_oracle_graal_hotspot_meta_HotSpotInstalledCode,           Opt) \
   do_klass(HotSpotJavaType_klass,                 com_oracle_graal_hotspot_meta_HotSpotJavaType,                Opt) \
@@ -252,7 +251,6 @@
     Opt,                        // preload tried; NULL if not present
     Opt_Only_JDK14NewRef,       // preload tried; use only with NewReflection
     Opt_Only_JDK15,             // preload tried; use only with JDK1.5+
-    Opt_Kernel,                 // preload tried only #ifdef KERNEL
     OPTION_LIMIT,
     CEIL_LG_OPTION_LIMIT = 4    // OPTION_LIMIT <= (1<<CEIL_LG_OPTION_LIMIT)
   };
@@ -435,7 +433,6 @@
   static Klass* check_klass_Pre(       Klass* k) { return check_klass(k); }
   static Klass* check_klass_Pre_JSR292(Klass* k) { return EnableInvokeDynamic ? check_klass(k) : k; }
   static Klass* check_klass_Opt(       Klass* k) { return k; }
-  static Klass* check_klass_Opt_Kernel(Klass* k) { return k; } //== Opt
   static Klass* check_klass_Opt_Only_JDK15(Klass* k) {
     assert(JDK_Version::is_gte_jdk15x_version(), "JDK 1.5 only");
     return k;
--- a/src/share/vm/classfile/verifier.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/verifier.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,8 @@
 # include "bytes_ppc.hpp"
 #endif
 
-#define NOFAILOVER_MAJOR_VERSION 51
+#define NOFAILOVER_MAJOR_VERSION                  51
+#define STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION  52
 
 // Access to external entry for VerifyClassCodes - old byte code verifier
 
@@ -2317,6 +2318,11 @@
       types = (1 << JVM_CONSTANT_InterfaceMethodref) |
               (1 << JVM_CONSTANT_Methodref);
       break;
+    case Bytecodes::_invokestatic:
+      types = (_klass->major_version() < STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION) ?
+        (1 << JVM_CONSTANT_Methodref) :
+        ((1 << JVM_CONSTANT_InterfaceMethodref) | (1 << JVM_CONSTANT_Methodref));
+      break;
     default:
       types = 1 << JVM_CONSTANT_Methodref;
   }
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -108,7 +108,6 @@
   template(java_lang_Compiler,                        "java/lang/Compiler")                       \
   template(sun_misc_Signal,                           "sun/misc/Signal")                          \
   template(java_lang_AssertionStatusDirectives,       "java/lang/AssertionStatusDirectives")      \
-  template(sun_jkernel_DownloadManager,               "sun/jkernel/DownloadManager")              \
   template(getBootClassPathEntryForClass_name,        "getBootClassPathEntryForClass")            \
   template(sun_misc_PostVMInitHook,                   "sun/misc/PostVMInitHook")                  \
   template(sun_misc_Launcher_ExtClassLoader,          "sun/misc/Launcher$ExtClassLoader")         \
@@ -295,6 +294,7 @@
   template(com_oracle_graal_hotspot_HotSpotKlassOop,                 "com/oracle/graal/hotspot/HotSpotKlassOop")                      \
   template(com_oracle_graal_hotspot_HotSpotOptions,                  "com/oracle/graal/hotspot/HotSpotOptions")                       \
   template(com_oracle_graal_hotspot_HotSpotCompilationResult,        "com/oracle/graal/hotspot/HotSpotCompilationResult")             \
+  template(com_oracle_graal_hotspot_HotSpotRuntimeCallTarget,        "com/oracle/graal/hotspot/HotSpotRuntimeCallTarget")             \
   template(com_oracle_graal_hotspot_bridge_VMToCompiler,             "com/oracle/graal/hotspot/bridge/VMToCompiler")                  \
   template(com_oracle_graal_hotspot_meta_HotSpotCodeInfo,            "com/oracle/graal/hotspot/meta/HotSpotCodeInfo")                 \
   template(com_oracle_graal_hotspot_meta_HotSpotInstalledCode,       "com/oracle/graal/hotspot/meta/HotSpotInstalledCode")            \
--- a/src/share/vm/code/codeBlob.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/codeBlob.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -39,7 +39,6 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/vframe.hpp"
 #include "services/memoryService.hpp"
-#include "utilities/machineCodePrinter.hpp"
 #ifdef TARGET_ARCH_x86
 # include "nativeInst_x86.hpp"
 #endif
@@ -134,11 +133,10 @@
   cb->copy_code_and_locs_to(this);
   set_oop_maps(oop_maps);
   _frame_size = frame_size;
-#if defined(COMPILER1) || defined(GRAAL)
-
+#ifdef COMPILER1
   // probably wrong for tiered
   assert(_frame_size >= -1, "must use frame size or -1 for runtime stubs");
-#endif // COMPILER1 || GRAAL
+#endif // COMPILER1
 }
 
 
@@ -345,10 +343,6 @@
 
   trace_new_stub(stub, "RuntimeStub - ", stub_name);
 
-  if (PrintMachineCodeToFile) {
-    MachineCodePrinter::print(stub);
-  }
-
   return stub;
 }
 
@@ -384,7 +378,9 @@
   _unpack_offset           = unpack_offset;
   _unpack_with_exception   = unpack_with_exception_offset;
   _unpack_with_reexecution = unpack_with_reexecution_offset;
+#ifdef COMPILER1
   _unpack_with_exception_in_tls   = -1;
+#endif
 }
 
 
--- a/src/share/vm/code/compiledIC.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/compiledIC.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -95,7 +95,7 @@
   // Don't use ic_destination for this test since that forwards
   // through ICBuffer instead of returning the actual current state of
   // the CompiledIC.
-  if (is_icholder_entry(_ic_call->destination())) {
+  if (is_icholder_entry(_ic_call->destination()) GRAAL_ONLY(&& _value != NULL)) {
     // When patching for the ICStub case the cached value isn't
     // overwritten until the ICStub copied into the CompiledIC during
     // the next safepoint.  Make sure that the CompiledICHolder* is
@@ -126,6 +126,13 @@
   _ic_call->set_destination_mt_safe(entry_point);
 }
 
+#ifdef GRAAL
+  if (_value == NULL) {
+    // Can happen when Graal converted a virtual call into an invoke special based on static analysis.
+    return;
+  }
+#endif
+
   if (is_optimized() || is_icstub) {
     // Optimized call sites don't have a cache value and ICStub call
     // sites only change the entry point.  Changing the value in that
@@ -265,12 +272,14 @@
     // Check if we are calling into our own codeblob (i.e., to a stub)
     CodeBlob* cb = CodeCache::find_blob(_ic_call->instruction_address());
     address dest = ic_destination();
+#ifndef GRAAL
 #ifdef ASSERT
     {
       CodeBlob* db = CodeCache::find_blob_unsafe(dest);
       assert(!db->is_adapter_blob(), "must use stub!");
     }
 #endif /* ASSERT */
+#endif
     is_call_to_interpreted = cb->contains(dest);
   }
   return is_call_to_interpreted;
@@ -552,6 +561,12 @@
 
 void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) {
   address stub=find_stub();
+#ifdef GRAAL
+  if (stub == NULL) {
+    set_destination_mt_safe(entry);
+    return;
+  }
+#endif
   assert(stub!=NULL, "stub not found");
 
   if (TraceICs) {
@@ -702,9 +717,11 @@
 
   // Verify stub
   address stub = find_stub();
+#ifndef GRAAL
   assert(stub != NULL, "no stub found for static call");
   NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);   // creation also verifies the object
   NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
+#endif
 
   // Verify state
   assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
--- a/src/share/vm/code/debugInfo.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/debugInfo.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -77,11 +77,7 @@
 
 enum { LOCATION_CODE = 0, CONSTANT_INT_CODE = 1,  CONSTANT_OOP_CODE = 2,
                           CONSTANT_LONG_CODE = 3, CONSTANT_DOUBLE_CODE = 4,
-                          OBJECT_CODE = 5,        OBJECT_ID_CODE = 6,
-#ifdef GRAAL
-                          DEFERRED_READ_CODE = 7, DEFERRED_WRITE_CODE = 8
-#endif // GRAAL
-};
+                          OBJECT_CODE = 5,        OBJECT_ID_CODE = 6 };
 
 ScopeValue* ScopeValue::read_from(DebugInfoReadStream* stream) {
   ScopeValue* result = NULL;
@@ -93,10 +89,6 @@
    case CONSTANT_DOUBLE_CODE: result = new ConstantDoubleValue(stream);  break;
    case OBJECT_CODE:          result = stream->read_object_value();      break;
    case OBJECT_ID_CODE:       result = stream->get_cached_object();      break;
-#ifdef GRAAL
-   case DEFERRED_READ_CODE:   result = new DeferredReadValue(stream);    break;
-   case DEFERRED_WRITE_CODE:  result = new DeferredWriteValue(stream);   break;
-#endif // GRAAL
    default: ShouldNotReachHere();
   }
   return result;
@@ -117,63 +109,6 @@
   location().print_on(st);
 }
 
-#ifdef GRAAL
-
-// DeferredLocationValue
-
-DeferredLocationValue::DeferredLocationValue(DebugInfoReadStream* stream) {
-  _base = read_from(stream);
-  _index = read_from(stream);
-  _scale = stream->read_int();
-  _disp = stream->read_long();
-}
-
-void DeferredLocationValue::write_on(DebugInfoWriteStream* stream) {
-  _base->write_on(stream);
-  _index->write_on(stream);
-  stream->write_int(_scale);
-  stream->write_long(_disp);
-}
-
-void DeferredLocationValue::print_on(outputStream* st) const {
-  _base->print_on(st);
-  _index->print_on(st);
-  st->print("%i %i", _scale, _disp);
-}
-
-// DeferredReadValue
-
-DeferredReadValue::DeferredReadValue(DebugInfoReadStream* stream)
-: DeferredLocationValue(stream) {
-}
-
-void DeferredReadValue::write_on(DebugInfoWriteStream* st) {
-  DeferredLocationValue::write_on(st);
-}
-
-void DeferredReadValue::print_on(outputStream* st) const {
-  DeferredLocationValue::print_on(st);
-}
-
-// DeferredWriteValue
-
-DeferredWriteValue::DeferredWriteValue(DebugInfoReadStream* stream)
-: DeferredLocationValue(stream) {
-  _value = read_from(stream);
-}
-
-void DeferredWriteValue::write_on(DebugInfoWriteStream* st) {
-  DeferredLocationValue::write_on(st);
-  _value->write_on(st);
-}
-
-void DeferredWriteValue::print_on(outputStream* st) const {
-  DeferredLocationValue::print_on(st);
-  _value->print_on(st);
-}
-
-#endif // GRAAL
-
 // ObjectValue
 
 void ObjectValue::read_object(DebugInfoReadStream* stream) {
--- a/src/share/vm/code/debugInfo.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/debugInfo.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -61,11 +61,6 @@
   // Serialization of debugging information
   virtual void write_on(DebugInfoWriteStream* stream) = 0;
   static ScopeValue* read_from(DebugInfoReadStream* stream);
-
-#ifdef GRAAL
-  // Printing
-  virtual void print_on(outputStream* st) const = 0;
-#endif // GRAAL
 };
 
 
@@ -88,64 +83,6 @@
   void print_on(outputStream* st) const;
 };
 
-#ifdef GRAAL
-
-class DeferredLocationValue: public ScopeValue {
-private:
-  ScopeValue* _base;
-  ScopeValue* _index;
-  jint _scale;
-  jlong _disp;
-public:
-  DeferredLocationValue(ScopeValue* base, ScopeValue* index, jint scale, jlong disp)
-  : _base(base), _index(index), _scale(scale), _disp(disp) { }
-
-  ScopeValue* base() { return _base; }
-  ScopeValue* index() { return _index; }
-  jint scale() { return _scale; }
-  jlong disp() { return _disp; }
-
-  // Serialization of debugging information
-  DeferredLocationValue(DebugInfoReadStream* stream);
-  void write_on(DebugInfoWriteStream* stream);
-
-  // Printing
-  void print_on(outputStream* st) const;
-};
-
-
-class DeferredReadValue: public DeferredLocationValue {
-public:
-  DeferredReadValue(ScopeValue* base, ScopeValue* index, jint scale, jint disp)
-  : DeferredLocationValue(base, index, scale, disp) { }
-
-  // Serialization of debugging information
-  DeferredReadValue(DebugInfoReadStream* stream);
-  void write_on(DebugInfoWriteStream* stream);
-
-  // Printing
-  void print_on(outputStream* st) const;
-};
-
-class DeferredWriteValue: public DeferredLocationValue {
-private:
-  ScopeValue* _value;
-public:
-  DeferredWriteValue(ScopeValue* base, ScopeValue* index, jint scale, jint disp, ScopeValue* value)
-  : DeferredLocationValue(base, index, scale, disp), _value(value) { }
-
-  ScopeValue* value() { return _value; }
-
-  // Serialization of debugging information
-  DeferredWriteValue(DebugInfoReadStream* stream);
-  void write_on(DebugInfoWriteStream* stream);
-
-  // Printing
-  void print_on(outputStream* st) const;
-};
-
-#endif // GRAAL
-
 
 // An ObjectValue describes an object eliminated by escape analysis.
 
--- a/src/share/vm/code/debugInfoRec.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/debugInfoRec.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -213,29 +213,6 @@
   return result;
 }
 
-#ifdef GRAAL
-
-int DebugInformationRecorder::serialize_deferred_writes(GrowableArray<DeferredWriteValue*>* deferred_writes) {
-  if (deferred_writes == NULL || deferred_writes->is_empty()) return DebugInformationRecorder::serialized_null;
-  assert(_recording_state == rs_safepoint, "must be recording a safepoint");
-  int result = stream()->position();
-  assert(result != serialized_null, "sanity");
-  stream()->write_int(deferred_writes->length());
-  for (int index = 0; index < deferred_writes->length(); index++) {
-    deferred_writes->at(index)->write_on(stream());
-  }
-
-  // (See comment below on DebugInformationRecorder::describe_scope.)
-  int shared_result = find_sharable_decode_offset(result);
-  if (shared_result != serialized_null) {
-    stream()->set_position(result);
-    result = shared_result;
-  }
-
-  return result;
-}
-
-#endif // GRAAL
 
 #ifndef PRODUCT
 // These variables are put into one block to reduce relocations
@@ -312,11 +289,7 @@
                                               bool        return_oop,
                                               DebugToken* locals,
                                               DebugToken* expressions,
-                                              DebugToken* monitors
-#ifdef GRAAL
-                                              , DebugToken* deferred_writes
-#endif // GRAAL
-                                              ) {
+                                              DebugToken* monitors) {
   assert(_recording_state != rs_null, "nesting of recording calls");
   PcDesc* last_pd = last_pc();
   assert(last_pd->pc_offset() == pc_offset, "must be last pc");
@@ -355,9 +328,6 @@
   stream()->write_int((intptr_t) locals);
   stream()->write_int((intptr_t) expressions);
   stream()->write_int((intptr_t) monitors);
-#ifdef GRAAL
-  stream()->write_int((intptr_t) deferred_writes);
-#endif // GRAAL
 
   // Here's a tricky bit.  We just wrote some bytes.
   // Wouldn't it be nice to find that we had already
@@ -439,14 +409,6 @@
   return (DebugToken*) (intptr_t) serialize_monitor_values(monitors);
 }
 
-#ifdef GRAAL
-
-DebugToken* DebugInformationRecorder::create_deferred_writes(GrowableArray<DeferredWriteValue*>* deferred_writes) {
-  assert(!recorders_frozen(), "not frozen yet");
-  return (DebugToken*) (intptr_t) serialize_deferred_writes(deferred_writes);
-}
-
-#endif // GRAAL
 
 int DebugInformationRecorder::data_size() {
   debug_only(mark_recorders_frozen());  // mark it "frozen" for asserts
--- a/src/share/vm/code/debugInfoRec.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/debugInfoRec.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -107,11 +107,7 @@
                       bool        return_oop = false,
                       DebugToken* locals      = NULL,
                       DebugToken* expressions = NULL,
-                      DebugToken* monitors    = NULL
-#ifdef GRAAL
-                      , DebugToken* deferred_writes = NULL
-#endif // GRAAL
-                      );
+                      DebugToken* monitors    = NULL);
 
 
   void dump_object_pool(GrowableArray<ScopeValue*>* objects);
@@ -124,9 +120,6 @@
   // helper fuctions for describe_scope to enable sharing
   DebugToken* create_scope_values(GrowableArray<ScopeValue*>* values);
   DebugToken* create_monitor_values(GrowableArray<MonitorValue*>* monitors);
-#ifdef GRAAL
-  DebugToken* create_deferred_writes(GrowableArray<DeferredWriteValue*>* deferred_writes);
-#endif // GRAAL
 
   // returns the size of the generated scopeDescs.
   int data_size();
@@ -201,9 +194,6 @@
 
   int  serialize_monitor_values(GrowableArray<MonitorValue*>* monitors);
   int  serialize_scope_values(GrowableArray<ScopeValue*>* values);
-#ifdef GRAAL
-  int serialize_deferred_writes(GrowableArray<DeferredWriteValue*>* deferred_writes);
-#endif // GRAAL
   int  find_sharable_decode_offset(int stream_offset);
 
 #ifndef PRODUCT
--- a/src/share/vm/code/dependencies.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/dependencies.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -563,6 +563,7 @@
   _size_in_bytes = bytes.position();
 }
 
+
 const char* Dependencies::_dep_name[TYPE_LIMIT] = {
   "end_marker",
   "evol_method",
--- a/src/share/vm/code/icBuffer.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/icBuffer.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -96,8 +96,8 @@
 void ICStub::verify() {
 }
 
-void ICStub::print_on(outputStream* st) {
-  st->print_cr("ICStub: site: " INTPTR_FORMAT, _ic_site);
+void ICStub::print() {
+  tty->print_cr("ICStub: site: " INTPTR_FORMAT, _ic_site);
 }
 #endif
 
--- a/src/share/vm/code/icBuffer.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/icBuffer.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -75,8 +75,8 @@
   void* cached_value() const;   // cached_value for stub
 
   // Debugging
-  void    verify()                   PRODUCT_RETURN;
-  void    print_on(outputStream* st) PRODUCT_RETURN;
+  void    verify()            PRODUCT_RETURN;
+  void    print()             PRODUCT_RETURN;
 
   // Creation
   friend ICStub* ICStub_from_destination_address(address destination_address);
--- a/src/share/vm/code/nmethod.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/nmethod.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -42,8 +42,6 @@
 #include "utilities/dtrace.hpp"
 #include "utilities/events.hpp"
 #include "utilities/xmlstream.hpp"
-#include "utilities/debug.hpp"
-#include "utilities/machineCodePrinter.hpp"
 #ifdef SHARK
 #include "shark/sharkCompiler.hpp"
 #endif
@@ -126,6 +124,7 @@
 //   PrintC1Statistics, PrintOptoStatistics, LogVMOutput, and LogCompilation.
 // (In the latter two cases, they like other stats are printed to the log only.)
 
+#ifndef PRODUCT
 // These variables are put into one block to reduce relocations
 // and make it simpler to print from the debugger.
 static
@@ -215,6 +214,7 @@
                   pc_desc_tests, pc_desc_searches, pc_desc_adds);
   }
 } nmethod_stats;
+#endif //PRODUCT
 
 
 //---------------------------------------------------------------------------------
@@ -490,6 +490,7 @@
   _compiler                = NULL;
 #ifdef GRAAL
   _graal_installed_code   = NULL;
+  _triggered_deoptimizations = NULL;
 #endif
 #ifdef HAVE_DTRACE_H
   _trap_offset             = 0;
@@ -520,13 +521,9 @@
               code_buffer, frame_size,
               basic_lock_owner_sp_offset, basic_lock_sp_offset,
               oop_maps);
-    if (nm != NULL)  nmethod_stats.note_native_nmethod(nm);
+    NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_native_nmethod(nm));
     if (PrintAssembly && nm != NULL)
       Disassembler::decode(nm);
-
-    if (PrintMachineCodeToFile) {
-      MachineCodePrinter::print(nm);
-    }
   }
   // verify nmethod
   debug_only(if (nm) nm->verify();) // might block
@@ -558,7 +555,7 @@
 
     nm = new (nmethod_size) nmethod(method(), nmethod_size, &offsets, code_buffer, frame_size);
 
-    if (nm != NULL)  nmethod_stats.note_nmethod(nm);
+    NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_nmethod(nm));
     if (PrintAssembly && nm != NULL)
       Disassembler::decode(nm);
   }
@@ -589,7 +586,8 @@
   int comp_level,
   GrowableArray<jlong>* leaf_graph_ids
 #ifdef GRAAL
-  , Handle installed_code
+  , Handle installed_code,
+  Handle triggered_deoptimizations
 #endif
 )
 {
@@ -617,7 +615,8 @@
               comp_level,
               leaf_graph_ids
 #ifdef GRAAL
-              , installed_code
+              , installed_code,
+              triggered_deoptimizations
 #endif
               );
     if (nm != NULL) {
@@ -637,13 +636,9 @@
         InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
       }
     }
-    if (nm != NULL)  nmethod_stats.note_nmethod(nm);
+    NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_nmethod(nm));
     if (PrintAssembly && nm != NULL)
       Disassembler::decode(nm);
-
-    if (nm != NULL && PrintMachineCodeToFile) {
-      MachineCodePrinter::print(nm);
-    }
   }
 
   // verify nmethod
@@ -847,7 +842,8 @@
   int comp_level,
   GrowableArray<jlong>* leaf_graph_ids
 #ifdef GRAAL
-  , Handle installed_code
+  , Handle installed_code,
+  Handle triggered_deoptimizations
 #endif
   )
   : CodeBlob("nmethod", code_buffer, sizeof(nmethod),
@@ -874,6 +870,7 @@
 
 #ifdef GRAAL
     _graal_installed_code = installed_code();
+    _triggered_deoptimizations = (typeArrayOop)triggered_deoptimizations();
 #endif
     if (compiler->is_graal()) {
       // Graal might not produce any stub sections
@@ -1693,8 +1690,16 @@
 
 #ifdef GRAAL
   // Follow Graal method
-  if (_graal_installed_code != NULL && can_unload(is_alive, (oop*)&_graal_installed_code, unloading_occurred)) {
-    return;
+  if (_graal_installed_code != NULL) {
+    if (HotSpotInstalledCode::isDefault(_graal_installed_code)) {
+      if (!is_alive->do_object_b(_graal_installed_code)) {
+        _graal_installed_code = NULL;
+      }
+    } else {
+      if (can_unload(is_alive, (oop*)&_graal_installed_code, unloading_occurred)) {
+        return;
+      }
+    }
   }
 #endif
 
@@ -1819,8 +1824,8 @@
 // really alive.
 void nmethod::verify_metadata_loaders(address low_boundary, BoolObjectClosure* is_alive) {
 #ifdef ASSERT
-  RelocIterator iter(this, low_boundary);
-  while (iter.next()) {
+    RelocIterator iter(this, low_boundary);
+    while (iter.next()) {
     // static_stub_Relocations may have dangling references to
     // Method*s so trim them out here.  Otherwise it looks like
     // compiled code is maintaining a link to dead metadata.
@@ -1829,13 +1834,11 @@
       CompiledIC* cic = CompiledIC_at(iter.reloc());
       if (!cic->is_call_to_interpreted()) {
         static_call_addr = iter.addr();
-        cic->set_to_clean();
       }
     } else if (iter.type() == relocInfo::static_call_type) {
       CompiledStaticCall* csc = compiledStaticCall_at(iter.reloc());
       if (!csc->is_call_to_interpreted()) {
         static_call_addr = iter.addr();
-        csc->set_to_clean();
       }
     }
     if (static_call_addr != NULL) {
@@ -1923,6 +1926,9 @@
   if (_graal_installed_code != NULL) {
     f->do_oop((oop*) &_graal_installed_code);
   }
+  if (_triggered_deoptimizations != NULL) {
+    f->do_oop((oop*) &_triggered_deoptimizations);
+  }
 #endif
 
   RelocIterator iter(this, low_boundary);
@@ -2513,9 +2519,7 @@
         // information in a table.
         break;
     }
-#ifndef GRAAL
     assert(stub == NULL || stub_contains(stub), "static call stub outside stub section");
-#endif
   }
 }
 
@@ -3007,8 +3011,6 @@
   ImplicitExceptionTable(this).print(code_begin());
 }
 
-#endif // PRODUCT
-
 void nmethod::print_statistics() {
   ttyLocker ttyl;
   if (xtty != NULL)  xtty->head("statistics type='nmethod'");
@@ -3020,18 +3022,4 @@
   if (xtty != NULL)  xtty->tail("statistics");
 }
 
-#ifdef GRAAL
-void DebugScopedNMethod::print_on(outputStream* st) {
-  if (_nm != NULL) {
-    st->print("nmethod@%p", _nm);
-    Method* method = _nm->method();
-    if (method != NULL) {
-      char holder[O_BUFLEN];
-      char nameAndSig[O_BUFLEN];
-      method->method_holder()->name()->as_C_string(holder, O_BUFLEN);
-      method->name_and_sig_as_C_string(nameAndSig, O_BUFLEN);
-      st->print(" - %s::%s", holder, nameAndSig);
-    }
-  }
-}
-#endif
+#endif // PRODUCT
--- a/src/share/vm/code/nmethod.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/nmethod.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -119,6 +119,7 @@
 #ifdef GRAAL
   // Needed to keep nmethods alive that are not the default nmethod for the associated Method.
   oop       _graal_installed_code;
+  typeArrayOop _triggered_deoptimizations;
 #endif
 
   // To support simple linked-list chaining of nmethods:
@@ -271,7 +272,8 @@
           int comp_level,
           GrowableArray<jlong>* leaf_graph_ids
 #ifdef GRAAL
-          , Handle installed_code
+          , Handle installed_code,
+          Handle triggered_deoptimizations
 #endif
           );
 
@@ -291,7 +293,7 @@
   // Inform external interfaces that a compiled method has been unloaded
   void post_compiled_method_unload();
 
-  // Initialize fields to their default values
+  // Initailize fields to their default values
   void init_defaults();
 
  public:
@@ -312,7 +314,8 @@
                               int comp_level,
                               GrowableArray<jlong>* leaf_graph_ids = NULL
 #ifdef GRAAL
-                              , Handle installed_code = NULL
+                              , Handle installed_code = Handle(),
+                              Handle triggered_deoptimizations = Handle()
 #endif
   );
 
@@ -357,9 +360,6 @@
   bool is_compiled_by_c2() const;
   bool is_compiled_by_shark() const;
 
-
-#define CHECK_POSITIVE(val) assert(val, "should be positive")
-
   // boundaries for different parts
   address consts_begin          () const          { return           header_begin() + _consts_offset        ; }
   address consts_end            () const          { return           header_begin() +  code_offset()        ; }
@@ -367,8 +367,8 @@
   address insts_end             () const          { return           header_begin() + _stub_offset          ; }
   address stub_begin            () const          { return           header_begin() + _stub_offset          ; }
   address stub_end              () const          { return           header_begin() + _oops_offset          ; }
-  address exception_begin       () const          { assert(_exception_offset >= 0, "no exception handler"); return header_begin() + _exception_offset ; }
-  address deopt_handler_begin   () const          { assert(_deoptimize_offset >= 0, "no deopt handler"); return header_begin() + _deoptimize_offset ; }
+  address exception_begin       () const          { return           header_begin() + _exception_offset     ; }
+  address deopt_handler_begin   () const          { return           header_begin() + _deoptimize_offset    ; }
   address deopt_mh_handler_begin() const          { return           header_begin() + _deoptimize_mh_offset ; }
   address unwind_handler_begin  () const          { return _unwind_handler_offset != -1 ? (header_begin() + _unwind_handler_offset) : NULL; }
   oop*    oops_begin            () const          { return (oop*)   (header_begin() + _oops_offset)         ; }
@@ -689,7 +689,7 @@
 
   // Prints a comment for one native instruction (reloc info, pc desc)
   void print_code_comment_on(outputStream* st, int column, address begin, address end);
-  static void print_statistics();
+  static void print_statistics()                  PRODUCT_RETURN;
 
   // Compiler task identification.  Note that all OSR methods
   // are numbered in an independent sequence if CICountOSR is true,
@@ -774,19 +774,4 @@
   }
 };
 
-#ifdef GRAAL
-class DebugScopedNMethod : public DebugScopedValue {
-private:
-  nmethod* _nm;
-public:
-  DebugScopedNMethod(const char* file, int line, nmethod* nm) : DebugScopedValue(file, line), _nm(nm) {}
-  void print_on(outputStream* st);
-};
-#define DS_NMETHOD(nm) DebugScopedNMethod __dsnm__(__FILE__, __LINE__, nm)
-#define DS_NMETHOD1(name, nm) DebugScopedNMethod name(__FILE__, __LINE__, nm)
-#else
-#define DS_NMETHOD(nm) do {} while (0)
-#define DS_NMETHOD1(name, nm) do {} while (0)
-#endif
-
 #endif // SHARE_VM_CODE_NMETHOD_HPP
--- a/src/share/vm/code/pcDesc.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/pcDesc.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -81,8 +81,7 @@
   bool is_same_info(const PcDesc* pd) {
     return _scope_decode_offset == pd->_scope_decode_offset &&
       _obj_decode_offset == pd->_obj_decode_offset &&
-      _flags == pd->_flags
-      ;
+      _flags == pd->_flags;
   }
 
   bool     is_method_handle_invoke()       const { return (_flags & PCDESC_is_method_handle_invoke) != 0;     }
--- a/src/share/vm/code/scopeDesc.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/scopeDesc.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -73,9 +73,6 @@
     _locals_decode_offset = DebugInformationRecorder::serialized_null;
     _expressions_decode_offset = DebugInformationRecorder::serialized_null;
     _monitors_decode_offset = DebugInformationRecorder::serialized_null;
-#ifdef GRAAL
-    _deferred_writes_decode_offset = DebugInformationRecorder::serialized_null;
-#endif // GRAAL
   } else {
     // decode header
     DebugInfoReadStream* stream  = stream_at(decode_offset());
@@ -88,9 +85,6 @@
     _locals_decode_offset      = stream->read_int();
     _expressions_decode_offset = stream->read_int();
     _monitors_decode_offset    = stream->read_int();
-#ifdef GRAAL
-    _deferred_writes_decode_offset = stream->read_int();
-#endif // GRAAL
   }
 }
 
@@ -132,25 +126,6 @@
   return result;
 }
 
-#ifdef GRAAL
-
-GrowableArray<DeferredWriteValue*>* ScopeDesc::decode_deferred_writes(int decode_offset) {
-  if (decode_offset == DebugInformationRecorder::serialized_null) return NULL;
-  DebugInfoReadStream* stream  = stream_at(decode_offset);
-  int length = stream->read_int();
-  GrowableArray<DeferredWriteValue*>* result = new GrowableArray<DeferredWriteValue*> (length);
-  for (int index = 0; index < length; index++) {
-    result->push(new DeferredWriteValue(stream));
-  }
-  return result;
-}
-
-GrowableArray<DeferredWriteValue*>* ScopeDesc::deferred_writes() {
-  return decode_deferred_writes(_deferred_writes_decode_offset);
-}
-
-#endif // GRAAL
-
 DebugInfoReadStream* ScopeDesc::stream_at(int decode_offset) const {
   return new DebugInfoReadStream(_code, decode_offset, _objects);
 }
@@ -261,19 +236,6 @@
     }
   }
 #endif // COMPILER2 || GRAAL
-#ifdef GRAAL
-  // deferred writes
-  { GrowableArray<DeferredWriteValue*>* l = ((ScopeDesc*) this)->deferred_writes();
-    if (l != NULL) {
-      st->print_cr("   Deferred writes");
-      for (int index = 0; index < l->length(); index++) {
-        st->print("    - @%d: ", index);
-        l->at(index)->print_on(st);
-        st->cr();
-      }
-    }
-  }
-#endif
 }
 
 #endif
--- a/src/share/vm/code/scopeDesc.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/scopeDesc.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -78,9 +78,6 @@
   GrowableArray<ScopeValue*>*   expressions();
   GrowableArray<MonitorValue*>* monitors();
   GrowableArray<ScopeValue*>*   objects();
-#ifdef GRAAL
-  GrowableArray<DeferredWriteValue*>* deferred_writes();
-#endif // GRAAL
 
   // Stack walking, returns NULL if this is the outer most scope.
   ScopeDesc* sender() const;
@@ -110,9 +107,6 @@
   int _locals_decode_offset;
   int _expressions_decode_offset;
   int _monitors_decode_offset;
-#ifdef GRAAL
-  int _deferred_writes_decode_offset;
-#endif // GRAAL
 
   // Object pool
   GrowableArray<ScopeValue*>* _objects;
@@ -125,9 +119,6 @@
   GrowableArray<ScopeValue*>* decode_scope_values(int decode_offset);
   GrowableArray<MonitorValue*>* decode_monitor_values(int decode_offset);
   GrowableArray<ScopeValue*>* decode_object_values(int decode_offset);
-#ifdef GRAAL
-  GrowableArray<DeferredWriteValue*>* decode_deferred_writes(int decode_offset);
-#endif // GRAAL
 
   DebugInfoReadStream* stream_at(int decode_offset) const;
 
--- a/src/share/vm/code/stubs.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/stubs.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -254,9 +254,10 @@
   guarantee(_queue_begin != _queue_end || n == 0, "buffer indices must be the same");
 }
 
-void StubQueue::print_on(outputStream* st) const {
+
+void StubQueue::print() {
   MutexLockerEx lock(_mutex);
   for (Stub* s = first(); s != NULL; s = next(s)) {
-    stub_print(s, st);
+    stub_print(s);
   }
 }
--- a/src/share/vm/code/stubs.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/code/stubs.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -107,21 +107,20 @@
  public:
   // Initialization/finalization
   virtual void    initialize(Stub* self, int size,
-                             CodeComments& comments)           = 0; // called after creation (called twice if allocated via (request, commit))
-  virtual void    finalize(Stub* self)                         = 0; // called before deallocation
+                             CodeComments& comments)       = 0; // called after creation (called twice if allocated via (request, commit))
+  virtual void    finalize(Stub* self)                     = 0; // called before deallocation
 
   // General info/converters
-  virtual int     size(Stub* self) const                       = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment)
-  virtual int     code_size_to_size(int code_size) const       = 0; // computes the total stub size in bytes given the code size in bytes
+  virtual int     size(Stub* self) const                   = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment)
+  virtual int     code_size_to_size(int code_size) const   = 0; // computes the total stub size in bytes given the code size in bytes
 
   // Code info
-  virtual address code_begin(Stub* self) const                 = 0; // points to the first code byte
-  virtual address code_end(Stub* self) const                   = 0; // points to the first byte after the code
+  virtual address code_begin(Stub* self) const             = 0; // points to the first code byte
+  virtual address code_end(Stub* self) const               = 0; // points to the first byte after the code
 
   // Debugging
-  virtual void    verify(Stub* self) const                     = 0; // verifies the stub
-  NOT_PRODUCT(using AllocatedObj::print_on;)
-  virtual void    print_on(Stub* self, outputStream* st) const = 0; // prints information about the stub
+  virtual void    verify(Stub* self)                       = 0; // verifies the stub
+  virtual void    print(Stub* self)                        = 0; // prints information about the stub
 };
 
 
@@ -129,29 +128,28 @@
 // class, forwarding stub interface calls to the corresponding
 // stub calls.
 
-#define DEF_STUB_INTERFACE(stub)                                 \
-  class stub##Interface: public StubInterface {                  \
-   private:                                                      \
-    static stub*    cast(Stub* self)                             { return (stub*)self; }                 \
-                                                                 \
-   public:                                                       \
-    /* Initialization/finalization */                            \
-    virtual void    initialize(Stub* self, int size,             \
-                               CodeComments& comments)           { cast(self)->initialize(size, comments); } \
-    virtual void    finalize(Stub* self)                         { cast(self)->finalize(); }             \
-                                                                 \
-    /* General info */                                           \
-    virtual int     size(Stub* self) const                       { return cast(self)->size(); }          \
-    virtual int     code_size_to_size(int code_size) const       { return stub::code_size_to_size(code_size); } \
-                                                                 \
-    /* Code info */                                              \
-    virtual address code_begin(Stub* self) const                 { return cast(self)->code_begin(); }    \
-    virtual address code_end(Stub* self) const                   { return cast(self)->code_end(); }      \
-                                                                 \
-    /* Debugging */                                              \
-    virtual void    verify(Stub* self) const                     { cast(self)->verify(); }               \
-    NOT_PRODUCT(using AllocatedObj::print_on;)                   \
-    virtual void    print_on(Stub* self, outputStream* st) const { cast(self)->print_on(st); }           \
+#define DEF_STUB_INTERFACE(stub)                           \
+  class stub##Interface: public StubInterface {            \
+   private:                                                \
+    static stub*    cast(Stub* self)                       { return (stub*)self; }                 \
+                                                           \
+   public:                                                 \
+    /* Initialization/finalization */                      \
+    virtual void    initialize(Stub* self, int size,       \
+                               CodeComments& comments)     { cast(self)->initialize(size, comments); } \
+    virtual void    finalize(Stub* self)                   { cast(self)->finalize(); }             \
+                                                           \
+    /* General info */                                     \
+    virtual int     size(Stub* self) const                 { return cast(self)->size(); }          \
+    virtual int     code_size_to_size(int code_size) const { return stub::code_size_to_size(code_size); } \
+                                                           \
+    /* Code info */                                        \
+    virtual address code_begin(Stub* self) const           { return cast(self)->code_begin(); }    \
+    virtual address code_end(Stub* self) const             { return cast(self)->code_end(); }      \
+                                                           \
+    /* Debugging */                                        \
+    virtual void    verify(Stub* self)                     { cast(self)->verify(); }               \
+    virtual void    print(Stub* self)                      { cast(self)->print(); }                \
   };
 
 
@@ -184,7 +182,7 @@
   bool  stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); }
   int   stub_code_size_to_size(int code_size) const { return _stub_interface->code_size_to_size(code_size); }
   void  stub_verify(Stub* s)                     { _stub_interface->verify(s); }
-  void  stub_print(Stub* s, outputStream* st) const { _stub_interface->print_on(s, st); }
+  void  stub_print(Stub* s)                      { _stub_interface->print(s); }
 
   static void register_queue(StubQueue*);
 
@@ -228,9 +226,8 @@
   address stub_code_end(Stub* s) const           { return _stub_interface->code_end(s);   }
 
   // Debugging/printing
-  void verify();                                 // verifies the stub queue
-  virtual void print() const                     { print_on(tty); }
-  virtual void print_on(outputStream* st) const;
+  void  verify();                                // verifies the stub queue
+  void  print();                                 // prints information about the stub queue
 };
 
 #endif // SHARE_VM_CODE_STUBS_HPP
--- a/src/share/vm/compiler/compileBroker.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/compiler/compileBroker.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -44,9 +44,6 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/sweeper.hpp"
 #include "utilities/dtrace.hpp"
-#ifdef GRAAL
-#include "graal/graalCompiler.hpp"
-#endif
 #include "utilities/events.hpp"
 #ifdef COMPILER1
 #include "c1/c1_Compiler.hpp"
@@ -1421,7 +1418,7 @@
       method->print_short_name(tty);
       tty->cr();
     }
-    method->set_not_compilable_quietly();
+    method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompilerOracle");
   }
 
   return false;
--- a/src/share/vm/compiler/oopMap.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/compiler/oopMap.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -47,7 +47,7 @@
 class OopMapValue: public StackObj {
   friend class VMStructs;
 private:
-  int _value;
+  short _value;
   int value() const                                 { return _value; }
   void set_value(int value)                         { _value = value; }
   short _content_reg;
@@ -55,7 +55,7 @@
 public:
   // Constants
   enum { type_bits                = 5,
-         register_bits            = BitsPerJavaInteger - type_bits };
+         register_bits            = BitsPerShort - type_bits };
 
   enum { type_shift               = 0,
          register_shift           = type_bits };
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -102,7 +102,7 @@
   // temporarily disabled).
   switch (dictionaryChoice) {
     case FreeBlockDictionary<FreeChunk>::dictionaryBinaryTree:
-      _dictionary = new BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>(mr);
+      _dictionary = new AFLBinaryTreeDictionary(mr);
       break;
     case FreeBlockDictionary<FreeChunk>::dictionarySplayTree:
     case FreeBlockDictionary<FreeChunk>::dictionarySkipList:
@@ -122,7 +122,8 @@
   // moved to its new location before the klass is moved.
   // Set the _refillSize for the linear allocation blocks
   if (!use_adaptive_freelists) {
-    FreeChunk* fc = _dictionary->get_chunk(mr.word_size());
+    FreeChunk* fc = _dictionary->get_chunk(mr.word_size(),
+                                           FreeBlockDictionary<FreeChunk>::atLeast);
     // The small linAB initially has all the space and will allocate
     // a chunk of any size.
     HeapWord* addr = (HeapWord*) fc;
@@ -1647,7 +1648,8 @@
 FreeChunk*
 CompactibleFreeListSpace::getChunkFromDictionary(size_t size) {
   assert_locked();
-  FreeChunk* fc = _dictionary->get_chunk(size);
+  FreeChunk* fc = _dictionary->get_chunk(size,
+                                         FreeBlockDictionary<FreeChunk>::atLeast);
   if (fc == NULL) {
     return NULL;
   }
@@ -1664,7 +1666,8 @@
 FreeChunk*
 CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) {
   assert_locked();
-  FreeChunk* fc = _dictionary->get_chunk(size);
+  FreeChunk* fc = _dictionary->get_chunk(size,
+                                         FreeBlockDictionary<FreeChunk>::atLeast);
   if (fc == NULL) {
     return fc;
   }
@@ -1677,7 +1680,8 @@
   if (fc->size() < size + MinChunkSize) {
     // Return the chunk to the dictionary and go get a bigger one.
     returnChunkToDictionary(fc);
-    fc = _dictionary->get_chunk(size + MinChunkSize);
+    fc = _dictionary->get_chunk(size + MinChunkSize,
+                                FreeBlockDictionary<FreeChunk>::atLeast);
     if (fc == NULL) {
       return NULL;
     }
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -131,7 +131,7 @@
   LinearAllocBlock _smallLinearAllocBlock;
 
   FreeBlockDictionary<FreeChunk>::DictionaryChoice _dictionaryChoice;
-  FreeBlockDictionary<FreeChunk>* _dictionary;    // ptr to dictionary for large size blocks
+  AFLBinaryTreeDictionary* _dictionary;    // ptr to dictionary for large size blocks
 
   AdaptiveFreeList<FreeChunk> _indexedFreeList[IndexSetSize];
                                        // indexed array for small size blocks
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -274,8 +274,8 @@
 // end of a collection, we let CMSTriggerRatio of the (purported) free
 // space be allocated before initiating a new collection cycle.
 //
-void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, intx tr) {
-  assert(io <= 100 && tr >= 0 && tr <= 100, "Check the arguments");
+void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, uintx tr) {
+  assert(io <= 100 && tr <= 100, "Check the arguments");
   if (io >= 0) {
     _initiating_occupancy = (double)io / 100.0;
   } else {
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1093,7 +1093,7 @@
 
   // getter and initializer for _initiating_occupancy field.
   double initiating_occupancy() const { return _initiating_occupancy; }
-  void   init_initiating_occupancy(intx io, intx tr);
+  void   init_initiating_occupancy(intx io, uintx tr);
 
  public:
   ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_VMSTRUCTS_CMS_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_VMSTRUCTS_CMS_HPP
 
-typedef BinaryTreeDictionary<FreeChunk, AdaptiveFreeList> AFLBinaryTreeDictionary;
-
 #define VM_STRUCTS_CMS(nonstatic_field, \
                    volatile_nonstatic_field, \
                    static_field) \
@@ -34,14 +32,15 @@
   nonstatic_field(CompactibleFreeListSpace,    _bt,                                           BlockOffsetArrayNonContigSpace)        \
                                                                                                                                      \
   nonstatic_field(CMSBitMap,                   _bmWordSize,                                   size_t)                                \
-  nonstatic_field(CMSBitMap,                   _shifter,                                      const int)                            \
-  nonstatic_field(CMSBitMap,                      _bm,                                           BitMap)                            \
-  nonstatic_field(CMSBitMap,                   _virtual_space,                                VirtualSpace)                         \
+  nonstatic_field(CMSBitMap,                   _shifter,                                      const int)                             \
+  nonstatic_field(CMSBitMap,                      _bm,                                           BitMap)                             \
+  nonstatic_field(CMSBitMap,                   _virtual_space,                                VirtualSpace)                          \
   nonstatic_field(CMSCollector,                _markBitMap,                                   CMSBitMap)                             \
   nonstatic_field(ConcurrentMarkSweepGeneration, _cmsSpace,                                   CompactibleFreeListSpace*)             \
      static_field(ConcurrentMarkSweepThread,   _collector,                                    CMSCollector*)                         \
   nonstatic_field(LinearAllocBlock,            _word_size,                                    size_t)                                \
   nonstatic_field(AFLBinaryTreeDictionary,     _total_size,                                   size_t)                                \
+  nonstatic_field(CompactibleFreeListSpace,    _dictionary,                                   AFLBinaryTreeDictionary*)              \
   nonstatic_field(CompactibleFreeListSpace,    _indexedFreeList[0],                           FreeList<FreeChunk>)                   \
   nonstatic_field(CompactibleFreeListSpace,    _smallLinearAllocBlock,                        LinearAllocBlock)
 
@@ -62,10 +61,9 @@
   declare_toplevel_type(SurrogateLockerThread*)                           \
   declare_toplevel_type(CompactibleFreeListSpace*)                        \
   declare_toplevel_type(CMSCollector*)                                    \
-  declare_toplevel_type(AFLBinaryTreeDictionary*)                         \
+  declare_toplevel_type(AFLBinaryTreeDictionary)                          \
   declare_toplevel_type(LinearAllocBlock)                                 \
-  declare_toplevel_type(FreeBlockDictionary<FreeChunk>)                   \
-           declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary<FreeChunk>)
+  declare_toplevel_type(FreeBlockDictionary<FreeChunk>)
 
 #define VM_INT_CONSTANTS_CMS(declare_constant)                            \
   declare_constant(Generation::ConcurrentMarkSweep)                       \
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -571,19 +571,14 @@
     _sleep_factor             =     0.0;
     _marking_task_overhead    =     1.0;
   } else {
-    if (ConcGCThreads > 0) {
-      // notice that ConcGCThreads overwrites G1MarkingOverheadPercent
+    if (!FLAG_IS_DEFAULT(ConcGCThreads) && ConcGCThreads > 0) {
+      // Note: ConcGCThreads has precedence over G1MarkingOverheadPercent
       // if both are set
-
-      _parallel_marking_threads = (uint) ConcGCThreads;
-      _max_parallel_marking_threads = _parallel_marking_threads;
       _sleep_factor             = 0.0;
       _marking_task_overhead    = 1.0;
     } else if (G1MarkingOverheadPercent > 0) {
-      // we will calculate the number of parallel marking threads
-      // based on a target overhead with respect to the soft real-time
-      // goal
-
+      // We will calculate the number of parallel marking threads based
+      // on a target overhead with respect to the soft real-time goal
       double marking_overhead = (double) G1MarkingOverheadPercent / 100.0;
       double overall_cm_overhead =
         (double) MaxGCPauseMillis * marking_overhead /
@@ -596,17 +591,22 @@
       double sleep_factor =
                          (1.0 - marking_task_overhead) / marking_task_overhead;
 
-      _parallel_marking_threads = (uint) marking_thread_num;
-      _max_parallel_marking_threads = _parallel_marking_threads;
+      FLAG_SET_ERGO(uintx, ConcGCThreads, (uint) marking_thread_num);
       _sleep_factor             = sleep_factor;
       _marking_task_overhead    = marking_task_overhead;
     } else {
-      _parallel_marking_threads = scale_parallel_threads((uint)ParallelGCThreads);
-      _max_parallel_marking_threads = _parallel_marking_threads;
+      // Calculate the number of parallel marking threads by scaling
+      // the number of parallel GC threads.
+      uint marking_thread_num = scale_parallel_threads((uint) ParallelGCThreads);
+      FLAG_SET_ERGO(uintx, ConcGCThreads, marking_thread_num);
       _sleep_factor             = 0.0;
       _marking_task_overhead    = 1.0;
     }
 
+    assert(ConcGCThreads > 0, "Should have been set");
+    _parallel_marking_threads = (uint) ConcGCThreads;
+    _max_parallel_marking_threads = _parallel_marking_threads;
+
     if (parallel_marking_threads() > 1) {
       _cleanup_task_overhead = 1.0;
     } else {
@@ -1190,7 +1190,7 @@
     uint active_workers = MAX2(1U, parallel_marking_threads());
 
     CMRootRegionScanTask task(this);
-    if (parallel_marking_threads() > 0) {
+    if (use_parallel_marking_threads()) {
       _parallel_workers->set_active_workers((int) active_workers);
       _parallel_workers->run_task(&task);
     } else {
@@ -1226,7 +1226,7 @@
   set_phase(active_workers, true /* concurrent */);
 
   CMConcurrentMarkingTask markingTask(this, cmThread());
-  if (parallel_marking_threads() > 0) {
+  if (use_parallel_marking_threads()) {
     _parallel_workers->set_active_workers((int)active_workers);
     // Don't set _n_par_threads because it affects MT in proceess_strong_roots()
     // and the decisions on that MT processing is made elsewhere.
@@ -2167,7 +2167,8 @@
   assert(tmp_free_list.is_empty(), "post-condition");
 }
 
-// Support closures for reference procssing in G1
+// Supporting Object and Oop closures for reference discovery
+// and processing in during marking
 
 bool G1CMIsAliveClosure::do_object_b(oop obj) {
   HeapWord* addr = (HeapWord*)obj;
@@ -2175,73 +2176,26 @@
          (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_ill(obj));
 }
 
-class G1CMKeepAliveClosure: public ExtendedOopClosure {
-  G1CollectedHeap* _g1;
-  ConcurrentMark*  _cm;
- public:
-  G1CMKeepAliveClosure(G1CollectedHeap* g1, ConcurrentMark* cm) :
-    _g1(g1), _cm(cm) {
-    assert(Thread::current()->is_VM_thread(), "otherwise fix worker id");
-  }
-
-  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
-  virtual void do_oop(      oop* p) { do_oop_work(p); }
-
-  template <class T> void do_oop_work(T* p) {
-    oop obj = oopDesc::load_decode_heap_oop(p);
-    HeapWord* addr = (HeapWord*)obj;
-
-    if (_cm->verbose_high()) {
-      gclog_or_tty->print_cr("\t[0] we're looking at location "
-                             "*"PTR_FORMAT" = "PTR_FORMAT,
-                             p, (void*) obj);
-    }
-
-    if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(obj)) {
-      _cm->mark_and_count(obj);
-      _cm->mark_stack_push(obj);
-    }
-  }
-};
-
-class G1CMDrainMarkingStackClosure: public VoidClosure {
-  ConcurrentMark*               _cm;
-  CMMarkStack*                  _markStack;
-  G1CMKeepAliveClosure*         _oopClosure;
- public:
-  G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMMarkStack* markStack,
-                               G1CMKeepAliveClosure* oopClosure) :
-    _cm(cm),
-    _markStack(markStack),
-    _oopClosure(oopClosure) { }
-
-  void do_void() {
-    _markStack->drain(_oopClosure, _cm->nextMarkBitMap(), false);
-  }
-};
-
-// 'Keep Alive' closure used by parallel reference processing.
-// An instance of this closure is used in the parallel reference processing
-// code rather than an instance of G1CMKeepAliveClosure. We could have used
-// the G1CMKeepAliveClosure as it is MT-safe. Also reference objects are
-// placed on to discovered ref lists once so we can mark and push with no
-// need to check whether the object has already been marked. Using the
-// G1CMKeepAliveClosure would mean, however, having all the worker threads
-// operating on the global mark stack. This means that an individual
-// worker would be doing lock-free pushes while it processes its own
-// discovered ref list followed by drain call. If the discovered ref lists
-// are unbalanced then this could cause interference with the other
-// workers. Using a CMTask (and its embedded local data structures)
-// avoids that potential interference.
-class G1CMParKeepAliveAndDrainClosure: public OopClosure {
+// 'Keep Alive' oop closure used by both serial parallel reference processing.
+// Uses the CMTask associated with a worker thread (for serial reference
+// processing the CMTask for worker 0 is used) to preserve (mark) and
+// trace referent objects.
+//
+// Using the CMTask and embedded local queues avoids having the worker
+// threads operating on the global mark stack. This reduces the risk
+// of overflowing the stack - which we would rather avoid at this late
+// state. Also using the tasks' local queues removes the potential
+// of the workers interfering with each other that could occur if
+// operating on the global stack.
+
+class G1CMKeepAliveAndDrainClosure: public OopClosure {
   ConcurrentMark*  _cm;
   CMTask*          _task;
   int              _ref_counter_limit;
   int              _ref_counter;
  public:
-  G1CMParKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) :
-    _cm(cm), _task(task),
-    _ref_counter_limit(G1RefProcDrainInterval) {
+  G1CMKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) :
+    _cm(cm), _task(task), _ref_counter_limit(G1RefProcDrainInterval) {
     assert(_ref_counter_limit > 0, "sanity");
     _ref_counter = _ref_counter_limit;
   }
@@ -2262,18 +2216,22 @@
       _ref_counter--;
 
       if (_ref_counter == 0) {
-        // We have dealt with _ref_counter_limit references, pushing them and objects
-        // reachable from them on to the local stack (and possibly the global stack).
-        // Call do_marking_step() to process these entries. We call the routine in a
-        // loop, which we'll exit if there's nothing more to do (i.e. we're done
-        // with the entries that we've pushed as a result of the deal_with_reference
-        // calls above) or we overflow.
-        // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag
-        // while there may still be some work to do. (See the comment at the
-        // beginning of CMTask::do_marking_step() for those conditions - one of which
-        // is reaching the specified time target.) It is only when
-        // CMTask::do_marking_step() returns without setting the has_aborted() flag
-        // that the marking has completed.
+        // We have dealt with _ref_counter_limit references, pushing them
+        // and objects reachable from them on to the local stack (and
+        // possibly the global stack). Call CMTask::do_marking_step() to
+        // process these entries.
+        //
+        // We call CMTask::do_marking_step() in a loop, which we'll exit if
+        // there's nothing more to do (i.e. we're done with the entries that
+        // were pushed as a result of the CMTask::deal_with_reference() calls
+        // above) or we overflow.
+        //
+        // Note: CMTask::do_marking_step() can set the CMTask::has_aborted()
+        // flag while there may still be some work to do. (See the comment at
+        // the beginning of CMTask::do_marking_step() for those conditions -
+        // one of which is reaching the specified time target.) It is only
+        // when CMTask::do_marking_step() returns without setting the
+        // has_aborted() flag that the marking step has completed.
         do {
           double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
           _task->do_marking_step(mark_step_duration_ms,
@@ -2290,36 +2248,59 @@
   }
 };
 
-class G1CMParDrainMarkingStackClosure: public VoidClosure {
+// 'Drain' oop closure used by both serial and parallel reference processing.
+// Uses the CMTask associated with a given worker thread (for serial
+// reference processing the CMtask for worker 0 is used). Calls the
+// do_marking_step routine, with an unbelievably large timeout value,
+// to drain the marking data structures of the remaining entries
+// added by the 'keep alive' oop closure above.
+
+class G1CMDrainMarkingStackClosure: public VoidClosure {
   ConcurrentMark* _cm;
-  CMTask* _task;
+  CMTask*         _task;
+  bool            _do_stealing;
+  bool            _do_termination;
  public:
-  G1CMParDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task) :
-    _cm(cm), _task(task) { }
+  G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task, bool is_par) :
+    _cm(cm), _task(task) {
+    assert(is_par || _task->worker_id() == 0,
+           "Only task for worker 0 should be used if ref processing is single threaded");
+    // We only allow stealing and only enter the termination protocol
+    // in CMTask::do_marking_step() if this closure is being instantiated
+    // for parallel reference processing.
+    _do_stealing = _do_termination = is_par;
+  }
 
   void do_void() {
     do {
       if (_cm->verbose_high()) {
-        gclog_or_tty->print_cr("\t[%u] Drain: Calling do marking_step",
-                               _task->worker_id());
+        gclog_or_tty->print_cr("\t[%u] Drain: Calling do_marking_step - "
+                               "stealing: %s, termination: %s",
+                               _task->worker_id(),
+                               BOOL_TO_STR(_do_stealing),
+                               BOOL_TO_STR(_do_termination));
       }
 
-      // We call CMTask::do_marking_step() to completely drain the local and
-      // global marking stacks. The routine is called in a loop, which we'll
-      // exit if there's nothing more to do (i.e. we'completely drained the
-      // entries that were pushed as a result of applying the
-      // G1CMParKeepAliveAndDrainClosure to the entries on the discovered ref
-      // lists above) or we overflow the global marking stack.
-      // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag
-      // while there may still be some work to do. (See the comment at the
-      // beginning of CMTask::do_marking_step() for those conditions - one of which
-      // is reaching the specified time target.) It is only when
-      // CMTask::do_marking_step() returns without setting the has_aborted() flag
-      // that the marking has completed.
+      // We call CMTask::do_marking_step() to completely drain the local
+      // and global marking stacks of entries pushed by the 'keep alive'
+      // oop closure (an instance of G1CMKeepAliveAndDrainClosure above).
+      //
+      // CMTask::do_marking_step() is called in a loop, which we'll exit
+      // if there's nothing more to do (i.e. we'completely drained the
+      // entries that were pushed as a a result of applying the 'keep alive'
+      // closure to the entries on the discovered ref lists) or we overflow
+      // the global marking stack.
+      //
+      // Note: CMTask::do_marking_step() can set the CMTask::has_aborted()
+      // flag while there may still be some work to do. (See the comment at
+      // the beginning of CMTask::do_marking_step() for those conditions -
+      // one of which is reaching the specified time target.) It is only
+      // when CMTask::do_marking_step() returns without setting the
+      // has_aborted() flag that the marking step has completed.
 
       _task->do_marking_step(1000000000.0 /* something very large */,
-                             true /* do_stealing    */,
-                             true /* do_termination */);
+                             _do_stealing,
+                             _do_termination);
     } while (_task->has_aborted() && !_cm->has_overflown());
   }
 };
@@ -2352,19 +2333,23 @@
   ProcessTask&     _proc_task;
   G1CollectedHeap* _g1h;
   ConcurrentMark*  _cm;
+  bool             _processing_is_mt;
 
 public:
   G1CMRefProcTaskProxy(ProcessTask& proc_task,
                      G1CollectedHeap* g1h,
                      ConcurrentMark* cm) :
     AbstractGangTask("Process reference objects in parallel"),
-    _proc_task(proc_task), _g1h(g1h), _cm(cm) { }
+    _proc_task(proc_task), _g1h(g1h), _cm(cm) {
+      ReferenceProcessor* rp = _g1h->ref_processor_cm();
+      _processing_is_mt = rp->processing_is_mt();
+    }
 
   virtual void work(uint worker_id) {
     CMTask* marking_task = _cm->task(worker_id);
     G1CMIsAliveClosure g1_is_alive(_g1h);
-    G1CMParKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task);
-    G1CMParDrainMarkingStackClosure g1_par_drain(_cm, marking_task);
+    G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task);
+    G1CMDrainMarkingStackClosure g1_par_drain(_cm, marking_task, _processing_is_mt);
 
     _proc_task.work(worker_id, g1_is_alive, g1_par_keep_alive, g1_par_drain);
   }
@@ -2372,6 +2357,7 @@
 
 void G1CMRefProcTaskExecutor::execute(ProcessTask& proc_task) {
   assert(_workers != NULL, "Need parallel worker threads.");
+  assert(_g1h->ref_processor_cm()->processing_is_mt(), "processing is not MT");
 
   G1CMRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm);
 
@@ -2399,6 +2385,7 @@
 
 void G1CMRefProcTaskExecutor::execute(EnqueueTask& enq_task) {
   assert(_workers != NULL, "Need parallel worker threads.");
+  assert(_g1h->ref_processor_cm()->processing_is_mt(), "processing is not MT");
 
   G1CMRefEnqueueTaskProxy enq_task_proxy(enq_task);
 
@@ -2429,59 +2416,58 @@
     // See the comment in G1CollectedHeap::ref_processing_init()
     // about how reference processing currently works in G1.
 
-    // Process weak references.
+    // Set the soft reference policy
     rp->setup_policy(clear_all_soft_refs);
     assert(_markStack.isEmpty(), "mark stack should be empty");
 
-    G1CMKeepAliveClosure g1_keep_alive(g1h, this);
-    G1CMDrainMarkingStackClosure
-      g1_drain_mark_stack(this, &_markStack, &g1_keep_alive);
-
-    // We use the work gang from the G1CollectedHeap and we utilize all
-    // the worker threads.
-    uint active_workers = g1h->workers() ? g1h->workers()->active_workers() : 1U;
+    // Non-MT instances 'Keep Alive' and 'Complete GC' oop closures.
+    G1CMKeepAliveAndDrainClosure g1_keep_alive(this, task(0));
+    G1CMDrainMarkingStackClosure g1_drain_mark_stack(this, task(0), false);
+
+    // We need at least one active thread. If reference processing is
+    // not multi-threaded we use the current (ConcurrentMarkThread) thread,
+    // otherwise we use the work gang from the G1CollectedHeap and we
+    // utilize all the worker threads we can.
+    uint active_workers = (rp->processing_is_mt() && g1h->workers() != NULL
+                                ? g1h->workers()->active_workers()
+                                : 1U);
+
     active_workers = MAX2(MIN2(active_workers, _max_worker_id), 1U);
 
     G1CMRefProcTaskExecutor par_task_executor(g1h, this,
                                               g1h->workers(), active_workers);
 
-    if (rp->processing_is_mt()) {
-      // Set the degree of MT here.  If the discovery is done MT, there
-      // may have been a different number of threads doing the discovery
-      // and a different number of discovered lists may have Ref objects.
-      // That is OK as long as the Reference lists are balanced (see
-      // balance_all_queues() and balance_queues()).
-      rp->set_active_mt_degree(active_workers);
-
-      rp->process_discovered_references(&g1_is_alive,
+    AbstractRefProcTaskExecutor* executor = (rp->processing_is_mt()
+                                                ? &par_task_executor
+                                                : NULL);
+
+    // Set the degree of MT processing here.  If the discovery was done MT,
+    // the number of threads involved during discovery could differ from
+    // the number of active workers.  This is OK as long as the discovered
+    // Reference lists are balanced (see balance_all_queues() and balance_queues()).
+    rp->set_active_mt_degree(active_workers);
+
+    // Process the weak references.
+    rp->process_discovered_references(&g1_is_alive,
                                       &g1_keep_alive,
                                       &g1_drain_mark_stack,
-                                      &par_task_executor);
-
-      // The work routines of the parallel keep_alive and drain_marking_stack
-      // will set the has_overflown flag if we overflow the global marking
-      // stack.
-    } else {
-      rp->process_discovered_references(&g1_is_alive,
-                                        &g1_keep_alive,
-                                        &g1_drain_mark_stack,
-                                        NULL);
-    }
+                                      executor);
+
+    // The do_oop work routines of the keep_alive and drain_marking_stack
+    // oop closures will set the has_overflown flag if we overflow the
+    // global marking stack.
 
     assert(_markStack.overflow() || _markStack.isEmpty(),
             "mark stack should be empty (unless it overflowed)");
     if (_markStack.overflow()) {
-      // Should have been done already when we tried to push an
+      // This should have been done already when we tried to push an
       // entry on to the global mark stack. But let's do it again.
       set_has_overflown();
     }
 
-    if (rp->processing_is_mt()) {
-      assert(rp->num_q() == active_workers, "why not");
-      rp->enqueue_discovered_references(&par_task_executor);
-    } else {
-      rp->enqueue_discovered_references();
-    }
+    assert(rp->num_q() == active_workers, "why not");
+
+    rp->enqueue_discovered_references(executor);
 
     rp->verify_no_references_recorded();
     assert(!rp->discovery_enabled(), "Post condition");
@@ -3242,7 +3228,9 @@
 }
 
 void ConcurrentMark::print_worker_threads_on(outputStream* st) const {
-  _parallel_workers->print_worker_threads_on(st);
+  if (use_parallel_marking_threads()) {
+    _parallel_workers->print_worker_threads_on(st);
+  }
 }
 
 // We take a break if someone is trying to stop the world.
@@ -4074,15 +4062,36 @@
       if (_cm->verbose_low()) {
         gclog_or_tty->print_cr("[%u] we're scanning part "
                                "["PTR_FORMAT", "PTR_FORMAT") "
-                               "of region "PTR_FORMAT,
-                               _worker_id, _finger, _region_limit, _curr_region);
+                               "of region "HR_FORMAT,
+                               _worker_id, _finger, _region_limit,
+                               HR_FORMAT_PARAMS(_curr_region));
       }
 
-      // Let's iterate over the bitmap of the part of the
-      // region that is left.
-      if (mr.is_empty() || _nextMarkBitMap->iterate(&bitmap_closure, mr)) {
-        // We successfully completed iterating over the region. Now,
-        // let's give up the region.
+      assert(!_curr_region->isHumongous() || mr.start() == _curr_region->bottom(),
+             "humongous regions should go around loop once only");
+
+      // Some special cases:
+      // If the memory region is empty, we can just give up the region.
+      // If the current region is humongous then we only need to check
+      // the bitmap for the bit associated with the start of the object,
+      // scan the object if it's live, and give up the region.
+      // Otherwise, let's iterate over the bitmap of the part of the region
+      // that is left.
+      // If the iteration is successful, give up the region.
+      if (mr.is_empty()) {
+        giveup_current_region();
+        regular_clock_call();
+      } else if (_curr_region->isHumongous() && mr.start() == _curr_region->bottom()) {
+        if (_nextMarkBitMap->isMarked(mr.start())) {
+          // The object is marked - apply the closure
+          BitMap::idx_t offset = _nextMarkBitMap->heapWordToOffset(mr.start());
+          bitmap_closure.do_bit(offset);
+        }
+        // Even if this task aborted while scanning the humongous object
+        // we can (and should) give up the current region.
+        giveup_current_region();
+        regular_clock_call();
+      } else if (_nextMarkBitMap->iterate(&bitmap_closure, mr)) {
         giveup_current_region();
         regular_clock_call();
       } else {
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -371,8 +371,8 @@
   friend class CalcLiveObjectsClosure;
   friend class G1CMRefProcTaskProxy;
   friend class G1CMRefProcTaskExecutor;
-  friend class G1CMParKeepAliveAndDrainClosure;
-  friend class G1CMParDrainMarkingStackClosure;
+  friend class G1CMKeepAliveAndDrainClosure;
+  friend class G1CMDrainMarkingStackClosure;
 
 protected:
   ConcurrentMarkThread* _cmThread;   // the thread doing the work
@@ -499,17 +499,26 @@
   }
 
   // accessor methods
-  uint parallel_marking_threads() { return _parallel_marking_threads; }
-  uint max_parallel_marking_threads() { return _max_parallel_marking_threads;}
-  double sleep_factor()             { return _sleep_factor; }
-  double marking_task_overhead()    { return _marking_task_overhead;}
-  double cleanup_sleep_factor()     { return _cleanup_sleep_factor; }
-  double cleanup_task_overhead()    { return _cleanup_task_overhead;}
+  uint parallel_marking_threads() const     { return _parallel_marking_threads; }
+  uint max_parallel_marking_threads() const { return _max_parallel_marking_threads;}
+  double sleep_factor()                     { return _sleep_factor; }
+  double marking_task_overhead()            { return _marking_task_overhead;}
+  double cleanup_sleep_factor()             { return _cleanup_sleep_factor; }
+  double cleanup_task_overhead()            { return _cleanup_task_overhead;}
 
-  HeapWord*               finger()        { return _finger;   }
-  bool                    concurrent()    { return _concurrent; }
-  uint                    active_tasks()  { return _active_tasks; }
-  ParallelTaskTerminator* terminator()    { return &_terminator; }
+  bool use_parallel_marking_threads() const {
+    assert(parallel_marking_threads() <=
+           max_parallel_marking_threads(), "sanity");
+    assert((_parallel_workers == NULL && parallel_marking_threads() == 0) ||
+           parallel_marking_threads() > 0,
+           "parallel workers not set up correctly");
+    return _parallel_workers != NULL;
+  }
+
+  HeapWord*               finger()          { return _finger;   }
+  bool                    concurrent()      { return _concurrent; }
+  uint                    active_tasks()    { return _active_tasks; }
+  ParallelTaskTerminator* terminator()      { return &_terminator; }
 
   // It claims the next available region to be scanned by a marking
   // task/thread. It might return NULL if the next region is empty or
--- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -117,7 +117,7 @@
         if (G1Log::fine()) {
           gclog_or_tty->date_stamp(PrintGCDateStamps);
           gclog_or_tty->stamp(PrintGCTimeStamps);
-          gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf]",
+          gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf secs]",
                                  scan_end - scan_start);
         }
       }
@@ -150,7 +150,7 @@
           if (G1Log::fine()) {
             gclog_or_tty->date_stamp(PrintGCDateStamps);
             gclog_or_tty->stamp(PrintGCTimeStamps);
-            gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf sec]",
+            gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf secs]",
                                       mark_end_sec - mark_start_sec);
           }
 
@@ -234,7 +234,7 @@
         if (G1Log::fine()) {
           gclog_or_tty->date_stamp(PrintGCDateStamps);
           gclog_or_tty->stamp(PrintGCTimeStamps);
-          gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]",
+          gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf secs]",
                                  cleanup_end_sec - cleanup_start_sec);
         }
       }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1893,7 +1893,6 @@
   _ref_processor_stw(NULL),
   _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)),
   _bot_shared(NULL),
-  _objs_with_preserved_marks(NULL), _preserved_marks_of_objs(NULL),
   _evac_failure_scan_stack(NULL) ,
   _mark_in_progress(false),
   _cg1r(NULL), _summary_bytes_used(0),
@@ -4225,22 +4224,15 @@
   assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
 
   // Now restore saved marks, if any.
-  if (_objs_with_preserved_marks != NULL) {
-    assert(_preserved_marks_of_objs != NULL, "Both or none.");
-    guarantee(_objs_with_preserved_marks->length() ==
-              _preserved_marks_of_objs->length(), "Both or none.");
-    for (int i = 0; i < _objs_with_preserved_marks->length(); i++) {
-      oop obj   = _objs_with_preserved_marks->at(i);
-      markOop m = _preserved_marks_of_objs->at(i);
-      obj->set_mark(m);
-    }
-
-    // Delete the preserved marks growable arrays (allocated on the C heap).
-    delete _objs_with_preserved_marks;
-    delete _preserved_marks_of_objs;
-    _objs_with_preserved_marks = NULL;
-    _preserved_marks_of_objs = NULL;
-  }
+  assert(_objs_with_preserved_marks.size() ==
+            _preserved_marks_of_objs.size(), "Both or none.");
+  while (!_objs_with_preserved_marks.is_empty()) {
+    oop obj = _objs_with_preserved_marks.pop();
+    markOop m = _preserved_marks_of_objs.pop();
+    obj->set_mark(m);
+  }
+  _objs_with_preserved_marks.clear(true);
+  _preserved_marks_of_objs.clear(true);
 }
 
 void G1CollectedHeap::push_on_evac_failure_scan_stack(oop obj) {
@@ -4323,15 +4315,8 @@
   // We want to call the "for_promotion_failure" version only in the
   // case of a promotion failure.
   if (m->must_be_preserved_for_promotion_failure(obj)) {
-    if (_objs_with_preserved_marks == NULL) {
-      assert(_preserved_marks_of_objs == NULL, "Both or none.");
-      _objs_with_preserved_marks =
-        new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(40, true);
-      _preserved_marks_of_objs =
-        new (ResourceObj::C_HEAP, mtGC) GrowableArray<markOop>(40, true);
-    }
-    _objs_with_preserved_marks->push(obj);
-    _preserved_marks_of_objs->push(m);
+    _objs_with_preserved_marks.push(obj);
+    _preserved_marks_of_objs.push(m);
   }
 }
 
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -37,6 +37,7 @@
 #include "memory/barrierSet.hpp"
 #include "memory/memRegion.hpp"
 #include "memory/sharedHeap.hpp"
+#include "utilities/stack.hpp"
 
 // A "G1CollectedHeap" is an implementation of a java heap for HotSpot.
 // It uses the "Garbage First" heap organization and algorithm, which
@@ -883,10 +884,9 @@
   // forwarding pointers to themselves.  Reset them.
   void remove_self_forwarding_pointers();
 
-  // When one is non-null, so is the other.  Together, they each pair is
-  // an object with a preserved mark, and its mark value.
-  GrowableArray<oop>*     _objs_with_preserved_marks;
-  GrowableArray<markOop>* _preserved_marks_of_objs;
+  // Together, these store an object with a preserved mark, and its mark value.
+  Stack<oop, mtGC>     _objs_with_preserved_marks;
+  Stack<markOop, mtGC> _preserved_marks_of_objs;
 
   // Preserve the mark of "obj", if necessary, in preparation for its mark
   // word being overwritten with a self-forwarding-pointer.
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -267,7 +267,15 @@
   double max_gc_time = (double) MaxGCPauseMillis / 1000.0;
   double time_slice  = (double) GCPauseIntervalMillis / 1000.0;
   _mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
-  _sigma = (double) G1ConfidencePercent / 100.0;
+
+  uintx confidence_perc = G1ConfidencePercent;
+  // Put an artificial ceiling on this so that it's not set to a silly value.
+  if (confidence_perc > 100) {
+    confidence_perc = 100;
+    warning("G1ConfidencePercent is set to a value that is too large, "
+            "it's been updated to %u", confidence_perc);
+  }
+  _sigma = (double) confidence_perc / 100.0;
 
   // start conservatively (around 50ms is about right)
   _concurrent_mark_remark_times_ms->add(0.05);
--- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -28,8 +28,9 @@
 #include "memory/cardTableModRefBS.hpp"
 #include "memory/memRegion.hpp"
 #include "oops/oop.inline.hpp"
+#include "utilities/macros.hpp"
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
 class DirtyCardQueueSet;
 
@@ -120,6 +121,6 @@
 };
 
 
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP
--- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -32,7 +32,7 @@
 
 #define G1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw) \
                                                                             \
-  product(intx, G1ConfidencePercent, 50,                                    \
+  product(uintx, G1ConfidencePercent, 50,                                   \
           "Confidence level for MMU/pause predictions")                     \
                                                                             \
   develop(intx, G1MarkingOverheadPercent, 0,                                \
@@ -101,9 +101,6 @@
           "to-space, we will allow regions whose survival rate is up to "   \
           "S + (1 - S)*X, where X is this parameter (as a fraction.)")      \
                                                                             \
-  develop(intx, G1InitYoungSurvRatio, 50,                                   \
-          "Expected Survival Rate for newly allocated bytes")               \
-                                                                            \
   develop(bool, G1SATBPrintStubs, false,                                    \
           "If true, print generated stubs for the SATB barrier")            \
                                                                             \
--- a/src/share/vm/gc_implementation/g1/heapRegion.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -32,8 +32,9 @@
 #include "gc_implementation/shared/spaceDecorator.hpp"
 #include "memory/space.inline.hpp"
 #include "memory/watermark.hpp"
+#include "utilities/macros.hpp"
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
 // A HeapRegion is the smallest piece of a G1CollectedHeap that
 // can be collected independently.
@@ -837,6 +838,6 @@
   bool complete() { return _complete; }
 };
 
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP
--- a/src/share/vm/gc_implementation/shared/allocationStats.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/allocationStats.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -23,10 +23,11 @@
  */
 
 #include "precompiled.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/allocationStats.hpp"
 #include "utilities/ostream.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // Technically this should be derived from machine speed, and
 // ideally it would be dynamically adjusted.
--- a/src/share/vm/gc_implementation/shared/allocationStats.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/allocationStats.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,11 +25,12 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/gcUtil.hpp"
 #include "memory/allocation.hpp"
 #include "utilities/globalDefinitions.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 class AllocationStats VALUE_OBJ_CLASS_SPEC {
   // A duration threshold (in ms) used to filter
--- a/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,9 +25,10 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "runtime/thread.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 class VoidClosure;
 
--- a/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -23,11 +23,12 @@
  */
 
 #include "precompiled.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/gSpaceCounters.hpp"
 #include "memory/generation.hpp"
 #include "memory/resourceArea.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 GSpaceCounters::GSpaceCounters(const char* name, int ordinal, size_t max_size,
                                Generation* g, GenerationCounters* gc,
--- a/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,11 +25,12 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GSPACECOUNTERS_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GSPACECOUNTERS_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/generationCounters.hpp"
 #include "memory/generation.hpp"
 #include "runtime/perfData.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // A GSpaceCounter is a holder class for performance counters
 // that track a space;
--- a/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,10 +25,11 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCADAPTIVEPOLICYCOUNTERS_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCADAPTIVEPOLICYCOUNTERS_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/adaptiveSizePolicy.hpp"
 #include "gc_implementation/shared/gcPolicyCounters.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // This class keeps statistical information and computes the
 // size of the heap.
--- a/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,11 +25,12 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_HSPACECOUNTERS_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_HSPACECOUNTERS_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/generationCounters.hpp"
 #include "memory/generation.hpp"
 #include "runtime/perfData.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // A HSpaceCounter is a holder class for performance counters
 // that track a collections (logical spaces) in a heap;
--- a/src/share/vm/gc_implementation/shared/immutableSpace.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/immutableSpace.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -23,11 +23,12 @@
  */
 
 #include "precompiled.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/immutableSpace.hpp"
 #include "memory/universe.hpp"
 #include "oops/oop.inline.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 void ImmutableSpace::initialize(MemRegion mr) {
   HeapWord* bottom = mr.start();
--- a/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,9 +25,10 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_ISGCACTIVEMARK_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_ISGCACTIVEMARK_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // This class provides a method for block structured setting of the
 // _is_gc_active state without requiring accessors in CollectedHeap
--- a/src/share/vm/gc_implementation/shared/markSweep.inline.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/markSweep.inline.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -28,9 +28,10 @@
 #include "gc_implementation/shared/markSweep.hpp"
 #include "gc_interface/collectedHeap.hpp"
 #include "utilities/stack.inline.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 inline void MarkSweep::mark_object(oop obj) {
   // some marks may contain information we need to preserve so we store them away
--- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,10 +25,11 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_MUTABLENUMASPACE_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_MUTABLENUMASPACE_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/gcUtil.hpp"
 #include "gc_implementation/shared/mutableSpace.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 /*
  *    The NUMA-aware allocator (MutableNUMASpace) is basically a modification
--- a/src/share/vm/gc_implementation/shared/mutableSpace.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/mutableSpace.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -23,13 +23,14 @@
  */
 
 #include "precompiled.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/mutableSpace.hpp"
 #include "gc_implementation/shared/spaceDecorator.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/thread.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 MutableSpace::MutableSpace(size_t alignment): ImmutableSpace(), _top(NULL), _alignment(alignment) {
   assert(MutableSpace::alignment() >= 0 &&
--- a/src/share/vm/gc_implementation/shared/spaceCounters.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/spaceCounters.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -23,10 +23,11 @@
  */
 
 #include "precompiled.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/spaceCounters.hpp"
 #include "memory/resourceArea.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 SpaceCounters::SpaceCounters(const char* name, int ordinal, size_t max_size,
                              MutableSpace* m, GenerationCounters* gc) :
--- a/src/share/vm/gc_implementation/shared/spaceCounters.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/spaceCounters.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,12 +25,13 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_SPACECOUNTERS_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_SPACECOUNTERS_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/shared/generationCounters.hpp"
 #include "gc_implementation/shared/immutableSpace.hpp"
 #include "gc_implementation/shared/mutableSpace.hpp"
 #include "runtime/perfData.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // A SpaceCounter is a holder class for performance counters
 // that track a space;
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,9 +36,10 @@
 #include "runtime/interfaceSupport.hpp"
 #include "utilities/dtrace.hpp"
 #include "utilities/preserveException.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 #ifndef USDT2
 HS_DTRACE_PROBE_DECL1(hotspot, gc__begin, bool);
@@ -167,7 +168,9 @@
       ch->collect_as_vm_thread(GCCause::_heap_inspection);
     }
   }
-  HeapInspection::heap_inspection(_out, _need_prologue /* need_prologue */);
+  HeapInspection inspect(_csv_format, _print_help, _print_class_stats,
+                         _columns);
+  inspect.heap_inspection(_out, _need_prologue /* need_prologue */);
 }
 
 
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/vmGCOperations.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -130,6 +130,10 @@
   outputStream* _out;
   bool _full_gc;
   bool _need_prologue;
+  bool _csv_format; // "comma separated values" format for spreadsheet.
+  bool _print_help;
+  bool _print_class_stats;
+  const char* _columns;
  public:
   VM_GC_HeapInspection(outputStream* out, bool request_full_gc,
                        bool need_prologue) :
@@ -140,6 +144,10 @@
     _out = out;
     _full_gc = request_full_gc;
     _need_prologue = need_prologue;
+    _csv_format = false;
+    _print_help = false;
+    _print_class_stats = false;
+    _columns = NULL;
   }
 
   ~VM_GC_HeapInspection() {}
@@ -147,6 +155,10 @@
   virtual bool skip_operation() const;
   virtual bool doit_prologue();
   virtual void doit();
+  void set_csv_format(bool value) {_csv_format = value;}
+  void set_print_help(bool value) {_print_help = value;}
+  void set_print_class_stats(bool value) {_print_class_stats = value;}
+  void set_columns(const char* value) {_columns = value;}
 };
 
 
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -29,7 +29,6 @@
 #include "graal/graalCodeInstaller.hpp"
 #include "graal/graalJavaAccess.hpp"
 #include "graal/graalCompilerToVM.hpp"
-#include "graal/graalVmIds.hpp"
 #include "graal/graalRuntime.hpp"
 #include "asm/register.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -127,6 +126,10 @@
         assert((Klass*) prim == klass, err_msg("%s @ %p != %p", klass->name()->as_C_string(), klass, prim));
         int index = oop_recorder->find_index(klass);
         TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string());
+      } else if (obj->is_a(HotSpotResolvedJavaMethod::klass())) {
+        Method* method = (Method*) (address) HotSpotResolvedJavaMethod::metaspaceMethod(obj);
+        int index = oop_recorder->find_index(method);
+        TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->name()->as_C_string());
       } else {
         assert(java_lang_String::is_instance(obj),
             err_msg("unexpected annotation type (%s) for constant %ld (%p) of kind %c", obj->klass()->name()->as_C_string(), prim, prim, kind));
@@ -209,7 +212,7 @@
         return new ConstantOopWriteValue(JNIHandles::make_local(obj));
       }
     } else if (type == T_ADDRESS) {
-      return new ConstantLongValue(prim);
+      ShouldNotReachHere();
     }
     tty->print("%i", type);
   } else if (value->is_a(VirtualObject::klass())) {
@@ -323,7 +326,7 @@
 }
 
 // constructor used to create a method
-CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code) {
+CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code, Handle triggered_deoptimizations) {
   GraalCompiler::initialize_buffer_blob();
   CodeBuffer buffer(JavaThread::current()->get_buffer_blob());
   jobject comp_result_obj = JNIHandles::make_local(comp_result());
@@ -341,7 +344,7 @@
   GrowableArray<jlong>* leaf_graph_ids = get_leaf_graph_ids(comp_result);
 
   result = GraalEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
-    &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, leaf_graph_ids, installed_code);
+    GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, leaf_graph_ids, installed_code, triggered_deoptimizations);
 
   method->clear_queued_for_compilation();
 }
@@ -362,7 +365,7 @@
   const char* cname = java_lang_String::as_utf8_string(_name);
   blob = BufferBlob::create(strdup(cname), &buffer); // this is leaking strings... but only a limited number of stubs will be created
   IF_TRACE_graal_3 Disassembler::decode((CodeBlob*) blob);
-  id = VmIds::addStub(blob->code_begin());
+  id = (jlong)blob->code_begin();
 }
 
 void CodeInstaller::initialize_fields(oop comp_result, methodHandle method) {
@@ -383,7 +386,6 @@
 
   // (very) conservative estimate: each site needs a constant section entry
   _constants_size = _sites->length() * (BytesPerLong*2);
-  _total_size = align_size_up(_code_size, HeapWordSize) + _constants_size;
 
   _next_call_type = MARK_INVOKE_INVALID;
 }
@@ -572,13 +574,9 @@
   DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions);
   DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors);
 
-  GrowableArray<DeferredWriteValue*>* deferred_writes = new GrowableArray<DeferredWriteValue*> ();
-//  deferred_writes->append(new DeferredWriteValue(new LocationValue(Location::new_reg_loc(Location::lng, rax->as_VMReg())), new ConstantIntValue(0), 0, 100, new ConstantIntValue(123)));
-  DebugToken* deferred_writes_token = _debug_recorder->create_deferred_writes(deferred_writes);
-
   bool throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE;
 
-  _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token, deferred_writes_token);
+  _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token);
 }
 
 void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) {
@@ -606,7 +604,7 @@
   oop hotspot_method = NULL; // JavaMethod
   oop global_stub = NULL;
 
-  if (target_klass->is_subclass_of(SystemDictionary::Long_klass())) {
+  if (target_klass->is_subclass_of(SystemDictionary::HotSpotRuntimeCallTarget_klass())) {
     global_stub = target;
   } else {
     hotspot_method = target;
@@ -618,7 +616,6 @@
 
   NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
   jint next_pc_offset = 0x0;
-  bool is_call_reg = false;
   if (inst->is_call() || inst->is_jump()) {
     assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
     next_pc_offset = pc_offset + NativeCall::instruction_size;
@@ -631,10 +628,8 @@
   } else if (inst->is_call_reg()) {
     // the inlined vtable stub contains a "call register" instruction
     assert(hotspot_method != NULL, "only valid for virtual calls");
-    is_call_reg = true;
     next_pc_offset = pc_offset + ((NativeCallReg *) inst)->next_instruction_offset();
   } else {
-    tty->print_cr("at pc_offset %d", pc_offset);
     fatal("unsupported type of instruction for call site");
   }
 
@@ -659,21 +654,20 @@
   }
 
   if (global_stub != NULL) {
-    assert(java_lang_boxing_object::is_instance(global_stub, T_LONG), "global_stub needs to be of type Long");
-
+    jlong global_stub_destination = HotSpotRuntimeCallTarget::address(global_stub);
     if (inst->is_call()) {
       // NOTE: for call without a mov, the offset must fit a 32-bit immediate
       //       see also CompilerToVM.getMaxCallTargetOffset()
       NativeCall* call = nativeCall_at((address) (inst));
-      call->set_destination(VmIds::getStub(global_stub));
+      call->set_destination((address) global_stub_destination);
       _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
     } else if (inst->is_mov_literal64()) {
       NativeMovConstReg* mov = nativeMovConstReg_at((address) (inst));
-      mov->set_data((intptr_t) VmIds::getStub(global_stub));
+      mov->set_data((intptr_t) global_stub_destination);
       _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
     } else {
       NativeJump* jump = nativeJump_at((address) (inst));
-      jump->set_jump_destination(VmIds::getStub(global_stub));
+      jump->set_jump_destination((address) global_stub_destination);
       _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
     }
     TRACE_graal_3("relocating (stub)  at %p", inst);
@@ -690,9 +684,8 @@
 
     TRACE_graal_3("method call");
     switch (_next_call_type) {
-      case MARK_INLINE_INVOKEVIRTUAL: {
+      case MARK_INLINE_INVOKE:
         break;
-      }
       case MARK_INVOKEVIRTUAL:
       case MARK_INVOKEINTERFACE: {
         assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
@@ -712,13 +705,11 @@
       }
       case MARK_INVOKESPECIAL: {
         assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
-
         NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
         call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
         _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand);
         break;
       }
-      case MARK_INVOKE_INVALID:
       default:
         fatal("invalid _next_call_type value");
         break;
@@ -818,14 +809,6 @@
       case MARK_DEOPT_HANDLER_ENTRY:
         _offsets.set_value(CodeOffsets::Deopt, pc_offset);
         break;
-      case MARK_STATIC_CALL_STUB: {
-        _instructions->relocate(instruction, metadata_Relocation::spec_for_immediate());
-        assert(references->length() == 1, "static call stub needs one reference");
-        oop ref = ((oop*) references->base(T_OBJECT))[0];
-        address call_pc = _instructions->start() + CompilationResult_Site::pcOffset(ref);
-        _instructions->relocate(instruction, static_stub_Relocation::spec(call_pc));
-        break;
-      }
       case MARK_INVOKEVIRTUAL:
       case MARK_INVOKEINTERFACE: {
         // Convert the initial value of the Klass* slot in an inline cache
@@ -834,16 +817,12 @@
         assert(n_copy->data() == 0, "inline cache Klass* initial value should be 0L");
         n_copy->set_data((intptr_t)Universe::non_oop_word());
       }
-      case MARK_INLINE_INVOKEVIRTUAL:
-      case MARK_INVOKE_INVALID:
+      case MARK_INLINE_INVOKE:
+      case MARK_INVOKESTATIC:
       case MARK_INVOKESPECIAL:
-      case MARK_INVOKESTATIC:
         _next_call_type = (MarkId) id;
         _invoke_mark_pc = instruction;
         break;
-      case MARK_IMPLICIT_NULL:
-        _implicit_exception_table.append(pc_offset, pc_offset);
-        break;
       case MARK_POLL_NEAR: {
         NativeInstruction* ni = nativeInstruction_at(instruction);
         int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -31,24 +31,21 @@
 private:
   // these need to correspond to Marks.java
   enum MarkId {
-    MARK_VERIFIED_ENTRY             = 0x0001,
-    MARK_UNVERIFIED_ENTRY           = 0x0002,
-    MARK_OSR_ENTRY                  = 0x0003,
-  //MARK_UNWIND_ENTRY               = 0x0004,
-    MARK_EXCEPTION_HANDLER_ENTRY    = 0x0005,
-    MARK_DEOPT_HANDLER_ENTRY        = 0x0006,
-    MARK_STATIC_CALL_STUB           = 0x1000,
-    MARK_INVOKE_INVALID             = 0x2000,
-    MARK_INVOKEINTERFACE            = 0x2001,
-    MARK_INVOKESTATIC               = 0x2002,
-    MARK_INVOKESPECIAL              = 0x2003,
-    MARK_INVOKEVIRTUAL              = 0x2004,
-    MARK_INLINE_INVOKEVIRTUAL       = 0x2005,
-    MARK_IMPLICIT_NULL              = 0x3000,
-    MARK_POLL_NEAR                  = 0x3001,
-    MARK_POLL_RETURN_NEAR           = 0x3002,
-    MARK_POLL_FAR                   = 0x3003,
-    MARK_POLL_RETURN_FAR            = 0x3004
+    MARK_VERIFIED_ENTRY             = 1,
+    MARK_UNVERIFIED_ENTRY           = 2,
+    MARK_OSR_ENTRY                  = 3,
+    MARK_EXCEPTION_HANDLER_ENTRY    = 4,
+    MARK_DEOPT_HANDLER_ENTRY        = 5,
+    MARK_INVOKEINTERFACE            = 6,
+    MARK_INVOKEVIRTUAL              = 7,
+    MARK_INVOKESTATIC               = 8,
+    MARK_INVOKESPECIAL              = 9,
+    MARK_INLINE_INVOKE              = 10,
+    MARK_POLL_NEAR                  = 11,
+    MARK_POLL_RETURN_NEAR           = 12,
+    MARK_POLL_FAR                   = 13,
+    MARK_POLL_RETURN_FAR            = 14,
+    MARK_INVOKE_INVALID             = -1
   };
 
   Arena         _arena;
@@ -65,7 +62,6 @@
   jint          _custom_stack_area_offset;
   jint          _parameter_count;
   jint          _constants_size;
-  jint          _total_size;
 
   MarkId        _next_call_type;
   address       _invoke_mark_pc;
@@ -77,12 +73,11 @@
   DebugInformationRecorder* _debug_recorder;
   Dependencies*             _dependencies;
   ExceptionHandlerTable     _exception_handler_table;
-  ImplicitExceptionTable    _implicit_exception_table;
 
 public:
 
   // constructor used to create a method
-  CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code);
+  CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code, Handle triggered_deoptimizations);
 
   // constructor used to create a stub
   CodeInstaller(Handle& target_method, BufferBlob*& blob, jlong& id);
--- a/src/share/vm/graal/graalCompiler.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -28,7 +28,6 @@
 #include "graal/graalJavaAccess.hpp"
 #include "graal/graalVMToCompiler.hpp"
 #include "graal/graalCompilerToVM.hpp"
-#include "graal/graalVmIds.hpp"
 #include "graal/graalEnv.hpp"
 #include "graal/graalRuntime.hpp"
 #include "runtime/arguments.hpp"
@@ -160,11 +159,10 @@
 
   assert(_initialized, "must already be initialized");
   ResourceMark rm;
-  assert(JavaThread::current()->env() == NULL, "ciEnv should be null");
-  JavaThread::current()->set_compiling(true);
+  JavaThread::current()->set_is_compiling(true);
   Handle holder = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK);
   jboolean success = VMToCompiler::compileMethod(method(), holder, entry_bci, blocking, method->graal_priority());
-  JavaThread::current()->set_compiling(false);
+  JavaThread::current()->set_is_compiling(false);
   if (success != JNI_TRUE) {
     method->clear_queued_for_compilation();
     CompilationPolicy::policy()->delay_compilation(method());
@@ -188,7 +186,7 @@
 }
 
 Handle GraalCompiler::get_JavaType(Symbol* klass_name, TRAPS) {
-   return VMToCompiler::createUnresolvedJavaType(VmIds::toString<Handle>(klass_name, THREAD), THREAD);
+   return VMToCompiler::createUnresolvedJavaType(java_lang_String::create_from_symbol(klass_name, THREAD), THREAD);
 }
 
 Handle GraalCompiler::get_JavaTypeFromSignature(Symbol* signature, KlassHandle loading_klass, TRAPS) {
@@ -255,12 +253,12 @@
 }
 
 Handle GraalCompiler::get_JavaType(KlassHandle klass, TRAPS) {
-  Handle name = VmIds::toString<Handle>(klass->name(), THREAD);
+  Handle name = java_lang_String::create_from_symbol(klass->name(), THREAD);
   return createHotSpotResolvedObjectType(klass, name, CHECK_NULL);
 }
 
 Handle GraalCompiler::get_JavaField(int offset, int flags, Symbol* field_name, Handle field_holder, Handle field_type, TRAPS) {
-  Handle name = VmIds::toString<Handle>(field_name, CHECK_NULL);
+  Handle name = java_lang_String::create_from_symbol(field_name, CHECK_NULL);
   return VMToCompiler::createJavaField(field_holder, name, field_type, offset, flags, false, CHECK_NULL);
 }
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -37,7 +37,6 @@
 #include "graal/graalJavaAccess.hpp"
 #include "graal/graalCodeInstaller.hpp"
 #include "graal/graalVMToCompiler.hpp"
-#include "graal/graalVmIds.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
 
 
@@ -87,7 +86,7 @@
       memcpy(reconstituted_code, (jbyte *) method->code_base(), code_size);
     }
     BytecodeStream s(method);
-    while(!s.is_last_bytecode()) {
+    while (!s.is_last_bytecode()) {
       s.next();
       Bytecodes::Code opcode = s.raw_code();
       if (!Bytecodes::is_java_code(opcode)) {
@@ -121,7 +120,7 @@
 C2V_VMENTRY(jstring, getSignature, (JNIEnv *env, jobject, jlong metaspace_method))
   Method* method = asMethod(metaspace_method);
   assert(method != NULL && method->signature() != NULL, "signature required");
-  return VmIds::toString<jstring>(method->signature(), THREAD);
+  return (jstring)JNIHandles::make_local(java_lang_String::create_from_symbol(method->signature(), THREAD)());
 C2V_END
 
 C2V_VMENTRY(jobjectArray, initializeExceptionHandlers, (JNIEnv *, jobject, jlong metaspace_method, jobjectArray java_handlers))
@@ -272,7 +271,7 @@
 
 C2V_VMENTRY(void, initializeMethod,(JNIEnv *, jobject, jlong metaspace_method, jobject hotspot_method))
   methodHandle method = asMethod(metaspace_method);
-  Handle name = VmIds::toString<Handle>(method->name(), CHECK);
+  Handle name = java_lang_String::create_from_symbol(method->name(), CHECK);
   InstanceKlass::cast(HotSpotResolvedJavaMethod::klass())->initialize(CHECK);
   HotSpotResolvedJavaMethod::set_name(hotspot_method, name());
   HotSpotResolvedJavaMethod::set_codeSize(hotspot_method, method->code_size());
@@ -324,8 +323,8 @@
 C2V_VMENTRY(jobject, lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve))
   ResourceMark rm;
 
-  Symbol* nameSymbol = VmIds::toSymbol(jname);
   Handle name = JNIHandles::resolve(jname);
+  Symbol* nameSymbol = java_lang_String::as_symbol(name, THREAD);
   assert(nameSymbol != NULL, "name to symbol creation failed");
 
   oop result = NULL;
@@ -409,10 +408,6 @@
   } else if (tag.is_klass() || tag.is_unresolved_klass()) {
     Handle type = GraalCompiler::get_JavaType(cp, index, cp->pool_holder(), CHECK_NULL);
     result = type();
-  } else if (tag.is_object()) {
-    oop obj = cp->object_at(index);
-    assert(obj->is_instance(), "must be an instance");
-    result = VMToCompiler::createConstantObject(obj, CHECK_NULL);
   } else {
     tty->print("unknown constant pool tag (%s) at cpi %d in %s: ", tag.internal_name(), index, cp->pool_holder()->name()->as_C_string());
     ShouldNotReachHere();
@@ -433,8 +428,8 @@
     return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD));
   } else {
     // Get the method's name and signature.
-    Handle name = VmIds::toString<Handle>(cp->name_ref_at(index), CHECK_NULL);
-    Handle signature  = VmIds::toString<Handle>(cp->signature_ref_at(index), CHECK_NULL);
+    Handle name = java_lang_String::create_from_symbol(cp->name_ref_at(index), CHECK_NULL);
+    Handle signature  = java_lang_String::create_from_symbol(cp->signature_ref_at(index), CHECK_NULL);
     int holder_index = cp->klass_ref_index_at(index);
     Handle type = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL);
     return JNIHandles::make_local(THREAD, VMToCompiler::createUnresolvedJavaMethod(name, signature, type, THREAD));
@@ -515,8 +510,8 @@
 
   assert(JNIHandles::resolve(resolved_type) != NULL, "");
   Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(resolved_type));
-  Symbol* name_symbol = VmIds::toSymbol(name);
-  Symbol* signature_symbol = VmIds::toSymbol(signature);
+  Symbol* name_symbol = java_lang_String::as_symbol(JNIHandles::resolve(name), THREAD);
+  Symbol* signature_symbol = java_lang_String::as_symbol(JNIHandles::resolve(signature), THREAD);
   methodHandle method = klass->lookup_method(name_symbol, signature_symbol);
   if (method.is_null()) {
     if (TraceGraal >= 3) {
@@ -552,7 +547,7 @@
       Handle type = GraalCompiler::get_JavaTypeFromSignature(fs.signature(), k, Thread::current());
       int flags = fs.access_flags().as_int();
       bool internal = fs.access_flags().is_internal();
-      Handle name = VmIds::toString<Handle>(fs.name(), Thread::current());
+      Handle name = java_lang_String::create_from_symbol(fs.name(), Thread::current());
       Handle field = VMToCompiler::createJavaField(JNIHandles::resolve(klass), name, type, fs.offset(), flags, internal, Thread::current());
       fields.append(field());
     }
@@ -599,6 +594,7 @@
 #define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0)
 #define set_int(name, value) do { env->SetIntField(config, getFieldID(env, config, name, "I"), value); } while (0)
 #define set_long(name, value) do { env->SetLongField(config, getFieldID(env, config, name, "J"), value); } while (0)
+#define set_stub(name, value) do { set_long(name, (jlong) value); } while (0)
 #define set_object(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "Ljava/lang/Object;"), value); } while (0)
 #define set_int_array(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "[I"), value); } while (0)
 
@@ -617,7 +613,6 @@
   set_boolean("useTLAB", UseTLAB);
   set_boolean("useG1GC", UseG1GC);
   set_int("codeEntryAlignment", CodeEntryAlignment);
-  set_int("vmPageSize", os::vm_page_size());
   set_int("stackShadowPages", StackShadowPages);
   set_int("hubOffset", oopDesc::klass_offset_in_bytes());
   set_int("markOffset", oopDesc::mark_offset_in_bytes());
@@ -669,6 +664,9 @@
   assert((Klass::_lh_array_tag_obj_value & Klass::_lh_array_tag_type_value & 0x80000000) != 0, "obj_array and type_array must have first bit set");
   set_int("arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset()));
   
+
+  set_int("pendingDeoptimizationOffset", in_bytes(ThreadShadow::pending_deoptimization_offset()));
+
   set_int("metaspaceArrayLengthOffset", Array<Klass*>::length_offset_in_bytes());
   set_int("metaspaceArrayBaseOffset", Array<Klass*>::base_offset_in_bytes());
   set_int("methodDataOopDataOffset", in_bytes(MethodData::data_offset()));
@@ -709,44 +707,42 @@
   set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask);
   set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset()));
 
-  set_long("debugStub", VmIds::addStub((address)warning));
-  set_long("instanceofStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_slow_subtype_check_id)));
-  set_long("newInstanceStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_instance_id)));
-  set_long("newArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_array_id)));
-  set_long("newMultiArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_multi_array_id)));
-  set_long("identityHashCodeStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_identity_hash_code_id)));
-  set_long("threadIsInterruptedStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_thread_is_interrupted_id)));
-  set_long("inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub()));
-  set_long("handleExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_handle_exception_nofpu_id)));
-  set_long("handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack()));
-  set_long("monitorEnterStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorenter_id)));
-  set_long("monitorExitStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorexit_id)));
-  set_long("wbPreCallStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_wb_pre_call_id)));
-  set_long("wbPostCallStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_wb_post_call_id)));
+
+  set_stub("wbPreCallStub", GraalRuntime::entry_for(GraalRuntime::wb_pre_call_id));
+  set_stub("wbPostCallStub", GraalRuntime::entry_for(GraalRuntime::wb_post_call_id));
 
-  set_long("verifyOopStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_verify_oop_id)));
-  set_long("vmErrorStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_vm_error_id)));
-  set_long("deoptimizeStub", VmIds::addStub(SharedRuntime::deopt_blob()->uncommon_trap()));
-  set_long("unwindExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_unwind_exception_call_id)));
-  set_long("osrMigrationEndStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_OSR_migration_end_id)));
-  set_long("registerFinalizerStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_register_finalizer_id)));
-  set_long("setDeoptInfoStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_set_deopt_info_id)));
-  set_long("createNullPointerExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_null_pointer_exception_id)));
-  set_long("createOutOfBoundsExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_out_of_bounds_exception_id)));
-  set_long("javaTimeMillisStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeMillis)));
-  set_long("javaTimeNanosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeNanos)));
-  set_long("arithmeticFremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_frem_id)));
-  set_long("arithmeticDremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_drem_id)));
-  set_long("arithmeticSinStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dsin)));
-  set_long("arithmeticCosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dcos)));
-  set_long("arithmeticTanStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dtan)));
-  set_long("logPrimitiveStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_primitive_id)));
-  set_long("logObjectStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_object_id)));
-  set_long("logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id)));
-  set_long("aescryptEncryptBlockStub", VmIds::addStub(StubRoutines::aescrypt_encryptBlock()));
-  set_long("aescryptDecryptBlockStub", VmIds::addStub(StubRoutines::aescrypt_decryptBlock()));
-  set_long("cipherBlockChainingEncryptAESCryptStub", VmIds::addStub(StubRoutines::cipherBlockChaining_encryptAESCrypt()));
-  set_long("cipherBlockChainingDecryptAESCryptStub", VmIds::addStub(StubRoutines::cipherBlockChaining_decryptAESCrypt()));
+  set_stub("newInstanceStub", GraalRuntime::entry_for(GraalRuntime::new_instance_id));
+  set_stub("newArrayStub", GraalRuntime::entry_for(GraalRuntime::new_array_id));
+  set_stub("newMultiArrayStub", GraalRuntime::entry_for(GraalRuntime::new_multi_array_id));
+  set_stub("identityHashCodeStub", GraalRuntime::entry_for(GraalRuntime::identity_hash_code_id));
+  set_stub("threadIsInterruptedStub", GraalRuntime::entry_for(GraalRuntime::thread_is_interrupted_id));
+  set_stub("inlineCacheMissStub", SharedRuntime::get_ic_miss_stub());
+  set_stub("handleExceptionStub", GraalRuntime::entry_for(GraalRuntime::handle_exception_nofpu_id));
+  set_stub("handleDeoptStub", SharedRuntime::deopt_blob()->unpack());
+  set_stub("monitorEnterStub", GraalRuntime::entry_for(GraalRuntime::monitorenter_id));
+  set_stub("monitorExitStub", GraalRuntime::entry_for(GraalRuntime::monitorexit_id));
+  set_stub("verifyOopStub", GraalRuntime::entry_for(GraalRuntime::verify_oop_id));
+  set_stub("vmErrorStub", GraalRuntime::entry_for(GraalRuntime::vm_error_id));
+  set_stub("deoptimizeStub", SharedRuntime::deopt_blob()->uncommon_trap());
+  set_stub("unwindExceptionStub", GraalRuntime::entry_for(GraalRuntime::unwind_exception_call_id));
+  set_stub("osrMigrationEndStub", GraalRuntime::entry_for(GraalRuntime::OSR_migration_end_id));
+  set_stub("registerFinalizerStub", GraalRuntime::entry_for(GraalRuntime::register_finalizer_id));
+  set_stub("createNullPointerExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_null_pointer_exception_id));
+  set_stub("createOutOfBoundsExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_out_of_bounds_exception_id));
+  set_stub("javaTimeMillisStub", CAST_FROM_FN_PTR(address, os::javaTimeMillis));
+  set_stub("javaTimeNanosStub", CAST_FROM_FN_PTR(address, os::javaTimeNanos));
+  set_stub("arithmeticFremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_frem_id));
+  set_stub("arithmeticDremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_drem_id));
+  set_stub("arithmeticSinStub", CAST_FROM_FN_PTR(address, SharedRuntime::dsin));
+  set_stub("arithmeticCosStub", CAST_FROM_FN_PTR(address, SharedRuntime::dcos));
+  set_stub("arithmeticTanStub", CAST_FROM_FN_PTR(address, SharedRuntime::dtan));
+  set_stub("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::log_primitive_id));
+  set_stub("logObjectStub", GraalRuntime::entry_for(GraalRuntime::log_object_id));
+  set_stub("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::log_printf_id));
+  set_stub("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock());
+  set_stub("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock());
+  set_stub("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt());
+  set_stub("cipherBlockChainingDecryptAESCryptStub", StubRoutines::cipherBlockChaining_decryptAESCrypt());
 
   set_int("deoptReasonNone", Deoptimization::Reason_none);
   set_int("deoptReasonNullCheck", Deoptimization::Reason_null_check);
@@ -807,49 +803,43 @@
 
 C2V_END
 
-C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compResult, jobject installed_code, jobject info))
+C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compResult, jobject installed_code, jobject triggered_deoptimizations))
   ResourceMark rm;
   HandleMark hm;
   Handle compResultHandle = JNIHandles::resolve(compResult);
   nmethod* nm = NULL;
   methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(compResult));
   Handle installed_code_handle = JNIHandles::resolve(installed_code);
+  Handle triggered_deoptimizations_handle = JNIHandles::resolve(triggered_deoptimizations);
   GraalEnv::CodeInstallResult result;
-  CodeInstaller installer(compResultHandle, method, result, nm, installed_code_handle);
+  CodeInstaller installer(compResultHandle, method, result, nm, installed_code_handle, triggered_deoptimizations_handle);
 
   if (result != GraalEnv::ok) {
     assert(nm == NULL, "should be");
   } else {
-    if (info != NULL) {
-      arrayOop codeCopy = oopFactory::new_byteArray(nm->code_size(), CHECK_0);
-      memcpy(codeCopy->base(T_BYTE), nm->code_begin(), nm->code_size());
-      HotSpotCodeInfo::set_code(info, codeCopy);
-      HotSpotCodeInfo::set_start(info, (jlong) nm->code_begin());
-    }
-
     if (!installed_code_handle.is_null()) {
       assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type");
       HotSpotInstalledCode::set_nmethod(installed_code_handle, (jlong) nm);
       HotSpotInstalledCode::set_method(installed_code_handle, HotSpotCompilationResult::method(compResult));
+      HotSpotInstalledCode::set_start(installed_code_handle, (jlong) nm->code_begin());
       assert(nm == NULL || !installed_code_handle->is_scavengable() || nm->on_scavenge_root_list(), "nm should be scavengable if installed_code is scavengable");
     }
   }
   return result;
 C2V_END
 
-C2V_VMENTRY(jobject, disassembleNative, (JNIEnv *jniEnv, jobject, jbyteArray code, jlong start_address))
+C2V_VMENTRY(jobject, getCode, (JNIEnv *jniEnv, jobject,  jlong metaspace_nmethod))
   ResourceMark rm;
   HandleMark hm;
 
-  stringStream(st);
-  arrayOop code_oop = (arrayOop) JNIHandles::resolve(code);
-  int len = code_oop->length();
-  address begin = (address) code_oop->base(T_BYTE);
-  address end = begin + len;
-  Disassembler::decode(begin, end, &st);
-
-  Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL);
-  return JNIHandles::make_local(result());
+  nmethod* nm = (nmethod*) (address) metaspace_nmethod;
+  if (nm == NULL || !nm->is_alive()) {
+    return NULL;
+  }
+  int length = nm->code_size();
+  arrayOop codeCopy = oopFactory::new_byteArray(length, CHECK_0);
+  memcpy(codeCopy->base(T_BYTE), nm->code_begin(), length);
+  return JNIHandles::make_local(codeCopy);
 C2V_END
 
 C2V_VMENTRY(jobject, disassembleNMethod, (JNIEnv *jniEnv, jobject, jlong metaspace_nmethod))
@@ -893,7 +883,8 @@
     THROW_0(vmSymbols::MethodInvalidatedException());
   }
 
-  JavaCalls::call(&result, mh, nm, &jca, CHECK_NULL);
+  jca.set_alternative_target(nm);
+  JavaCalls::call(&result, mh, &jca, CHECK_NULL);
 
   if (jap.get_ret_type() == T_VOID) {
     return NULL;
@@ -922,7 +913,8 @@
     THROW_0(vmSymbols::MethodInvalidatedException());
   }
 
-  JavaCalls::call(&result, method, nm, &args, CHECK_NULL);
+  args.set_alternative_target(nm);
+  JavaCalls::call(&result, method, &args, CHECK_NULL);
 
   return JNIHandles::make_local((oop) result.get_jobject());
 C2V_END
@@ -952,30 +944,9 @@
   return JNIHandles::make_local(array);
 C2V_END
 
-C2V_VMENTRY(jobject, decodePC, (JNIEnv *, jobject, jlong pc))
-  stringStream(st);
-  CodeBlob* blob = CodeCache::find_blob_unsafe((void*) pc);
-  if (blob == NULL) {
-    st.print("[unidentified pc]");
-  } else {
-    st.print(blob->name());
-
-    nmethod* nm = blob->as_nmethod_or_null();
-    if (nm != NULL && nm->method() != NULL) {
-      st.print(" %s.", nm->method()->method_holder()->external_name());
-      nm->method()->name()->print_symbol_on(&st);
-      st.print("  @ %d", pc - (jlong) nm->entry_point());
-    }
-  }
-  Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL);
-  return JNIHandles::make_local(result());
-C2V_END
-
 C2V_ENTRY(jlongArray, getLineNumberTable, (JNIEnv *env, jobject, jobject hotspot_method))
-// XXX: Attention: it seEms that the line number table of a method just contains lines that are important, means that
-// empty lines are left out or lines that can't have a breakpoint on it; eg int a; or try {
   Method* method = getMethodFromHotSpotMethod(JNIHandles::resolve(hotspot_method));
-  if(!method->has_linenumber_table()) {
+  if (!method->has_linenumber_table()) {
     return NULL;
   }
   u2 num_entries = 0;
@@ -1004,7 +975,7 @@
   ResourceMark rm;
 
   Method* method = getMethodFromHotSpotMethod(JNIHandles::resolve(hotspot_method));
-  if(!method->has_localvariable_table()) {
+  if (!method->has_localvariable_table()) {
     return NULL;
   }
   int localvariable_table_length = method->localvariable_table_length();
@@ -1074,7 +1045,6 @@
 #define HS_CONFIG             "Lcom/oracle/graal/hotspot/HotSpotVMConfig;"
 #define HS_METHOD             "Lcom/oracle/graal/hotspot/meta/HotSpotMethod;"
 #define HS_INSTALLED_CODE     "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;"
-#define HS_CODE_INFO          "Lcom/oracle/graal/hotspot/meta/HotSpotCodeInfo;"
 #define METHOD_DATA           "Lcom/oracle/graal/hotspot/meta/HotSpotMethodData;"
 #define METASPACE_METHOD      "J"
 #define METASPACE_METHOD_DATA "J"
@@ -1110,13 +1080,12 @@
   {CC"getMetaspaceConstructor",       CC"("REFLECT_CONSTRUCTOR"["HS_RESOLVED_TYPE")"METASPACE_METHOD,   FN_PTR(getMetaspaceConstructor)},
   {CC"getJavaField",                  CC"("REFLECT_FIELD")"HS_RESOLVED_FIELD,                           FN_PTR(getJavaField)},
   {CC"initializeConfiguration",       CC"("HS_CONFIG")V",                                               FN_PTR(initializeConfiguration)},
-  {CC"installCode0",                  CC"("HS_COMP_RESULT HS_INSTALLED_CODE HS_CODE_INFO")I",           FN_PTR(installCode0)},
-  {CC"disassembleNative",             CC"([BJ)"STRING,                                                  FN_PTR(disassembleNative)},
+  {CC"installCode0",                  CC"("HS_COMP_RESULT HS_INSTALLED_CODE"[Z)I",                      FN_PTR(installCode0)},
+  {CC"getCode",                       CC"(J)[B",                                                        FN_PTR(getCode)},
   {CC"disassembleNMethod",            CC"(J)"STRING,                                                    FN_PTR(disassembleNMethod)},
   {CC"executeCompiledMethod",         CC"("METASPACE_METHOD NMETHOD OBJECT OBJECT OBJECT")"OBJECT,      FN_PTR(executeCompiledMethod)},
   {CC"executeCompiledMethodVarargs",  CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT,                 FN_PTR(executeCompiledMethodVarargs)},
   {CC"getDeoptedLeafGraphIds",        CC"()[J",                                                         FN_PTR(getDeoptedLeafGraphIds)},
-  {CC"decodePC",                      CC"(J)"STRING,                                                    FN_PTR(decodePC)},
   {CC"getLineNumberTable",            CC"("HS_RESOLVED_METHOD")[J",                                     FN_PTR(getLineNumberTable)},
   {CC"getLocalVariableTable",         CC"("HS_RESOLVED_METHOD")["LOCAL,                                 FN_PTR(getLocalVariableTable)},
   {CC"getFileName",                   CC"("HS_RESOLVED_JAVA_TYPE")"STRING,                              FN_PTR(getFileName)},
--- a/src/share/vm/graal/graalEnv.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/graal/graalEnv.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -43,6 +43,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/dtrace.hpp"
 #include "graal/graalRuntime.hpp"
+#include "graal/graalJavaAccess.hpp"
 
 // ------------------------------------------------------------------
 // Note: the logic of this method should mirror the logic of
@@ -410,7 +411,6 @@
                                 int frame_words,
                                 OopMapSet* oop_map_set,
                                 ExceptionHandlerTable* handler_table,
-                                ImplicitExceptionTable* inc_table,
                                 AbstractCompiler* compiler,
                                 DebugInformationRecorder* debug_info,
                                 Dependencies* dependencies,
@@ -419,7 +419,8 @@
                                 bool has_debug_info,
                                 bool has_unsafe_access,
                                 GrowableArray<jlong>* leaf_graph_ids,
-                                Handle installed_code) {
+                                Handle installed_code,
+                                Handle triggered_deoptimizations) {
   GRAAL_EXCEPTION_CONTEXT;
   NMethodSweeper::possibly_sweep();
   nm = NULL;
@@ -455,7 +456,7 @@
       //code_buffer->free_blob();
       return GraalEnv::dependencies_failed;
     }
-
+    ImplicitExceptionTable implicit_tbl;
     nm =  nmethod::new_nmethod(method,
                                compile_id,
                                entry_bci,
@@ -463,8 +464,8 @@
                                orig_pc_offset,
                                debug_info, dependencies, code_buffer,
                                frame_words, oop_map_set,
-                               handler_table, inc_table,
-                               compiler, comp_level, leaf_graph_ids, installed_code);
+                               handler_table, &implicit_tbl,
+                               compiler, comp_level, leaf_graph_ids, installed_code, triggered_deoptimizations);
 
     // Free codeBlobs
     //code_buffer->free_blob();
@@ -493,7 +494,7 @@
       // (Put nm into the task handle *before* publishing to the Java heap.)
       if (task != NULL)  task->set_code(nm);
 
-      if (installed_code.is_null()) {
+      if (HotSpotInstalledCode::isDefault(installed_code())) {
         if (entry_bci == InvocationEntryBci) {
           if (TieredCompilation) {
             // If there is an old version we're done with it
--- a/src/share/vm/graal/graalEnv.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/graal/graalEnv.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -138,7 +138,6 @@
                        int                       frame_words,
                        OopMapSet*                oop_map_set,
                        ExceptionHandlerTable*    handler_table,
-                       ImplicitExceptionTable*   inc_table,
                        AbstractCompiler*         compiler,
                        DebugInformationRecorder* debug_info,
                        Dependencies*             dependencies,
@@ -147,7 +146,8 @@
                        bool                      has_debug_info,
                        bool                      has_unsafe_access,
                        GrowableArray<jlong>*     leaf_graph_ids,
-                       Handle                    installed_code);
+                       Handle                    installed_code,
+                       Handle                    triggered_deoptimizations);
 
   // converts the Klass* representing the holder of a method into a
   // InstanceKlass*.  This is needed since the holder of a method in
--- a/src/share/vm/graal/graalGlobals.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/graal/graalGlobals.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -52,9 +52,6 @@
   product(bool, BootstrapGraal, GRAALVM_ONLY(true) NOT_GRAALVM(false),      \
           "Bootstrap Graal before running Java main method")                \
                                                                             \
-  product(ccstr, GraalClassPath, NULL,                                      \
-          "Use this path, zip, or jar, to locate Graal-specific classes")   \
-                                                                            \
   product(intx, TraceGraal, 0,                                              \
           "Trace level for Graal")                                          \
                                                                             \
--- a/src/share/vm/graal/graalJavaAccess.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -75,10 +75,8 @@
   start_class(HotSpotInstalledCode)                                                                                                                            \
     long_field(HotSpotInstalledCode, nmethod)                                                                                                                  \
     oop_field(HotSpotInstalledCode, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;")                                                       \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCodeInfo)                                                                                                                                 \
-    long_field(HotSpotCodeInfo, start)                                                                                                                         \
-    oop_field(HotSpotCodeInfo, code, "[B")                                                                                                                     \
+    long_field(HotSpotInstalledCode, start)                                                                                                                    \
+    boolean_field(HotSpotInstalledCode, isDefault)                                                                                                             \
   end_class                                                                                                                                                    \
   start_class(HotSpotCompilationResult)                                                                                                                        \
     oop_field(HotSpotCompilationResult, comp, "Lcom/oracle/graal/api/code/CompilationResult;")                                                                 \
@@ -88,6 +86,9 @@
     oop_field(HotSpotCompilationResult, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;")                                                          \
     oop_field(HotSpotCompilationResult, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;")                                  \
   end_class                                                                                                                                                    \
+  start_class(HotSpotRuntimeCallTarget)                                                                                                                        \
+    long_field(HotSpotRuntimeCallTarget, address)                                                                                                              \
+  end_class                                                                                                                                                    \
   start_class(ExceptionHandler)                                                                                                                                \
     int_field(ExceptionHandler, startBCI)                                                                                                                      \
     int_field(ExceptionHandler, endBCI)                                                                                                                        \
@@ -122,7 +123,7 @@
     int_field(CompilationResult_Site, pcOffset)                                                                                                                \
   end_class                                                                                                                                                    \
   start_class(CompilationResult_Call)                                                                                                                          \
-    oop_field(CompilationResult_Call, target, "Ljava/lang/Object;")                                                                                            \
+    oop_field(CompilationResult_Call, target, "Lcom/oracle/graal/api/meta/InvokeTarget;")                                                                                            \
     oop_field(CompilationResult_Call, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;")                                                                      \
   end_class                                                                                                                                                    \
   start_class(CompilationResult_DataPatch)                                                                                                                     \
--- a/src/share/vm/graal/graalRuntime.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/graal/graalRuntime.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -127,18 +127,15 @@
   // Make sure that stubs that need oopmaps have them
   switch (id) {
     // These stubs don't need to have an oopmap
-    case graal_slow_subtype_check_id:
 #if defined(SPARC) || defined(PPC)
-    case graal_handle_exception_nofpu_id:  // Unused on sparc
+    case handle_exception_nofpu_id:  // Unused on sparc
 #endif
-    case graal_verify_oop_id:
-    case graal_unwind_exception_call_id:
-    case graal_OSR_migration_end_id:
-    case graal_arithmetic_frem_id:
-    case graal_arithmetic_drem_id:
-    case graal_set_deopt_info_id:
-    break;
-
+    case verify_oop_id:
+    case unwind_exception_call_id:
+    case OSR_migration_end_id:
+    case arithmetic_frem_id:
+    case arithmetic_drem_id:
+      break;
     // All other stubs should have oopmaps
     default:
       assert(oop_maps != NULL, "must have an oopmap");
@@ -443,17 +440,17 @@
   return continuation;
 }
 
-JRT_ENTRY(void, GraalRuntime::graal_create_null_exception(JavaThread* thread))
+JRT_ENTRY(void, GraalRuntime::create_null_exception(JavaThread* thread))
   thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL)());
 JRT_END
 
-JRT_ENTRY(void, GraalRuntime::graal_create_out_of_bounds_exception(JavaThread* thread, jint index))
+JRT_ENTRY(void, GraalRuntime::create_out_of_bounds_exception(JavaThread* thread, jint index))
   char message[jintAsStringSize];
   sprintf(message, "%d", index);
   thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message)());
 JRT_END
 
-JRT_ENTRY_NO_ASYNC(void, GraalRuntime::graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock))
+JRT_ENTRY_NO_ASYNC(void, GraalRuntime::monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock))
   if (TraceGraal >= 3) {
     char type[O_BUFLEN];
     obj->klass()->name()->as_C_string(type, O_BUFLEN);
@@ -484,15 +481,15 @@
   }
 JRT_END
 
-JRT_LEAF(void, GraalRuntime::graal_wb_pre_call(JavaThread* thread, oopDesc* obj))
+JRT_LEAF(void, GraalRuntime::wb_pre_call(JavaThread* thread, oopDesc* obj))
     thread->satb_mark_queue().enqueue(obj);
 JRT_END
 
-JRT_LEAF(void, GraalRuntime::graal_wb_post_call(JavaThread* thread, oopDesc* obj, void* card_addr))
+JRT_LEAF(void, GraalRuntime::wb_post_call(JavaThread* thread, oopDesc* obj, void* card_addr))
     thread->dirty_card_queue().enqueue(card_addr);
 JRT_END
 
-JRT_LEAF(void, GraalRuntime::graal_monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock))
+JRT_LEAF(void, GraalRuntime::monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock))
   assert(thread == JavaThread::current(), "threads must correspond");
   assert(thread->last_Java_sp(), "last_Java_sp must be set");
   // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown
@@ -524,7 +521,7 @@
   }
 JRT_END
 
-JRT_ENTRY(void, GraalRuntime::graal_log_object(JavaThread* thread, oop obj, jint flags))
+JRT_ENTRY(void, GraalRuntime::log_object(JavaThread* thread, oop obj, jint flags))
   bool string =  mask_bits_are_true(flags, LOG_OBJECT_STRING);
   bool address = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS);
   bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE);
@@ -546,7 +543,7 @@
   }
 JRT_END
 
-JRT_ENTRY(void, GraalRuntime::graal_vm_error(JavaThread* thread, oop where, oop format, jlong value))
+JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oop where, oop format, jlong value))
   ResourceMark rm;
   assert(where == NULL || java_lang_String::is_instance(where), "must be");
   const char *error_msg = where == NULL ? "<internal Graal error>" : java_lang_String::as_utf8_string(where);
@@ -560,14 +557,15 @@
   report_vm_error(__FILE__, __LINE__, error_msg, detail_msg);
 JRT_END
 
-JRT_LEAF(void, GraalRuntime::graal_log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3))
+
+JRT_LEAF(void, GraalRuntime::log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3))
   ResourceMark rm;
   assert(format != NULL && java_lang_String::is_instance(format), "must be");
   char *buf = java_lang_String::as_utf8_string(format);
   tty->print(buf, v1, v2, v3);
 JRT_END
 
-JRT_ENTRY(void, GraalRuntime::graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))
+JRT_ENTRY(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))
   union {
       jlong l;
       jdouble d;
@@ -590,11 +588,11 @@
   }
 JRT_END
 
-JRT_ENTRY(jint, GraalRuntime::graal_identity_hash_code(JavaThread* thread, oop obj))
+JRT_ENTRY(jint, GraalRuntime::identity_hash_code(JavaThread* thread, oop obj))
   return (jint) obj->identity_hash();
 JRT_END
 
-JRT_ENTRY(jboolean, GraalRuntime::graal_thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted))
+JRT_ENTRY(jboolean, GraalRuntime::thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted))
   // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
   Handle receiverHandle(thread, receiver);
   MutexLockerEx ml(thread->threadObj() == receiver ? NULL : Threads_lock);
--- a/src/share/vm/graal/graalRuntime.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/graal/graalRuntime.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -81,31 +81,29 @@
 // runtime routines needed by code code generated
 // by Graal.
 #define GRAAL_STUBS(stub, last_entry) \
-  stub(graal_register_finalizer)      \
-  stub(graal_new_instance)            \
-  stub(graal_new_array)               \
-  stub(graal_new_multi_array)         \
-  stub(graal_handle_exception_nofpu) /* optimized version that does not preserve fpu registers */ \
-  stub(graal_slow_subtype_check)      \
-  stub(graal_unwind_exception_call)   \
-  stub(graal_OSR_migration_end)       \
-  stub(graal_arithmetic_frem)         \
-  stub(graal_arithmetic_drem)         \
-  stub(graal_monitorenter)            \
-  stub(graal_monitorexit)             \
-  stub(graal_verify_oop)              \
-  stub(graal_vm_error)                \
-  stub(graal_set_deopt_info)          \
-  stub(graal_create_null_pointer_exception) \
-  stub(graal_create_out_of_bounds_exception) \
-  stub(graal_log_object)              \
-  stub(graal_log_printf)              \
-  stub(graal_log_primitive)           \
-  stub(graal_identity_hash_code)      \
-  stub(graal_thread_is_interrupted)   \
-  stub(graal_wb_pre_call)             \
-  stub(graal_wb_post_call)             \
-  last_entry(number_of_ids)
+  stub(register_finalizer)      \
+  stub(new_instance)            \
+  stub(new_array)               \
+  stub(new_multi_array)         \
+  stub(handle_exception_nofpu) /* optimized version that does not preserve fpu registers */ \
+  stub(unwind_exception_call)   \
+  stub(OSR_migration_end)       \
+  stub(arithmetic_frem)         \
+  stub(arithmetic_drem)         \
+  stub(monitorenter)            \
+  stub(monitorexit)             \
+  stub(verify_oop)              \
+  stub(vm_error)                \
+  stub(create_null_pointer_exception) \
+  stub(create_out_of_bounds_exception) \
+  stub(log_object)              \
+  stub(log_printf)              \
+  stub(log_primitive)           \
+  stub(identity_hash_code)      \
+  stub(thread_is_interrupted)   \
+  stub(wb_pre_call)             \
+  stub(wb_post_call)             \
+ last_entry(number_of_ids)
 
 #define DECLARE_STUB_ID(x)       x ## _id ,
 #define DECLARE_LAST_STUB_ID(x)  x
@@ -142,19 +140,18 @@
 
   static address exception_handler_for_pc(JavaThread* thread);
 
-  static void graal_verify_oop(JavaThread* thread, oopDesc* obj);
-  static void graal_wb_pre_call(JavaThread* thread, oopDesc* obj);
-  static void graal_wb_post_call(JavaThread* thread, oopDesc* obj,void* obj);
-  static void graal_create_null_exception(JavaThread* thread);
-  static void graal_create_out_of_bounds_exception(JavaThread* thread, jint index);
-  static void graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock);
-  static void graal_monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
-  static void graal_vm_error(JavaThread* thread, oop where, oop format, jlong value);
-  static void graal_log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3);
-  static void graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);
-  
-  static jint graal_identity_hash_code(JavaThread* thread, oopDesc* objd);
-  static jboolean graal_thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupte);
+  static void create_null_exception(JavaThread* thread);
+  static void create_out_of_bounds_exception(JavaThread* thread, jint index);
+  static void monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock);
+  static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
+  static void vm_error(JavaThread* thread, oop where, oop format, jlong value);
+  static void log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3);
+  static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);
+  static void wb_pre_call(JavaThread* thread, oopDesc* obj);
+  static void wb_post_call(JavaThread* thread, oopDesc* obj,void* obj);
+
+  static jint identity_hash_code(JavaThread* thread, oopDesc* objd);
+  static jboolean thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupte);
 
   // Note: Must be kept in sync with constants in com.oracle.graal.snippets.Log
   enum {
@@ -162,7 +159,7 @@
     LOG_OBJECT_STRING  = 0x02,
     LOG_OBJECT_ADDRESS = 0x04
   };
-  static void graal_log_object(JavaThread* thread, oop msg, jint flags);
+  static void log_object(JavaThread* thread, oop msg, jint flags);
 
  public:
   // initialization
--- a/src/share/vm/graal/graalVmIds.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "graal/graalVmIds.hpp"
-#include "ci/ciUtilities.hpp"
-
-// VmIds implementation
-
-jlong VmIds::addStub(address stub) {
-  return (jlong)stub;
-}
-
-address VmIds::getStub(jlong id) {
-  return (address)id;
-}
-
--- a/src/share/vm/graal/graalVmIds.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP
-#define SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP
-
-#include "memory/allocation.hpp"
-#include "utilities/growableArray.hpp"
-#include "oops/oop.hpp"
-#include "runtime/handles.hpp"
-#include "runtime/thread.hpp"
-#include "classfile/javaClasses.hpp"
-#include "runtime/jniHandles.hpp"
-
-class VmIds : public AllStatic {
-
-public:
-  // Adds a stub address, and returns the corresponding vmId (which is of type STUB)
-  static jlong addStub(address stub);
-
-  // Returns the stub address with the given vmId
-  static address getStub(jlong id);
-
-  // Returns the stub address with the given vmId taken from a java.lang.Long
-  static address getStub(oop id);
-
-  // Helper function to convert a symbol to a java.lang.String object
-  template <typename T> static T toString(Symbol* symbol, TRAPS);
-
-  // Helper function to convert a java.lang.String object to a symbol (this will return NULL if the symbol doesn't exist in the system)
-  static Symbol* toSymbol(jstring string);
-
-  // Helper function to get the contents of a java.lang.Long
-  static jlong getBoxedLong(oop obj);
-};
-
-inline address VmIds::getStub(oop obj) {
-  return getStub(getBoxedLong(obj));
-}
-
-template <> inline Handle VmIds::toString<Handle>(Symbol* symbol, TRAPS) {
-  return java_lang_String::create_from_symbol(symbol, THREAD);
-}
-
-template <> inline oop VmIds::toString<oop>(Symbol* symbol, TRAPS) {
-  return toString<Handle>(symbol, THREAD)();
-}
-
-template <> inline jstring VmIds::toString<jstring>(Symbol* symbol, TRAPS) {
-  return (jstring)JNIHandles::make_local(toString<oop>(symbol, THREAD));
-}
-
-template <> inline jobject VmIds::toString<jobject>(Symbol* symbol, TRAPS) {
-  return JNIHandles::make_local(toString<oop>(symbol, THREAD));
-}
-
-inline Symbol* VmIds::toSymbol(jstring string) {
-  return java_lang_String::as_symbol(JNIHandles::resolve(string), Thread::current());
-}
-
-inline jlong VmIds::getBoxedLong(oop obj) {
-  assert(obj->is_oop(true), "cannot unbox null or non-oop");
-  return obj->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG));
-}
-
-#endif // SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -3099,9 +3099,9 @@
   tty->print_cr("&native_fresult: " INTPTR_FORMAT, (uintptr_t) &this->_native_fresult);
   tty->print_cr("native_lresult: " INTPTR_FORMAT, (uintptr_t) this->_native_lresult);
 #endif
-#if defined(IA64) && !defined(ZERO)
+#if !defined(ZERO)
   tty->print_cr("last_Java_fp: " INTPTR_FORMAT, (uintptr_t) this->_last_Java_fp);
-#endif // IA64 && !ZERO
+#endif // !ZERO
   tty->print_cr("self_link: " INTPTR_FORMAT, (uintptr_t) this->_self_link);
 }
 
--- a/src/share/vm/interpreter/bytecodeTracer.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/interpreter/bytecodeTracer.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -335,9 +335,6 @@
     st->print_cr(" %s", constants->resolved_klass_at(i)->external_name());
   } else if (tag.is_unresolved_klass()) {
     st->print_cr(" <unresolved klass at %d>", i);
-  } else if (tag.is_object()) {
-    st->print(" <Object>");
-    print_oop(constants->object_at(i), st);
   } else if (tag.is_method_type()) {
     int i2 = constants->method_type_index_at(i);
     st->print(" <MethodType> %d", i2);
--- a/src/share/vm/interpreter/interpreter.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/interpreter/interpreter.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -63,8 +63,9 @@
 
 void InterpreterCodelet::print_on(outputStream* st) const {
   ttyLocker ttyl;
-  if (PrintInterpreter || PrintMachineCodeToFile) {
 
+  if (PrintInterpreter) {
+    st->cr();
     st->print_cr("----------------------------------------------------------------------");
   }
 
@@ -73,7 +74,8 @@
   st->print_cr("[" INTPTR_FORMAT ", " INTPTR_FORMAT "]  %d bytes",
                 code_begin(), code_end(), code_size());
 
-  if (PrintInterpreter || PrintMachineCodeToFile) {
+  if (PrintInterpreter) {
+    st->cr();
     Disassembler::decode(code_begin(), code_end(), st, DEBUG_ONLY(_comments) NOT_DEBUG(CodeComments()));
   }
 }
@@ -388,7 +390,6 @@
   assert(method->contains(bcp), "just checkin'");
   Bytecodes::Code code   = Bytecodes::java_code_at(method, bcp);
 #if defined(COMPILER1) || defined(GRAAL)
-
   if(code == Bytecodes::_athrow ) {
     return Interpreter::rethrow_exception_entry();
   }
@@ -434,8 +435,7 @@
     case Bytecodes::_getstatic :
     case Bytecodes::_putstatic :
     case Bytecodes::_aastore   :
-#if defined(COMPILER1)
-
+#ifdef COMPILER1
     //special case of reexecution
     case Bytecodes::_athrow    :
 #endif
--- a/src/share/vm/interpreter/linkResolver.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/interpreter/linkResolver.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1241,7 +1241,6 @@
 
 void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
   assert(EnableInvokeDynamic, "");
-  pool->set_invokedynamic();    // mark header to flag active call sites
 
   //resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK);
   Symbol* method_name       = pool->name_ref_at(index);
--- a/src/share/vm/interpreter/rewriter.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/interpreter/rewriter.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,6 @@
         add_cp_cache_entry(i);
         break;
       case JVM_CONSTANT_String:
-      case JVM_CONSTANT_Object:
       case JVM_CONSTANT_MethodHandle      : // fall through
       case JVM_CONSTANT_MethodType        : // fall through
         add_resolved_references_entry(i);
@@ -116,9 +115,7 @@
   while (!bcs.is_last_bytecode()) {
     Bytecodes::Code opcode = bcs.raw_next();
     switch (opcode) {
-      case Bytecodes::_return:
-          *bcs.bcp() = Bytecodes::_return_register_finalizer;
-        break;
+      case Bytecodes::_return: *bcs.bcp() = Bytecodes::_return_register_finalizer; break;
 
       case Bytecodes::_istore:
       case Bytecodes::_lstore:
@@ -240,7 +237,7 @@
     address p = bcp + offset;
     int cp_index = is_wide ? Bytes::get_Java_u2(p) : (u1)(*p);
     constantTag tag = _pool->tag_at(cp_index).value();
-    if (tag.is_method_handle() || tag.is_method_type() || tag.is_string() || tag.is_object()) {
+    if (tag.is_method_handle() || tag.is_method_type() || tag.is_string()) {
       int ref_index = cp_entry_to_resolved_references(cp_index);
       if (is_wide) {
         (*bcp) = Bytecodes::_fast_aldc_w;
@@ -318,12 +315,12 @@
       switch (c) {
         case Bytecodes::_lookupswitch   : {
 #ifndef CC_INTERP
-            Bytecode_lookupswitch bc(method, bcp);
-            (*bcp) = (
-              bc.number_of_pairs() < BinarySwitchThreshold
-              ? Bytecodes::_fast_linearswitch
-              : Bytecodes::_fast_binaryswitch
-            );
+          Bytecode_lookupswitch bc(method, bcp);
+          (*bcp) = (
+            bc.number_of_pairs() < BinarySwitchThreshold
+            ? Bytecodes::_fast_linearswitch
+            : Bytecodes::_fast_binaryswitch
+          );
 #endif
           break;
         }
--- a/src/share/vm/interpreter/templateInterpreter.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/interpreter/templateInterpreter.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -27,7 +27,6 @@
 #include "interpreter/interpreterGenerator.hpp"
 #include "interpreter/interpreterRuntime.hpp"
 #include "interpreter/templateTable.hpp"
-#include "utilities/machineCodePrinter.hpp"
 
 #ifndef CC_INTERP
 
@@ -52,9 +51,6 @@
                           "Interpreter");
     InterpreterGenerator g(_code);
     if (PrintInterpreter) print();
-    if (PrintMachineCodeToFile) {
-      MachineCodePrinter::print(_code);
-    }
   }
 
   // initialize dispatch table
@@ -184,7 +180,7 @@
 #endif // !PRODUCT
 EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries];
 EntryPoint TemplateInterpreter::_earlyret_entry;
-EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ];
+EntryPoint TemplateInterpreter::_deopt_entry[TemplateInterpreter::number_of_deopt_entries ];
 EntryPoint TemplateInterpreter::_continuation_entry;
 EntryPoint TemplateInterpreter::_safept_entry;
 
@@ -276,15 +272,15 @@
     for (int i = 0; i < Interpreter::number_of_deopt_entries; i++) {
       Interpreter::_deopt_entry[i] =
         EntryPoint(
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(atos, i),
-          generate_deopt_entry_for(itos, i),
-          generate_deopt_entry_for(ltos, i),
-          generate_deopt_entry_for(ftos, i),
-          generate_deopt_entry_for(dtos, i),
-          generate_deopt_entry_for(vtos, i)
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(atos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(itos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(ltos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(ftos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(dtos, i),
+          ((InterpreterGenerator*)this)->generate_deopt_entry_for(vtos, i)
         );
     }
   }
--- a/src/share/vm/interpreter/templateInterpreterGenerator.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/interpreter/templateInterpreterGenerator.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -55,7 +55,6 @@
   address generate_continuation_for(TosState state);
   address generate_return_entry_for(TosState state, int step);
   address generate_earlyret_entry_for(TosState state);
-  address generate_deopt_entry_for(TosState state, int step);
   address generate_safept_entry_for(TosState state, address runtime_entry);
   void    generate_throw_exception();
 
--- a/src/share/vm/memory/allocation.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/allocation.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -34,9 +34,6 @@
 #ifdef COMPILER2
 #include "opto/c2_globals.hpp"
 #endif
-#ifdef GRAAL
-#include "graal/graalGlobals.hpp"
-#endif
 
 #include <new>
 
@@ -148,9 +145,10 @@
   mtChunk             = 0x0B00,  // chunk that holds content of arenas
   mtJavaHeap          = 0x0C00,  // Java heap
   mtClassShared       = 0x0D00,  // class data sharing
-  mt_number_of_types  = 0x000D,  // number of memory types (mtDontTrack
+  mtTest              = 0x0E00,  // Test type for verifying NMT
+  mt_number_of_types  = 0x000E,  // number of memory types (mtDontTrack
                                  // is not included as validate type)
-  mtDontTrack         = 0x0E00,  // memory we do not or cannot track
+  mtDontTrack         = 0x0F00,  // memory we do not or cannot track
   mt_masks            = 0x7F00,
 
   // object type mask
--- a/src/share/vm/memory/binaryTreeDictionary.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/binaryTreeDictionary.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "utilities/macros.hpp"
 #include "gc_implementation/shared/allocationStats.hpp"
 #include "memory/binaryTreeDictionary.hpp"
 #include "memory/freeList.hpp"
@@ -31,12 +32,13 @@
 #include "memory/metachunk.hpp"
 #include "runtime/globals.hpp"
 #include "utilities/ostream.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp"
 #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
 #include "gc_implementation/shared/spaceDecorator.hpp"
 #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 ////////////////////////////////////////////////////////////////////////////////
 // A binary tree based search structure for free blocks.
@@ -118,7 +120,7 @@
 }
 
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 // Specialize for AdaptiveFreeList which tries to avoid
 // splitting a chunk of a size that is under populated in favor of
 // an over populated size.  The general get_better_list() just returns
@@ -160,7 +162,7 @@
   }
   return curTL;
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 template <class Chunk_t, template <class> class FreeList_t>
 TreeList<Chunk_t, FreeList_t>*
@@ -871,9 +873,9 @@
 template <class Chunk_t, template <class> class FreeList_t>
 void BinaryTreeDictionary<Chunk_t, FreeList_t>::dict_census_update(size_t size, bool split, bool birth){}
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 template <>
-void BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::dict_census_update(size_t size, bool split, bool birth){
+void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){
   TreeList<FreeChunk, AdaptiveFreeList>* nd = find_list(size);
   if (nd) {
     if (split) {
@@ -900,7 +902,7 @@
   //   This is a birth associated with a LinAB.  The chunk
   //     for the LinAB is not in the dictionary.
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 template <class Chunk_t, template <class> class FreeList_t>
 bool BinaryTreeDictionary<Chunk_t, FreeList_t>::coal_dict_over_populated(size_t size) {
@@ -909,9 +911,9 @@
   return true;
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 template <>
-bool BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::coal_dict_over_populated(size_t size) {
+bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) {
   if (FLSAlwaysCoalesceLarge) return true;
 
   TreeList<FreeChunk, AdaptiveFreeList>* list_of_size = find_list(size);
@@ -919,7 +921,7 @@
   return list_of_size == NULL || list_of_size->coal_desired() <= 0 ||
          list_of_size->count() > list_of_size->coal_desired();
 }
-#endif  // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 // Closures for walking the binary tree.
 //   do_list() walks the free list in a node applying the closure
@@ -979,7 +981,7 @@
 
   void do_list(FreeList<Chunk_t>* fl) {}
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   void do_list(AdaptiveFreeList<Chunk_t>* fl) {
     double coalSurplusPercent = _percentage;
     fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
@@ -987,7 +989,7 @@
     fl->set_before_sweep(fl->count());
     fl->set_bfr_surp(fl->surplus());
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 };
 
 // Used to search the tree until a condition is met.
@@ -1134,13 +1136,13 @@
   setTreeSurplusClosure(double v) { percentage = v; }
   void do_list(FreeList<Chunk_t>* fl) {}
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   void do_list(AdaptiveFreeList<Chunk_t>* fl) {
     double splitSurplusPercent = percentage;
     fl->set_surplus(fl->count() -
                    (ssize_t)((double)fl->desired() * splitSurplusPercent));
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 };
 
 template <class Chunk_t, template <class> class FreeList_t>
@@ -1157,7 +1159,7 @@
   setTreeHintsClosure(size_t v) { hint = v; }
   void do_list(FreeList<Chunk_t>* fl) {}
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   void do_list(AdaptiveFreeList<Chunk_t>* fl) {
     fl->set_hint(hint);
     assert(fl->hint() == 0 || fl->hint() > fl->size(),
@@ -1166,7 +1168,7 @@
       hint = fl->size();
     }
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 };
 
 template <class Chunk_t, template <class> class FreeList_t>
@@ -1180,7 +1182,7 @@
 class clearTreeCensusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
   void do_list(FreeList<Chunk_t>* fl) {}
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   void do_list(AdaptiveFreeList<Chunk_t>* fl) {
     fl->set_prev_sweep(fl->count());
     fl->set_coal_births(0);
@@ -1188,7 +1190,7 @@
     fl->set_split_births(0);
     fl->set_split_deaths(0);
   }
-#endif  // SERIALGC
+#endif // INCLUDE_ALL_GCS
 };
 
 template <class Chunk_t, template <class> class FreeList_t>
@@ -1252,7 +1254,7 @@
     total()->set_count(      total()->count()       + fl->count()      );
   }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   void do_list(AdaptiveFreeList<Chunk_t>* fl) {
     if (++_print_line >= 40) {
       FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, "size");
@@ -1271,7 +1273,7 @@
     total()->set_split_births(total()->split_births() + fl->split_births());
     total()->set_split_deaths(total()->split_deaths() + fl->split_deaths());
   }
-#endif  // SERIALGC
+#endif // INCLUDE_ALL_GCS
 };
 
 template <class Chunk_t, template <class> class FreeList_t>
@@ -1286,9 +1288,9 @@
   FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, " ");
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 template <>
-void BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::print_dict_census(void) const {
+void AFLBinaryTreeDictionary::print_dict_census(void) const {
 
   gclog_or_tty->print("\nBinaryTree\n");
   AdaptiveFreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
@@ -1308,7 +1310,7 @@
              (double)(total->desired() - total->count())
              /(total->desired() != 0 ? (double)total->desired() : 1.0));
 }
-#endif  // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 template <class Chunk_t, template <class> class FreeList_t>
 class PrintFreeListsClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
@@ -1414,10 +1416,10 @@
 template class TreeChunk<Metachunk, FreeList>;
 
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 // Explicitly instantiate these types for FreeChunk.
 template class TreeList<FreeChunk, AdaptiveFreeList>;
 template class BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>;
 template class TreeChunk<FreeChunk, AdaptiveFreeList>;
 
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
--- a/src/share/vm/memory/binaryTreeDictionary.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/binaryTreeDictionary.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -43,6 +43,10 @@
 template <class Chunk_t, template <class> class FreeList_t> class DescendTreeCensusClosure;
 template <class Chunk_t, template <class> class FreeList_t> class DescendTreeSearchClosure;
 
+class FreeChunk;
+template <class> class AdaptiveFreeList;
+typedef BinaryTreeDictionary<FreeChunk, AdaptiveFreeList> AFLBinaryTreeDictionary;
+
 template <class Chunk_t, template <class> class FreeList_t>
 class TreeList : public FreeList_t<Chunk_t> {
   friend class TreeChunk<Chunk_t, FreeList_t>;
--- a/src/share/vm/memory/cardTableModRefBS.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/cardTableModRefBS.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -34,6 +34,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/virtualspace.hpp"
 #include "services/memTracker.hpp"
+#include "utilities/macros.hpp"
 #ifdef COMPILER1
 #include "c1/c1_LIR.hpp"
 #include "c1/c1_LIRGenerator.hpp"
@@ -499,13 +500,13 @@
     int n_threads =  SharedHeap::heap()->n_par_threads();
     bool is_par = n_threads > 0;
     if (is_par) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
       assert(SharedHeap::heap()->n_par_threads() ==
              SharedHeap::heap()->workers()->active_workers(), "Mismatch");
       non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads);
-#else  // SERIALGC
+#else  // INCLUDE_ALL_GCS
       fatal("Parallel gc not supported here.");
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
     } else {
       // We do not call the non_clean_card_iterate_serial() version below because
       // we want to clear the cards (which non_clean_card_iterate_serial() does not
--- a/src/share/vm/memory/cardTableRS.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/cardTableRS.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -31,10 +31,11 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/os.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/concurrentMark.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 CardTableRS::CardTableRS(MemRegion whole_heap,
                          int max_covered_regions) :
@@ -42,7 +43,7 @@
   _cur_youngergen_card_val(youngergenP1_card),
   _regions_to_iterate(max_covered_regions - 1)
 {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   if (UseG1GC) {
       _ct_bs = new G1SATBCardTableLoggingModRefBS(whole_heap,
                                                   max_covered_regions);
--- a/src/share/vm/memory/collectorPolicy.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/collectorPolicy.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,10 +39,11 @@
 #include "runtime/java.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/vmThread.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp"
 #include "gc_implementation/concurrentMarkSweep/cmsGCAdaptivePolicyCounters.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // CollectorPolicy methods.
 
@@ -167,11 +168,11 @@
 void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size,
                                                 size_t init_promo_size,
                                                 size_t init_survivor_size) {
-  const double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
+  const double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0;
   _size_policy = new AdaptiveSizePolicy(init_eden_size,
                                         init_promo_size,
                                         init_survivor_size,
-                                        max_gc_minor_pause_sec,
+                                        max_gc_pause_sec,
                                         GCTimeRatio);
 }
 
@@ -235,6 +236,18 @@
   if (NewSize + OldSize > MaxHeapSize) {
     MaxHeapSize = NewSize + OldSize;
   }
+
+  if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(NewSize)) {
+    // NewRatio will be used later to set the young generation size so we use
+    // it to calculate how big the heap should be based on the requested OldSize
+    // and NewRatio.
+    assert(NewRatio > 0, "NewRatio should have been set up earlier");
+    size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1);
+
+    calculated_heapsize = align_size_up(calculated_heapsize, max_alignment());
+    MaxHeapSize = calculated_heapsize;
+    InitialHeapSize = calculated_heapsize;
+  }
   MaxHeapSize = align_size_up(MaxHeapSize, max_alignment());
 
   always_do_update_barrier = UseConcMarkSweepGC;
@@ -384,14 +397,15 @@
 // keeping it simple also seems a worthwhile goal.
 bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr,
                                                      size_t* gen1_size_ptr,
-                                                     size_t heap_size,
-                                                     size_t min_gen0_size) {
+                                                     const size_t heap_size,
+                                                     const size_t min_gen1_size) {
   bool result = false;
+
   if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) {
-    if (((*gen0_size_ptr + OldSize) > heap_size) &&
-       (heap_size - min_gen0_size) >= min_alignment()) {
-      // Adjust gen0 down to accomodate OldSize
-      *gen0_size_ptr = heap_size - min_gen0_size;
+    if ((heap_size < (*gen0_size_ptr + min_gen1_size)) &&
+        (heap_size >= min_gen1_size + min_alignment())) {
+      // Adjust gen0 down to accommodate min_gen1_size
+      *gen0_size_ptr = heap_size - min_gen1_size;
       *gen0_size_ptr =
         MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()),
              min_alignment());
--- a/src/share/vm/memory/collectorPolicy.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/collectorPolicy.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 #include "memory/barrierSet.hpp"
 #include "memory/generationSpec.hpp"
 #include "memory/genRemSet.hpp"
+#include "utilities/macros.hpp"
 
 // This class (or more correctly, subtypes of this class)
 // are used to define global garbage collector attributes.
@@ -48,10 +49,10 @@
 class GenCollectorPolicy;
 class TwoGenerationCollectorPolicy;
 class AdaptiveSizePolicy;
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 class ConcurrentMarkSweepPolicy;
 class G1CollectorPolicy;
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 class GCPolicyCounters;
 class MarkSweepPolicy;
@@ -134,21 +135,21 @@
   virtual GenCollectorPolicy*           as_generation_policy()            { return NULL; }
   virtual TwoGenerationCollectorPolicy* as_two_generation_policy()        { return NULL; }
   virtual MarkSweepPolicy*              as_mark_sweep_policy()            { return NULL; }
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   virtual ConcurrentMarkSweepPolicy*    as_concurrent_mark_sweep_policy() { return NULL; }
   virtual G1CollectorPolicy*            as_g1_policy()                    { return NULL; }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
   // Note that these are not virtual.
   bool is_generation_policy()            { return as_generation_policy() != NULL; }
   bool is_two_generation_policy()        { return as_two_generation_policy() != NULL; }
   bool is_mark_sweep_policy()            { return as_mark_sweep_policy() != NULL; }
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   bool is_concurrent_mark_sweep_policy() { return as_concurrent_mark_sweep_policy() != NULL; }
   bool is_g1_policy()                    { return as_g1_policy() != NULL; }
-#else  // SERIALGC
+#else  // INCLUDE_ALL_GCS
   bool is_concurrent_mark_sweep_policy() { return false; }
   bool is_g1_policy()                    { return false; }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 
   virtual BarrierSet::Name barrier_set_name() = 0;
@@ -321,7 +322,7 @@
 
   // Returns true is gen0 sizes were adjusted
   bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr,
-                               size_t heap_size, size_t min_gen1_size);
+                         const size_t heap_size, const size_t min_gen1_size);
 };
 
 class MarkSweepPolicy : public TwoGenerationCollectorPolicy {
--- a/src/share/vm/memory/filemap.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/filemap.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -210,13 +210,14 @@
     tty->print_cr("   %s", _full_path);
   }
 
-  // Remove the existing file in case another process has it open.
+#ifdef _WINDOWS  // On Windows, need WRITE permission to remove the file.
+  chmod(_full_path, _S_IREAD | _S_IWRITE);
+#endif
+
+  // Use remove() to delete the existing file because, on Unix, this will
+  // allow processes that have it open continued access to the file.
   remove(_full_path);
-#ifdef _WINDOWS  // if 0444 is used on Windows, then remove() will fail.
-  int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0744);
-#else
   int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444);
-#endif
   if (fd < 0) {
     fail_stop("Unable to create shared archive file %s.", _full_path);
   }
--- a/src/share/vm/memory/freeBlockDictionary.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/freeBlockDictionary.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -23,13 +23,15 @@
  */
 
 #include "precompiled.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 #include "memory/freeBlockDictionary.hpp"
 #include "memory/metablock.hpp"
 #include "memory/metachunk.hpp"
 #include "runtime/thread.inline.hpp"
+#include "utilities/macros.hpp"
 
 #ifndef PRODUCT
 template <class Chunk> Mutex* FreeBlockDictionary<Chunk>::par_lock() const {
@@ -56,7 +58,7 @@
 template class FreeBlockDictionary<Metablock>;
 template class FreeBlockDictionary<Metachunk>;
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 // Explicitly instantiate for FreeChunk
 template class FreeBlockDictionary<FreeChunk>;
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
--- a/src/share/vm/memory/freeList.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/freeList.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -31,10 +31,11 @@
 #include "runtime/globals.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/vmThread.hpp"
+#include "utilities/macros.hpp"
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 // Free list.  A FreeList is used to access a linked list of chunks
 // of space in the heap.  The head and tail are maintained so that
@@ -341,6 +342,6 @@
 
 template class FreeList<Metablock>;
 template class FreeList<Metachunk>;
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 template class FreeList<FreeChunk>;
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
--- a/src/share/vm/memory/genCollectedHeap.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/genCollectedHeap.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -51,10 +51,11 @@
 #include "services/memoryService.hpp"
 #include "utilities/vmError.hpp"
 #include "utilities/workgroup.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
 #include "gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 GenCollectedHeap* GenCollectedHeap::_gch;
 NOT_PRODUCT(size_t GenCollectedHeap::_skip_header_HeapWords = 0;)
@@ -141,14 +142,14 @@
   }
   clear_incremental_collection_failed();
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // If we are running CMS, create the collector responsible
   // for collecting the CMS generations.
   if (collector_policy()->is_concurrent_mark_sweep_policy()) {
     bool success = create_cms_collector();
     if (!success) return JNI_ENOMEM;
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   return JNI_OK;
 }
@@ -686,12 +687,12 @@
 
 void GenCollectedHeap::collect(GCCause::Cause cause) {
   if (should_do_concurrent_full_gc(cause)) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     // mostly concurrent full collection
     collect_mostly_concurrent(cause);
-#else  // SERIALGC
+#else  // INCLUDE_ALL_GCS
     ShouldNotReachHere();
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
   } else {
 #ifdef ASSERT
     if (cause == GCCause::_scavenge_alot) {
@@ -736,7 +737,7 @@
   }
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 bool GenCollectedHeap::create_cms_collector() {
 
   assert(((_gens[1]->kind() == Generation::ConcurrentMarkSweep) ||
@@ -772,7 +773,7 @@
     VMThread::execute(&op);
   }
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) {
    do_full_collection(clear_all_soft_refs, _n_gens - 1);
@@ -1116,22 +1117,22 @@
   if (workers() != NULL) {
     workers()->threads_do(tc);
   }
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   if (UseConcMarkSweepGC) {
     ConcurrentMarkSweepThread::threads_do(tc);
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 }
 
 void GenCollectedHeap::print_gc_threads_on(outputStream* st) const {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   if (UseParNewGC) {
     workers()->print_worker_threads_on(st);
   }
   if (UseConcMarkSweepGC) {
     ConcurrentMarkSweepThread::print_all_on(st);
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 }
 
 void GenCollectedHeap::print_tracing_info() const {
--- a/src/share/vm/memory/generationSpec.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/generationSpec.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -30,11 +30,12 @@
 #include "memory/generationSpec.hpp"
 #include "memory/tenuredGeneration.hpp"
 #include "runtime/java.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parNew/asParNewGeneration.hpp"
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
 #include "gc_implementation/parNew/parNewGeneration.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 Generation* GenerationSpec::init(ReservedSpace rs, int level,
                                  GenRemSet* remset) {
@@ -45,7 +46,7 @@
     case Generation::MarkSweepCompact:
       return new TenuredGeneration(rs, init_size(), level, remset);
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case Generation::ParNew:
       return new ParNewGeneration(rs, init_size(), level);
 
@@ -94,7 +95,7 @@
 
       return g;
     }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
     default:
       guarantee(false, "unrecognized GenerationName");
--- a/src/share/vm/memory/heap.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/heap.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -127,7 +127,7 @@
   assert(_number_of_reserved_segments >= _number_of_committed_segments, "just checking");
 
   // reserve space for _segmap
-  if (!_segmap.initialize(align_to_allocation_size(_number_of_reserved_segments), align_to_allocation_size(_number_of_committed_segments))) {
+  if (!_segmap.initialize(align_to_page_size(_number_of_reserved_segments), align_to_page_size(_number_of_committed_segments))) {
     return false;
   }
 
--- a/src/share/vm/memory/heapInspection.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/heapInspection.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,15 +23,17 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/classLoaderData.hpp"
 #include "gc_interface/collectedHeap.hpp"
 #include "memory/genCollectedHeap.hpp"
 #include "memory/heapInspection.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/os.hpp"
 #include "utilities/globalDefinitions.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // HeapInspection
 
@@ -41,12 +43,24 @@
   } else if(e1->_instance_words < e2->_instance_words) {
     return 1;
   }
-  return 0;
+  // Sort alphabetically, note 'Z' < '[' < 'a', but it's better to group
+  // the array classes before all the instance classes.
+  ResourceMark rm;
+  const char* name1 = e1->klass()->external_name();
+  const char* name2 = e2->klass()->external_name();
+  bool d1 = (name1[0] == '[');
+  bool d2 = (name2[0] == '[');
+  if (d1 && !d2) {
+    return -1;
+  } else if (d2 && !d1) {
+    return 1;
+  } else {
+    return strcmp(name1, name2);
+  }
 }
 
-void KlassInfoEntry::print_on(outputStream* st) const {
-  ResourceMark rm;
-  const char* name;;
+const char* KlassInfoEntry::name() const {
+  const char* name;
   if (_klass->name() != NULL) {
     name = _klass->external_name();
   } else {
@@ -60,11 +74,17 @@
     if (_klass == Universe::longArrayKlassObj())         name = "<longArrayKlass>";         else
       name = "<no name>";
   }
+  return name;
+}
+
+void KlassInfoEntry::print_on(outputStream* st) const {
+  ResourceMark rm;
+
   // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit
   st->print_cr(INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13) "  %s",
                (jlong)  _instance_count,
                (julong) _instance_words * HeapWordSize,
-               name);
+               name());
 }
 
 KlassInfoEntry* KlassInfoBucket::lookup(Klass* const k) {
@@ -101,7 +121,14 @@
   }
 }
 
-KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) {
+void KlassInfoTable::AllClassesFinder::do_klass(Klass* k) {
+  // This has the SIDE EFFECT of creating a KlassInfoEntry
+  // for <k>, if one doesn't exist yet.
+  _table->lookup(k);
+}
+
+KlassInfoTable::KlassInfoTable(int size, HeapWord* ref,
+                               bool need_class_stats) {
   _size = 0;
   _ref = ref;
   _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal);
@@ -110,6 +137,10 @@
     for (int index = 0; index < _size; index++) {
       _buckets[index].initialize();
     }
+    if (need_class_stats) {
+      AllClassesFinder finder(this);
+      ClassLoaderDataGraph::classes_do(&finder);
+    }
   }
 }
 
@@ -165,7 +196,8 @@
   return (*e1)->compare(*e1,*e2);
 }
 
-KlassInfoHisto::KlassInfoHisto(const char* title, int estimatedCount) :
+KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount) :
+  _cit(cit),
   _title(title) {
   _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(estimatedCount,true);
 }
@@ -196,9 +228,205 @@
                total, totalw * HeapWordSize);
 }
 
-void KlassInfoHisto::print_on(outputStream* st) const {
-  st->print_cr("%s",title());
-  print_elements(st);
+#define MAKE_COL_NAME(field, name, help)     #name,
+#define MAKE_COL_HELP(field, name, help)     help,
+
+static const char *name_table[] = {
+  HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_NAME)
+};
+
+static const char *help_table[] = {
+  HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_HELP)
+};
+
+bool KlassInfoHisto::is_selected(const char *col_name) {
+  if (_selected_columns == NULL) {
+    return true;
+  }
+  if (strcmp(_selected_columns, col_name) == 0) {
+    return true;
+  }
+
+  const char *start = strstr(_selected_columns, col_name);
+  if (start == NULL) {
+    return false;
+  }
+
+  // The following must be true, because _selected_columns != col_name
+  if (start > _selected_columns && start[-1] != ',') {
+    return false;
+  }
+  char x = start[strlen(col_name)];
+  if (x != ',' && x != '\0') {
+    return false;
+  }
+
+  return true;
+}
+
+void KlassInfoHisto::print_title(outputStream* st, bool csv_format,
+                                 bool selected[], int width_table[],
+                                 const char *name_table[]) {
+  if (csv_format) {
+    st->print("Index,Super");
+    for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+       if (selected[c]) {st->print(",%s", name_table[c]);}
+    }
+    st->print(",ClassName");
+  } else {
+    st->print("Index Super");
+    for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+      if (selected[c]) {st->print(str_fmt(width_table[c]), name_table[c]);}
+    }
+    st->print(" ClassName");
+  }
+
+  if (is_selected("ClassLoader")) {
+    st->print(",ClassLoader");
+  }
+  st->cr();
+}
+
+void KlassInfoHisto::print_class_stats(outputStream* st,
+                                      bool csv_format, const char *columns) {
+  ResourceMark rm;
+  KlassSizeStats sz, sz_sum;
+  int i;
+  julong *col_table = (julong*)(&sz);
+  julong *colsum_table = (julong*)(&sz_sum);
+  int width_table[KlassSizeStats::_num_columns];
+  bool selected[KlassSizeStats::_num_columns];
+
+  _selected_columns = columns;
+
+  memset(&sz_sum, 0, sizeof(sz_sum));
+  for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+    selected[c] = is_selected(name_table[c]);
+  }
+
+  for(i=0; i < elements()->length(); i++) {
+    elements()->at(i)->set_index(i+1);
+  }
+
+  for (int pass=1; pass<=2; pass++) {
+    if (pass == 2) {
+      print_title(st, csv_format, selected, width_table, name_table);
+    }
+    for(i=0; i < elements()->length(); i++) {
+      KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i);
+      const Klass* k = e->klass();
+
+      memset(&sz, 0, sizeof(sz));
+      sz._inst_count = e->count();
+      sz._inst_bytes = HeapWordSize * e->words();
+      k->collect_statistics(&sz);
+      sz._total_bytes = sz._ro_bytes + sz._rw_bytes;
+
+      if (pass == 1) {
+        for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+          colsum_table[c] += col_table[c];
+        }
+      } else {
+        int super_index = -1;
+        if (k->oop_is_instance()) {
+          Klass* super = ((InstanceKlass*)k)->java_super();
+          if (super) {
+            KlassInfoEntry* super_e = _cit->lookup(super);
+            if (super_e) {
+              super_index = super_e->index();
+            }
+          }
+        }
+
+        if (csv_format) {
+          st->print("%d,%d", e->index(), super_index);
+          for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+            if (selected[c]) {st->print("," JULONG_FORMAT, col_table[c]);}
+          }
+          st->print(",%s",e->name());
+        } else {
+          st->print("%5d %5d", e->index(), super_index);
+          for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+            if (selected[c]) {print_julong(st, width_table[c], col_table[c]);}
+          }
+          st->print(" %s", e->name());
+        }
+        if (is_selected("ClassLoader")) {
+          ClassLoaderData* loader_data = k->class_loader_data();
+          st->print(",");
+          loader_data->print_value_on(st);
+        }
+        st->cr();
+      }
+    }
+
+    if (pass == 1) {
+      for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+        width_table[c] = col_width(colsum_table[c], name_table[c]);
+      }
+    }
+  }
+
+  sz_sum._inst_size = 0;
+
+  if (csv_format) {
+    st->print(",");
+    for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+      if (selected[c]) {st->print("," JULONG_FORMAT, colsum_table[c]);}
+    }
+  } else {
+    st->print("           ");
+    for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+      if (selected[c]) {print_julong(st, width_table[c], colsum_table[c]);}
+    }
+    st->print(" Total");
+    if (sz_sum._total_bytes > 0) {
+      st->cr();
+      st->print("           ");
+      for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+        if (selected[c]) {
+          switch (c) {
+          case KlassSizeStats::_index_inst_size:
+          case KlassSizeStats::_index_inst_count:
+          case KlassSizeStats::_index_method_count:
+            st->print(str_fmt(width_table[c]), "-");
+            break;
+          default:
+            {
+              double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes;
+              st->print(perc_fmt(width_table[c]), perc);
+            }
+          }
+        }
+      }
+    }
+  }
+  st->cr();
+
+  if (!csv_format) {
+    print_title(st, csv_format, selected, width_table, name_table);
+  }
+}
+
+julong KlassInfoHisto::annotations_bytes(Array<AnnotationArray*>* p) const {
+  julong bytes = 0;
+  if (p != NULL) {
+    for (int i = 0; i < p->length(); i++) {
+      bytes += count_bytes_array(p->at(i));
+    }
+    bytes += count_bytes_array(p);
+  }
+  return bytes;
+}
+
+void KlassInfoHisto::print_histo_on(outputStream* st, bool print_stats,
+                                    bool csv_format, const char *columns) {
+  if (print_stats) {
+    print_class_stats(st, csv_format, columns);
+  } else {
+    st->print_cr("%s",title());
+    print_elements(st);
+  }
 }
 
 class HistoClosure : public KlassInfoClosure {
@@ -236,8 +464,26 @@
   CollectedHeap* heap = Universe::heap();
   bool is_shared_heap = false;
 
+  if (_print_help) {
+    for (int c=0; c<KlassSizeStats::_num_columns; c++) {
+      st->print("%s:\n\t", name_table[c]);
+      const int max_col = 60;
+      int col = 0;
+      for (const char *p = help_table[c]; *p; p++,col++) {
+        if (col >= max_col && *p == ' ') {
+          st->print("\n\t");
+          col = 0;
+        } else {
+          st->print("%c", *p);
+        }
+      }
+      st->print_cr(".\n");
+    }
+    return;
+  }
+
   // Collect klass instance info
-  KlassInfoTable cit(KlassInfoTable::cit_size, ref);
+  KlassInfoTable cit(KlassInfoTable::cit_size, ref, _print_class_stats);
   if (!cit.allocation_failed()) {
     // Iterate over objects in the heap
     RecordInstanceClosure ric(&cit);
@@ -252,14 +498,14 @@
                    missed_count);
     }
     // Sort and print klass instance info
-    KlassInfoHisto histo("\n"
-                     " num     #instances         #bytes  class name\n"
-                     "----------------------------------------------",
-                     KlassInfoHisto::histo_initial_size);
+    const char *title = "\n"
+              " num     #instances         #bytes  class name\n"
+              "----------------------------------------------";
+    KlassInfoHisto histo(&cit, title, KlassInfoHisto::histo_initial_size);
     HistoClosure hc(&histo);
     cit.iterate(&hc);
     histo.sort();
-    histo.print_on(st);
+    histo.print_histo_on(st, _print_class_stats, _csv_format, _columns);
   } else {
     st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
   }
--- a/src/share/vm/memory/heapInspection.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/heapInspection.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@
 
 #include "memory/allocation.inline.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/annotations.hpp"
+#include "utilities/macros.hpp"
 
 #if INCLUDE_SERVICES
 
@@ -44,16 +46,148 @@
 // to KlassInfoEntry's and is used to sort
 // the entries.
 
+#define HEAP_INSPECTION_COLUMNS_DO(f) \
+    f(inst_size, InstSize, \
+        "Size of each object instance of the Java class") \
+    f(inst_count, InstCount, \
+        "Number of object instances of the Java class")  \
+    f(inst_bytes, InstBytes, \
+        "This is usually (InstSize * InstNum). The only exception is " \
+        "java.lang.Class, whose InstBytes also includes the slots " \
+        "used to store static fields. InstBytes is not counted in " \
+        "ROAll, RWAll or Total") \
+    f(mirror_bytes, Mirror, \
+        "Size of the Klass::java_mirror() object") \
+    f(klass_bytes, KlassBytes, \
+        "Size of the InstanceKlass or ArrayKlass for this class. " \
+        "Note that this includes VTab, ITab, OopMap") \
+    f(secondary_supers_bytes, K_secondary_supers, \
+        "Number of bytes used by the Klass::secondary_supers() array") \
+    f(vtab_bytes, VTab, \
+        "Size of the embedded vtable in InstanceKlass") \
+    f(itab_bytes, ITab, \
+        "Size of the embedded itable in InstanceKlass") \
+    f(nonstatic_oopmap_bytes, OopMap, \
+        "Size of the embedded nonstatic_oop_map in InstanceKlass") \
+    f(methods_array_bytes, IK_methods, \
+        "Number of bytes used by the InstanceKlass::methods() array") \
+    f(method_ordering_bytes, IK_method_ordering, \
+        "Number of bytes used by the InstanceKlass::method_ordering() array") \
+    f(local_interfaces_bytes, IK_local_interfaces, \
+        "Number of bytes used by the InstanceKlass::local_interfaces() array") \
+    f(transitive_interfaces_bytes, IK_transitive_interfaces, \
+        "Number of bytes used by the InstanceKlass::transitive_interfaces() array") \
+    f(fields_bytes, IK_fields, \
+        "Number of bytes used by the InstanceKlass::fields() array") \
+    f(inner_classes_bytes, IK_inner_classes, \
+        "Number of bytes used by the InstanceKlass::inner_classes() array") \
+    f(signers_bytes, IK_signers, \
+        "Number of bytes used by the InstanceKlass::singers() array") \
+    f(class_annotations_bytes, class_annotations, \
+        "Size of class annotations") \
+    f(class_type_annotations_bytes, class_type_annotations, \
+        "Size of class type annotations") \
+    f(fields_annotations_bytes, fields_annotations, \
+        "Size of field annotations") \
+    f(fields_type_annotations_bytes, fields_type_annotations, \
+        "Size of field type annotations") \
+    f(methods_annotations_bytes, methods_annotations, \
+        "Size of method annotations") \
+    f(methods_parameter_annotations_bytes, methods_parameter_annotations, \
+        "Size of method parameter annotations") \
+    f(methods_type_annotations_bytes, methods_type_annotations, \
+        "Size of methods type annotations") \
+    f(methods_default_annotations_bytes, methods_default_annotations, \
+        "Size of methods default annotations") \
+    f(annotations_bytes, annotations, \
+        "Size of all annotations") \
+    f(cp_bytes, Cp, \
+        "Size of InstanceKlass::constants()") \
+    f(cp_tags_bytes, CpTags, \
+        "Size of InstanceKlass::constants()->tags()") \
+    f(cp_cache_bytes, CpCache, \
+        "Size of InstanceKlass::constants()->cache()") \
+    f(cp_operands_bytes, CpOperands, \
+        "Size of InstanceKlass::constants()->operands()") \
+    f(cp_refmap_bytes, CpRefMap, \
+        "Size of InstanceKlass::constants()->reference_map()") \
+    f(cp_all_bytes, CpAll, \
+        "Sum of Cp + CpTags + CpCache + CpOperands + CpRefMap") \
+    f(method_count, MethodCount, \
+        "Number of methods in this class") \
+    f(method_bytes, MethodBytes, \
+        "Size of the Method object") \
+    f(const_method_bytes, ConstMethod, \
+        "Size of the ConstMethod object") \
+    f(method_data_bytes, MethodData, \
+        "Size of the MethodData object") \
+    f(stackmap_bytes, StackMap, \
+        "Size of the stackmap_data") \
+    f(bytecode_bytes, Bytecodes, \
+        "Of the MethodBytes column, how much are the space taken up by bytecodes") \
+    f(method_all_bytes, MethodAll, \
+        "Sum of MethodBytes + Constmethod + Stackmap + Methoddata") \
+    f(ro_bytes, ROAll, \
+        "Size of all class meta data that could (potentially) be placed " \
+        "in read-only memory. (This could change with CDS design)") \
+    f(rw_bytes, RWAll, \
+        "Size of all class meta data that must be placed in read/write " \
+        "memory. (This could change with CDS design) ") \
+    f(total_bytes, Total, \
+        "ROAll + RWAll. Note that this does NOT include InstBytes.")
+
+// Size statistics for a Klass - filled in by Klass::collect_statistics()
+class KlassSizeStats {
+public:
+#define COUNT_KLASS_SIZE_STATS_FIELD(field, name, help)   _index_ ## field,
+#define DECLARE_KLASS_SIZE_STATS_FIELD(field, name, help) julong _ ## field;
+
+  enum {
+    HEAP_INSPECTION_COLUMNS_DO(COUNT_KLASS_SIZE_STATS_FIELD)
+    _num_columns
+  };
+
+  HEAP_INSPECTION_COLUMNS_DO(DECLARE_KLASS_SIZE_STATS_FIELD)
+
+  static int count(oop x) {
+    return (HeapWordSize * ((x) ? (x)->size() : 0));
+  }
+
+  static int count_array(objArrayOop x) {
+    return (HeapWordSize * ((x) ? (x)->size() : 0));
+  }
+
+  template <class T> static int count(T* x) {
+    return (HeapWordSize * ((x) ? (x)->size() : 0));
+  }
+
+  template <class T> static int count_array(T* x) {
+    if (x == NULL) {
+      return 0;
+    }
+    if (x->length() == 0) {
+      // This is a shared array, e.g., Universe::the_empty_int_array(). Don't
+      // count it to avoid double-counting.
+      return 0;
+    }
+    return HeapWordSize * x->size();
+  }
+};
+
+
+
+
 class KlassInfoEntry: public CHeapObj<mtInternal> {
  private:
   KlassInfoEntry* _next;
   Klass*          _klass;
   long            _instance_count;
   size_t          _instance_words;
+  long            _index;
 
  public:
   KlassInfoEntry(Klass* k, KlassInfoEntry* next) :
-    _klass(k), _instance_count(0), _instance_words(0), _next(next)
+    _klass(k), _instance_count(0), _instance_words(0), _next(next), _index(-1)
   {}
   KlassInfoEntry* next()     { return _next; }
   bool is_equal(Klass* k)  { return k == _klass; }
@@ -62,8 +196,11 @@
   void set_count(long ct)    { _instance_count = ct; }
   size_t words()             { return _instance_words; }
   void set_words(size_t wds) { _instance_words = wds; }
+  void set_index(long index) { _index = index; }
+  long index()               { return _index; }
   int compare(KlassInfoEntry* e1, KlassInfoEntry* e2);
   void print_on(outputStream* st) const;
+  const char* name() const;
 };
 
 class KlassInfoClosure: public StackObj {
@@ -95,45 +232,132 @@
 
   KlassInfoBucket* _buckets;
   uint hash(Klass* p);
-  KlassInfoEntry* lookup(Klass* const k);
+  KlassInfoEntry* lookup(Klass* const k); // allocates if not found!
+
+  class AllClassesFinder : public KlassClosure {
+    KlassInfoTable *_table;
+   public:
+    AllClassesFinder(KlassInfoTable* table) : _table(table) {}
+    virtual void do_klass(Klass* k);
+  };
 
  public:
   // Table size
   enum {
     cit_size = 20011
   };
-  KlassInfoTable(int size, HeapWord* ref);
+  KlassInfoTable(int size, HeapWord* ref, bool need_class_stats);
   ~KlassInfoTable();
   bool record_instance(const oop obj);
   void iterate(KlassInfoClosure* cic);
   bool allocation_failed() { return _buckets == NULL; }
+
+  friend class KlassInfoHisto;
 };
 
 class KlassInfoHisto : public StackObj {
  private:
+  KlassInfoTable *_cit;
   GrowableArray<KlassInfoEntry*>* _elements;
   GrowableArray<KlassInfoEntry*>* elements() const { return _elements; }
   const char* _title;
   const char* title() const { return _title; }
   static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2);
   void print_elements(outputStream* st) const;
+  void print_class_stats(outputStream* st, bool csv_format, const char *columns);
+  julong annotations_bytes(Array<AnnotationArray*>* p) const;
+  const char *_selected_columns;
+  bool is_selected(const char *col_name);
+  void print_title(outputStream* st, bool csv_format,
+                   bool selected_columns_table[], int width_table[],
+                   const char *name_table[]);
+
+  template <class T> static int count_bytes(T* x) {
+    return (HeapWordSize * ((x) ? (x)->size() : 0));
+  }
+
+  template <class T> static int count_bytes_array(T* x) {
+    if (x == NULL) {
+      return 0;
+    }
+    if (x->length() == 0) {
+      // This is a shared array, e.g., Universe::the_empty_int_array(). Don't
+      // count it to avoid double-counting.
+      return 0;
+    }
+    return HeapWordSize * x->size();
+  }
+
+  // returns a format string to print a julong with the given width. E.g,
+  // printf(num_fmt(6), julong(10)) would print out the number 10 with 4
+  // leading spaces.
+  static void print_julong(outputStream* st, int width, julong n) {
+    int num_spaces = width - julong_width(n);
+    if (num_spaces > 0) {
+      st->print(str_fmt(num_spaces), "");
+    }
+    st->print(JULONG_FORMAT, n);
+  }
+
+  static char* perc_fmt(int width) {
+    static char buf[32];
+    jio_snprintf(buf, sizeof(buf), "%%%d.1f%%%%", width-1);
+    return buf;
+  }
+
+  static char* str_fmt(int width) {
+    static char buf[32];
+    jio_snprintf(buf, sizeof(buf), "%%%ds", width);
+    return buf;
+  }
+
+  static int julong_width(julong n) {
+    if (n == 0) {
+      return 1;
+    }
+    int w = 0;
+    while (n > 0) {
+      n /= 10;
+      w += 1;
+    }
+    return w;
+  }
+
+  static int col_width(julong n, const char *name) {
+    int w = julong_width(n);
+    int min = (int)(strlen(name));
+    if (w < min) {
+        w = min;
+    }
+    // add a leading space for separation.
+    return w + 1;
+  }
+
  public:
   enum {
     histo_initial_size = 1000
   };
-  KlassInfoHisto(const char* title,
+  KlassInfoHisto(KlassInfoTable* cit, const char* title,
              int estimatedCount);
   ~KlassInfoHisto();
   void add(KlassInfoEntry* cie);
-  void print_on(outputStream* st) const;
+  void print_histo_on(outputStream* st, bool print_class_stats, bool csv_format, const char *columns);
   void sort();
 };
 
 #endif // INCLUDE_SERVICES
 
-class HeapInspection : public AllStatic {
+class HeapInspection : public StackObj {
+  bool _csv_format; // "comma separated values" format for spreadsheet.
+  bool _print_help;
+  bool _print_class_stats;
+  const char* _columns;
  public:
-  static void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN;
+  HeapInspection(bool csv_format, bool print_help,
+                 bool print_class_stats, const char *columns) :
+      _csv_format(csv_format), _print_help(print_help),
+      _print_class_stats(print_class_stats), _columns(columns) {}
+  void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN;
   static void find_instances_at_safepoint(Klass* k, GrowableArray<oop>* result) NOT_SERVICES_RETURN;
 };
 
--- a/src/share/vm/memory/metaspace.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/metaspace.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1064,11 +1064,11 @@
 //
 // After the GC the compute_new_size() for MetaspaceGC is called to
 // resize the capacity of the metaspaces.  The current implementation
-// is based on the flags MinHeapFreeRatio and MaxHeapFreeRatio used
+// is based on the flags MinMetaspaceFreeRatio and MaxHeapFreeRatio used
 // to resize the Java heap by some GC's.  New flags can be implemented
 // if really needed.  MinHeapFreeRatio is used to calculate how much
 // free space is desirable in the metaspace capacity to decide how much
-// to increase the HWM.  MaxHeapFreeRatio is used to decide how much
+// to increase the HWM.  MaxMetaspaceFreeRatio is used to decide how much
 // free space is desirable in the metaspace capacity before decreasing
 // the HWM.
 
@@ -1166,7 +1166,7 @@
   size_t capacity_until_GC = vsl->capacity_bytes_sum();
   size_t free_after_gc = capacity_until_GC - used_after_gc;
 
-  const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
+  const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0;
   const double maximum_used_percentage = 1.0 - minimum_free_percentage;
 
   const double min_tmp = used_after_gc / maximum_used_percentage;
@@ -1232,8 +1232,8 @@
     max_shrink_words));
 
   // Should shrinking be considered?
-  if (MaxHeapFreeRatio < 100) {
-    const double maximum_free_percentage = MaxHeapFreeRatio / 100.0;
+  if (MaxMetaspaceFreeRatio < 100) {
+    const double maximum_free_percentage = MaxMetaspaceFreeRatio / 100.0;
     const double minimum_used_percentage = 1.0 - maximum_free_percentage;
     const double max_tmp = used_after_gc / minimum_used_percentage;
     size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
@@ -1737,10 +1737,10 @@
     *class_chunk_word_size = ClassSmallChunk;
     break;
   }
-  assert(chunk_word_size != 0 && class_chunk_word_size != 0,
+  assert(*chunk_word_size != 0 && *class_chunk_word_size != 0,
     err_msg("Initial chunks sizes bad: data  " SIZE_FORMAT
             " class " SIZE_FORMAT,
-            chunk_word_size, class_chunk_word_size));
+            *chunk_word_size, *class_chunk_word_size));
 }
 
 size_t SpaceManager::sum_free_in_chunks_in_use() const {
@@ -2040,7 +2040,7 @@
            align_size_up(humongous_chunks->word_size(),
                              HumongousChunkGranularity),
            err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT
-                   " granularity " SIZE_FORMAT,
+                   " granularity %d",
                    humongous_chunks->word_size(), HumongousChunkGranularity));
     Metachunk* next_humongous_chunks = humongous_chunks->next();
     chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks);
@@ -2264,7 +2264,8 @@
   }
   MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
   assert(allocation_total() == sum_used_in_chunks_in_use(),
-    err_msg("allocation total is not consistent %d vs %d",
+    err_msg("allocation total is not consistent " SIZE_FORMAT
+            " vs " SIZE_FORMAT,
             allocation_total(), sum_used_in_chunks_in_use()));
 }
 
@@ -2578,7 +2579,8 @@
 // argument passed in is at the top of the compressed space
 void Metaspace::initialize_class_space(ReservedSpace rs) {
   // The reserved space size may be bigger because of alignment, esp with UseLargePages
-  assert(rs.size() >= ClassMetaspaceSize, err_msg("%d != %d", rs.size(), ClassMetaspaceSize));
+  assert(rs.size() >= ClassMetaspaceSize,
+         err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), ClassMetaspaceSize));
   _class_space_list = new VirtualSpaceList(rs);
 }
 
--- a/src/share/vm/memory/space.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/space.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -40,6 +40,7 @@
 #include "runtime/safepoint.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
 
 void SpaceMemRegionOopsIterClosure::do_oop(oop* p)       { SpaceMemRegionOopsIterClosure::do_oop_work(p); }
 void SpaceMemRegionOopsIterClosure::do_oop(narrowOop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); }
@@ -658,7 +659,7 @@
   }
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define ContigSpace_PAR_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)         \
                                                                             \
   void ContiguousSpace::par_oop_iterate(MemRegion mr, OopClosureType* blk) {\
@@ -673,7 +674,7 @@
   ALL_PAR_OOP_ITERATE_CLOSURES(ContigSpace_PAR_OOP_ITERATE_DEFN)
 
 #undef ContigSpace_PAR_OOP_ITERATE_DEFN
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 void ContiguousSpace::oop_iterate(ExtendedOopClosure* blk) {
   if (is_empty()) return;
--- a/src/share/vm/memory/space.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/space.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -34,6 +34,7 @@
 #include "oops/markOop.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/prefetch.hpp"
+#include "utilities/macros.hpp"
 #include "utilities/workgroup.hpp"
 #ifdef TARGET_OS_FAMILY_linux
 # include "os_linux.inline.hpp"
@@ -884,14 +885,14 @@
   }
 
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // In support of parallel oop_iterate.
   #define ContigSpace_PAR_OOP_ITERATE_DECL(OopClosureType, nv_suffix)  \
     void par_oop_iterate(MemRegion mr, OopClosureType* blk);
 
     ALL_PAR_OOP_ITERATE_CLOSURES(ContigSpace_PAR_OOP_ITERATE_DECL)
   #undef ContigSpace_PAR_OOP_ITERATE_DECL
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // Compaction support
   virtual void reset_after_compaction() {
--- a/src/share/vm/memory/specialized_oop_closures.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/specialized_oop_closures.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -26,9 +26,10 @@
 #define SHARE_VM_MEMORY_SPECIALIZED_OOP_CLOSURES_HPP
 
 #include "runtime/atomic.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1_specialized_oop_closures.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // The following OopClosure types get specialized versions of
 // "oop_oop_iterate" that invoke the closures' do_oop methods
@@ -80,20 +81,20 @@
   f(FastScanClosure,_nv)                                \
   f(FilteringClosure,_nv)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f)       \
   f(ParScanWithBarrierClosure,_nv)                      \
   f(ParScanWithoutBarrierClosure,_nv)
-#else  // SERIALGC
+#else  // INCLUDE_ALL_GCS
 #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f)       \
   f(NoHeaderExtendedOopClosure,_nv)                     \
   SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f)             \
   SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f)       \
   f(MarkRefsIntoAndScanClosure,_nv)                     \
   f(Par_MarkRefsIntoAndScanClosure,_nv)                 \
@@ -104,9 +105,9 @@
   f(CMSKeepAliveClosure,_nv)                            \
   f(CMSInnerParMarkAndPushClosure,_nv)                  \
   FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES(f)
-#else  // SERIALGC
+#else  // INCLUDE_ALL_GCS
 #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 
 // We separate these out, because sometime the general one has
@@ -120,7 +121,7 @@
 #define ALL_OOP_OOP_ITERATE_CLOSURES_2(f)               \
   SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 // This macro applies an argument macro to all OopClosures for which we
 // want specialized bodies of a family of methods related to
 // "par_oop_iterate".  The arguments to f are the same as above.
@@ -136,7 +137,7 @@
 #define ALL_PAR_OOP_ITERATE_CLOSURES(f)                \
   f(ExtendedOopClosure,_v)                             \
   SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 // This macro applies an argument macro to all OopClosures for which we
 // want specialized bodies of a family of methods related to
@@ -155,14 +156,14 @@
   f(ScanClosure,_nv)                                     \
   f(FastScanClosure,_nv)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) \
   f(ParScanWithBarrierClosure,_nv)                       \
   f(ParScanWithoutBarrierClosure,_nv)                    \
   FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f)
-#else  // SERIALGC
+#else  // INCLUDE_ALL_GCS
 #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f)  \
   SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f)      \
--- a/src/share/vm/memory/tenuredGeneration.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/tenuredGeneration.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -33,6 +33,7 @@
 #include "memory/tenuredGeneration.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/java.hpp"
+#include "utilities/macros.hpp"
 
 TenuredGeneration::TenuredGeneration(ReservedSpace rs,
                                      size_t initial_byte_size, int level,
@@ -61,7 +62,7 @@
   _space_counters = new CSpaceCounters(gen_name, 0,
                                        _virtual_space.reserved_size(),
                                        _the_space, _gen_counters);
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   if (UseParNewGC) {
     typedef ParGCAllocBufferWithBOT* ParGCAllocBufferWithBOTPtr;
     _alloc_buffers = NEW_C_HEAP_ARRAY(ParGCAllocBufferWithBOTPtr,
@@ -77,7 +78,7 @@
   } else {
     _alloc_buffers = NULL;
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 }
 
 
@@ -339,7 +340,7 @@
 }
 
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 oop TenuredGeneration::par_promote(int thread_num,
                                    oop old, markOop m, size_t word_sz) {
 
@@ -423,10 +424,10 @@
   }
 }
 
-#else  // SERIALGC
+#else  // INCLUDE_ALL_GCS
 void TenuredGeneration::retire_alloc_buffers_before_full_gc() {}
 void TenuredGeneration::verify_alloc_buffers_clean() {}
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 bool TenuredGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
   size_t available = max_contiguous_available();
--- a/src/share/vm/memory/tenuredGeneration.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/tenuredGeneration.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -29,6 +29,7 @@
 #include "gc_implementation/shared/gcStats.hpp"
 #include "gc_implementation/shared/generationCounters.hpp"
 #include "memory/generation.hpp"
+#include "utilities/macros.hpp"
 
 // TenuredGeneration models the heap containing old (promoted/tenured) objects.
 
@@ -45,11 +46,11 @@
   size_t _capacity_at_prologue;
   size_t _used_at_prologue;
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // To support parallel promotion: an array of parallel allocation
   // buffers, one per thread, initially NULL.
   ParGCAllocBufferWithBOT** _alloc_buffers;
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // Retire all alloc buffers before a full GC, so that they will be
   // re-allocated at the start of the next young GC.
@@ -93,14 +94,14 @@
                        size_t size,
                        bool is_tlab);
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // Overrides.
   virtual oop par_promote(int thread_num,
                           oop obj, markOop m, size_t word_sz);
   virtual void par_promote_alloc_undo(int thread_num,
                                       HeapWord* obj, size_t word_sz);
   virtual void par_promote_alloc_done(int thread_num);
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // Performance Counter support
   void update_counters();
--- a/src/share/vm/memory/universe.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/universe.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -70,13 +70,14 @@
 #include "utilities/events.hpp"
 #include "utilities/hashtable.inline.hpp"
 #include "utilities/preserveException.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp"
 #include "gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // Known objects
 Klass* Universe::_boolArrayKlassObj                 = NULL;
@@ -144,6 +145,7 @@
 NarrowPtrStruct Universe::_narrow_klass = { NULL, 0, true };
 address Universe::_narrow_ptrs_base;
 
+size_t          Universe::_class_metaspace_size;
 
 void Universe::basic_type_classes_do(void f(Klass*)) {
   f(boolArrayKlassObj());
@@ -689,8 +691,15 @@
     // Return specified base for the first request.
     if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) {
       base = HeapBaseMinAddress;
-    } else if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) {
-      if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) &&
+
+    // If the total size and the metaspace size are small enough to allow
+    // UnscaledNarrowOop then just use UnscaledNarrowOop.
+    } else if ((total_size <= OopEncodingHeapMax) && (mode != HeapBasedNarrowOop) &&
+        (!UseCompressedKlassPointers ||
+          (((OopEncodingHeapMax - heap_size) + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax))) {
+      // We don't need to check the metaspace size here because it is always smaller
+      // than total_size.
+      if ((total_size <= NarrowOopHeapMax) && (mode == UnscaledNarrowOop) &&
           (Universe::narrow_oop_shift() == 0)) {
         // Use 32-bits oops without encoding and
         // place heap's top on the 4Gb boundary
@@ -706,14 +715,24 @@
           base = (OopEncodingHeapMax - heap_size);
         }
       }
+
+    // See if ZeroBaseNarrowOop encoding will work for a heap based at
+    // (KlassEncodingMetaspaceMax - class_metaspace_size()).
+    } else if (UseCompressedKlassPointers && (mode != HeapBasedNarrowOop) &&
+        (Universe::class_metaspace_size() + HeapBaseMinAddress <= KlassEncodingMetaspaceMax) &&
+        (KlassEncodingMetaspaceMax + heap_size - Universe::class_metaspace_size() <= OopEncodingHeapMax)) {
+      base = (KlassEncodingMetaspaceMax - Universe::class_metaspace_size());
     } else {
-      // Can't reserve below 32Gb.
+      // UnscaledNarrowOop encoding didn't work, and no base was found for ZeroBasedOops or
+      // HeapBasedNarrowOop encoding was requested.  So, can't reserve below 32Gb.
       Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
     }
+
     // Set narrow_oop_base and narrow_oop_use_implicit_null_checks
     // used in ReservedHeapSpace() constructors.
     // The final values will be set in initialize_heap() below.
-    if (base != 0 && (base + heap_size) <= OopEncodingHeapMax) {
+    if ((base != 0) && ((base + heap_size) <= OopEncodingHeapMax) &&
+        (!UseCompressedKlassPointers || (base + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax)) {
       // Use zero based compressed oops
       Universe::set_narrow_oop_base(NULL);
       // Don't need guard page for implicit checks in indexed
@@ -740,20 +759,20 @@
 jint Universe::initialize_heap() {
 
   if (UseParallelGC) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     Universe::_collectedHeap = new ParallelScavengeHeap();
-#else  // SERIALGC
+#else  // INCLUDE_ALL_GCS
     fatal("UseParallelGC not supported in this VM.");
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   } else if (UseG1GC) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     G1CollectorPolicy* g1p = new G1CollectorPolicy();
     G1CollectedHeap* g1h = new G1CollectedHeap(g1p);
     Universe::_collectedHeap = g1h;
-#else  // SERIALGC
+#else  // INCLUDE_ALL_GCS
     fatal("UseG1GC not supported in java kernel vm.");
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   } else {
     GenCollectorPolicy *gc_policy;
@@ -761,15 +780,15 @@
     if (UseSerialGC) {
       gc_policy = new MarkSweepPolicy();
     } else if (UseConcMarkSweepGC) {
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
       if (UseAdaptiveSizePolicy) {
         gc_policy = new ASConcurrentMarkSweepPolicy();
       } else {
         gc_policy = new ConcurrentMarkSweepPolicy();
       }
-#else   // SERIALGC
+#else  // INCLUDE_ALL_GCS
     fatal("UseConcMarkSweepGC not supported in this VM.");
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
     } else { // default old generation
       gc_policy = new MarkSweepPolicy();
     }
@@ -796,7 +815,9 @@
       tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB",
                  Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M);
     }
-    if ((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) {
+    if (((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) ||
+        (UseCompressedKlassPointers &&
+        ((uint64_t)Universe::heap()->base() + Universe::class_metaspace_size() > KlassEncodingMetaspaceMax))) {
       // Can't reserve heap below 32Gb.
       // keep the Universe::narrow_oop_base() set in Universe::reserve_heap()
       Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
@@ -862,8 +883,8 @@
   // be compressed the same as instances.
   // Need to round class space size up because it's below the heap and
   // the actual alignment depends on its size.
-  size_t metaspace_size = align_size_up(ClassMetaspaceSize, alignment);
-  size_t total_reserved = align_size_up(heap_size + metaspace_size, alignment);
+  Universe::set_class_metaspace_size(align_size_up(ClassMetaspaceSize, alignment));
+  size_t total_reserved = align_size_up(heap_size + Universe::class_metaspace_size(), alignment);
   char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
 
   ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr);
@@ -904,8 +925,8 @@
   // compressed oops is greater than the one used for compressed klass
   // ptrs, a metadata space on top of the heap could become
   // unreachable.
-  ReservedSpace class_rs = total_rs.first_part(metaspace_size);
-  ReservedSpace heap_rs = total_rs.last_part(metaspace_size, alignment);
+  ReservedSpace class_rs = total_rs.first_part(Universe::class_metaspace_size());
+  ReservedSpace heap_rs = total_rs.last_part(Universe::class_metaspace_size(), alignment);
   Metaspace::initialize_class_space(class_rs);
 
   if (UseCompressedOops) {
--- a/src/share/vm/memory/universe.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/memory/universe.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -211,6 +211,9 @@
   static struct NarrowPtrStruct _narrow_klass;
   static address _narrow_ptrs_base;
 
+  // Aligned size of the metaspace.
+  static size_t _class_metaspace_size;
+
   // array of dummy objects used with +FullGCAlot
   debug_only(static objArrayOop _fullgc_alot_dummy_array;)
   // index of next entry to clear
@@ -278,6 +281,13 @@
   static bool     reserve_metaspace_helper(bool with_base = false);
   static ReservedHeapSpace reserve_heap_metaspace(size_t heap_size, size_t alignment, bool& contiguous);
 
+  static size_t  class_metaspace_size() {
+    return _class_metaspace_size;
+  }
+  static void    set_class_metaspace_size(size_t metaspace_size) {
+    _class_metaspace_size = metaspace_size;
+  }
+
   // Debugging
   static int _verify_count;                           // number of verifies done
   // True during call to verify().  Should only be set/cleared in verify().
--- a/src/share/vm/oops/annotations.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/annotations.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/classLoaderData.hpp"
+#include "memory/heapInspection.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/annotations.hpp"
@@ -35,16 +36,8 @@
   return new (loader_data, size(), true, THREAD) Annotations();
 }
 
-Annotations* Annotations::allocate(ClassLoaderData* loader_data,
-                                   Array<AnnotationArray*>* fa,
-                                   Array<AnnotationArray*>* ma,
-                                   Array<AnnotationArray*>* mpa,
-                                   Array<AnnotationArray*>* mda, TRAPS) {
-  return new (loader_data, size(), true, THREAD) Annotations(fa, ma, mpa, mda);
-}
-
 // helper
-static void free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p) {
+void Annotations::free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p) {
   if (p != NULL) {
     for (int i = 0; i < p->length(); i++) {
       MetadataFactory::free_array<u1>(loader_data, p->at(i));
@@ -58,44 +51,16 @@
     MetadataFactory::free_array<u1>(loader_data, class_annotations());
   }
   free_contents(loader_data, fields_annotations());
-  free_contents(loader_data, methods_annotations());
-  free_contents(loader_data, methods_parameter_annotations());
-  free_contents(loader_data, methods_default_annotations());
 
-  // Recursively deallocate optional Annotations linked through this one
-  MetadataFactory::free_metadata(loader_data, type_annotations());
+  if (class_type_annotations() != NULL) {
+    MetadataFactory::free_array<u1>(loader_data, class_type_annotations());
+  }
+  free_contents(loader_data, fields_type_annotations());
 }
 
-// Set the annotation at 'idnum' to 'anno'.
-// We don't want to create or extend the array if 'anno' is NULL, since that is the
-// default value.  However, if the array exists and is long enough, we must set NULL values.
-void Annotations::set_methods_annotations_of(instanceKlassHandle ik,
-                                             int idnum, AnnotationArray* anno,
-                                             Array<AnnotationArray*>** md_p,
-                                             TRAPS) {
-  Array<AnnotationArray*>* md = *md_p;
-  if (md != NULL && md->length() > idnum) {
-    md->at_put(idnum, anno);
-  } else if (anno != NULL) {
-    // create the array
-    int length = MAX2(idnum+1, (int)ik->idnum_allocated_count());
-    md = MetadataFactory::new_array<AnnotationArray*>(ik->class_loader_data(), length, CHECK);
-    if (*md_p != NULL) {
-      // copy the existing entries
-      for (int index = 0; index < (*md_p)->length(); index++) {
-        md->at_put(index, (*md_p)->at(index));
-      }
-    }
-    set_annotations(md, md_p);
-    md->at_put(idnum, anno);
-  } // if no array and idnum isn't included there is nothing to do
-}
-
-// Keep created annotations in a global growable array (should be hashtable)
-// need to add, search, delete when class is unloaded.
-// Does it need a lock?  yes.  This sucks.
-
 // Copy annotations to JVM call or reflection to the java heap.
+// The alternative to creating this array and adding to Java heap pressure
+// is to have a hashtable of the already created typeArrayOops
 typeArrayOop Annotations::make_java_array(AnnotationArray* annotations, TRAPS) {
   if (annotations != NULL) {
     int length = annotations->length();
@@ -114,14 +79,44 @@
   st->print("Anotations(" INTPTR_FORMAT ")", this);
 }
 
+#if INCLUDE_SERVICES
+// Size Statistics
+
+julong Annotations::count_bytes(Array<AnnotationArray*>* p) {
+  julong bytes = 0;
+  if (p != NULL) {
+    for (int i = 0; i < p->length(); i++) {
+      bytes += KlassSizeStats::count_array(p->at(i));
+    }
+    bytes += KlassSizeStats::count_array(p);
+  }
+  return bytes;
+}
+
+void Annotations::collect_statistics(KlassSizeStats *sz) const {
+  sz->_annotations_bytes = sz->count(this);
+  sz->_class_annotations_bytes = sz->count(class_annotations());
+  sz->_class_type_annotations_bytes = sz->count(class_type_annotations());
+  sz->_fields_annotations_bytes = count_bytes(fields_annotations());
+  sz->_fields_type_annotations_bytes = count_bytes(fields_type_annotations());
+
+  sz->_annotations_bytes +=
+      sz->_class_annotations_bytes +
+      sz->_class_type_annotations_bytes +
+      sz->_fields_annotations_bytes +
+      sz->_fields_type_annotations_bytes;
+
+  sz->_ro_bytes += sz->_annotations_bytes;
+}
+#endif // INCLUDE_SERVICES
+
 #define BULLET  " - "
 
 #ifndef PRODUCT
 void Annotations::print_on(outputStream* st) const {
   st->print(BULLET"class_annotations            "); class_annotations()->print_value_on(st);
   st->print(BULLET"fields_annotations           "); fields_annotations()->print_value_on(st);
-  st->print(BULLET"methods_annotations          "); methods_annotations()->print_value_on(st);
-  st->print(BULLET"methods_parameter_annotations"); methods_parameter_annotations()->print_value_on(st);
-  st->print(BULLET"methods_default_annotations  "); methods_default_annotations()->print_value_on(st);
+  st->print(BULLET"class_type_annotations       "); class_type_annotations()->print_value_on(st);
+  st->print(BULLET"fields_type_annotations      "); fields_type_annotations()->print_value_on(st);
 }
 #endif // PRODUCT
--- a/src/share/vm/oops/annotations.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/annotations.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@
 
 class ClassLoaderData;
 class outputStream;
+class KlassSizeStats;
 
 typedef Array<u1> AnnotationArray;
 
@@ -48,101 +49,46 @@
   // Annotation objects (byte arrays) for fields, or null if no annotations.
   // Indices correspond to entries (not indices) in fields array.
   Array<AnnotationArray*>*     _fields_annotations;
-  // Annotation objects (byte arrays) for methods, or null if no annotations.
-  // Index is the idnum, which is initially the same as the methods array index.
-  Array<AnnotationArray*>*     _methods_annotations;
-  // Annotation objects (byte arrays) for methods' parameters, or null if no
-  // such annotations.
-  // Index is the idnum, which is initially the same as the methods array index.
-  Array<AnnotationArray*>*     _methods_parameter_annotations;
-  // Annotation objects (byte arrays) for methods' default values, or null if no
-  // such annotations.
-  // Index is the idnum, which is initially the same as the methods array index.
-  Array<AnnotationArray*>*     _methods_default_annotations;
   // Type annotations for this class, or null if none.
-  Annotations*                 _type_annotations;
-
-  // Constructor where some some values are known to not be null
-  Annotations(Array<AnnotationArray*>* fa, Array<AnnotationArray*>* ma,
-              Array<AnnotationArray*>* mpa, Array<AnnotationArray*>* mda) :
-                 _class_annotations(NULL),
-                 _fields_annotations(fa),
-                 _methods_annotations(ma),
-                 _methods_parameter_annotations(mpa),
-                 _methods_default_annotations(mda),
-                 _type_annotations(NULL) {}
+  AnnotationArray*             _class_type_annotations;
+  Array<AnnotationArray*>*     _fields_type_annotations;
 
  public:
   // Allocate instance of this class
   static Annotations* allocate(ClassLoaderData* loader_data, TRAPS);
-  static Annotations* allocate(ClassLoaderData* loader_data,
-                               Array<AnnotationArray*>* fa,
-                               Array<AnnotationArray*>* ma,
-                               Array<AnnotationArray*>* mpa,
-                               Array<AnnotationArray*>* mda, TRAPS);
+
+  static void free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p);
   void deallocate_contents(ClassLoaderData* loader_data);
   DEBUG_ONLY(bool on_stack() { return false; })  // for template
+
+  // Sizing (in words)
   static int size()    { return sizeof(Annotations) / wordSize; }
+#if INCLUDE_SERVICES
+  void collect_statistics(KlassSizeStats *sz) const;
+#endif
 
   // Constructor to initialize to null
   Annotations() : _class_annotations(NULL),
                   _fields_annotations(NULL),
-                  _methods_annotations(NULL),
-                  _methods_parameter_annotations(NULL),
-                  _methods_default_annotations(NULL),
-                  _type_annotations(NULL) {}
+                  _class_type_annotations(NULL),
+                  _fields_type_annotations(NULL) {}
 
   AnnotationArray* class_annotations() const                       { return _class_annotations; }
   Array<AnnotationArray*>* fields_annotations() const              { return _fields_annotations; }
-  Array<AnnotationArray*>* methods_annotations() const             { return _methods_annotations; }
-  Array<AnnotationArray*>* methods_parameter_annotations() const   { return _methods_parameter_annotations; }
-  Array<AnnotationArray*>* methods_default_annotations() const     { return _methods_default_annotations; }
-  Annotations* type_annotations() const                            { return _type_annotations; }
+  AnnotationArray* class_type_annotations() const                  { return _class_type_annotations; }
+  Array<AnnotationArray*>* fields_type_annotations() const         { return _fields_type_annotations; }
 
   void set_class_annotations(AnnotationArray* md)                     { _class_annotations = md; }
   void set_fields_annotations(Array<AnnotationArray*>* md)            { _fields_annotations = md; }
-  void set_methods_annotations(Array<AnnotationArray*>* md)           { _methods_annotations = md; }
-  void set_methods_parameter_annotations(Array<AnnotationArray*>* md) { _methods_parameter_annotations = md; }
-  void set_methods_default_annotations(Array<AnnotationArray*>* md)   { _methods_default_annotations = md; }
-  void set_type_annotations(Annotations* annos)                       { _type_annotations = annos; }
-
-  // Redefine classes support
-  AnnotationArray* get_method_annotations_of(int idnum)
-                                                { return get_method_annotations_from(idnum, _methods_annotations); }
-
-  AnnotationArray* get_method_parameter_annotations_of(int idnum)
-                                                { return get_method_annotations_from(idnum, _methods_parameter_annotations); }
-  AnnotationArray* get_method_default_annotations_of(int idnum)
-                                                { return get_method_annotations_from(idnum, _methods_default_annotations); }
-
-
-  void set_method_annotations_of(instanceKlassHandle ik,
-                                 int idnum, AnnotationArray* anno, TRAPS) {
-    set_methods_annotations_of(ik, idnum, anno, &_methods_annotations, THREAD);
-  }
-
-  void set_method_parameter_annotations_of(instanceKlassHandle ik,
-                                 int idnum, AnnotationArray* anno, TRAPS) {
-    set_methods_annotations_of(ik, idnum, anno, &_methods_parameter_annotations, THREAD);
-  }
-
-  void set_method_default_annotations_of(instanceKlassHandle ik,
-                                 int idnum, AnnotationArray* anno, TRAPS) {
-    set_methods_annotations_of(ik, idnum, anno, &_methods_default_annotations, THREAD);
-  }
+  void set_class_type_annotations(AnnotationArray* cta)               { _class_type_annotations = cta; }
+  void set_fields_type_annotations(Array<AnnotationArray*>* fta)      { _fields_type_annotations = fta; }
 
   // Turn metadata annotations into a Java heap object (oop)
   static typeArrayOop make_java_array(AnnotationArray* annotations, TRAPS);
 
-  inline AnnotationArray* get_method_annotations_from(int idnum, Array<AnnotationArray*>* annos);
-  void set_annotations(Array<AnnotationArray*>* md, Array<AnnotationArray*>** md_p)  { *md_p = md; }
-
   bool is_klass() const { return false; }
  private:
-  void set_methods_annotations_of(instanceKlassHandle ik,
-                                  int idnum, AnnotationArray* anno,
-                                  Array<AnnotationArray*>** md_p, TRAPS);
-
+  static julong count_bytes(Array<AnnotationArray*>* p);
  public:
   const char* internal_name() const { return "{constant pool}"; }
 #ifndef PRODUCT
@@ -150,13 +96,4 @@
 #endif
   void print_value_on(outputStream* st) const;
 };
-
-
-// For method with idnum get the method's Annotations
-inline AnnotationArray* Annotations::get_method_annotations_from(int idnum, Array<AnnotationArray*>* annos) {
-  if (annos == NULL || annos->length() <= idnum) {
-    return NULL;
-  }
-  return annos->at(idnum);
-}
 #endif // SHARE_VM_OOPS_ANNOTATIONS_HPP
--- a/src/share/vm/oops/arrayKlass.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/arrayKlass.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -106,6 +106,14 @@
   static int header_size()                 { return sizeof(ArrayKlass)/HeapWordSize; }
   static int static_size(int header_size);
 
+#if INCLUDE_SERVICES
+  virtual void collect_statistics(KlassSizeStats *sz) const {
+    Klass::collect_statistics(sz);
+    // Do nothing for now, but remember to modify if you add new
+    // stuff to ArrayKlass.
+  }
+#endif
+
   // Java vtable
   klassVtable* vtable() const;             // return new klassVtable
   int  vtable_length() const               { return _vtable_len; }
--- a/src/share/vm/oops/constMethod.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/constMethod.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/gcLocker.hpp"
+#include "memory/heapInspection.hpp"
 #include "memory/metadataFactory.hpp"
 #include "oops/constMethod.hpp"
 #include "oops/method.hpp"
@@ -35,51 +36,26 @@
 
 ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
                                    int byte_code_size,
-                                   int compressed_line_number_size,
-                                   int localvariable_table_length,
-                                   int exception_table_length,
-                                   int checked_exceptions_length,
-                                   int method_parameters_length,
-                                   u2  generic_signature_index,
+                                   InlineTableSizes* sizes,
                                    MethodType method_type,
                                    TRAPS) {
-  int size = ConstMethod::size(byte_code_size,
-                               compressed_line_number_size,
-                               localvariable_table_length,
-                               exception_table_length,
-                               checked_exceptions_length,
-                               method_parameters_length,
-                               generic_signature_index);
+  int size = ConstMethod::size(byte_code_size, sizes);
   return new (loader_data, size, true, THREAD) ConstMethod(
-      byte_code_size, compressed_line_number_size, localvariable_table_length,
-      exception_table_length, checked_exceptions_length,
-      method_parameters_length, generic_signature_index,
-      method_type, size);
+      byte_code_size, sizes, method_type, size);
 }
 
 ConstMethod::ConstMethod(int byte_code_size,
-                         int compressed_line_number_size,
-                         int localvariable_table_length,
-                         int exception_table_length,
-                         int checked_exceptions_length,
-                         int method_parameters_length,
-                         u2  generic_signature_index,
+                         InlineTableSizes* sizes,
                          MethodType method_type,
                          int size) {
 
   No_Safepoint_Verifier no_safepoint;
-  set_interpreter_kind(Interpreter::invalid);
   init_fingerprint();
   set_constants(NULL);
   set_stackmap_data(NULL);
   set_code_size(byte_code_size);
   set_constMethod_size(size);
-  set_inlined_tables_length(generic_signature_index,
-                            checked_exceptions_length,
-                            compressed_line_number_size,
-                            localvariable_table_length,
-                            exception_table_length,
-                            method_parameters_length);
+  set_inlined_tables_length(sizes);
   set_method_type(method_type);
   assert(this->size() == size, "wrong size for object");
 }
@@ -87,47 +63,70 @@
 
 // Deallocate metadata fields associated with ConstMethod*
 void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
-  set_interpreter_kind(Interpreter::invalid);
   if (stackmap_data() != NULL) {
     MetadataFactory::free_array<u1>(loader_data, stackmap_data());
   }
   set_stackmap_data(NULL);
+
+  // deallocate annotation arrays
+  if (has_method_annotations())
+    MetadataFactory::free_array<u1>(loader_data, method_annotations());
+  if (has_parameter_annotations())
+    MetadataFactory::free_array<u1>(loader_data, parameter_annotations());
+  if (has_type_annotations())
+    MetadataFactory::free_array<u1>(loader_data, type_annotations());
+  if (has_default_annotations())
+    MetadataFactory::free_array<u1>(loader_data, default_annotations());
 }
 
 // How big must this constMethodObject be?
 
 int ConstMethod::size(int code_size,
-                      int compressed_line_number_size,
-                      int local_variable_table_length,
-                      int exception_table_length,
-                      int checked_exceptions_length,
-                      int method_parameters_length,
-                      u2  generic_signature_index) {
+                      InlineTableSizes* sizes) {
   int extra_bytes = code_size;
-  if (compressed_line_number_size > 0) {
-    extra_bytes += compressed_line_number_size;
+  if (sizes->compressed_linenumber_size() > 0) {
+    extra_bytes += sizes->compressed_linenumber_size();
   }
-  if (checked_exceptions_length > 0) {
+  if (sizes->checked_exceptions_length() > 0) {
     extra_bytes += sizeof(u2);
-    extra_bytes += checked_exceptions_length * sizeof(CheckedExceptionElement);
+    extra_bytes += sizes->checked_exceptions_length() * sizeof(CheckedExceptionElement);
   }
-  if (local_variable_table_length > 0) {
+  if (sizes->localvariable_table_length() > 0) {
     extra_bytes += sizeof(u2);
     extra_bytes +=
-              local_variable_table_length * sizeof(LocalVariableTableElement);
+              sizes->localvariable_table_length() * sizeof(LocalVariableTableElement);
   }
-  if (exception_table_length > 0) {
+  if (sizes->exception_table_length() > 0) {
     extra_bytes += sizeof(u2);
-    extra_bytes += exception_table_length * sizeof(ExceptionTableElement);
+    extra_bytes += sizes->exception_table_length() * sizeof(ExceptionTableElement);
   }
-  if (generic_signature_index != 0) {
+  if (sizes->generic_signature_index() != 0) {
     extra_bytes += sizeof(u2);
   }
-  if (method_parameters_length > 0) {
+  if (sizes->method_parameters_length() > 0) {
     extra_bytes += sizeof(u2);
-    extra_bytes += method_parameters_length * sizeof(MethodParametersElement);
+    extra_bytes += sizes->method_parameters_length() * sizeof(MethodParametersElement);
+  }
+
+  // Align sizes up to a word.
+  extra_bytes = align_size_up(extra_bytes, BytesPerWord);
+
+  // One pointer per annotation array
+  if (sizes->method_annotations_length() > 0) {
+    extra_bytes += sizeof(AnnotationArray*);
   }
+  if (sizes->parameter_annotations_length() > 0) {
+    extra_bytes += sizeof(AnnotationArray*);
+  }
+  if (sizes->type_annotations_length() > 0) {
+    extra_bytes += sizeof(AnnotationArray*);
+  }
+  if (sizes->default_annotations_length() > 0) {
+    extra_bytes += sizeof(AnnotationArray*);
+  }
+
   int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
+  assert(extra_words == extra_bytes/BytesPerWord, "should already be aligned");
   return align_object_size(header_size() + extra_words);
 }
 
@@ -144,12 +143,28 @@
   return code_end();
 }
 
+// Last short in ConstMethod* before annotations
+u2* ConstMethod::last_u2_element() const {
+  int offset = 0;
+  if (has_method_annotations()) offset++;
+  if (has_parameter_annotations()) offset++;
+  if (has_type_annotations()) offset++;
+  if (has_default_annotations()) offset++;
+  return (u2*)((AnnotationArray**)constMethod_end() - offset) - 1;
+}
+
 u2* ConstMethod::generic_signature_index_addr() const {
   // Located at the end of the constMethod.
   assert(has_generic_signature(), "called only if generic signature exists");
   return last_u2_element();
 }
 
+u2* ConstMethod::method_parameters_length_addr() const {
+  assert(has_method_parameters(), "called only if table is present");
+  return has_generic_signature() ? (last_u2_element() - 1) :
+                                    last_u2_element();
+}
+
 u2* ConstMethod::checked_exceptions_length_addr() const {
   // Located immediately before the generic signature index.
   assert(has_checked_exceptions(), "called only if table is present");
@@ -163,12 +178,6 @@
   }
 }
 
-u2* ConstMethod::method_parameters_length_addr() const {
-  assert(has_method_parameters(), "called only if table is present");
-  return has_generic_signature() ? (last_u2_element() - 1) :
-                                    last_u2_element();
-}
-
 u2* ConstMethod::exception_table_length_addr() const {
   assert(has_exception_handler(), "called only if table is present");
   if (has_checked_exceptions()) {
@@ -180,9 +189,9 @@
       return (u2*)method_parameters_start() - 1;
     } else {
       // Else, the exception table is at the end of the constMethod.
-    return has_generic_signature() ? (last_u2_element() - 1) :
-                                      last_u2_element();
-  }
+      return has_generic_signature() ? (last_u2_element() - 1) :
+                                        last_u2_element();
+    }
   }
 }
 
@@ -203,32 +212,38 @@
         // Else, the exception table is at the end of the constMethod.
       return has_generic_signature() ? (last_u2_element() - 1) :
                                         last_u2_element();
+      }
     }
   }
-  }
 }
 
 // Update the flags to indicate the presence of these optional fields.
-void ConstMethod::set_inlined_tables_length(u2  generic_signature_index,
-                                            int checked_exceptions_len,
-                                            int compressed_line_number_size,
-                                            int localvariable_table_len,
-                                            int exception_table_len,
-                                            int method_parameters_len) {
-  assert(_flags == 0, "Error");
-  if (compressed_line_number_size > 0)
+void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) {
+  _flags = 0;
+  if (sizes->compressed_linenumber_size() > 0)
     _flags |= _has_linenumber_table;
-  if (generic_signature_index != 0)
+  if (sizes->generic_signature_index() != 0)
     _flags |= _has_generic_signature;
-  if (method_parameters_len > 0)
+  if (sizes->method_parameters_length() > 0)
     _flags |= _has_method_parameters;
-  if (checked_exceptions_len > 0)
+  if (sizes->checked_exceptions_length() > 0)
     _flags |= _has_checked_exceptions;
-  if (exception_table_len > 0)
+  if (sizes->exception_table_length() > 0)
     _flags |= _has_exception_table;
-  if (localvariable_table_len > 0)
+  if (sizes->localvariable_table_length() > 0)
     _flags |= _has_localvariable_table;
 
+  // annotations, they are all pointer sized embedded objects so don't have
+  // a length embedded also.
+  if (sizes->method_annotations_length() > 0)
+    _flags |= _has_method_annotations;
+  if (sizes->parameter_annotations_length() > 0)
+    _flags |= _has_parameter_annotations;
+  if (sizes->type_annotations_length() > 0)
+    _flags |= _has_type_annotations;
+  if (sizes->default_annotations_length() > 0)
+    _flags |= _has_default_annotations;
+
   // This code is extremely brittle and should possibly be revised.
   // The *_length_addr functions walk backwards through the
   // constMethod data, using each of the length indexes ahead of them,
@@ -241,17 +256,17 @@
   // Also, the servicability agent needs to be informed anytime
   // anything is added here.  It might be advisable to have some sort
   // of indication of this inline.
-  if (generic_signature_index != 0)
-    *(generic_signature_index_addr()) = generic_signature_index;
+  if (sizes->generic_signature_index() != 0)
+    *(generic_signature_index_addr()) = sizes->generic_signature_index();
   // New data should probably go here.
-  if (method_parameters_len > 0)
-    *(method_parameters_length_addr()) = method_parameters_len;
-  if (checked_exceptions_len > 0)
-    *(checked_exceptions_length_addr()) = checked_exceptions_len;
-  if (exception_table_len > 0)
-    *(exception_table_length_addr()) = exception_table_len;
-  if (localvariable_table_len > 0)
-    *(localvariable_table_length_addr()) = localvariable_table_len;
+  if (sizes->method_parameters_length() > 0)
+    *(method_parameters_length_addr()) = sizes->method_parameters_length();
+  if (sizes->checked_exceptions_length() > 0)
+    *(checked_exceptions_length_addr()) = sizes->checked_exceptions_length();
+  if (sizes->exception_table_length() > 0)
+    *(exception_table_length_addr()) = sizes->exception_table_length();
+  if (sizes->localvariable_table_length() > 0)
+    *(localvariable_table_length_addr()) = sizes->localvariable_table_length();
 }
 
 int ConstMethod::method_parameters_length() const {
@@ -306,6 +321,34 @@
   return (ExceptionTableElement*)addr;
 }
 
+AnnotationArray** ConstMethod::method_annotations_addr() const {
+  assert(has_method_annotations(), "should only be called if method annotations are present");
+  return (AnnotationArray**)constMethod_end() - 1;
+}
+
+AnnotationArray** ConstMethod::parameter_annotations_addr() const {
+  assert(has_parameter_annotations(), "should only be called if method parameter annotations are present");
+  int offset = 1;
+  if (has_method_annotations()) offset++;
+  return (AnnotationArray**)constMethod_end() - offset;
+}
+
+AnnotationArray** ConstMethod::type_annotations_addr() const {
+  assert(has_type_annotations(), "should only be called if method type annotations are present");
+  int offset = 1;
+  if (has_method_annotations()) offset++;
+  if (has_parameter_annotations()) offset++;
+  return (AnnotationArray**)constMethod_end() - offset;
+}
+
+AnnotationArray** ConstMethod::default_annotations_addr() const {
+  assert(has_default_annotations(), "should only be called if method default annotations are present");
+  int offset = 1;
+  if (has_method_annotations()) offset++;
+  if (has_parameter_annotations()) offset++;
+  if (has_type_annotations()) offset++;
+  return (AnnotationArray**)constMethod_end() - offset;
+}
 
 // Printing
 
@@ -330,6 +373,35 @@
   method()->print_value_on(st);
 }
 
+#if INCLUDE_SERVICES
+// Size Statistics
+void ConstMethod::collect_statistics(KlassSizeStats *sz) const {
+  int n1, n2, n3;
+  sz->_const_method_bytes += (n1 = sz->count(this));
+  sz->_bytecode_bytes     += (n2 = code_size());
+  sz->_stackmap_bytes     += (n3 = sz->count_array(stackmap_data()));
+
+  // Count method annotations
+  int a1 = 0, a2 = 0, a3 = 0, a4 = 0;
+  if (has_method_annotations()) {
+    sz->_methods_annotations_bytes += (a1 = sz->count_array(method_annotations()));
+  }
+  if (has_parameter_annotations()) {
+    sz->_methods_parameter_annotations_bytes += (a2 = sz->count_array(parameter_annotations()));
+  }
+  if (has_type_annotations()) {
+    sz->_methods_type_annotations_bytes += (a3 = sz->count_array(type_annotations()));
+  }
+  if (has_default_annotations()) {
+    sz->_methods_default_annotations_bytes += (a4 = sz->count_array(default_annotations()));
+  }
+
+  int size_annotations = a1 + a2 + a3 + a4;
+
+  sz->_method_all_bytes += n1 + n3 + size_annotations; // note: n2 is part of n3
+  sz->_ro_bytes += n1 + n3 + size_annotations;
+}
+#endif // INCLUDE_SERVICES
 
 // Verification
 
@@ -339,10 +411,9 @@
 
   // Verification can occur during oop construction before the method or
   // other fields have been initialized.
-  guarantee(is_metadata(), err_msg("Should be metadata " PTR_FORMAT, this));
   guarantee(method()->is_method(), "should be method");
 
-  address m_end = (address)((oop*) this + size());
+  address m_end = (address)((intptr_t) this + size());
   address compressed_table_start = code_end();
   guarantee(compressed_table_start <= m_end, "invalid method layout");
   address compressed_table_end = compressed_table_start;
--- a/src/share/vm/oops/constMethod.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/constMethod.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -86,19 +86,22 @@
 // | generic signature index (u2)                         |
 // |  (indexed from start of constMethodOop)              |
 // |------------------------------------------------------|
+// | annotations arrays - method, parameter, type, default|
+// | pointer to Array<u1> if annotation is present        |
+// |------------------------------------------------------|
 //
 // IMPORTANT: If anything gets added here, there need to be changes to
 // ensure that ServicabilityAgent doesn't get broken as a result!
 
 
-// Utitily class decribing elements in checked exceptions table inlined in Method*.
+// Utility class describing elements in checked exceptions table inlined in Method*.
 class CheckedExceptionElement VALUE_OBJ_CLASS_SPEC {
  public:
   u2 class_cp_index;
 };
 
 
-// Utitily class decribing elements in local variable table inlined in Method*.
+// Utility class describing elements in local variable table inlined in Method*.
 class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
  public:
   u2 start_bci;
@@ -109,7 +112,7 @@
   u2 slot;
 };
 
-// Utitily class describing elements in exception table
+// Utility class describing elements in exception table
 class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
  public:
   u2 start_pc;
@@ -122,14 +125,55 @@
 class MethodParametersElement VALUE_OBJ_CLASS_SPEC {
  public:
   u2 name_cp_index;
-  // This has to happen, otherwise it will cause SIGBUS from a
-  // misaligned u4 on some architectures (ie SPARC)
-  // because MethodParametersElements are only aligned mod 2
-  // within the ConstMethod container  u2 flags_hi;
-  u2 flags_hi;
-  u2 flags_lo;
+  u2 flags;
 };
 
+class KlassSizeStats;
+
+// Class to collect the sizes of ConstMethod inline tables
+#define INLINE_TABLES_DO(do_element)            \
+  do_element(localvariable_table_length)        \
+  do_element(compressed_linenumber_size)        \
+  do_element(exception_table_length)            \
+  do_element(checked_exceptions_length)         \
+  do_element(method_parameters_length)          \
+  do_element(generic_signature_index)           \
+  do_element(method_annotations_length)         \
+  do_element(parameter_annotations_length)      \
+  do_element(type_annotations_length)           \
+  do_element(default_annotations_length)
+
+#define INLINE_TABLE_DECLARE(sym)    int _##sym;
+#define INLINE_TABLE_PARAM(sym)      int sym,
+#define INLINE_TABLE_INIT(sym)       _##sym(sym),
+#define INLINE_TABLE_NULL(sym)       _##sym(0),
+#define INLINE_TABLE_ACCESSOR(sym)   int sym() const { return _##sym; }
+
+class InlineTableSizes : StackObj {
+  // declarations
+  INLINE_TABLES_DO(INLINE_TABLE_DECLARE)
+  int _end;
+ public:
+  InlineTableSizes(
+      INLINE_TABLES_DO(INLINE_TABLE_PARAM)
+      int end) :
+      INLINE_TABLES_DO(INLINE_TABLE_INIT)
+      _end(end) {}
+
+  // Default constructor for no inlined tables
+  InlineTableSizes() :
+      INLINE_TABLES_DO(INLINE_TABLE_NULL)
+      _end(0) {}
+
+  // Accessors
+  INLINE_TABLES_DO(INLINE_TABLE_ACCESSOR)
+};
+#undef INLINE_TABLE_ACCESSOR
+#undef INLINE_TABLE_NULL
+#undef INLINE_TABLE_INIT
+#undef INLINE_TABLE_PARAM
+#undef INLINE_TABLE_DECLARE
+
 
 class ConstMethod : public MetaspaceObj {
   friend class VMStructs;
@@ -139,13 +183,17 @@
 
 private:
   enum {
-    _has_linenumber_table = 1,
-    _has_checked_exceptions = 2,
-    _has_localvariable_table = 4,
-    _has_exception_table = 8,
-    _has_generic_signature = 16,
-    _has_method_parameters = 32,
-    _is_overpass = 64
+    _has_linenumber_table = 0x0001,
+    _has_checked_exceptions = 0x0002,
+    _has_localvariable_table = 0x0004,
+    _has_exception_table = 0x0008,
+    _has_generic_signature = 0x0010,
+    _has_method_parameters = 0x0020,
+    _is_overpass = 0x0040,
+    _has_method_annotations = 0x0080,
+    _has_parameter_annotations = 0x0100,
+    _has_type_annotations = 0x0200,
+    _has_default_annotations = 0x0400
   };
 
   // Bit vector of signature
@@ -162,8 +210,7 @@
   Array<u1>*        _stackmap_data;
 
   int               _constMethod_size;
-  jbyte             _interpreter_kind;
-  jbyte             _flags;
+  u2                _flags;
 
   // Size of Java bytecodes allocated immediately after Method*.
   u2                _code_size;
@@ -178,36 +225,21 @@
 
   // Constructor
   ConstMethod(int byte_code_size,
-              int compressed_line_number_size,
-              int localvariable_table_length,
-              int exception_table_length,
-              int checked_exceptions_length,
-              int method_parameters_length,
-              u2  generic_signature_index,
+              InlineTableSizes* sizes,
               MethodType is_overpass,
               int size);
 public:
 
   static ConstMethod* allocate(ClassLoaderData* loader_data,
                                int byte_code_size,
-                               int compressed_line_number_size,
-                               int localvariable_table_length,
-                               int exception_table_length,
-                               int checked_exceptions_length,
-                               int method_parameters_length,
-                               u2  generic_signature_index,
+                               InlineTableSizes* sizes,
                                MethodType mt,
                                TRAPS);
 
   bool is_constMethod() const { return true; }
 
   // Inlined tables
-  void set_inlined_tables_length(u2  generic_signature_index,
-                                 int checked_exceptions_len,
-                                 int compressed_line_number_size,
-                                 int localvariable_table_len,
-                                 int exception_table_len,
-                                 int method_parameters_length);
+  void set_inlined_tables_length(InlineTableSizes* sizes);
 
   bool has_generic_signature() const
     { return (_flags & _has_generic_signature) != 0; }
@@ -239,10 +271,6 @@
     }
   }
 
-
-  void set_interpreter_kind(int kind)      { _interpreter_kind = kind; }
-  int  interpreter_kind(void) const        { return _interpreter_kind; }
-
   // constant pool
   ConstantPool* constants() const        { return _constants; }
   void set_constants(ConstantPool* c)    { _constants = c; }
@@ -311,15 +339,13 @@
   }
 
   // Size needed
-  static int size(int code_size, int compressed_line_number_size,
-                  int local_variable_table_length,
-                  int exception_table_length,
-                  int checked_exceptions_length,
-                  int method_parameters_length,
-                  u2  generic_signature_index);
+  static int size(int code_size, InlineTableSizes* sizes);
 
   int size() const                    { return _constMethod_size;}
   void set_constMethod_size(int size)     { _constMethod_size = size; }
+#if INCLUDE_SERVICES
+  void collect_statistics(KlassSizeStats *sz) const;
+#endif
 
   // code size
   int code_size() const                          { return _code_size; }
@@ -355,6 +381,65 @@
   int method_parameters_length() const;
   MethodParametersElement* method_parameters_start() const;
 
+  // method annotations
+  bool has_method_annotations() const
+    { return (_flags & _has_method_annotations) != 0; }
+
+  bool has_parameter_annotations() const
+    { return (_flags & _has_parameter_annotations) != 0; }
+
+  bool has_type_annotations() const
+    { return (_flags & _has_type_annotations) != 0; }
+
+  bool has_default_annotations() const
+    { return (_flags & _has_default_annotations) != 0; }
+
+
+  AnnotationArray** method_annotations_addr() const;
+  AnnotationArray* method_annotations() const  {
+    return has_method_annotations() ? *(method_annotations_addr()) : NULL;
+  }
+  void set_method_annotations(AnnotationArray* anno) {
+    *(method_annotations_addr()) = anno;
+  }
+
+  AnnotationArray** parameter_annotations_addr() const;
+  AnnotationArray* parameter_annotations() const {
+    return has_parameter_annotations() ? *(parameter_annotations_addr()) : NULL;
+  }
+  void set_parameter_annotations(AnnotationArray* anno) {
+    *(parameter_annotations_addr()) = anno;
+  }
+
+  AnnotationArray** type_annotations_addr() const;
+  AnnotationArray* type_annotations() const {
+    return has_type_annotations() ? *(type_annotations_addr()) : NULL;
+  }
+  void set_type_annotations(AnnotationArray* anno) {
+    *(type_annotations_addr()) = anno;
+  }
+
+  AnnotationArray** default_annotations_addr() const;
+  AnnotationArray* default_annotations() const {
+    return has_default_annotations() ? *(default_annotations_addr()) : NULL;
+  }
+  void set_default_annotations(AnnotationArray* anno) {
+    *(default_annotations_addr()) = anno;
+  }
+
+  int method_annotations_length() const {
+    return has_method_annotations() ? method_annotations()->length() : 0;
+  }
+  int parameter_annotations_length() const {
+    return has_parameter_annotations() ? parameter_annotations()->length() : 0;
+  }
+  int type_annotations_length() const {
+    return has_type_annotations() ? type_annotations()->length() : 0;
+  }
+  int default_annotations_length() const {
+    return has_default_annotations() ? default_annotations()->length() : 0;
+  }
+
   // byte codes
   void    set_code(address code) {
     if (code_size() > 0) {
@@ -410,11 +495,10 @@
 
   // First byte after ConstMethod*
   address constMethod_end() const
-                          { return (address)((oop*)this + _constMethod_size); }
+                          { return (address)((intptr_t*)this + _constMethod_size); }
 
   // Last short in ConstMethod*
-  u2* last_u2_element() const
-                                         { return (u2*)constMethod_end() - 1; }
+  u2* last_u2_element() const;
 
  public:
   // Printing
--- a/src/share/vm/oops/constantPool.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/constantPool.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,16 +25,17 @@
 #include "precompiled.hpp"
 #include "classfile/classLoaderData.hpp"
 #include "classfile/javaClasses.hpp"
+#include "classfile/metadataOnStackMark.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "interpreter/linkResolver.hpp"
+#include "memory/heapInspection.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/constantPool.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/objArrayKlass.hpp"
-#include "prims/jvmtiRedefineClasses.hpp"
 #include "runtime/fieldType.hpp"
 #include "runtime/init.hpp"
 #include "runtime/javaCalls.hpp"
@@ -65,11 +66,10 @@
   set_operands(NULL);
   set_pool_holder(NULL);
   set_flags(0);
+
   // only set to non-zero if constant pool is merged by RedefineClasses
   set_version(0);
   set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock"));
-  // all fields are initialized; needed for GC
-  set_on_stack(false);
 
   // initialize tag array
   int length = tags->length();
@@ -100,18 +100,6 @@
   set_lock(NULL);
 }
 
-void ConstantPool::set_flag_at(FlagBit fb) {
-  const int MAX_STATE_CHANGES = 2;
-  for (int i = MAX_STATE_CHANGES + 10; i > 0; i--) {
-    int oflags = _flags;
-    int nflags = oflags | (1 << (int)fb);
-    if (Atomic::cmpxchg(nflags, &_flags, oflags) == oflags)
-      return;
-  }
-  assert(false, "failed to cmpxchg flags");
-  _flags |= (1 << (int)fb);     // better than nothing
-}
-
 objArrayOop ConstantPool::resolved_references() const {
   return (objArrayOop)JNIHandles::resolve(_resolved_references);
 }
@@ -707,10 +695,6 @@
     result_oop = string_at_impl(this_oop, index, cache_index, CHECK_NULL);
     break;
 
-  case JVM_CONSTANT_Object:
-    result_oop = this_oop->object_at(index);
-    break;
-
   case JVM_CONSTANT_MethodHandleInError:
   case JVM_CONSTANT_MethodTypeInError:
     {
@@ -1111,32 +1095,9 @@
 } // end compare_entry_to()
 
 
-// Copy this constant pool's entries at start_i to end_i (inclusive)
-// to the constant pool to_cp's entries starting at to_i. A total of
-// (end_i - start_i) + 1 entries are copied.
-void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i,
-       constantPoolHandle to_cp, int to_i, TRAPS) {
-
-  int dest_i = to_i;  // leave original alone for debug purposes
-
-  for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) {
-    copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK);
-
-    switch (from_cp->tag_at(src_i).value()) {
-    case JVM_CONSTANT_Double:
-    case JVM_CONSTANT_Long:
-      // double and long take two constant pool entries
-      src_i += 2;
-      dest_i += 2;
-      break;
-
-    default:
-      // all others take one constant pool entry
-      src_i++;
-      dest_i++;
-      break;
-    }
-  }
+void ConstantPool::copy_operands(constantPoolHandle from_cp,
+                                 constantPoolHandle to_cp,
+                                 TRAPS) {
 
   int from_oplen = operand_array_length(from_cp->operands());
   int old_oplen  = operand_array_length(to_cp->operands());
@@ -1164,7 +1125,7 @@
                                    (len = old_off) * sizeof(u2));
       fillp += len;
       // first part of src
-      Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(0),
+      Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(0),
                                    new_operands->adr_at(fillp),
                                    (len = from_off) * sizeof(u2));
       fillp += len;
@@ -1174,7 +1135,7 @@
                                    (len = old_len - old_off) * sizeof(u2));
       fillp += len;
       // second part of src
-      Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(from_off),
+      Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(from_off),
                                    new_operands->adr_at(fillp),
                                    (len = from_len - from_off) * sizeof(u2));
       fillp += len;
@@ -1192,8 +1153,39 @@
       to_cp->set_operands(new_operands);
     }
   }
+} // end copy_operands()
 
-} // end copy_cp_to()
+
+// Copy this constant pool's entries at start_i to end_i (inclusive)
+// to the constant pool to_cp's entries starting at to_i. A total of
+// (end_i - start_i) + 1 entries are copied.
+void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i,
+       constantPoolHandle to_cp, int to_i, TRAPS) {
+
+
+  int dest_i = to_i;  // leave original alone for debug purposes
+
+  for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) {
+    copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK);
+
+    switch (from_cp->tag_at(src_i).value()) {
+    case JVM_CONSTANT_Double:
+    case JVM_CONSTANT_Long:
+      // double and long take two constant pool entries
+      src_i += 2;
+      dest_i += 2;
+      break;
+
+    default:
+      // all others take one constant pool entry
+      src_i++;
+      dest_i++;
+      break;
+    }
+  }
+  copy_operands(from_cp, to_cp, CHECK);
+
+} // end copy_cp_to_impl()
 
 
 // Copy this constant pool's entry at from_i to the constant pool
@@ -1755,7 +1747,11 @@
 
 
 void ConstantPool::set_on_stack(const bool value) {
-  _on_stack = value;
+  if (value) {
+    _flags |= _on_stack;
+  } else {
+    _flags &= ~_on_stack;
+  }
   if (value) MetadataOnStackMark::record(this);
 }
 
@@ -1824,9 +1820,8 @@
   st->print_cr(internal_name());
   if (flags() != 0) {
     st->print(" - flags: 0x%x", flags());
-    if (has_pseudo_string()) st->print(" has_pseudo_string");
-    if (has_invokedynamic()) st->print(" has_invokedynamic");
     if (has_preresolution()) st->print(" has_preresolution");
+    if (on_stack()) st->print(" on_stack");
     st->cr();
   }
   if (pool_holder() != NULL) {
@@ -1868,13 +1863,14 @@
       st->print(" name_and_type_index=%d", uncached_name_and_type_ref_index_at(index));
       break;
     case JVM_CONSTANT_String :
-      unresolved_string_at(index)->print_value_on(st);
+      if (is_pseudo_string_at(index)) {
+        oop anObj = pseudo_string_at(index);
+        anObj->print_value_on(st);
+        st->print(" {0x%lx}", (address)anObj);
+      } else {
+        unresolved_string_at(index)->print_value_on(st);
+      }
       break;
-    case JVM_CONSTANT_Object : {
-      oop anObj = object_at(index);
-      anObj->print_value_on(st);
-      st->print(" {0x%lx}", (address)anObj);
-      } break;
     case JVM_CONSTANT_Integer :
       st->print("%d", int_at(index));
       break;
@@ -1938,8 +1934,6 @@
 void ConstantPool::print_value_on(outputStream* st) const {
   assert(is_constantPool(), "must be constantPool");
   st->print("constant pool [%d]", length());
-  if (has_pseudo_string()) st->print("/pseudo_string");
-  if (has_invokedynamic()) st->print("/invokedynamic");
   if (has_preresolution()) st->print("/preresolution");
   if (operands() != NULL)  st->print("/operands[%d]", operands()->length());
   print_address_on(st);
@@ -1954,6 +1948,20 @@
   }
 }
 
+#if INCLUDE_SERVICES
+// Size Statistics
+void ConstantPool::collect_statistics(KlassSizeStats *sz) const {
+  sz->_cp_all_bytes += (sz->_cp_bytes          = sz->count(this));
+  sz->_cp_all_bytes += (sz->_cp_tags_bytes     = sz->count_array(tags()));
+  sz->_cp_all_bytes += (sz->_cp_cache_bytes    = sz->count(cache()));
+  sz->_cp_all_bytes += (sz->_cp_operands_bytes = sz->count_array(operands()));
+  sz->_cp_all_bytes += (sz->_cp_refmap_bytes   = sz->count_array(reference_map()));
+
+  sz->_ro_bytes += sz->_cp_operands_bytes + sz->_cp_tags_bytes +
+                   sz->_cp_refmap_bytes;
+  sz->_rw_bytes += sz->_cp_bytes + sz->_cp_cache_bytes;
+}
+#endif // INCLUDE_SERVICES
 
 // Verification
 
--- a/src/share/vm/oops/constantPool.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/constantPool.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -80,6 +80,7 @@
   }
 };
 
+class KlassSizeStats;
 class ConstantPool : public Metadata {
   friend class VMStructs;
   friend class BytecodeInterpreter;  // Directly extracts an oop in the pool for fast instanceof/checkcast
@@ -95,11 +96,14 @@
   jobject              _resolved_references;
   Array<u2>*           _reference_map;
 
-  int                  _flags;         // a few header bits to describe contents for GC
+  enum {
+    _has_preresolution = 1,           // Flags
+    _on_stack          = 2
+  };
+
+  int                  _flags;  // old fashioned bit twiddling
   int                  _length; // number of elements in the array
 
-  bool                 _on_stack;     // Redefined method still executing refers to this constant pool.
-
   union {
     // set for CDS to restore resolved references
     int                _resolved_reference_length;
@@ -115,17 +119,8 @@
 
   void set_operands(Array<u2>* operands)       { _operands = operands; }
 
-  enum FlagBit {
-    FB_has_invokedynamic = 1,
-    FB_has_pseudo_string = 2,
-    FB_has_preresolution = 3
-  };
-
-  int flags() const                         { return _flags; }
-  void set_flags(int f)                     { _flags = f; }
-  bool flag_at(FlagBit fb) const            { return (_flags & (1 << (int)fb)) != 0; }
-  void set_flag_at(FlagBit fb);
-  // no clear_flag_at function; they only increase
+  int flags() const                            { return _flags; }
+  void set_flags(int f)                        { _flags = f; }
 
  private:
   intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); }
@@ -178,18 +173,14 @@
   Array<u1>* tags() const                   { return _tags; }
   Array<u2>* operands() const               { return _operands; }
 
-  bool has_pseudo_string() const            { return flag_at(FB_has_pseudo_string); }
-  bool has_invokedynamic() const            { return flag_at(FB_has_invokedynamic); }
-  bool has_preresolution() const            { return flag_at(FB_has_preresolution); }
-  void set_pseudo_string()                  {    set_flag_at(FB_has_pseudo_string); }
-  void set_invokedynamic()                  {    set_flag_at(FB_has_invokedynamic); }
-  void set_preresolution()                  {    set_flag_at(FB_has_preresolution); }
+  bool has_preresolution() const            { return (_flags & _has_preresolution) != 0; }
+  void set_has_preresolution()              { _flags |= _has_preresolution; }
 
   // Redefine classes support.  If a method refering to this constant pool
   // is on the executing stack, or as a handle in vm code, this constant pool
   // can't be removed from the set of previous versions saved in the instance
   // class.
-  bool on_stack() const                     { return _on_stack; }
+  bool on_stack() const                      { return (_flags &_on_stack) != 0; }
   void set_on_stack(const bool value);
 
   // Klass holding pool
@@ -325,14 +316,6 @@
     resolved_references()->obj_at_put(obj_index, str);
   }
 
-  void set_object_tag_at(int which) {
-    release_tag_at_put(which, JVM_CONSTANT_Object);
-    }
-
-  void object_at_put(int which, oop obj) {
-    resolved_references()->obj_at_put(cp_to_object_index(which), obj);
-  }
-
   // For temporary use while constructing constant pool
   void string_index_at_put(int which, int string_index) {
     tag_at_put(which, JVM_CONSTANT_StringIndex);
@@ -430,12 +413,6 @@
   // Version that can be used before string oop array is created.
   oop uncached_string_at(int which, TRAPS);
 
-  oop object_at(int which) {
-    assert(tag_at(which).is_object(), "Corrupted constant pool");
-    int obj_index = cp_to_object_index(which);
-    return resolved_references()->obj_at(obj_index);
-  }
-
   // A "pseudo-string" is an non-string oop that has found is way into
   // a String entry.
   // Under EnableInvokeDynamic this can happen if the user patches a live
@@ -455,10 +432,18 @@
     return s;
   }
 
+  oop pseudo_string_at(int which) {
+    assert(tag_at(which).is_string(), "Corrupted constant pool");
+    assert(unresolved_string_at(which) == NULL, "shouldn't have symbol");
+    int obj_index = cp_to_object_index(which);
+    oop s = resolved_references()->obj_at(obj_index);
+    return s;
+  }
+
   void pseudo_string_at_put(int which, int obj_index, oop x) {
     assert(EnableInvokeDynamic, "");
-    set_pseudo_string();        // mark header
     assert(tag_at(which).is_string(), "Corrupted constant pool");
+    unresolved_string_at_put(which, NULL); // indicates patched string
     string_at_put(which, obj_index, x);    // this works just fine
   }
 
@@ -686,9 +671,13 @@
     return 0 <= index && index < length();
   }
 
+  // Sizing (in words)
   static int header_size()             { return sizeof(ConstantPool)/HeapWordSize; }
   static int size(int length)          { return align_object_size(header_size() + length); }
   int size() const                     { return size(length()); }
+#if INCLUDE_SERVICES
+  void collect_statistics(KlassSizeStats *sz) const;
+#endif
 
   friend class ClassFileParser;
   friend class SystemDictionary;
@@ -785,6 +774,7 @@
   }
   static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS);
   static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS);
+  static void copy_operands(constantPoolHandle from_cp, constantPoolHandle to_cp, TRAPS);
   int  find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS);
   int  version() const                    { return _saved._version; }
   void set_version(int version)           { _saved._version = version; }
--- a/src/share/vm/oops/cpCache.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/cpCache.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,9 +33,10 @@
 #include "prims/jvmtiRedefineClassesTrace.hpp"
 #include "prims/methodHandles.hpp"
 #include "runtime/handles.inline.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 # include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 
 // Implememtation of ConstantPoolCacheEntry
@@ -401,8 +402,9 @@
 }
 
 
+#if INCLUDE_JVMTI
 // RedefineClasses() API support:
-// If this constantPoolCacheEntry refers to old_method then update it
+// If this ConstantPoolCacheEntry refers to old_method then update it
 // to refer to new_method.
 bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
        Method* new_method, bool * trace_name_printed) {
@@ -460,16 +462,24 @@
   return false;
 }
 
-#ifndef PRODUCT
-bool ConstantPoolCacheEntry::check_no_old_entries() {
+// a constant pool cache entry should never contain old or obsolete methods
+bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
   if (is_vfinal()) {
+    // virtual and final so _f2 contains method ptr instead of vtable index
     Metadata* f2 = (Metadata*)_f2;
-    return (f2->is_valid() && f2->is_method() && !((Method*)f2)->is_old());
-  } else {
-    return (_f1 == NULL || (_f1->is_valid() && _f1->is_method() && !((Method*)_f1)->is_old()));
+    // Return false if _f2 refers to an old or an obsolete method.
+    // _f2 == NULL || !_f2->is_method() are just as unexpected here.
+    return (f2 != NULL NOT_PRODUCT(&& f2->is_valid()) && f2->is_method() &&
+            !((Method*)f2)->is_old() && !((Method*)f2)->is_obsolete());
+  } else if (_f1 == NULL ||
+             (NOT_PRODUCT(_f1->is_valid() &&) !_f1->is_method())) {
+    // _f1 == NULL || !_f1->is_method() are OK here
+    return true;
   }
+  // return false if _f1 refers to an old or an obsolete method
+  return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() &&
+          !((Method*)_f1)->is_old() && !((Method*)_f1)->is_obsolete());
 }
-#endif
 
 bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
   if (!is_method_entry()) {
@@ -502,13 +512,15 @@
   // the method is in the interesting class so the entry is interesting
   return true;
 }
+#endif // INCLUDE_JVMTI
 
 void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
   // print separator
   if (index == 0) st->print_cr("                 -------------");
   // print entry
   st->print("%3d  ("PTR_FORMAT")  ", index, (intptr_t)this);
-    st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
+  st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(),
+               constant_pool_index());
   st->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)_f1);
   st->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)_f2);
   st->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)_flags);
@@ -552,8 +564,9 @@
   }
 }
 
+#if INCLUDE_JVMTI
 // RedefineClasses() API support:
-// If any entry of this constantPoolCache points to any of
+// If any entry of this ConstantPoolCache points to any of
 // old_methods, replace it with the corresponding new_method.
 void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new_methods,
                                                      int methods_length, bool * trace_name_printed) {
@@ -572,7 +585,7 @@
       continue;
     }
 
-    // The constantPoolCache contains entries for several different
+    // The ConstantPoolCache contains entries for several different
     // things, but we only care about methods. In fact, we only care
     // about methods in the same class as the one that contains the
     // old_methods. At this point, we have an interesting entry.
@@ -591,17 +604,25 @@
   }
 }
 
-#ifndef PRODUCT
-bool ConstantPoolCache::check_no_old_entries() {
+// the constant pool cache should never contain old or obsolete methods
+bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
   for (int i = 1; i < length(); i++) {
     if (entry_at(i)->is_interesting_method_entry(NULL) &&
-       !entry_at(i)->check_no_old_entries()) {
+        !entry_at(i)->check_no_old_or_obsolete_entries()) {
       return false;
     }
   }
   return true;
 }
-#endif // PRODUCT
+
+void ConstantPoolCache::dump_cache() {
+  for (int i = 1; i < length(); i++) {
+    if (entry_at(i)->is_interesting_method_entry(NULL)) {
+      entry_at(i)->print(tty, i);
+    }
+  }
+}
+#endif // INCLUDE_JVMTI
 
 
 // Printing
--- a/src/share/vm/oops/cpCache.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/cpCache.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -337,16 +337,18 @@
   static ByteSize f2_offset()                    { return byte_offset_of(ConstantPoolCacheEntry, _f2); }
   static ByteSize flags_offset()                 { return byte_offset_of(ConstantPoolCacheEntry, _flags); }
 
+#if INCLUDE_JVMTI
   // RedefineClasses() API support:
-  // If this constantPoolCacheEntry refers to old_method then update it
+  // If this ConstantPoolCacheEntry refers to old_method then update it
   // to refer to new_method.
   // trace_name_printed is set to true if the current call has
   // printed the klass name so that other routines in the adjust_*
   // group don't print the klass name.
   bool adjust_method_entry(Method* old_method, Method* new_method,
          bool * trace_name_printed);
-  NOT_PRODUCT(bool check_no_old_entries();)
+  bool check_no_old_or_obsolete_entries();
   bool is_interesting_method_entry(Klass* k);
+#endif // INCLUDE_JVMTI
 
   // Debugging & Printing
   void print (outputStream* st, int index) const;
@@ -423,15 +425,18 @@
     return (base_offset() + ConstantPoolCacheEntry::size_in_bytes() * index);
   }
 
+#if INCLUDE_JVMTI
   // RedefineClasses() API support:
-  // If any entry of this constantPoolCache points to any of
+  // If any entry of this ConstantPoolCache points to any of
   // old_methods, replace it with the corresponding new_method.
   // trace_name_printed is set to true if the current call has
   // printed the klass name so that other routines in the adjust_*
   // group don't print the klass name.
   void adjust_method_entries(Method** old_methods, Method** new_methods,
                              int methods_length, bool * trace_name_printed);
-  NOT_PRODUCT(bool check_no_old_entries();)
+  bool check_no_old_or_obsolete_entries();
+  void dump_cache();
+#endif // INCLUDE_JVMTI
 
   // Deallocate - no fields to deallocate
   DEBUG_ONLY(bool on_stack() { return false; })
--- a/src/share/vm/oops/generateOopMap.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/generateOopMap.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1853,7 +1853,6 @@
   if (tag.is_klass() ||
       tag.is_unresolved_klass() ||
       tag.is_string() ||
-      tag.is_object() ||
       tag.is_method_handle() ||
       tag.is_method_type()) {
     assert(bt == T_OBJECT, "Guard is incorrect");
--- a/src/share/vm/oops/instanceClassLoaderKlass.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/instanceClassLoaderKlass.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -36,12 +36,13 @@
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parNew/parOopClosures.inline.hpp"
 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
 #include "oops/oop.pcgc.inline.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 #define if_do_metadata_checked(closure, nv_suffix)                    \
   /* Make sure the non-virtual and the virtual versions match. */     \
@@ -73,7 +74,7 @@
   return size;                                                                  \
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
                                                                                 \
 int InstanceClassLoaderKlass::                                                  \
@@ -83,7 +84,7 @@
   int size = InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \
   return size;                                                                  \
 }
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 
 #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)      \
@@ -111,10 +112,10 @@
 
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN)
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m)
 
@@ -129,7 +130,7 @@
   }
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void InstanceClassLoaderKlass::oop_follow_contents(ParCompactionManager* cm,
         oop obj) {
   InstanceKlass::oop_follow_contents(cm, obj);
@@ -155,5 +156,5 @@
   }
   return size_helper();
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
--- a/src/share/vm/oops/instanceClassLoaderKlass.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/instanceClassLoaderKlass.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -26,6 +26,7 @@
 #define SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_HPP
 
 #include "oops/instanceKlass.hpp"
+#include "utilities/macros.hpp"
 
 // An InstanceClassLoaderKlass is a specialization of the InstanceKlass. It does
 // not add any field.  It is added to walk the dependencies for the class loader
@@ -61,13 +62,13 @@
   ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL)
   ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix)      \
   int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk);
 
   ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
   ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
     // Garbage collection
   void oop_follow_contents(oop obj);
--- a/src/share/vm/oops/instanceKlass.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/instanceKlass.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@
 #include "interpreter/rewriter.hpp"
 #include "jvmtifiles/jvmti.h"
 #include "memory/genOopClosures.inline.hpp"
+#include "memory/heapInspection.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/fieldStreams.hpp"
@@ -55,7 +56,8 @@
 #include "runtime/thread.inline.hpp"
 #include "services/threadService.hpp"
 #include "utilities/dtrace.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
@@ -66,7 +68,7 @@
 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
 #include "oops/oop.pcgc.inline.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_Compiler.hpp"
 #endif
@@ -164,20 +166,19 @@
 volatile int InstanceKlass::_total_instanceKlass_count = 0;
 
 Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
-                                                int vtable_len,
-                                                int itable_len,
-                                                int static_field_size,
-                                                int nonstatic_oop_map_size,
-                                                ReferenceType rt,
-                                                AccessFlags access_flags,
-                                                Symbol* name,
+                                              int vtable_len,
+                                              int itable_len,
+                                              int static_field_size,
+                                              int nonstatic_oop_map_size,
+                                              ReferenceType rt,
+                                              AccessFlags access_flags,
+                                              Symbol* name,
                                               Klass* super_klass,
-                                                KlassHandle host_klass,
-                                                TRAPS) {
+                                              bool is_anonymous,
+                                              TRAPS) {
 
   int size = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
-                                 access_flags.is_interface(),
-                                 !host_klass.is_null());
+                                 access_flags.is_interface(), is_anonymous);
 
   // Allocation
   InstanceKlass* ik;
@@ -185,25 +186,25 @@
     if (name == vmSymbols::java_lang_Class()) {
       ik = new (loader_data, size, THREAD) InstanceMirrorKlass(
         vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
-        access_flags, !host_klass.is_null());
+        access_flags, is_anonymous);
     } else if (name == vmSymbols::java_lang_ClassLoader() ||
           (SystemDictionary::ClassLoader_klass_loaded() &&
           super_klass != NULL &&
           super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass()))) {
       ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(
         vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
-        access_flags, !host_klass.is_null());
+        access_flags, is_anonymous);
     } else {
       // normal class
       ik = new (loader_data, size, THREAD) InstanceKlass(
         vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
-        access_flags, !host_klass.is_null());
+        access_flags, is_anonymous);
     }
   } else {
     // reference klass
     ik = new (loader_data, size, THREAD) InstanceRefKlass(
         vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
-        access_flags, !host_klass.is_null());
+        access_flags, is_anonymous);
   }
 
   Atomic::inc(&_total_instanceKlass_count);
@@ -2042,7 +2043,7 @@
     assert_is_in_closed_subset)
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void InstanceKlass::oop_follow_contents(ParCompactionManager* cm,
                                         oop obj) {
   assert(obj != NULL, "can't follow the content of NULL object");
@@ -2054,7 +2055,7 @@
     PSParallelCompact::mark_and_push(cm, p), \
     assert_is_in)
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 // closure's do_metadata() method dictates whether the given closure should be
 // applied to the klass ptr in the object header.
@@ -2082,7 +2083,7 @@
   return size_helper();                                                 \
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
                                                                                 \
 int InstanceKlass::oop_oop_iterate_backwards##nv_suffix(oop obj,                \
@@ -2100,7 +2101,7 @@
     assert_is_in_closed_subset)                                                 \
    return size_helper();                                                        \
 }
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #define InstanceKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \
                                                                         \
@@ -2124,10 +2125,10 @@
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN)
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN_m)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN_m)
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 int InstanceKlass::oop_adjust_pointers(oop obj) {
   int size = size_helper();
@@ -2139,7 +2140,7 @@
   return size;
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void InstanceKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   InstanceKlass_OOP_MAP_REVERSE_ITERATE( \
     obj, \
@@ -2159,7 +2160,7 @@
   return size;
 }
 
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
   assert(is_loader_alive(is_alive), "this klass should be live");
@@ -2791,7 +2792,10 @@
     st->print("%s", source_debug_extension());
     st->cr();
   }
-  st->print(BULLET"annotations:       "); annotations()->print_value_on(st); st->cr();
+  st->print(BULLET"class annotations:       "); class_annotations()->print_value_on(st); st->cr();
+  st->print(BULLET"class type annotations:  "); class_type_annotations()->print_value_on(st); st->cr();
+  st->print(BULLET"field annotations:       "); fields_annotations()->print_value_on(st); st->cr();
+  st->print(BULLET"field type annotations:  "); fields_type_annotations()->print_value_on(st); st->cr();
   {
     ResourceMark rm;
     // PreviousVersionInfo objects returned via PreviousVersionWalker
@@ -2960,6 +2964,52 @@
   return external_name();
 }
 
+#if INCLUDE_SERVICES
+// Size Statistics
+void InstanceKlass::collect_statistics(KlassSizeStats *sz) const {
+  Klass::collect_statistics(sz);
+
+  sz->_inst_size  = HeapWordSize * size_helper();
+  sz->_vtab_bytes = HeapWordSize * align_object_offset(vtable_length());
+  sz->_itab_bytes = HeapWordSize * align_object_offset(itable_length());
+  sz->_nonstatic_oopmap_bytes = HeapWordSize *
+        ((is_interface() || is_anonymous()) ?
+         align_object_offset(nonstatic_oop_map_size()) :
+         nonstatic_oop_map_size());
+
+  int n = 0;
+  n += (sz->_methods_array_bytes         = sz->count_array(methods()));
+  n += (sz->_method_ordering_bytes       = sz->count_array(method_ordering()));
+  n += (sz->_local_interfaces_bytes      = sz->count_array(local_interfaces()));
+  n += (sz->_transitive_interfaces_bytes = sz->count_array(transitive_interfaces()));
+  n += (sz->_signers_bytes               = sz->count_array(signers()));
+  n += (sz->_fields_bytes                = sz->count_array(fields()));
+  n += (sz->_inner_classes_bytes         = sz->count_array(inner_classes()));
+  sz->_ro_bytes += n;
+
+  const ConstantPool* cp = constants();
+  if (cp) {
+    cp->collect_statistics(sz);
+  }
+
+  const Annotations* anno = annotations();
+  if (anno) {
+    anno->collect_statistics(sz);
+  }
+
+  const Array<Method*>* methods_array = methods();
+  if (methods()) {
+    for (int i = 0; i < methods_array->length(); i++) {
+      Method* method = methods_array->at(i);
+      if (method) {
+        sz->_method_count ++;
+        method->collect_statistics(sz);
+      }
+    }
+  }
+}
+#endif // INCLUDE_SERVICES
+
 // Verification
 
 class VerifyFieldClosure: public OopClosure {
--- a/src/share/vm/oops/instanceKlass.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/instanceKlass.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
 #include "runtime/os.hpp"
 #include "utilities/accessFlags.hpp"
 #include "utilities/bitMap.inline.hpp"
+#include "utilities/macros.hpp"
 
 // An InstanceKlass is the VM level representation of a Java class.
 // It contains all information needed for at class at execution runtime.
@@ -154,8 +155,8 @@
                                           ReferenceType rt,
                                           AccessFlags access_flags,
                                           Symbol* name,
-                                        Klass* super_klass,
-                                          KlassHandle host_klass,
+                                          Klass* super_klass,
+                                          bool is_anonymous,
                                           TRAPS);
 
   InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
@@ -256,6 +257,16 @@
   // JVMTI fields can be moved to their own structure - see 6315920
   unsigned char * _cached_class_file_bytes;       // JVMTI: cached class file, before retransformable agent modified it in CFLH
   jint            _cached_class_file_len;         // JVMTI: length of above
+
+  volatile u2     _idnum_allocated_count;         // JNI/JVMTI: increments with the addition of methods, old ids don't change
+
+  // Class states are defined as ClassState (see above).
+  // Place the _init_state here to utilize the unused 2-byte after
+  // _idnum_allocated_count.
+  u1              _init_state;                    // state of class
+  u1              _reference_type;                // reference type
+
+
   JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map;  // JVMTI: used during heap iteration
 
   // Method array.
@@ -281,15 +292,6 @@
   //     ...
   Array<u2>*      _fields;
 
-  volatile u2     _idnum_allocated_count;         // JNI/JVMTI: increments with the addition of methods, old ids don't change
-
-  // Class states are defined as ClassState (see above).
-  // Place the _init_state here to utilize the unused 2-byte after
-  // _idnum_allocated_count.
-  u1              _init_state;                    // state of class
-
-  u1              _reference_type;                // reference type
-
   // embedded Java vtable follows here
   // embedded Java itables follows here
   // embedded static fields follows here
@@ -677,19 +679,19 @@
   // annotations support
   Annotations* annotations() const          { return _annotations; }
   void set_annotations(Annotations* anno)   { _annotations = anno; }
+
   AnnotationArray* class_annotations() const {
-    if (annotations() == NULL) return NULL;
-    return annotations()->class_annotations();
+    return (_annotations != NULL) ? _annotations->class_annotations() : NULL;
   }
   Array<AnnotationArray*>* fields_annotations() const {
-    if (annotations() == NULL) return NULL;
-    return annotations()->fields_annotations();
+    return (_annotations != NULL) ? _annotations->fields_annotations() : NULL;
   }
-  Annotations* type_annotations() const {
-    if (annotations() == NULL) return NULL;
-    return annotations()->type_annotations();
+  AnnotationArray* class_type_annotations() const {
+    return (_annotations != NULL) ? _annotations->class_type_annotations() : NULL;
   }
-
+  Array<AnnotationArray*>* fields_type_annotations() const {
+    return (_annotations != NULL) ? _annotations->fields_type_annotations() : NULL;
+  }
   // allocation
   instanceOop allocate_instance(TRAPS);
 
@@ -808,6 +810,7 @@
 
   // Sizing (in words)
   static int header_size()            { return align_object_offset(sizeof(InstanceKlass)/HeapWordSize); }
+
   static int size(int vtable_length, int itable_length,
                   int nonstatic_oop_map_size,
                   bool is_interface, bool is_anonymous) {
@@ -826,6 +829,9 @@
                                                is_interface(),
                                                is_anonymous());
   }
+#if INCLUDE_SERVICES
+  virtual void collect_statistics(KlassSizeStats *sz) const;
+#endif
 
   static int vtable_start_offset()    { return header_size(); }
   static int vtable_length_offset()   { return offset_of(InstanceKlass, _vtable_len) / HeapWordSize; }
@@ -842,10 +848,14 @@
     return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length()));
   }
 
+  Klass** end_of_nonstatic_oop_maps() const {
+    return (Klass**)(start_of_nonstatic_oop_maps() +
+                     nonstatic_oop_map_count());
+  }
+
   Klass** adr_implementor() const {
     if (is_interface()) {
-      return (Klass**)(start_of_nonstatic_oop_maps() +
-                    nonstatic_oop_map_count());
+      return (Klass**)end_of_nonstatic_oop_maps();
     } else {
       return NULL;
     }
@@ -857,8 +867,7 @@
       if (adr_impl != NULL) {
         return adr_impl + 1;
       } else {
-        return (Klass**)(start_of_nonstatic_oop_maps() +
-                      nonstatic_oop_map_count());
+        return end_of_nonstatic_oop_maps();
       }
     } else {
       return NULL;
@@ -932,13 +941,13 @@
   ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DECL)
   ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DECL)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
   int  oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk);
 
   ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
   ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   u2 idnum_allocated_count() const      { return _idnum_allocated_count; }
 private:
@@ -1015,6 +1024,7 @@
   void print_value_on(outputStream* st) const;
 
   void oop_print_value_on(oop obj, outputStream* st);
+
 #ifndef PRODUCT
   void oop_print_on      (oop obj, outputStream* st);
 
--- a/src/share/vm/oops/instanceMirrorKlass.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/instanceMirrorKlass.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -35,7 +35,8 @@
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
@@ -45,7 +46,7 @@
 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
 #include "oops/oop.pcgc.inline.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 int InstanceMirrorKlass::_offset_of_static_fields = 0;
 
@@ -168,7 +169,7 @@
     assert_is_in_closed_subset)
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void InstanceMirrorKlass::oop_follow_contents(ParCompactionManager* cm,
                                               oop obj) {
   InstanceKlass::oop_follow_contents(cm, obj);
@@ -189,7 +190,7 @@
     PSParallelCompact::mark_and_push(cm, p),                                          \
     assert_is_in)
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 int InstanceMirrorKlass::oop_adjust_pointers(oop obj) {
   int size = oop_size(obj);
@@ -262,7 +263,7 @@
   }                                                                                   \
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
                                                                                       \
 int InstanceMirrorKlass::                                                             \
@@ -278,7 +279,7 @@
     InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(oop, nv_suffix);                 \
   }                                                                                   \
 }
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 
 #define InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)         \
@@ -310,14 +311,14 @@
 
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN)
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void InstanceMirrorKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   // Note that we don't have to follow the mirror -> klass pointer, since all
   // klasses that are dirty will be scavenged when we iterate over the
@@ -353,7 +354,7 @@
     assert_nothing)
   return size;
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 int InstanceMirrorKlass::instance_size(KlassHandle k) {
   if (k() != NULL && k->oop_is_instance()) {
--- a/src/share/vm/oops/instanceMirrorKlass.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/instanceMirrorKlass.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -28,6 +28,7 @@
 #include "classfile/systemDictionary.hpp"
 #include "oops/instanceKlass.hpp"
 #include "runtime/handles.hpp"
+#include "utilities/macros.hpp"
 
 // An InstanceMirrorKlass is a specialized InstanceKlass for
 // java.lang.Class instances.  These instances are special because
@@ -107,13 +108,13 @@
   ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL)
   ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
   int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk);
 
   ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
   ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 };
 
 #endif // SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP
--- a/src/share/vm/oops/instanceRefKlass.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/instanceRefKlass.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -33,7 +33,8 @@
 #include "oops/instanceRefKlass.hpp"
 #include "oops/oop.inline.hpp"
 #include "utilities/preserveException.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
 #include "gc_implementation/g1/g1RemSet.inline.hpp"
@@ -42,7 +43,7 @@
 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
 #include "oops/oop.pcgc.inline.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 template <class T>
 void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) {
@@ -120,7 +121,7 @@
   }
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 template <class T>
 void specialized_oop_follow_contents(InstanceRefKlass* ref,
                                      ParCompactionManager* cm,
@@ -194,7 +195,7 @@
     specialized_oop_follow_contents<oop>(this, cm, obj);
   }
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #ifdef ASSERT
 template <class T> void trace_reference_gc(const char *s, oop obj,
@@ -317,7 +318,7 @@
   }                                                                             \
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
                                                                                 \
 int InstanceRefKlass::                                                          \
@@ -333,7 +334,7 @@
     InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains);         \
   }                                                                             \
 }
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 
 #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)      \
@@ -354,14 +355,14 @@
 
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 template <class T>
 void specialized_oop_push_contents(InstanceRefKlass *ref,
                                    PSPromotionManager* pm, oop obj) {
@@ -444,7 +445,7 @@
   }
   return size_helper();
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) {
   // Clear the nonstatic oop-map entries corresponding to referent
--- a/src/share/vm/oops/instanceRefKlass.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/instanceRefKlass.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -26,6 +26,7 @@
 #define SHARE_VM_OOPS_INSTANCEREFKLASS_HPP
 
 #include "oops/instanceKlass.hpp"
+#include "utilities/macros.hpp"
 
 // An InstanceRefKlass is a specialized InstanceKlass for Java
 // classes that are subclasses of java/lang/ref/Reference.
@@ -83,13 +84,13 @@
   ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DECL)
   ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DECL)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix)      \
   int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk);
 
   ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
   ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock);
   static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock);
--- a/src/share/vm/oops/klass.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/klass.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "gc_implementation/shared/markSweep.inline.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
+#include "memory/heapInspection.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
@@ -37,11 +38,12 @@
 #include "oops/oop.inline2.hpp"
 #include "runtime/atomic.hpp"
 #include "utilities/stack.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
 #include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 void Klass::set_name(Symbol* n) {
   _name = n;
@@ -624,6 +626,17 @@
   obj->print_address_on(st);
 }
 
+#if INCLUDE_SERVICES
+// Size Statistics
+void Klass::collect_statistics(KlassSizeStats *sz) const {
+  sz->_klass_bytes = sz->count(this);
+  sz->_mirror_bytes = sz->count(java_mirror());
+  sz->_secondary_supers_bytes = sz->count_array(secondary_supers());
+
+  sz->_ro_bytes += sz->_secondary_supers_bytes;
+  sz->_rw_bytes += sz->_klass_bytes + sz->_mirror_bytes;
+}
+#endif // INCLUDE_SERVICES
 
 // Verification
 
--- a/src/share/vm/oops/klass.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/klass.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,11 +35,12 @@
 #include "runtime/orderAccess.hpp"
 #include "trace/traceMacros.hpp"
 #include "utilities/accessFlags.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
 #include "gc_implementation/g1/g1OopClosures.hpp"
 #include "gc_implementation/parNew/parOopClosures.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 //
 // A Klass provides:
@@ -75,11 +76,11 @@
 //    [class_loader_data]
 //    [modifier_flags]
 //    [access_flags  ]
-//    [verify_count  ] - not in product
-//    [alloc_count   ]
 //    [last_biased_lock_bulk_revocation_time] (64 bits)
 //    [prototype_header]
 //    [biased_lock_revocation_count]
+//    [verify_count  ] - not in product
+//    [alloc_count   ]
 //    [_modified_oops]
 //    [_accumulated_modified_oops]
 //    [trace_id]
@@ -91,6 +92,7 @@
 class ClassLoaderData;
 class klassVtable;
 class ParCompactionManager;
+class KlassSizeStats;
 
 class Klass : public Metadata {
   friend class VMStructs;
@@ -168,18 +170,18 @@
   jint        _modifier_flags;  // Processed access flags, for use by Class.getModifiers.
   AccessFlags _access_flags;    // Access flags. The class/interface distinction is stored here.
 
+  // Biased locking implementation and statistics
+  // (the 64-bit chunk goes first, to avoid some fragmentation)
+  jlong    _last_biased_lock_bulk_revocation_time;
+  markOop  _prototype_header;   // Used when biased locking is both enabled and disabled for this type
+  jint     _biased_lock_revocation_count;
+
 #ifndef PRODUCT
   int           _verify_count;  // to avoid redundant verifies
 #endif
 
   juint    _alloc_count;        // allocation profiling support
 
-  // Biased locking implementation and statistics
-  // (the 64-bit chunk goes first, to avoid some fragmentation)
-  jlong    _last_biased_lock_bulk_revocation_time;
-  markOop  _prototype_header;   // Used when biased locking is both enabled and disabled for this type
-  jint     _biased_lock_revocation_count;
-
   TRACE_DEFINE_KLASS_TRACE_ID;
 
   // Remembered sets support for the oops in the klasses.
@@ -489,6 +491,9 @@
 
   // Size of klass in word size.
   virtual int size() const = 0;
+#if INCLUDE_SERVICES
+  virtual void collect_statistics(KlassSizeStats *sz) const;
+#endif
 
   // Returns the Java name for a class (Resource allocated)
   // For arrays, this returns the name of the element with a leading '['.
@@ -637,13 +642,13 @@
     return oop_oop_iterate(obj, blk);
   }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // In case we don't have a specialized backward scanner use forward
   // iteration.
   virtual int oop_oop_iterate_backwards_v(oop obj, ExtendedOopClosure* blk) {
     return oop_oop_iterate_v(obj, blk);
   }
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // Iterates "blk" over all the oops in "obj" (of type "this") within "mr".
   // (I don't see why the _m should be required, but without it the Solaris
@@ -675,7 +680,7 @@
   SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_DECL)
   SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_DECL)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define Klass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix)      \
   virtual int oop_oop_iterate_backwards##nv_suffix(oop obj,                  \
                                                    OopClosureType* blk) {    \
@@ -685,7 +690,7 @@
 
   SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL)
   SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL)
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   virtual void array_klasses_do(void f(Klass* k)) {}
   virtual void with_array_klasses_do(void f(Klass* k));
--- a/src/share/vm/oops/klassPS.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/klassPS.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -27,7 +27,9 @@
 
   // Expands to Parallel Scavenge and Parallel Old declarations
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+
+#if INCLUDE_ALL_GCS
 #define PARALLEL_GC_DECLS \
   virtual void oop_push_contents(PSPromotionManager* pm, oop obj);          \
   /* Parallel Old GC support                                                \
@@ -44,9 +46,9 @@
   virtual void oop_push_contents(PSPromotionManager* pm, oop obj) = 0;      \
   virtual void oop_follow_contents(ParCompactionManager* cm, oop obj) = 0;  \
   virtual int  oop_update_pointers(ParCompactionManager* cm, oop obj) = 0;
-#else  // SERIALGC
+#else  // INCLUDE_ALL_GCS
 #define PARALLEL_GC_DECLS
 #define PARALLEL_GC_DECLS_PV
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #endif // SHARE_VM_OOPS_KLASSPS_HPP
--- a/src/share/vm/oops/klassVtable.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/klassVtable.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -610,6 +610,7 @@
   Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size());
 }
 
+#if INCLUDE_JVMTI
 void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods,
                                         int methods_length, bool * trace_name_printed) {
   // search the vtable for uses of either obsolete or EMCP methods
@@ -638,11 +639,39 @@
                                 new_method->name()->as_C_string(),
                                 new_method->signature()->as_C_string()));
         }
+        // cannot 'break' here; see for-loop comment above.
       }
     }
   }
 }
 
+// a vtable should never contain old or obsolete methods
+bool klassVtable::check_no_old_or_obsolete_entries() {
+  for (int i = 0; i < length(); i++) {
+    Method* m = unchecked_method_at(i);
+    if (m != NULL &&
+        (NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void klassVtable::dump_vtable() {
+  tty->print_cr("vtable dump --");
+  for (int i = 0; i < length(); i++) {
+    Method* m = unchecked_method_at(i);
+    if (m != NULL) {
+      tty->print("      (%5d)  ", i);
+      m->access_flags().print_on(tty);
+      tty->print(" --  ");
+      m->print_name(tty);
+      tty->cr();
+    }
+  }
+}
+#endif // INCLUDE_JVMTI
+
 // CDS/RedefineClasses support - clear vtables so they can be reinitialized
 void klassVtable::clear_vtable() {
   for (int i = 0; i < _length; i++) table()[i].clear();
@@ -805,6 +834,7 @@
   }
 }
 
+#if INCLUDE_JVMTI
 void klassItable::adjust_method_entries(Method** old_methods, Method** new_methods,
                                         int methods_length, bool * trace_name_printed) {
   // search the itable for uses of either obsolete or EMCP methods
@@ -833,13 +863,44 @@
             new_method->name()->as_C_string(),
             new_method->signature()->as_C_string()));
         }
-        // Cannot break because there might be another entry for this method
+        // cannot 'break' here; see for-loop comment above.
       }
       ime++;
     }
   }
 }
 
+// an itable should never contain old or obsolete methods
+bool klassItable::check_no_old_or_obsolete_entries() {
+  itableMethodEntry* ime = method_entry(0);
+  for (int i = 0; i < _size_method_table; i++) {
+    Method* m = ime->method();
+    if (m != NULL &&
+        (NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) {
+      return false;
+    }
+    ime++;
+  }
+  return true;
+}
+
+void klassItable::dump_itable() {
+  itableMethodEntry* ime = method_entry(0);
+  tty->print_cr("itable dump --");
+  for (int i = 0; i < _size_method_table; i++) {
+    Method* m = ime->method();
+    if (m != NULL) {
+      tty->print("      (%5d)  ", i);
+      m->access_flags().print_on(tty);
+      tty->print(" --  ");
+      m->print_name(tty);
+      tty->cr();
+    }
+    ime++;
+  }
+}
+#endif // INCLUDE_JVMTI
+
 
 // Setup
 class InterfaceVisiterClosure : public StackObj {
@@ -1126,43 +1187,6 @@
   tty->print_cr("%6d bytes total", total);
 }
 
-bool klassVtable::check_no_old_entries() {
-  // Check that there really is no entry
-  for (int i = 0; i < length(); i++) {
-    Method* m = unchecked_method_at(i);
-    if (m != NULL) {
-        if (!m->is_valid() || m->is_old()) {
-            return false;
-        }
-    }
-  }
-  return true;
-}
-
-void klassVtable::dump_vtable() {
-  tty->print_cr("vtable dump --");
-  for (int i = 0; i < length(); i++) {
-    Method* m = unchecked_method_at(i);
-    if (m != NULL) {
-      tty->print("      (%5d)  ", i);
-      m->access_flags().print_on(tty);
-      tty->print(" --  ");
-      m->print_name(tty);
-      tty->cr();
-    }
-  }
-}
-
-bool klassItable::check_no_old_entries() {
-  itableMethodEntry* ime = method_entry(0);
-  for(int i = 0; i < _size_method_table; i++) {
-    Method* m = ime->method();
-    if (m != NULL && (!m->is_valid() || m->is_old())) return false;
-    ime++;
-  }
-  return true;
-}
-
 int  klassItable::_total_classes;   // Total no. of classes with itables
 long klassItable::_total_size;      // Total no. of bytes used for itables
 
--- a/src/share/vm/oops/klassVtable.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/klassVtable.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -90,6 +90,7 @@
       Array<Method*>* methods, AccessFlags class_flags, Handle classloader,
       Symbol* classname, Array<Klass*>* local_interfaces, TRAPS);
 
+#if INCLUDE_JVMTI
   // RedefineClasses() API support:
   // If any entry of this vtable points to any of old_methods,
   // replace it with the corresponding new_method.
@@ -98,17 +99,15 @@
   // group don't print the klass name.
   void adjust_method_entries(Method** old_methods, Method** new_methods,
                              int methods_length, bool * trace_name_printed);
+  bool check_no_old_or_obsolete_entries();
+  void dump_vtable();
+#endif // INCLUDE_JVMTI
 
   // Debugging code
   void print()                                              PRODUCT_RETURN;
   void verify(outputStream* st, bool force = false);
   static void print_statistics()                            PRODUCT_RETURN;
 
-#ifndef PRODUCT
-  bool check_no_old_entries();
-  void dump_vtable();
-#endif
-
  protected:
   friend class vtableEntry;
  private:
@@ -275,6 +274,7 @@
   // Updates
   void initialize_with_method(Method* m);
 
+#if INCLUDE_JVMTI
   // RedefineClasses() API support:
   // if any entry of this itable points to any of old_methods,
   // replace it with the corresponding new_method.
@@ -283,6 +283,9 @@
   // group don't print the klass name.
   void adjust_method_entries(Method** old_methods, Method** new_methods,
                              int methods_length, bool * trace_name_printed);
+  bool check_no_old_or_obsolete_entries();
+  void dump_itable();
+#endif // INCLUDE_JVMTI
 
   // Setup of itable
   static int compute_itable_size(Array<Klass*>* transitive_interfaces);
@@ -307,11 +310,6 @@
   NOT_PRODUCT(static long _total_size;)      // Total no. of bytes used for itables
 
   static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; })
-
- public:
-#ifndef PRODUCT
-  bool check_no_old_entries();
-#endif
 };
 
 #endif // SHARE_VM_OOPS_KLASSVTABLE_HPP
--- a/src/share/vm/oops/method.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/method.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/metadataOnStackMark.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/debugInfoRec.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
@@ -33,6 +34,7 @@
 #include "interpreter/oopMapCache.hpp"
 #include "memory/gcLocker.hpp"
 #include "memory/generation.hpp"
+#include "memory/heapInspection.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/constMethod.hpp"
@@ -41,7 +43,6 @@
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
 #include "prims/jvmtiExport.hpp"
-#include "prims/jvmtiRedefineClasses.hpp"
 #include "prims/methodHandles.hpp"
 #include "prims/nativeLookup.hpp"
 #include "runtime/arguments.hpp"
@@ -53,9 +54,6 @@
 #include "runtime/signature.hpp"
 #include "utilities/quickSort.hpp"
 #include "utilities/xmlstream.hpp"
-#ifdef GRAAL
-#include "graal/graalJavaAccess.hpp"
-#endif
 
 
 // Implementation of Method
@@ -63,24 +61,14 @@
 Method* Method::allocate(ClassLoaderData* loader_data,
                          int byte_code_size,
                          AccessFlags access_flags,
-                         int compressed_line_number_size,
-                         int localvariable_table_length,
-                         int exception_table_length,
-                         int checked_exceptions_length,
-                         int method_parameters_length,
-                         u2  generic_signature_index,
+                         InlineTableSizes* sizes,
                          ConstMethod::MethodType method_type,
                          TRAPS) {
   assert(!access_flags.is_native() || byte_code_size == 0,
          "native methods should not contain byte codes");
   ConstMethod* cm = ConstMethod::allocate(loader_data,
                                           byte_code_size,
-                                          compressed_line_number_size,
-                                          localvariable_table_length,
-                                          exception_table_length,
-                                          checked_exceptions_length,
-                                          method_parameters_length,
-                                          generic_signature_index,
+                                          sizes,
                                           method_type,
                                           CHECK_NULL);
 
@@ -324,14 +312,6 @@
 }
 
 
-void Method::set_interpreter_kind() {
-  int kind = Interpreter::method_kind(this);
-  assert(kind != Interpreter::invalid,
-         "interpreter entry must be valid");
-  set_interpreter_kind(kind);
-}
-
-
 // Attempt to return method oop to original state.  Clear any pointers
 // (to objects outside the shared spaces).  We won't be able to predict
 // where they should point in a new JVM.  Further initialize some
@@ -339,7 +319,6 @@
 
 void Method::remove_unshareable_info() {
   unlink_method();
-  set_interpreter_kind();
 }
 
 
@@ -707,7 +686,7 @@
 }
 
 
-void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report) {
+void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason) {
   if (PrintCompilation && report) {
     ttyLocker ttyl;
     tty->print("made not %scompilable on ", is_osr ? "OSR " : "");
@@ -721,15 +700,21 @@
     }
     this->print_short_name(tty);
     int size = this->code_size();
-    if (size > 0)
+    if (size > 0) {
       tty->print(" (%d bytes)", size);
+    }
+    if (reason != NULL) {
+      tty->print("   %s", reason);
+    }
     tty->cr();
   }
   if ((TraceDeoptimization || LogCompilation) && (xtty != NULL)) {
-    ResourceMark rm;
     ttyLocker ttyl;
     xtty->begin_elem("make_not_%scompilable thread='" UINTX_FORMAT "'",
                      is_osr ? "osr_" : "", os::current_thread_id());
+    if (reason != NULL) {
+      xtty->print(" reason=\'%s\'", reason);
+    }
     xtty->method(this);
     xtty->stamp();
     xtty->end_elem();
@@ -751,8 +736,8 @@
 }
 
 // call this when compiler finds that this method is not compilable
-void Method::set_not_compilable(int comp_level, bool report) {
-  print_made_not_compilable(comp_level, /*is_osr*/ false, report);
+void Method::set_not_compilable(int comp_level, bool report, const char* reason) {
+  print_made_not_compilable(comp_level, /*is_osr*/ false, report, reason);
   if (comp_level == CompLevel_all) {
     set_not_c1_compilable();
     set_not_c2_compilable();
@@ -777,8 +762,8 @@
   return false;
 }
 
-void Method::set_not_osr_compilable(int comp_level, bool report) {
-  print_made_not_compilable(comp_level, /*is_osr*/ true, report);
+void Method::set_not_osr_compilable(int comp_level, bool report, const char* reason) {
+  print_made_not_compilable(comp_level, /*is_osr*/ true, report, reason);
   if (comp_level == CompLevel_all) {
     set_not_c1_osr_compilable();
     set_not_c2_osr_compilable();
@@ -1036,7 +1021,7 @@
   cp->set_pool_holder(InstanceKlass::cast(holder()));
   cp->symbol_at_put(_imcp_invoke_name,       name);
   cp->symbol_at_put(_imcp_invoke_signature,  signature);
-  cp->set_preresolution();
+  cp->set_has_preresolution();
 
   // decide on access bits:  public or not?
   int flags_bits = (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_FINAL);
@@ -1046,9 +1031,9 @@
 
   methodHandle m;
   {
+    InlineTableSizes sizes;
     Method* m_oop = Method::allocate(loader_data, 0,
-                                     accessFlags_from(flags_bits),
-                                     0, 0, 0, 0, 0, 0,
+                                     accessFlags_from(flags_bits), &sizes,
                                      ConstMethod::NORMAL, CHECK_(empty));
     m = methodHandle(THREAD, m_oop);
   }
@@ -1097,22 +1082,35 @@
   assert(!m->is_native(), "cannot rewrite native methods");
   // Allocate new Method*
   AccessFlags flags = m->access_flags();
-  u2  generic_signature_index = m->generic_signature_index();
-  int checked_exceptions_len = m->checked_exceptions_length();
-  int localvariable_len = m->localvariable_table_length();
-  int exception_table_len = m->exception_table_length();
-  int method_parameters_len = m->method_parameters_length();
+
+  ConstMethod* cm = m->constMethod();
+  int checked_exceptions_len = cm->checked_exceptions_length();
+  int localvariable_len = cm->localvariable_table_length();
+  int exception_table_len = cm->exception_table_length();
+  int method_parameters_len = cm->method_parameters_length();
+  int method_annotations_len = cm->method_annotations_length();
+  int parameter_annotations_len = cm->parameter_annotations_length();
+  int type_annotations_len = cm->type_annotations_length();
+  int default_annotations_len = cm->default_annotations_length();
+
+  InlineTableSizes sizes(
+      localvariable_len,
+      new_compressed_linenumber_size,
+      exception_table_len,
+      checked_exceptions_len,
+      method_parameters_len,
+      cm->generic_signature_index(),
+      method_annotations_len,
+      parameter_annotations_len,
+      type_annotations_len,
+      default_annotations_len,
+      0);
 
   ClassLoaderData* loader_data = m->method_holder()->class_loader_data();
   Method* newm_oop = Method::allocate(loader_data,
                                       new_code_length,
                                       flags,
-                                      new_compressed_linenumber_size,
-                                      localvariable_len,
-                                      exception_table_len,
-                                      checked_exceptions_len,
-                                      method_parameters_len,
-                                      generic_signature_index,
+                                      &sizes,
                                       m->method_type(),
                                       CHECK_(methodHandle()));
   methodHandle newm (THREAD, newm_oop);
@@ -1312,29 +1310,6 @@
     MethodHandles::print_as_basic_type_signature_on(st, signature(), true);
 }
 
-// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
-static void reorder_based_on_method_index(Array<Method*>* methods,
-                                          Array<AnnotationArray*>* annotations,
-                                          GrowableArray<AnnotationArray*>* temp_array) {
-  if (annotations == NULL) {
-    return;
-  }
-
-  int length = methods->length();
-  int i;
-  // Copy to temp array
-  temp_array->clear();
-  for (i = 0; i < length; i++) {
-    temp_array->append(annotations->at(i));
-  }
-
-  // Copy back using old method indices
-  for (i = 0; i < length; i++) {
-    Method* m = methods->at(i);
-    annotations->at_put(i, temp_array->at(m->method_idnum()));
-  }
-}
-
 // Comparer for sorting an object array containing
 // Method*s.
 static int method_comparator(Method* a, Method* b) {
@@ -1342,48 +1317,13 @@
 }
 
 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
-void Method::sort_methods(Array<Method*>* methods,
-                                 Array<AnnotationArray*>* methods_annotations,
-                                 Array<AnnotationArray*>* methods_parameter_annotations,
-                                 Array<AnnotationArray*>* methods_default_annotations,
-                                 Array<AnnotationArray*>* methods_type_annotations,
-                                 bool idempotent) {
+void Method::sort_methods(Array<Method*>* methods, bool idempotent) {
   int length = methods->length();
   if (length > 1) {
-    bool do_annotations = false;
-    if (methods_annotations != NULL ||
-        methods_parameter_annotations != NULL ||
-        methods_default_annotations != NULL ||
-        methods_type_annotations != NULL) {
-      do_annotations = true;
-    }
-    if (do_annotations) {
-      // Remember current method ordering so we can reorder annotations
-      for (int i = 0; i < length; i++) {
-        Method* m = methods->at(i);
-        m->set_method_idnum(i);
-      }
-    }
     {
       No_Safepoint_Verifier nsv;
       QuickSort::sort<Method*>(methods->data(), length, method_comparator, idempotent);
     }
-
-    // Sort annotations if necessary
-    assert(methods_annotations == NULL           || methods_annotations->length() == methods->length(), "");
-    assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), "");
-    assert(methods_default_annotations == NULL   || methods_default_annotations->length() == methods->length(), "");
-    assert(methods_type_annotations == NULL   || methods_type_annotations->length() == methods->length(), "");
-    if (do_annotations) {
-      ResourceMark rm;
-      // Allocate temporary storage
-      GrowableArray<AnnotationArray*>* temp_array = new GrowableArray<AnnotationArray*>(length);
-      reorder_based_on_method_index(methods, methods_annotations, temp_array);
-      reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array);
-      reorder_based_on_method_index(methods, methods_default_annotations, temp_array);
-      reorder_based_on_method_index(methods, methods_type_annotations, temp_array);
-    }
-
     // Reset method ordering
     for (int i = 0; i < length; i++) {
       Method* m = methods->at(i);
@@ -1394,9 +1334,9 @@
 
 
 //-----------------------------------------------------------------------------------
-// Non-product code
+// Non-product code unless JVM/TI needs it
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || INCLUDE_JVMTI
 class SignatureTypePrinter : public SignatureTypeNames {
  private:
   outputStream* _st;
@@ -1431,8 +1371,13 @@
   sig.print_parameters();
   st->print(")");
 }
+#endif // !PRODUCT || INCLUDE_JVMTI
 
 
+//-----------------------------------------------------------------------------------
+// Non-product code
+
+#ifndef PRODUCT
 void Method::print_codes_on(outputStream* st) const {
   print_codes_on(0, code_size(), st);
 }
@@ -1963,6 +1908,22 @@
   if (WizardMode && code() != NULL) st->print(" ((nmethod*)%p)", code());
 }
 
+#if INCLUDE_SERVICES
+// Size Statistics
+void Method::collect_statistics(KlassSizeStats *sz) const {
+  int mysize = sz->count(this);
+  sz->_method_bytes += mysize;
+  sz->_method_all_bytes += mysize;
+  sz->_rw_bytes += mysize;
+
+  if (constMethod()) {
+    constMethod()->collect_statistics(sz);
+  }
+  if (method_data()) {
+    method_data()->collect_statistics(sz);
+  }
+}
+#endif // INCLUDE_SERVICES
 
 // Verification
 
@@ -1979,16 +1940,3 @@
   guarantee(md == NULL ||
       md->is_methodData(), "should be method data");
 }
-
-#ifdef GRAAL
-void DebugScopedMethod::print_on(outputStream* st) {
-  if (_method != NULL) {
-    st->print("Method@%p", _method);
-    char holder[O_BUFLEN];
-    char nameAndSig[O_BUFLEN];
-    _method->method_holder()->name()->as_C_string(holder, O_BUFLEN);
-    _method->name_and_sig_as_C_string(nameAndSig, O_BUFLEN);
-    st->print(" - %s::%s", holder, nameAndSig);
-  }
-}
-#endif
--- a/src/share/vm/oops/method.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/method.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -101,6 +101,8 @@
 class AdapterHandlerEntry;
 class MethodData;
 class ConstMethod;
+class InlineTableSizes;
+class KlassSizeStats;
 
 class Method : public Metadata {
  friend class VMStructs;
@@ -131,8 +133,8 @@
   int               _graal_priority;
 #endif
 #ifdef TIERED
+  float             _rate;                        // Events (invocation and backedge counter increments) per millisecond
   jlong             _prev_time;                   // Previous time the rate was acquired
-  float             _rate;                        // Events (invocation and backedge counter increments) per millisecond
 #endif
 
 #ifndef PRODUCT
@@ -160,12 +162,7 @@
   static Method* allocate(ClassLoaderData* loader_data,
                           int byte_code_size,
                           AccessFlags access_flags,
-                          int compressed_line_number_size,
-                          int localvariable_table_length,
-                          int exception_table_length,
-                          int checked_exceptions_length,
-                          int method_parameters_length,
-                          u2 generic_signature_index,
+                          InlineTableSizes* sizes,
                           ConstMethod::MethodType method_type,
                           TRAPS);
 
@@ -210,33 +207,17 @@
 
   // annotations support
   AnnotationArray* annotations() const           {
-    InstanceKlass* ik = method_holder();
-    if (ik->annotations() == NULL) {
-      return NULL;
-    }
-    return ik->annotations()->get_method_annotations_of(method_idnum());
+    return constMethod()->method_annotations();
   }
   AnnotationArray* parameter_annotations() const {
-    InstanceKlass* ik = method_holder();
-    if (ik->annotations() == NULL) {
-      return NULL;
-    }
-    return ik->annotations()->get_method_parameter_annotations_of(method_idnum());
+    return constMethod()->parameter_annotations();
   }
   AnnotationArray* annotation_default() const    {
-    InstanceKlass* ik = method_holder();
-    if (ik->annotations() == NULL) {
-      return NULL;
-    }
-    return ik->annotations()->get_method_default_annotations_of(method_idnum());
+    return constMethod()->default_annotations();
   }
-  AnnotationArray* type_annotations() const {
-  InstanceKlass* ik = method_holder();
-  Annotations* type_annos = ik->type_annotations();
-  if (type_annos == NULL)
-    return NULL;
-  return type_annos->get_method_annotations_of(method_idnum());
-}
+  AnnotationArray* type_annotations() const      {
+    return constMethod()->type_annotations();
+  }
 
 #ifdef CC_INTERP
   void set_result_index(BasicType type);
@@ -450,13 +431,6 @@
   address interpreter_entry() const              { return _i2i_entry; }
   // Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry
   void set_interpreter_entry(address entry)      { _i2i_entry = entry;  _from_interpreted_entry = entry; }
-  int  interpreter_kind(void) {
-     return constMethod()->interpreter_kind();
-  }
-  void set_interpreter_kind();
-  void set_interpreter_kind(int kind) {
-    constMethod()->set_interpreter_kind(kind);
-  }
 
   // native function (used for native methods only)
   enum {
@@ -494,6 +468,8 @@
   void print_codes_on(int from, int to, outputStream* st) const    PRODUCT_RETURN;
 
   // method parameters
+  bool has_method_parameters() const
+                         { return constMethod()->has_method_parameters(); }
   int method_parameters_length() const
                          { return constMethod()->method_parameters_length(); }
   MethodParametersElement* method_parameters_start() const
@@ -605,6 +581,9 @@
   static int header_size()                       { return sizeof(Method)/HeapWordSize; }
   static int size(bool is_native);
   int size() const                               { return method_size(); }
+#if INCLUDE_SERVICES
+  void collect_statistics(KlassSizeStats *sz) const;
+#endif
 
   // interpreter support
   static ByteSize const_offset()                 { return byte_offset_of(Method, _constMethod       ); }
@@ -776,18 +755,18 @@
   // whether it is not compilable for another reason like having a
   // breakpoint set in it.
   bool  is_not_compilable(int comp_level = CompLevel_any) const;
-  void set_not_compilable(int comp_level = CompLevel_all, bool report = true);
+  void set_not_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL);
   void set_not_compilable_quietly(int comp_level = CompLevel_all) {
     set_not_compilable(comp_level, false);
   }
   bool  is_not_osr_compilable(int comp_level = CompLevel_any) const;
-  void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true);
+  void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL);
   void set_not_osr_compilable_quietly(int comp_level = CompLevel_all) {
     set_not_osr_compilable(comp_level, false);
   }
 
  private:
-  void print_made_not_compilable(int comp_level, bool is_osr, bool report);
+  void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason);
 
  public:
   bool  is_not_c1_compilable() const          { return access_flags().is_not_c1_compilable(); }
@@ -812,16 +791,15 @@
   static bool has_unloaded_classes_in_signature(methodHandle m, TRAPS);
 
   // Printing
-  void print_short_name(outputStream* st = tty)  /*PRODUCT_RETURN*/; // prints as klassname::methodname; Exposed so field engineers can debug VM
+  void print_short_name(outputStream* st = tty); // prints as klassname::methodname; Exposed so field engineers can debug VM
+#if INCLUDE_JVMTI
+  void print_name(outputStream* st = tty); // prints as "virtual void foo(int)"; exposed for TraceRedefineClasses
+#else
   void print_name(outputStream* st = tty)        PRODUCT_RETURN; // prints as "virtual void foo(int)"
+#endif
 
   // Helper routine used for method sorting
-  static void sort_methods(Array<Method*>* methods,
-                           Array<AnnotationArray*>* methods_annotations,
-                           Array<AnnotationArray*>* methods_parameter_annotations,
-                           Array<AnnotationArray*>* methods_default_annotations,
-                           Array<AnnotationArray*>* methods_type_annotations,
-                           bool idempotent = false);
+  static void sort_methods(Array<Method*>* methods, bool idempotent = false);
 
   // Deallocation function for redefine classes or if an error occurs
   void deallocate_contents(ClassLoaderData* loader_data);
@@ -1022,20 +1000,4 @@
   }
 };
 
-#ifdef GRAAL
-class DebugScopedMethod : public DebugScopedValue {
-private:
-  Method* _method;
-public:
-  DebugScopedMethod(const char* file, int line, Method* method) : DebugScopedValue(file, line), _method(method) {}
-  void print_on(outputStream* st);
-};
-#define DS_METHOD(method) DebugScopedMethod __dsm__(__FILE__, __LINE__, method)
-#define DS_METHOD1(var, method) DebugScopedMethod var(__FILE__, __LINE__, method)
-#else
-#define DS_METHOD(method) do {} while (0)
-#define DS_METHOD1(var, method) do {} while (0)
-#endif
-
 #endif // SHARE_VM_OOPS_METHODOOP_HPP
-
--- a/src/share/vm/oops/methodData.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/methodData.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 #include "interpreter/bytecode.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/linkResolver.hpp"
+#include "memory/heapInspection.hpp"
 #include "oops/methodData.hpp"
 #include "prims/jvmtiRedefineClasses.hpp"
 #include "runtime/compilationPolicy.hpp"
@@ -759,13 +760,6 @@
   return CompilationPolicy::policy()->is_mature(_method);
 }
 
-void MethodData::inc_decompile_count() {
-  _nof_decompiles += 1;
-  if (decompile_count() > (uint)PerMethodRecompilationCutoff) {
-    method()->set_not_compilable(CompLevel_full_optimization);
-  }
-}
-
 // Translate a bci to its corresponding data index (di).
 address MethodData::bci_to_dp(int bci) {
   ResourceMark rm;
@@ -890,6 +884,15 @@
 }
 #endif
 
+#if INCLUDE_SERVICES
+// Size Statistics
+void MethodData::collect_statistics(KlassSizeStats *sz) const {
+  int n = sz->count(this);
+  sz->_method_data_bytes += n;
+  sz->_method_all_bytes += n;
+  sz->_rw_bytes += n;
+}
+#endif // INCLUDE_SERVICES
 
 // Verification
 
--- a/src/share/vm/oops/methodData.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/methodData.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 #include "runtime/orderAccess.hpp"
 
 class BytecodeStream;
+class KlassSizeStats;
 
 // The MethodData object collects counts and other profile information
 // during zeroth-tier (interpretive) and first-tier execution.
@@ -1301,6 +1302,9 @@
   // My size
   int size_in_bytes() const { return _size; }
   int size() const    { return align_object_size(align_size_up(_size, BytesPerWord)/BytesPerWord); }
+#if INCLUDE_SERVICES
+  void collect_statistics(KlassSizeStats *sz) const;
+#endif
 
   int      creation_mileage() const  { return _creation_mileage; }
   void set_creation_mileage(int x)   { _creation_mileage = x; }
@@ -1471,7 +1475,12 @@
   uint decompile_count() const {
     return _nof_decompiles;
   }
-  void inc_decompile_count();
+  void inc_decompile_count() {
+    _nof_decompiles += 1;
+    if (decompile_count() > (uint)PerMethodRecompilationCutoff) {
+      method()->set_not_compilable(CompLevel_full_optimization, true, "decompile_count > PerMethodRecompilationCutoff");
+    }
+  }
 
   // Support for code generation
   static ByteSize data_offset() {
--- a/src/share/vm/oops/objArrayKlass.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/objArrayKlass.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -43,7 +43,8 @@
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "utilities/copy.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
@@ -54,7 +55,7 @@
 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
 #include "oops/oop.pcgc.inline.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, KlassHandle klass_handle, Symbol* name, TRAPS) {
   assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(),
@@ -461,7 +462,7 @@
   }
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void ObjArrayKlass::oop_follow_contents(ParCompactionManager* cm,
                                         oop obj) {
   assert(obj->is_array(), "obj must be array");
@@ -472,7 +473,7 @@
     objarray_follow_contents<oop>(cm, obj, 0);
   }
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #define if_do_metadata_checked(closure, nv_suffix)                    \
   /* Make sure the non-virtual and the virtual versions match. */     \
@@ -573,7 +574,7 @@
   return size;
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void ObjArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   assert(obj->is_objArray(), "obj must be obj array");
   ObjArrayKlass_OOP_ITERATE( \
@@ -591,7 +592,7 @@
   ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p))
   return size;
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 // JVM support
 
--- a/src/share/vm/oops/objArrayKlass.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/objArrayKlass.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -28,6 +28,7 @@
 #include "classfile/classLoaderData.hpp"
 #include "memory/specialized_oop_closures.hpp"
 #include "oops/arrayKlass.hpp"
+#include "utilities/macros.hpp"
 
 // ObjArrayKlass is the klass for objArrays
 
@@ -111,11 +112,11 @@
 
   // Parallel Scavenge and Parallel Old
   PARALLEL_GC_DECLS
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   inline void oop_follow_contents(ParCompactionManager* cm, oop obj, int index);
   template <class T> inline void
     objarray_follow_contents(ParCompactionManager* cm, oop obj, int index);
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // Iterators
   int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) {
--- a/src/share/vm/oops/objArrayKlass.inline.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/objArrayKlass.inline.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -27,10 +27,11 @@
 
 #include "gc_implementation/shared/markSweep.inline.hpp"
 #include "oops/objArrayKlass.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parallelScavenge/psCompactionManager.inline.hpp"
 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 void ObjArrayKlass::oop_follow_contents(oop obj, int index) {
   if (UseCompressedOops) {
@@ -63,7 +64,7 @@
   }
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void ObjArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj,
                                         int index) {
   if (UseCompressedOops) {
@@ -96,6 +97,6 @@
     cm->push_objarray(a, end_index); // Push the continuation.
   }
 }
-#endif // #ifndef SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #endif // SHARE_VM_OOPS_OBJARRAYKLASS_INLINE_HPP
--- a/src/share/vm/oops/oop.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/oop.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -29,6 +29,7 @@
 #include "memory/memRegion.hpp"
 #include "memory/specialized_oop_closures.hpp"
 #include "oops/metadata.hpp"
+#include "utilities/macros.hpp"
 #include "utilities/top.hpp"
 
 // oopDesc is the top baseclass for objects classes.  The {name}Desc classes describe
@@ -298,7 +299,7 @@
   // reference field in "this".
   void follow_contents(void);
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // Parallel Scavenge
   void push_contents(PSPromotionManager* pm);
 
@@ -306,7 +307,7 @@
   void update_contents(ParCompactionManager* cm);
 
   void follow_contents(ParCompactionManager* cm);
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   bool is_scavengable() const;
 
@@ -316,13 +317,13 @@
   void forward_to(oop p);
   bool cas_forward_to(oop p, markOop compare);
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // Like "forward_to", but inserts the forwarding pointer atomically.
   // Exactly one thread succeeds in inserting the forwarding pointer, and
   // this call returns "NULL" for that thread; any other thread has the
   // value of the forwarding pointer returned and does not modify "this".
   oop forward_to_atomic(oop p);
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   oop forwardee() const;
 
@@ -334,10 +335,10 @@
   // return the size of this oop.  This is used by the MarkSweep collector.
   int adjust_pointers();
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // Parallel old
   void update_header(ParCompactionManager* cm);
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // mark-sweep support
   void follow_body(int begin, int end);
@@ -354,7 +355,7 @@
   ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DECL)
   ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DECL)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
 #define OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix)            \
   int oop_iterate_backwards(OopClosureType* blk);
--- a/src/share/vm/oops/oop.inline.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/oop.inline.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
 #include "oops/oop.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
+#include "utilities/macros.hpp"
 #ifdef TARGET_ARCH_x86
 # include "bytes_x86.hpp"
 #endif
@@ -227,12 +228,12 @@
 // might not be the same as oop.
 
 inline narrowOop oopDesc::encode_klass_not_null(Klass* v) {
-  assert(!is_null(v), "oop value can never be zero");
+  assert(!is_null(v), "klass value can never be zero");
   assert(check_klass_alignment(v), "Address not aligned");
   address base = Universe::narrow_klass_base();
   int    shift = Universe::narrow_klass_shift();
   uint64_t  pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1));
-  assert(OopEncodingHeapMax > pd, "change encoding max if new encoding");
+  assert(KlassEncodingMetaspaceMax > pd, "change encoding max if new encoding");
   uint64_t result = pd >> shift;
   assert((result & CONST64(0xffffffff00000000)) == 0, "narrow klass pointer overflow");
   assert(decode_klass(result) == v, "reversibility");
@@ -760,7 +761,7 @@
 ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DEFN)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DEFN)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #define OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix)              \
                                                                            \
 inline int oopDesc::oop_iterate_backwards(OopClosureType* blk) {           \
@@ -770,6 +771,6 @@
 
 ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DEFN)
 ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DEFN)
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #endif // SHARE_VM_OOPS_OOP_INLINE_HPP
--- a/src/share/vm/oops/oop.pcgc.inline.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/oop.pcgc.inline.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,14 +25,15 @@
 #ifndef SHARE_VM_OOPS_OOP_PCGC_INLINE_HPP
 #define SHARE_VM_OOPS_OOP_PCGC_INLINE_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parNew/parNewGeneration.hpp"
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
 #include "gc_implementation/parallelScavenge/psCompactionManager.hpp"
 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 inline void oopDesc::update_contents(ParCompactionManager* cm) {
   // The klass field must be updated before anything else
--- a/src/share/vm/oops/oop.psgc.inline.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/oop.psgc.inline.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,11 +25,12 @@
 #ifndef SHARE_VM_OOPS_OOP_PSGC_INLINE_HPP
 #define SHARE_VM_OOPS_OOP_PSGC_INLINE_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // ParallelScavengeHeap methods
 
--- a/src/share/vm/oops/symbol.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/symbol.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -152,6 +152,7 @@
 }
 
 void Symbol::print_symbol_on(outputStream* st) const {
+  ResourceMark rm;
   st = st ? st : tty;
   st->print("%s", as_quoted_ascii());
 }
--- a/src/share/vm/oops/typeArrayKlass.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/oops/typeArrayKlass.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -39,6 +39,7 @@
 #include "oops/typeArrayKlass.hpp"
 #include "oops/typeArrayOop.hpp"
 #include "runtime/handles.inline.hpp"
+#include "utilities/macros.hpp"
 
 bool TypeArrayKlass::compute_is_subtype_of(Klass* k) {
   if (!k->oop_is_typeArray()) {
@@ -208,13 +209,13 @@
   // know that Universe::TypeArrayKlass never moves.
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void TypeArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) {
   assert(obj->is_typeArray(),"must be a type array");
   // Performance tweak: We skip iterating over the klass pointer since we
   // know that Universe::TypeArrayKlass never moves.
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 int TypeArrayKlass::oop_adjust_pointers(oop obj) {
   assert(obj->is_typeArray(),"must be a type array");
@@ -240,7 +241,7 @@
   return t->object_size();
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void TypeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   ShouldNotReachHere();
   assert(obj->is_typeArray(),"must be a type array");
@@ -251,7 +252,7 @@
   assert(obj->is_typeArray(),"must be a type array");
   return typeArrayOop(obj)->object_size();
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 void TypeArrayKlass::initialize(TRAPS) {
   // Nothing to do. Having this function is handy since objArrayKlasses can be
--- a/src/share/vm/opto/bytecodeInfo.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/bytecodeInfo.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -47,7 +47,8 @@
   _site_invoke_ratio(site_invoke_ratio),
   _max_inline_level(max_inline_level),
   _count_inline_bcs(method()->code_size_for_inlining()),
-  _subtrees(c->comp_arena(), 2, 0, NULL)
+  _subtrees(c->comp_arena(), 2, 0, NULL),
+  _msg(NULL)
 {
   NOT_PRODUCT(_count_inlines = 0;)
   if (_caller_jvms != NULL) {
@@ -77,7 +78,8 @@
   _method(callee_method),
   _site_invoke_ratio(site_invoke_ratio),
   _max_inline_level(max_inline_level),
-  _count_inline_bcs(method()->code_size())
+  _count_inline_bcs(method()->code_size()),
+  _msg(NULL)
 {
   NOT_PRODUCT(_count_inlines = 0;)
   assert(!UseOldInlining, "do not use for old stuff");
@@ -95,8 +97,10 @@
          );
 }
 
-// positive filter: should callee be inlined?  returns NULL, if yes, or rejection msg
-const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const {
+// positive filter: should callee be inlined?
+bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method,
+                               int caller_bci, ciCallProfile& profile,
+                               WarmCallInfo* wci_result) {
   // Allows targeted inlining
   if(callee_method->should_inline()) {
     *wci_result = *(WarmCallInfo::always_hot());
@@ -104,11 +108,10 @@
       CompileTask::print_inline_indent(inline_level());
       tty->print_cr("Inlined method is hot: ");
     }
-    return NULL;
+    set_msg("force inline by CompilerOracle");
+    return true;
   }
 
-  // positive filter: should send be inlined?  returns NULL (--> yes)
-  // or rejection msg
   int size = callee_method->code_size_for_inlining();
 
   // Check for too many throws (and not too huge)
@@ -119,11 +122,13 @@
       CompileTask::print_inline_indent(inline_level());
       tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count());
     }
-    return NULL;
+    set_msg("many throws");
+    return true;
   }
 
   if (!UseOldInlining) {
-    return NULL;  // size and frequency are represented in a new way
+    set_msg("!UseOldInlining");
+    return true;  // size and frequency are represented in a new way
   }
 
   int default_max_inline_size = C->max_inline_size();
@@ -153,31 +158,44 @@
     // Not hot.  Check for medium-sized pre-existing nmethod at cold sites.
     if (callee_method->has_compiled_code() &&
         callee_method->instructions_size() > inline_small_code_size)
-      return "already compiled into a medium method";
+      set_msg("already compiled into a medium method");
+      return false;
   }
   if (size > max_inline_size) {
-    if (max_inline_size > default_max_inline_size)
-      return "hot method too big";
-    return "too big";
+    if (max_inline_size > default_max_inline_size) {
+      set_msg("hot method too big");
+    } else {
+      set_msg("too big");
+    }
+    return false;
   }
-  return NULL;
+  return true;
 }
 
 
-// negative filter: should callee NOT be inlined?  returns NULL, ok to inline, or rejection msg
-const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const {
-  // negative filter: should send NOT be inlined?  returns NULL (--> inline) or rejection msg
+// negative filter: should callee NOT be inlined?
+bool InlineTree::should_not_inline(ciMethod *callee_method,
+                                   ciMethod* caller_method,
+                                   WarmCallInfo* wci_result) {
+
+  const char* fail_msg = NULL;
+
+  // First check all inlining restrictions which are required for correctness
+  if ( callee_method->is_abstract()) {
+    fail_msg = "abstract method"; // // note: we allow ik->is_abstract()
+  } else if (!callee_method->holder()->is_initialized()) {
+    fail_msg = "method holder not initialized";
+  } else if ( callee_method->is_native()) {
+    fail_msg = "native method";
+  } else if ( callee_method->dont_inline()) {
+    fail_msg = "don't inline by annotation";
+  }
+
   if (!UseOldInlining) {
-    const char* fail = NULL;
-    if ( callee_method->is_abstract())               fail = "abstract method";
-    // note: we allow ik->is_abstract()
-    if (!callee_method->holder()->is_initialized())  fail = "method holder not initialized";
-    if ( callee_method->is_native())                 fail = "native method";
-    if ( callee_method->dont_inline())               fail = "don't inline by annotation";
-
-    if (fail) {
+    if (fail_msg != NULL) {
       *wci_result = *(WarmCallInfo::always_cold());
-      return fail;
+      set_msg(fail_msg);
+      return true;
     }
 
     if (callee_method->has_unloaded_classes_in_signature()) {
@@ -199,23 +217,27 @@
       // %%% adjust wci_result->size()?
     }
 
-    return NULL;
+    return false;
+  }
+
+  // one more inlining restriction
+  if (fail_msg == NULL && callee_method->has_unloaded_classes_in_signature()) {
+    fail_msg = "unloaded signature classes";
   }
 
-  // First check all inlining restrictions which are required for correctness
-  if ( callee_method->is_abstract())                        return "abstract method";
-  // note: we allow ik->is_abstract()
-  if (!callee_method->holder()->is_initialized())           return "method holder not initialized";
-  if ( callee_method->is_native())                          return "native method";
-  if ( callee_method->dont_inline())                        return "don't inline by annotation";
-  if ( callee_method->has_unloaded_classes_in_signature())  return "unloaded signature classes";
+  if (fail_msg != NULL) {
+    set_msg(fail_msg);
+    return true;
+  }
 
+  // ignore heuristic controls on inlining
   if (callee_method->should_inline()) {
-    // ignore heuristic controls on inlining
-    return NULL;
+    set_msg("force inline by CompilerOracle");
+    return false;
   }
   if (callee_method->should_not_inline()) {
-    return "disallowed by CompilerOracle";
+    set_msg("disallowed by CompilerOracle");
+    return false;
   }
 
   // Now perform checks which are heuristic
@@ -223,7 +245,8 @@
   if (!callee_method->force_inline()) {
     if (callee_method->has_compiled_code() &&
         callee_method->instructions_size() > InlineSmallCode) {
-    return "already compiled into a big method";
+      set_msg("already compiled into a big method");
+      return true;
     }
   }
 
@@ -234,17 +257,21 @@
     const InlineTree *top = this;
     while (top->caller_tree() != NULL) top = top->caller_tree();
     ciInstanceKlass* k = top->method()->holder();
-    if (!k->is_subclass_of(C->env()->Throwable_klass()))
-      return "exception method";
+    if (!k->is_subclass_of(C->env()->Throwable_klass())) {
+      set_msg("exception method");
+      return true;
+    }
   }
 
   if (callee_method->should_not_inline()) {
-    return "disallowed by CompilerOracle";
+    set_msg("disallowed by CompilerOracle");
+    return true;
   }
 
 #ifndef PRODUCT
   if (ciReplay::should_not_inline(callee_method)) {
-    return "disallowed by ciReplay";
+    set_msg("disallowed by ciReplay");
+    return true;
   }
 #endif
 
@@ -252,19 +279,23 @@
     // Do not inline StringCache::profile() method used only at the beginning.
     if (callee_method->name() == ciSymbol::profile_name() &&
         callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) {
-      return "profiling method";
+      set_msg("profiling method");
+      return true;
     }
   }
 
   // use frequency-based objections only for non-trivial methods
-  if (callee_method->code_size() <= MaxTrivialSize) return NULL;
+  if (callee_method->code_size() <= MaxTrivialSize) {
+    return false;
+  }
 
   // don't use counts with -Xcomp or CTW
   if (UseInterpreter && !CompileTheWorld) {
 
     if (!callee_method->has_compiled_code() &&
         !callee_method->was_executed_more_than(0)) {
-      return "never executed";
+      set_msg("never executed");
+      return true;
     }
 
     if (is_init_with_ea(callee_method, caller_method, C)) {
@@ -273,39 +304,44 @@
 
     } else if (!callee_method->was_executed_more_than(MIN2(MinInliningThreshold,
                                                            CompileThreshold >> 1))) {
-      return "executed < MinInliningThreshold times";
+      set_msg("executed < MinInliningThreshold times");
+      return true;
     }
   }
 
-  return NULL;
+  return false;
 }
 
 //-----------------------------try_to_inline-----------------------------------
-// return NULL if ok, reason for not inlining otherwise
+// return true if ok
 // Relocated from "InliningClosure::try_to_inline"
-const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay) {
-  // Old algorithm had funny accumulating BC-size counters
+bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method,
+                               int caller_bci, ciCallProfile& profile,
+                               WarmCallInfo* wci_result, bool& should_delay) {
+
+   // Old algorithm had funny accumulating BC-size counters
   if (UseOldInlining && ClipInlining
       && (int)count_inline_bcs() >= DesiredMethodLimit) {
     if (!callee_method->force_inline() || !IncrementalInline) {
-      return "size > DesiredMethodLimit";
+      set_msg("size > DesiredMethodLimit");
+      return false;
     } else if (!C->inlining_incrementally()) {
       should_delay = true;
     }
   }
 
-  const char *msg = NULL;
-  msg = should_inline(callee_method, caller_method, caller_bci, profile, wci_result);
-  if (msg != NULL)
-    return msg;
-
-  msg = should_not_inline(callee_method, caller_method, wci_result);
-  if (msg != NULL)
-    return msg;
+  if (!should_inline(callee_method, caller_method, caller_bci, profile,
+                     wci_result)) {
+    return false;
+  }
+  if (should_not_inline(callee_method, caller_method, wci_result)) {
+    return false;
+  }
 
   if (InlineAccessors && callee_method->is_accessor()) {
     // accessor methods are not subject to any of the following limits.
-    return NULL;
+    set_msg("accessor");
+    return true;
   }
 
   // suppress a few checks for accessors and trivial methods
@@ -315,7 +351,8 @@
     if (C->over_inlining_cutoff()) {
       if ((!callee_method->force_inline() && !caller_method->is_compiled_lambda_form())
           || !IncrementalInline) {
-        return "NodeCountInliningCutoff";
+        set_msg("NodeCountInliningCutoff");
+        return false;
       } else {
         should_delay = true;
       }
@@ -329,16 +366,19 @@
 
     } else if (profile.count() == 0) {
       // don't inline unreached call sites
-      return "call site not reached";
+       set_msg("call site not reached");
+       return false;
     }
   }
 
   if (!C->do_inlining() && InlineAccessors) {
-    return "not an accessor";
+    set_msg("not an accessor");
+    return false;
   }
   if (inline_level() > _max_inline_level) {
     if (!callee_method->force_inline() || !IncrementalInline) {
-      return "inlining too deep";
+      set_msg("inlining too deep");
+      return false;
     } else if (!C->inlining_incrementally()) {
       should_delay = true;
     }
@@ -348,15 +388,19 @@
   if (!callee_method->is_compiled_lambda_form()) {
     // count the current method and the callee
     int inline_level = (method() == callee_method) ? 1 : 0;
-    if (inline_level > MaxRecursiveInlineLevel)
-      return "recursively inlining too deep";
+    if (inline_level > MaxRecursiveInlineLevel) {
+      set_msg("recursively inlining too deep");
+      return false;
+    }
     // count callers of current method and callee
     JVMState* jvms = caller_jvms();
     while (jvms != NULL && jvms->has_method()) {
       if (jvms->method() == callee_method) {
         inline_level++;
-        if (inline_level > MaxRecursiveInlineLevel)
-          return "recursively inlining too deep";
+        if (inline_level > MaxRecursiveInlineLevel) {
+          set_msg("recursively inlining too deep");
+          return false;
+        }
       }
       jvms = jvms->caller();
     }
@@ -367,14 +411,15 @@
   if (UseOldInlining && ClipInlining
       && (int)count_inline_bcs() + size >= DesiredMethodLimit) {
     if (!callee_method->force_inline() || !IncrementalInline) {
-      return "size > DesiredMethodLimit";
+      set_msg("size > DesiredMethodLimit");
+      return false;
     } else if (!C->inlining_incrementally()) {
       should_delay = true;
     }
   }
 
   // ok, inline this method
-  return NULL;
+  return true;
 }
 
 //------------------------------pass_initial_checks----------------------------
@@ -423,14 +468,25 @@
 }
 
 //------------------------------print_inlining---------------------------------
-// Really, the failure_msg can be a success message also.
-void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const {
-  C->print_inlining(callee_method, inline_level(), caller_bci, failure_msg ? failure_msg : "inline");
-  if (callee_method == NULL)  tty->print(" callee not monotonic or profiled");
-  if (Verbose && callee_method) {
-    const InlineTree *top = this;
-    while( top->caller_tree() != NULL ) { top = top->caller_tree(); }
-    //tty->print("  bcs: %d+%d  invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count());
+void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci,
+                                bool success) const {
+  const char* inline_msg = msg();
+  assert(inline_msg != NULL, "just checking");
+  if (C->log() != NULL) {
+    if (success) {
+      C->log()->inline_success(inline_msg);
+    } else {
+      C->log()->inline_fail(inline_msg);
+    }
+  }
+  if (PrintInlining) {
+    C->print_inlining(callee_method, inline_level(), caller_bci, inline_msg);
+    if (callee_method == NULL) tty->print(" callee not monotonic or profiled");
+    if (Verbose && callee_method) {
+      const InlineTree *top = this;
+      while( top->caller_tree() != NULL ) { top = top->caller_tree(); }
+      //tty->print("  bcs: %d+%d  invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count());
+    }
   }
 }
 
@@ -448,48 +504,50 @@
   }
   assert(_method == jvms->method(), "redundant instance state");
 #endif
-  const char *failure_msg   = NULL;
   int         caller_bci    = jvms->bci();
-  ciMethod   *caller_method = jvms->method();
+  ciMethod*   caller_method = jvms->method();
 
   // Do some initial checks.
   if (!pass_initial_checks(caller_method, caller_bci, callee_method)) {
-    if (PrintInlining)  print_inlining(callee_method, caller_bci, "failed initial checks");
+    set_msg("failed initial checks");
+    print_inlining(callee_method, caller_bci, false /* !success */);
     return NULL;
   }
 
   // Do some parse checks.
-  failure_msg = check_can_parse(callee_method);
-  if (failure_msg != NULL) {
-    if (PrintInlining)  print_inlining(callee_method, caller_bci, failure_msg);
+  set_msg(check_can_parse(callee_method));
+  if (msg() != NULL) {
+    print_inlining(callee_method, caller_bci, false /* !success */);
     return NULL;
   }
 
   // Check if inlining policy says no.
   WarmCallInfo wci = *(initial_wci);
-  failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci, should_delay);
-  if (failure_msg != NULL && C->log() != NULL) {
-    C->log()->inline_fail(failure_msg);
-  }
+  bool success = try_to_inline(callee_method, caller_method, caller_bci,
+                               profile, &wci, should_delay);
 
 #ifndef PRODUCT
   if (UseOldInlining && InlineWarmCalls
       && (PrintOpto || PrintOptoInlining || PrintInlining)) {
     bool cold = wci.is_cold();
     bool hot  = !cold && wci.is_hot();
-    bool old_cold = (failure_msg != NULL);
+    bool old_cold = !success;
     if (old_cold != cold || (Verbose || WizardMode)) {
+      if (msg() == NULL) {
+        set_msg("OK");
+      }
       tty->print("   OldInlining= %4s : %s\n           WCI=",
-                 old_cold ? "cold" : "hot", failure_msg ? failure_msg : "OK");
+                 old_cold ? "cold" : "hot", msg());
       wci.print();
     }
   }
 #endif
   if (UseOldInlining) {
-    if (failure_msg == NULL)
+    if (success) {
       wci = *(WarmCallInfo::always_hot());
-    else
+    } else {
       wci = *(WarmCallInfo::always_cold());
+    }
   }
   if (!InlineWarmCalls) {
     if (!wci.is_cold() && !wci.is_hot()) {
@@ -499,11 +557,11 @@
   }
 
   if (!wci.is_cold()) {
-    // In -UseOldInlining, the failure_msg may also be a success message.
-    if (failure_msg == NULL)  failure_msg = "inline (hot)";
-
     // Inline!
-    if (PrintInlining)  print_inlining(callee_method, caller_bci, failure_msg);
+    if (msg() == NULL) {
+      set_msg("inline (hot)");
+    }
+    print_inlining(callee_method, caller_bci, true /* success */);
     if (UseOldInlining)
       build_inline_tree_for_callee(callee_method, jvms, caller_bci);
     if (InlineWarmCalls && !wci.is_hot())
@@ -512,8 +570,10 @@
   }
 
   // Do not inline
-  if (failure_msg == NULL)  failure_msg = "too cold to inline";
-  if (PrintInlining)  print_inlining(callee_method, caller_bci, failure_msg);
+  if (msg() == NULL) {
+    set_msg("too cold to inline");
+  }
+  print_inlining(callee_method, caller_bci, false /* !success */ );
   return NULL;
 }
 
--- a/src/share/vm/opto/c2_globals.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/c2_globals.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -618,6 +618,9 @@
                                                                             \
   product(intx, LiveNodeCountInliningCutoff, 20000,                         \
           "max number of live nodes in a method")                           \
+                                                                            \
+  diagnostic(bool, OptimizeExpensiveOps, true,                              \
+          "Find best control for expensive operations")                     \
 
 
 C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
--- a/src/share/vm/opto/callGenerator.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/callGenerator.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -305,11 +305,13 @@
 void LateInlineCallGenerator::do_late_inline() {
   // Can't inline it
   if (call_node() == NULL || call_node()->outcnt() == 0 ||
-      call_node()->in(0) == NULL || call_node()->in(0)->is_top())
+      call_node()->in(0) == NULL || call_node()->in(0)->is_top()) {
     return;
+  }
 
+  const TypeTuple *r = call_node()->tf()->domain();
   for (int i1 = 0; i1 < method()->arg_size(); i1++) {
-    if (call_node()->in(TypeFunc::Parms + i1)->is_top()) {
+    if (call_node()->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) {
       assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing");
       return;
     }
--- a/src/share/vm/opto/compile.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/compile.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -409,6 +409,13 @@
       remove_macro_node(n);
     }
   }
+  // Remove useless expensive node
+  for (int i = C->expensive_count()-1; i >= 0; i--) {
+    Node* n = C->expensive_node(i);
+    if (!useful.member(n)) {
+      remove_expensive_node(n);
+    }
+  }
   // clean up the late inline lists
   remove_useless_late_inlines(&_string_late_inlines, useful);
   remove_useless_late_inlines(&_late_inlines, useful);
@@ -1061,6 +1068,7 @@
   _intrinsics = NULL;
   _macro_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8,  0, NULL);
   _predicate_opaqs = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8,  0, NULL);
+  _expensive_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8,  0, NULL);
   register_library_intrinsics();
 }
 
@@ -1927,6 +1935,10 @@
 
   if (failing())  return;
 
+  // No more new expensive nodes will be added to the list from here
+  // so keep only the actual candidates for optimizations.
+  cleanup_expensive_nodes(igvn);
+
   // Perform escape analysis
   if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
     if (has_loops()) {
@@ -3010,6 +3022,15 @@
     return true;
   }
 
+  // Expensive nodes have their control input set to prevent the GVN
+  // from freely commoning them. There's no GVN beyond this point so
+  // no need to keep the control input. We want the expensive nodes to
+  // be freely moved to the least frequent code path by gcm.
+  assert(OptimizeExpensiveOps || expensive_count() == 0, "optimization off but list non empty?");
+  for (int i = 0; i < expensive_count(); i++) {
+    _expensive_nodes->at(i)->set_req(0, NULL);
+  }
+
   Final_Reshape_Counts frc;
 
   // Visit everybody reachable!
@@ -3525,3 +3546,126 @@
     }
   }
 }
+
+int Compile::cmp_expensive_nodes(Node* n1, Node* n2) {
+  if (n1->Opcode() < n2->Opcode())      return -1;
+  else if (n1->Opcode() > n2->Opcode()) return 1;
+
+  assert(n1->req() == n2->req(), err_msg_res("can't compare %s nodes: n1->req() = %d, n2->req() = %d", NodeClassNames[n1->Opcode()], n1->req(), n2->req()));
+  for (uint i = 1; i < n1->req(); i++) {
+    if (n1->in(i) < n2->in(i))      return -1;
+    else if (n1->in(i) > n2->in(i)) return 1;
+  }
+
+  return 0;
+}
+
+int Compile::cmp_expensive_nodes(Node** n1p, Node** n2p) {
+  Node* n1 = *n1p;
+  Node* n2 = *n2p;
+
+  return cmp_expensive_nodes(n1, n2);
+}
+
+void Compile::sort_expensive_nodes() {
+  if (!expensive_nodes_sorted()) {
+    _expensive_nodes->sort(cmp_expensive_nodes);
+  }
+}
+
+bool Compile::expensive_nodes_sorted() const {
+  for (int i = 1; i < _expensive_nodes->length(); i++) {
+    if (cmp_expensive_nodes(_expensive_nodes->adr_at(i), _expensive_nodes->adr_at(i-1)) < 0) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool Compile::should_optimize_expensive_nodes(PhaseIterGVN &igvn) {
+  if (_expensive_nodes->length() == 0) {
+    return false;
+  }
+
+  assert(OptimizeExpensiveOps, "optimization off?");
+
+  // Take this opportunity to remove dead nodes from the list
+  int j = 0;
+  for (int i = 0; i < _expensive_nodes->length(); i++) {
+    Node* n = _expensive_nodes->at(i);
+    if (!n->is_unreachable(igvn)) {
+      assert(n->is_expensive(), "should be expensive");
+      _expensive_nodes->at_put(j, n);
+      j++;
+    }
+  }
+  _expensive_nodes->trunc_to(j);
+
+  // Then sort the list so that similar nodes are next to each other
+  // and check for at least two nodes of identical kind with same data
+  // inputs.
+  sort_expensive_nodes();
+
+  for (int i = 0; i < _expensive_nodes->length()-1; i++) {
+    if (cmp_expensive_nodes(_expensive_nodes->adr_at(i), _expensive_nodes->adr_at(i+1)) == 0) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void Compile::cleanup_expensive_nodes(PhaseIterGVN &igvn) {
+  if (_expensive_nodes->length() == 0) {
+    return;
+  }
+
+  assert(OptimizeExpensiveOps, "optimization off?");
+
+  // Sort to bring similar nodes next to each other and clear the
+  // control input of nodes for which there's only a single copy.
+  sort_expensive_nodes();
+
+  int j = 0;
+  int identical = 0;
+  int i = 0;
+  for (; i < _expensive_nodes->length()-1; i++) {
+    assert(j <= i, "can't write beyond current index");
+    if (_expensive_nodes->at(i)->Opcode() == _expensive_nodes->at(i+1)->Opcode()) {
+      identical++;
+      _expensive_nodes->at_put(j++, _expensive_nodes->at(i));
+      continue;
+    }
+    if (identical > 0) {
+      _expensive_nodes->at_put(j++, _expensive_nodes->at(i));
+      identical = 0;
+    } else {
+      Node* n = _expensive_nodes->at(i);
+      igvn.hash_delete(n);
+      n->set_req(0, NULL);
+      igvn.hash_insert(n);
+    }
+  }
+  if (identical > 0) {
+    _expensive_nodes->at_put(j++, _expensive_nodes->at(i));
+  } else if (_expensive_nodes->length() >= 1) {
+    Node* n = _expensive_nodes->at(i);
+    igvn.hash_delete(n);
+    n->set_req(0, NULL);
+    igvn.hash_insert(n);
+  }
+  _expensive_nodes->trunc_to(j);
+}
+
+void Compile::add_expensive_node(Node * n) {
+  assert(!_expensive_nodes->contains(n), "duplicate entry in expensive list");
+  assert(n->is_expensive(), "expensive nodes with non-null control here only");
+  assert(!n->is_CFG() && !n->is_Mem(), "no cfg or memory nodes here");
+  if (OptimizeExpensiveOps) {
+    _expensive_nodes->append(n);
+  } else {
+    // Clear control input and let IGVN optimize expensive nodes if
+    // OptimizeExpensiveOps is off.
+    n->set_req(0, NULL);
+  }
+}
--- a/src/share/vm/opto/compile.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/compile.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -314,6 +314,7 @@
   GrowableArray<CallGenerator*>* _intrinsics;   // List of intrinsics.
   GrowableArray<Node*>* _macro_nodes;           // List of nodes which need to be expanded before matching.
   GrowableArray<Node*>* _predicate_opaqs;       // List of Opaque1 nodes for the loop predicates.
+  GrowableArray<Node*>* _expensive_nodes;       // List of nodes that are expensive to compute and that we'd better not let the GVN freely common
   ConnectionGraph*      _congraph;
 #ifndef PRODUCT
   IdealGraphPrinter*    _printer;
@@ -398,6 +399,13 @@
   GrowableArray<PrintInliningBuffer>* _print_inlining_list;
   int _print_inlining;
 
+  // Only keep nodes in the expensive node list that need to be optimized
+  void cleanup_expensive_nodes(PhaseIterGVN &igvn);
+  // Use for sorting expensive nodes to bring similar nodes together
+  static int cmp_expensive_nodes(Node** n1, Node** n2);
+  // Expensive nodes list already sorted?
+  bool expensive_nodes_sorted() const;
+
  public:
 
   outputStream* print_inlining_stream() const {
@@ -573,8 +581,10 @@
 
   int           macro_count()                   { return _macro_nodes->length(); }
   int           predicate_count()               { return _predicate_opaqs->length();}
+  int           expensive_count()               { return _expensive_nodes->length(); }
   Node*         macro_node(int idx)             { return _macro_nodes->at(idx); }
   Node*         predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);}
+  Node*         expensive_node(int idx)         { return _expensive_nodes->at(idx); }
   ConnectionGraph* congraph()                   { return _congraph;}
   void set_congraph(ConnectionGraph* congraph)  { _congraph = congraph;}
   void add_macro_node(Node * n) {
@@ -592,6 +602,12 @@
       _predicate_opaqs->remove(n);
     }
   }
+  void add_expensive_node(Node * n);
+  void remove_expensive_node(Node * n) {
+    if (_expensive_nodes->contains(n)) {
+      _expensive_nodes->remove(n);
+    }
+  }
   void add_predicate_opaq(Node * n) {
     assert(!_predicate_opaqs->contains(n), " duplicate entry in predicate opaque1");
     assert(_macro_nodes->contains(n), "should have already been in macro list");
@@ -604,6 +620,13 @@
     return _predicate_opaqs->contains(n);
   }
 
+  // Are there candidate expensive nodes for optimization?
+  bool should_optimize_expensive_nodes(PhaseIterGVN &igvn);
+  // Check whether n1 and n2 are similar
+  static int cmp_expensive_nodes(Node* n1, Node* n2);
+  // Sort expensive nodes to locate similar expensive nodes
+  void sort_expensive_nodes();
+
   // Compilation environment.
   Arena*            comp_arena()                { return &_comp_arena; }
   ciEnv*            env() const                 { return _env; }
--- a/src/share/vm/opto/generateOptoStub.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/generateOptoStub.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -88,12 +88,12 @@
                                             thread,
                                             in_bytes(JavaThread::frame_anchor_offset()) +
                                             in_bytes(JavaFrameAnchor::last_Java_pc_offset()));
-#if defined(SPARC) || defined(IA64)
+#if defined(SPARC)
   Node* adr_flags = basic_plus_adr(top(),
                                    thread,
                                    in_bytes(JavaThread::frame_anchor_offset()) +
                                    in_bytes(JavaFrameAnchor::flags_offset()));
-#endif /* defined(SPARC) || defined(IA64) */
+#endif /* defined(SPARC) */
 
 
   // Drop in the last_Java_sp.  last_Java_fp is not touched.
@@ -102,10 +102,8 @@
   // users will look at the other fields.
   //
   Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset()));
-#ifndef IA64
   Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS);
   store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias);
-#endif
 
   // Set _thread_in_native
   // The order of stores into TLS is critical!  Setting _thread_in_native MUST
@@ -210,19 +208,12 @@
   //-----------------------------
 
   // Clear last_Java_sp
-#ifdef IA64
-  if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease);
-#endif
-
   store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias);
-#ifdef IA64
-  if (os::is_MP() && UseMembar) insert_mem_bar(new MemBarVolatileNode());
-#endif // def IA64
   // Clear last_Java_pc and (optionally)_flags
   store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias);
-#if defined(SPARC) || defined(IA64)
+#if defined(SPARC)
   store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias);
-#endif /* defined(SPARC) || defined(IA64) */
+#endif /* defined(SPARC) */
 #ifdef IA64
   Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset()));
   if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease);
--- a/src/share/vm/opto/library_call.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/library_call.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1481,10 +1481,10 @@
   Node* arg = round_double_node(argument(0));
   Node* n;
   switch (id) {
-  case vmIntrinsics::_dabs:   n = new (C) AbsDNode(    arg);  break;
-  case vmIntrinsics::_dsqrt:  n = new (C) SqrtDNode(0, arg);  break;
-  case vmIntrinsics::_dlog:   n = new (C) LogDNode(    arg);  break;
-  case vmIntrinsics::_dlog10: n = new (C) Log10DNode(  arg);  break;
+  case vmIntrinsics::_dabs:   n = new (C) AbsDNode(                arg);  break;
+  case vmIntrinsics::_dsqrt:  n = new (C) SqrtDNode(C, control(),  arg);  break;
+  case vmIntrinsics::_dlog:   n = new (C) LogDNode(C, control(),   arg);  break;
+  case vmIntrinsics::_dlog10: n = new (C) Log10DNode(C, control(), arg);  break;
   default:  fatal_unexpected_iid(id);  break;
   }
   set_result(_gvn.transform(n));
@@ -1499,9 +1499,9 @@
   Node* n = NULL;
 
   switch (id) {
-  case vmIntrinsics::_dsin:  n = new (C) SinDNode(arg);  break;
-  case vmIntrinsics::_dcos:  n = new (C) CosDNode(arg);  break;
-  case vmIntrinsics::_dtan:  n = new (C) TanDNode(arg);  break;
+  case vmIntrinsics::_dsin:  n = new (C) SinDNode(C, control(), arg);  break;
+  case vmIntrinsics::_dcos:  n = new (C) CosDNode(C, control(), arg);  break;
+  case vmIntrinsics::_dtan:  n = new (C) TanDNode(C, control(), arg);  break;
   default:  fatal_unexpected_iid(id);  break;
   }
   n = _gvn.transform(n);
@@ -1653,7 +1653,7 @@
 // really odd corner cases (+/- Infinity).  Just uncommon-trap them.
 bool LibraryCallKit::inline_exp() {
   Node* arg = round_double_node(argument(0));
-  Node* n   = _gvn.transform(new (C) ExpDNode(0, arg));
+  Node* n   = _gvn.transform(new (C) ExpDNode(C, control(), arg));
 
   finish_pow_exp(n, arg, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP");
 
@@ -1688,7 +1688,7 @@
 
   if (!too_many_traps(Deoptimization::Reason_intrinsic)) {
     // Short form: skip the fancy tests and just check for NaN result.
-    result = _gvn.transform(new (C) PowDNode(0, x, y));
+    result = _gvn.transform(new (C) PowDNode(C, control(), x, y));
   } else {
     // If this inlining ever returned NaN in the past, include all
     // checks + call to the runtime.
@@ -1715,7 +1715,7 @@
     Node *complex_path = _gvn.transform( new (C) IfTrueNode(if1) );
 
     // Set fast path result
-    Node *fast_result = _gvn.transform( new (C) PowDNode(0, x, y) );
+    Node *fast_result = _gvn.transform( new (C) PowDNode(C, control(), x, y) );
     phi->init_req(3, fast_result);
 
     // Complex path
@@ -1775,7 +1775,7 @@
     // abs(x)
     Node *absx=_gvn.transform( new (C) AbsDNode(x));
     // abs(x)^y
-    Node *absxpowy = _gvn.transform( new (C) PowDNode(0, absx, y) );
+    Node *absxpowy = _gvn.transform( new (C) PowDNode(C, control(), absx, y) );
     // -abs(x)^y
     Node *negabsxpowy = _gvn.transform(new (C) NegDNode (absxpowy));
     // (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y)
--- a/src/share/vm/opto/loopnode.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/loopnode.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -88,9 +88,9 @@
   assert( !n->is_Phi() && !n->is_CFG(), "this code only handles data nodes" );
   uint i;
   Node *early;
-  if( n->in(0) ) {
+  if (n->in(0) && !n->is_expensive()) {
     early = n->in(0);
-    if( !early->is_CFG() ) // Might be a non-CFG multi-def
+    if (!early->is_CFG()) // Might be a non-CFG multi-def
       early = get_ctrl(early);        // So treat input as a straight data input
     i = 1;
   } else {
@@ -99,28 +99,28 @@
   }
   uint e_d = dom_depth(early);
   assert( early, "" );
-  for( ; i < n->req(); i++ ) {
+  for (; i < n->req(); i++) {
     Node *cin = get_ctrl(n->in(i));
     assert( cin, "" );
     // Keep deepest dominator depth
     uint c_d = dom_depth(cin);
-    if( c_d > e_d ) {           // Deeper guy?
+    if (c_d > e_d) {           // Deeper guy?
       early = cin;              // Keep deepest found so far
       e_d = c_d;
-    } else if( c_d == e_d &&    // Same depth?
-               early != cin ) { // If not equal, must use slower algorithm
+    } else if (c_d == e_d &&    // Same depth?
+               early != cin) { // If not equal, must use slower algorithm
       // If same depth but not equal, one _must_ dominate the other
       // and we want the deeper (i.e., dominated) guy.
       Node *n1 = early;
       Node *n2 = cin;
-      while( 1 ) {
+      while (1) {
         n1 = idom(n1);          // Walk up until break cycle
         n2 = idom(n2);
-        if( n1 == cin ||        // Walked early up to cin
-            dom_depth(n2) < c_d )
+        if (n1 == cin ||        // Walked early up to cin
+            dom_depth(n2) < c_d)
           break;                // early is deeper; keep him
-        if( n2 == early ||      // Walked cin up to early
-            dom_depth(n1) < c_d ) {
+        if (n2 == early ||      // Walked cin up to early
+            dom_depth(n1) < c_d) {
           early = cin;          // cin is deeper; keep him
           break;
         }
@@ -132,9 +132,108 @@
   // Return earliest legal location
   assert(early == find_non_split_ctrl(early), "unexpected early control");
 
+  if (n->is_expensive()) {
+    assert(n->in(0), "should have control input");
+    early = get_early_ctrl_for_expensive(n, early);
+  }
+
   return early;
 }
 
+//------------------------------get_early_ctrl_for_expensive---------------------------------
+// Move node up the dominator tree as high as legal while still beneficial
+Node *PhaseIdealLoop::get_early_ctrl_for_expensive(Node *n, Node* earliest) {
+  assert(n->in(0) && n->is_expensive(), "expensive node with control input here");
+  assert(OptimizeExpensiveOps, "optimization off?");
+
+  Node* ctl = n->in(0);
+  assert(ctl->is_CFG(), "expensive input 0 must be cfg");
+  uint min_dom_depth = dom_depth(earliest);
+#ifdef ASSERT
+  if (!is_dominator(ctl, earliest) && !is_dominator(earliest, ctl)) {
+    dump_bad_graph("Bad graph detected in get_early_ctrl_for_expensive", n, earliest, ctl);
+    assert(false, "Bad graph detected in get_early_ctrl_for_expensive");
+  }
+#endif
+  if (dom_depth(ctl) < min_dom_depth) {
+    return earliest;
+  }
+
+  while (1) {
+    Node *next = ctl;
+    // Moving the node out of a loop on the projection of a If
+    // confuses loop predication. So once we hit a Loop in a If branch
+    // that doesn't branch to an UNC, we stop. The code that process
+    // expensive nodes will notice the loop and skip over it to try to
+    // move the node further up.
+    if (ctl->is_CountedLoop() && ctl->in(1) != NULL && ctl->in(1)->in(0) != NULL && ctl->in(1)->in(0)->is_If()) {
+      if (!is_uncommon_trap_if_pattern(ctl->in(1)->as_Proj(), Deoptimization::Reason_none)) {
+        break;
+      }
+      next = idom(ctl->in(1)->in(0));
+    } else if (ctl->is_Proj()) {
+      // We only move it up along a projection if the projection is
+      // the single control projection for its parent: same code path,
+      // if it's a If with UNC or fallthrough of a call.
+      Node* parent_ctl = ctl->in(0);
+      if (parent_ctl == NULL) {
+        break;
+      } else if (parent_ctl->is_CountedLoopEnd() && parent_ctl->as_CountedLoopEnd()->loopnode() != NULL) {
+        next = parent_ctl->as_CountedLoopEnd()->loopnode()->init_control();
+      } else if (parent_ctl->is_If()) {
+        if (!is_uncommon_trap_if_pattern(ctl->as_Proj(), Deoptimization::Reason_none)) {
+          break;
+        }
+        assert(idom(ctl) == parent_ctl, "strange");
+        next = idom(parent_ctl);
+      } else if (ctl->is_CatchProj()) {
+        if (ctl->as_Proj()->_con != CatchProjNode::fall_through_index) {
+          break;
+        }
+        assert(parent_ctl->in(0)->in(0)->is_Call(), "strange graph");
+        next = parent_ctl->in(0)->in(0)->in(0);
+      } else {
+        // Check if parent control has a single projection (this
+        // control is the only possible successor of the parent
+        // control). If so, we can try to move the node above the
+        // parent control.
+        int nb_ctl_proj = 0;
+        for (DUIterator_Fast imax, i = parent_ctl->fast_outs(imax); i < imax; i++) {
+          Node *p = parent_ctl->fast_out(i);
+          if (p->is_Proj() && p->is_CFG()) {
+            nb_ctl_proj++;
+            if (nb_ctl_proj > 1) {
+              break;
+            }
+          }
+        }
+
+        if (nb_ctl_proj > 1) {
+          break;
+        }
+        assert(parent_ctl->is_Start() || parent_ctl->is_MemBar() || parent_ctl->is_Call(), "unexpected node");
+        assert(idom(ctl) == parent_ctl, "strange");
+        next = idom(parent_ctl);
+      }
+    } else {
+      next = idom(ctl);
+    }
+    if (next->is_Root() || next->is_Start() || dom_depth(next) < min_dom_depth) {
+      break;
+    }
+    ctl = next;
+  }
+
+  if (ctl != n->in(0)) {
+    _igvn.hash_delete(n);
+    n->set_req(0, ctl);
+    _igvn.hash_insert(n);
+  }
+
+  return ctl;
+}
+
+
 //------------------------------set_early_ctrl---------------------------------
 // Set earliest legal control
 void PhaseIdealLoop::set_early_ctrl( Node *n ) {
@@ -1892,6 +1991,98 @@
   }
 }
 
+//------------------------process_expensive_nodes-----------------------------
+// Expensive nodes have their control input set to prevent the GVN
+// from commoning them and as a result forcing the resulting node to
+// be in a more frequent path. Use CFG information here, to change the
+// control inputs so that some expensive nodes can be commoned while
+// not executed more frequently.
+bool PhaseIdealLoop::process_expensive_nodes() {
+  assert(OptimizeExpensiveOps, "optimization off?");
+
+  // Sort nodes to bring similar nodes together
+  C->sort_expensive_nodes();
+
+  bool progress = false;
+
+  for (int i = 0; i < C->expensive_count(); ) {
+    Node* n = C->expensive_node(i);
+    int start = i;
+    // Find nodes similar to n
+    i++;
+    for (; i < C->expensive_count() && Compile::cmp_expensive_nodes(n, C->expensive_node(i)) == 0; i++);
+    int end = i;
+    // And compare them two by two
+    for (int j = start; j < end; j++) {
+      Node* n1 = C->expensive_node(j);
+      if (is_node_unreachable(n1)) {
+        continue;
+      }
+      for (int k = j+1; k < end; k++) {
+        Node* n2 = C->expensive_node(k);
+        if (is_node_unreachable(n2)) {
+          continue;
+        }
+
+        assert(n1 != n2, "should be pair of nodes");
+
+        Node* c1 = n1->in(0);
+        Node* c2 = n2->in(0);
+
+        Node* parent_c1 = c1;
+        Node* parent_c2 = c2;
+
+        // The call to get_early_ctrl_for_expensive() moves the
+        // expensive nodes up but stops at loops that are in a if
+        // branch. See whether we can exit the loop and move above the
+        // If.
+        if (c1->is_Loop()) {
+          parent_c1 = c1->in(1);
+        }
+        if (c2->is_Loop()) {
+          parent_c2 = c2->in(1);
+        }
+
+        if (parent_c1 == parent_c2) {
+          _igvn._worklist.push(n1);
+          _igvn._worklist.push(n2);
+          continue;
+        }
+
+        // Look for identical expensive node up the dominator chain.
+        if (is_dominator(c1, c2)) {
+          c2 = c1;
+        } else if (is_dominator(c2, c1)) {
+          c1 = c2;
+        } else if (parent_c1->is_Proj() && parent_c1->in(0)->is_If() &&
+                   parent_c2->is_Proj() && parent_c1->in(0) == parent_c2->in(0)) {
+          // Both branches have the same expensive node so move it up
+          // before the if.
+          c1 = c2 = idom(parent_c1->in(0));
+        }
+        // Do the actual moves
+        if (n1->in(0) != c1) {
+          _igvn.hash_delete(n1);
+          n1->set_req(0, c1);
+          _igvn.hash_insert(n1);
+          _igvn._worklist.push(n1);
+          progress = true;
+        }
+        if (n2->in(0) != c2) {
+          _igvn.hash_delete(n2);
+          n2->set_req(0, c2);
+          _igvn.hash_insert(n2);
+          _igvn._worklist.push(n2);
+          progress = true;
+        }
+      }
+    }
+  }
+
+  return progress;
+}
+
+
 //=============================================================================
 //----------------------------build_and_optimize-------------------------------
 // Create a PhaseLoop.  Build the ideal Loop tree.  Map each Ideal Node to
@@ -1960,7 +2151,9 @@
   }
 
   // Nothing to do, so get out
-  if( !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only ) {
+  bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only;
+  bool do_expensive_nodes = C->should_optimize_expensive_nodes(_igvn);
+  if (stop_early && !do_expensive_nodes) {
     _igvn.optimize();           // Cleanup NeverBranches
     return;
   }
@@ -2058,6 +2251,21 @@
     return;
   }
 
+  if (stop_early) {
+    assert(do_expensive_nodes, "why are we here?");
+    if (process_expensive_nodes()) {
+      // If we made some progress when processing expensive nodes then
+      // the IGVN may modify the graph in a way that will allow us to
+      // make some more progress: we need to try processing expensive
+      // nodes again.
+      C->set_major_progress();
+    }
+
+    _igvn.optimize();
+
+    return;
+  }
+
   // Some parser-inserted loop predicates could never be used by loop
   // predication or they were moved away from loop during some optimizations.
   // For example, peeling. Eliminate them before next loop optimizations.
@@ -2120,6 +2328,10 @@
     NOT_PRODUCT( if( VerifyLoopOptimizations ) verify(); );
   }
 
+  if (!C->major_progress() && do_expensive_nodes && process_expensive_nodes()) {
+    C->set_major_progress();
+  }
+
   // Perform loop predication before iteration splitting
   if (C->has_loops() && !C->major_progress() && (C->predicate_count() > 0)) {
     _ltree_root->_child->loop_predication(this);
@@ -3299,7 +3511,7 @@
 #ifdef ASSERT
     if (legal->is_Start() && !early->is_Root()) {
       // Bad graph. Print idom path and fail.
-      dump_bad_graph(n, early, LCA);
+      dump_bad_graph("Bad graph detected in build_loop_late", n, early, LCA);
       assert(false, "Bad graph detected in build_loop_late");
     }
 #endif
@@ -3350,8 +3562,8 @@
 }
 
 #ifdef ASSERT
-void PhaseIdealLoop::dump_bad_graph(Node* n, Node* early, Node* LCA) {
-  tty->print_cr( "Bad graph detected in build_loop_late");
+void PhaseIdealLoop::dump_bad_graph(const char* msg, Node* n, Node* early, Node* LCA) {
+  tty->print_cr(msg);
   tty->print("n: "); n->dump();
   tty->print("early(n): "); early->dump();
   if (n->in(0) != NULL  && !n->in(0)->is_top() &&
--- a/src/share/vm/opto/loopnode.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/loopnode.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -263,9 +263,18 @@
   bool stride_is_con() const        { Node *tmp = stride  (); return (tmp != NULL && tmp->is_Con()); }
   BoolTest::mask test_trip() const  { return in(TestValue)->as_Bool()->_test._test; }
   CountedLoopNode *loopnode() const {
+    // The CountedLoopNode that goes with this CountedLoopEndNode may
+    // have been optimized out by the IGVN so be cautious with the
+    // pattern matching on the graph
+    if (phi() == NULL) {
+      return NULL;
+    }
     Node *ln = phi()->in(0);
-    assert( ln->Opcode() == Op_CountedLoop, "malformed loop" );
-    return (CountedLoopNode*)ln; }
+    if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) {
+      return (CountedLoopNode*)ln;
+    }
+    return NULL;
+  }
 
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
@@ -598,6 +607,7 @@
   // check if transform created new nodes that need _ctrl recorded
   Node *get_late_ctrl( Node *n, Node *early );
   Node *get_early_ctrl( Node *n );
+  Node *get_early_ctrl_for_expensive(Node *n, Node* earliest);
   void set_early_ctrl( Node *n );
   void set_subtree_ctrl( Node *root );
   void set_ctrl( Node *n, Node *ctrl ) {
@@ -905,6 +915,16 @@
   void collect_potentially_useful_predicates(IdealLoopTree *loop, Unique_Node_List &predicate_opaque1);
   void eliminate_useless_predicates();
 
+  // Change the control input of expensive nodes to allow commoning by
+  // IGVN when it is guaranteed to not result in a more frequent
+  // execution of the expensive node. Return true if progress.
+  bool process_expensive_nodes();
+
+  // Check whether node has become unreachable
+  bool is_node_unreachable(Node *n) const {
+    return !has_node(n) || n->is_unreachable(_igvn);
+  }
+
   // Eliminate range-checks and other trip-counter vs loop-invariant tests.
   void do_range_check( IdealLoopTree *loop, Node_List &old_new );
 
@@ -1043,7 +1063,7 @@
   void register_new_node( Node *n, Node *blk );
 
 #ifdef ASSERT
-void dump_bad_graph(Node* n, Node* early, Node* LCA);
+  void dump_bad_graph(const char* msg, Node* n, Node* early, Node* LCA);
 #endif
 
 #ifndef PRODUCT
--- a/src/share/vm/opto/memnode.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/memnode.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -320,6 +320,9 @@
 
   if (mem != old_mem) {
     set_req(MemNode::Memory, mem);
+    if (can_reshape && old_mem->outcnt() == 0) {
+        igvn->_worklist.push(old_mem);
+    }
     if (phase->type( mem ) == Type::TOP) return NodeSentinel;
     return this;
   }
@@ -2319,9 +2322,9 @@
   if (ReduceFieldZeroing && /*can_reshape &&*/
       mem->is_Proj() && mem->in(0)->is_Initialize()) {
     InitializeNode* init = mem->in(0)->as_Initialize();
-    intptr_t offset = init->can_capture_store(this, phase);
+    intptr_t offset = init->can_capture_store(this, phase, can_reshape);
     if (offset > 0) {
-      Node* moved = init->capture_store(this, offset, phase);
+      Node* moved = init->capture_store(this, offset, phase, can_reshape);
       // If the InitializeNode captured me, it made a raw copy of me,
       // and I need to disappear.
       if (moved != NULL) {
@@ -3134,7 +3137,7 @@
 // an initialization.  Returns zero if a check fails.
 // On success, returns the (constant) offset to which the store applies,
 // within the initialized memory.
-intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase) {
+intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape) {
   const int FAIL = 0;
   if (st->req() != MemNode::ValueIn + 1)
     return FAIL;                // an inscrutable StoreNode (card mark?)
@@ -3156,6 +3159,91 @@
   if (!detect_init_independence(val, true, complexity_count))
     return FAIL;                // stored value must be 'simple enough'
 
+  // The Store can be captured only if nothing after the allocation
+  // and before the Store is using the memory location that the store
+  // overwrites.
+  bool failed = false;
+  // If is_complete_with_arraycopy() is true the shape of the graph is
+  // well defined and is safe so no need for extra checks.
+  if (!is_complete_with_arraycopy()) {
+    // We are going to look at each use of the memory state following
+    // the allocation to make sure nothing reads the memory that the
+    // Store writes.
+    const TypePtr* t_adr = phase->type(adr)->isa_ptr();
+    int alias_idx = phase->C->get_alias_index(t_adr);
+    ResourceMark rm;
+    Unique_Node_List mems;
+    mems.push(mem);
+    Node* unique_merge = NULL;
+    for (uint next = 0; next < mems.size(); ++next) {
+      Node *m  = mems.at(next);
+      for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) {
+        Node *n = m->fast_out(j);
+        if (n->outcnt() == 0) {
+          continue;
+        }
+        if (n == st) {
+          continue;
+        } else if (n->in(0) != NULL && n->in(0) != ctl) {
+          // If the control of this use is different from the control
+          // of the Store which is right after the InitializeNode then
+          // this node cannot be between the InitializeNode and the
+          // Store.
+          continue;
+        } else if (n->is_MergeMem()) {
+          if (n->as_MergeMem()->memory_at(alias_idx) == m) {
+            // We can hit a MergeMemNode (that will likely go away
+            // later) that is a direct use of the memory state
+            // following the InitializeNode on the same slice as the
+            // store node that we'd like to capture. We need to check
+            // the uses of the MergeMemNode.
+            mems.push(n);
+          }
+        } else if (n->is_Mem()) {
+          Node* other_adr = n->in(MemNode::Address);
+          if (other_adr == adr) {
+            failed = true;
+            break;
+          } else {
+            const TypePtr* other_t_adr = phase->type(other_adr)->isa_ptr();
+            if (other_t_adr != NULL) {
+              int other_alias_idx = phase->C->get_alias_index(other_t_adr);
+              if (other_alias_idx == alias_idx) {
+                // A load from the same memory slice as the store right
+                // after the InitializeNode. We check the control of the
+                // object/array that is loaded from. If it's the same as
+                // the store control then we cannot capture the store.
+                assert(!n->is_Store(), "2 stores to same slice on same control?");
+                Node* base = other_adr;
+                assert(base->is_AddP(), err_msg_res("should be addp but is %s", base->Name()));
+                base = base->in(AddPNode::Base);
+                if (base != NULL) {
+                  base = base->uncast();
+                  if (base->is_Proj() && base->in(0) == alloc) {
+                    failed = true;
+                    break;
+                  }
+                }
+              }
+            }
+          }
+        } else {
+          failed = true;
+          break;
+        }
+      }
+    }
+  }
+  if (failed) {
+    if (!can_reshape) {
+      // We decided we couldn't capture the store during parsing. We
+      // should try again during the next IGVN once the graph is
+      // cleaner.
+      phase->C->record_for_igvn(st);
+    }
+    return FAIL;
+  }
+
   return offset;                // success
 }
 
@@ -3266,11 +3354,11 @@
 //                      rawstore1 rawstore2)
 //
 Node* InitializeNode::capture_store(StoreNode* st, intptr_t start,
-                                    PhaseTransform* phase) {
+                                    PhaseTransform* phase, bool can_reshape) {
   assert(stores_are_sane(phase), "");
 
   if (start < 0)  return NULL;
-  assert(can_capture_store(st, phase) == start, "sanity");
+  assert(can_capture_store(st, phase, can_reshape) == start, "sanity");
 
   Compile* C = phase->C;
   int size_in_bytes = st->memory_size();
--- a/src/share/vm/opto/memnode.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/memnode.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1072,11 +1072,11 @@
 
   // See if this store can be captured; return offset where it initializes.
   // Return 0 if the store cannot be moved (any sort of problem).
-  intptr_t can_capture_store(StoreNode* st, PhaseTransform* phase);
+  intptr_t can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape);
 
   // Capture another store; reformat it to write my internal raw memory.
   // Return the captured copy, else NULL if there is some sort of problem.
-  Node* capture_store(StoreNode* st, intptr_t start, PhaseTransform* phase);
+  Node* capture_store(StoreNode* st, intptr_t start, PhaseTransform* phase, bool can_reshape);
 
   // Find captured store which corresponds to the range [start..start+size).
   // Return my own memory projection (meaning the initial zero bits)
--- a/src/share/vm/opto/node.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/node.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -493,6 +493,8 @@
   }
   if (is_macro())
     compile->add_macro_node(n);
+  if (is_expensive())
+    compile->add_expensive_node(n);
 
   n->set_idx(compile->next_unique()); // Get new unique index as well
   debug_only( n->verify_construction() );
@@ -616,6 +618,9 @@
   if (is_macro()) {
     compile->remove_macro_node(this);
   }
+  if (is_expensive()) {
+    compile->remove_expensive_node(this);
+  }
 #ifdef ASSERT
   // We will not actually delete the storage, but we'll make the node unusable.
   *(address*)this = badAddress;  // smash the C++ vtbl, probably
@@ -689,6 +694,13 @@
 }
 #endif
 
+
+//------------------------------is_unreachable---------------------------------
+bool Node::is_unreachable(PhaseIterGVN &igvn) const {
+  assert(!is_Mach(), "doesn't work with MachNodes");
+  return outcnt() == 0 || igvn.type(this) == Type::TOP || in(0)->is_top();
+}
+
 //------------------------------add_req----------------------------------------
 // Add a new required input at the end
 void Node::add_req( Node *n ) {
@@ -1246,6 +1258,10 @@
       if (dead->is_macro()) {
         igvn->C->remove_macro_node(dead);
       }
+      if (dead->is_expensive()) {
+        igvn->C->remove_expensive_node(dead);
+      }
+      igvn->C->record_dead_node(dead->_idx);
       // Kill all inputs to the dead guy
       for (uint i=0; i < dead->req(); i++) {
         Node *n = dead->in(i);      // Get input to dead guy
--- a/src/share/vm/opto/node.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/node.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -378,6 +378,8 @@
   bool is_dead() const;
 #define is_not_dead(n) ((n) == NULL || !VerifyIterativeGVN || !((n)->is_dead()))
 #endif
+  // Check whether node has become unreachable
+  bool is_unreachable(PhaseIterGVN &igvn) const;
 
   // Set a required input edge, also updates corresponding output edge
   void add_req( Node *n ); // Append a NEW required input
@@ -646,7 +648,8 @@
     Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1,
     Flag_avoid_back_to_back  = Flag_may_be_short_branch << 1,
     Flag_has_call            = Flag_avoid_back_to_back << 1,
-    _max_flags = (Flag_has_call << 1) - 1 // allow flags combination
+    Flag_is_expensive        = Flag_has_call << 1,
+    _max_flags = (Flag_is_expensive << 1) - 1 // allow flags combination
   };
 
 private:
@@ -819,6 +822,8 @@
 
   // The node is a "macro" node which needs to be expanded before matching
   bool is_macro() const { return (_flags & Flag_is_macro) != 0; }
+  // The node is expensive: the best control is set during loop opts
+  bool is_expensive() const { return (_flags & Flag_is_expensive) != 0 && in(0) != NULL; }
 
 //----------------- Optimization
 
--- a/src/share/vm/opto/parse.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/parse.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -58,7 +58,7 @@
   GrowableArray<InlineTree*> _subtrees;
 
   void print_impl(outputStream* stj, int indent) const PRODUCT_RETURN;
-
+  const char* _msg;
 protected:
   InlineTree(Compile* C,
              const InlineTree* caller_tree,
@@ -70,16 +70,29 @@
   InlineTree *build_inline_tree_for_callee(ciMethod* callee_method,
                                            JVMState* caller_jvms,
                                            int caller_bci);
-  const char* try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay);
-  const char* should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const;
-  const char* should_not_inline(ciMethod* callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const;
-  void        print_inlining(ciMethod *callee_method, int caller_bci, const char *failure_msg) const;
+  bool        try_to_inline(ciMethod* callee_method,
+                            ciMethod* caller_method,
+                            int caller_bci,
+                            ciCallProfile& profile,
+                            WarmCallInfo* wci_result,
+                            bool& should_delay);
+  bool        should_inline(ciMethod* callee_method,
+                            ciMethod* caller_method,
+                            int caller_bci,
+                            ciCallProfile& profile,
+                            WarmCallInfo* wci_result);
+  bool        should_not_inline(ciMethod* callee_method,
+                                ciMethod* caller_method,
+                                WarmCallInfo* wci_result);
+  void        print_inlining(ciMethod* callee_method, int caller_bci,
+                             bool success) const;
 
-  InlineTree *caller_tree()       const { return _caller_tree;  }
+  InlineTree* caller_tree()       const { return _caller_tree;  }
   InlineTree* callee_at(int bci, ciMethod* m) const;
   int         inline_level()      const { return stack_depth(); }
   int         stack_depth()       const { return _caller_jvms ? _caller_jvms->depth() : 0; }
-
+  const char* msg()               const { return _msg; }
+  void        set_msg(const char* msg)  { _msg = msg; }
 public:
   static const char* check_can_parse(ciMethod* callee);
 
--- a/src/share/vm/opto/parse3.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/parse3.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -487,7 +487,8 @@
                           fun, NULL, TypeRawPtr::BOTTOM,
                           makecon(TypeKlassPtr::make(array_klass)),
                           length[0], length[1], length[2],
-                          length[3], length[4]);
+                          (ndimensions > 2) ? length[3] : NULL,
+                          (ndimensions > 3) ? length[4] : NULL);
   } else {
     // Create a java array for dimension sizes
     Node* dims = NULL;
--- a/src/share/vm/opto/phaseX.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/phaseX.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1197,12 +1197,27 @@
                 assert(!(i < imax), "sanity");
               }
             }
+            if (ReduceFieldZeroing && dead->is_Load() && i == MemNode::Memory &&
+                in->is_Proj() && in->in(0) != NULL && in->in(0)->is_Initialize()) {
+              // A Load that directly follows an InitializeNode is
+              // going away. The Stores that follow are candidates
+              // again to be captured by the InitializeNode.
+              for (DUIterator_Fast jmax, j = in->fast_outs(jmax); j < jmax; j++) {
+                Node *n = in->fast_out(j);
+                if (n->is_Store()) {
+                  _worklist.push(n);
+                }
+              }
+            }
           }
         }
         C->record_dead_node(dead->_idx);
         if (dead->is_macro()) {
           C->remove_macro_node(dead);
         }
+        if (dead->is_expensive()) {
+          C->remove_expensive_node(dead);
+        }
 
         if (recurse) {
           continue;
--- a/src/share/vm/opto/regmask.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/regmask.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -241,7 +241,8 @@
       } else {                  // Else its a split-pair case
         if( bit != _A[i] ) return false; // Found many bits, so fail
         i++;                    // Skip iteration forward
-        if( _A[i] != 1 ) return false; // Require 1 lo bit in next word
+        if( i >= RM_SIZE || _A[i] != 1 )
+          return false; // Require 1 lo bit in next word
       }
     }
   }
@@ -254,7 +255,7 @@
 // Find the lowest-numbered register set in the mask.  Return the
 // HIGHEST register number in the set, or BAD if no sets.
 // Works also for size 1.
-OptoReg::Name RegMask::find_first_set(int size) const {
+OptoReg::Name RegMask::find_first_set(const int size) const {
   verify_sets(size);
   for (int i = 0; i < RM_SIZE; i++) {
     if (_A[i]) {                // Found some bits
@@ -268,7 +269,7 @@
 
 //------------------------------clear_to_sets----------------------------------
 // Clear out partial bits; leave only aligned adjacent bit pairs
-void RegMask::clear_to_sets(int size) {
+void RegMask::clear_to_sets(const int size) {
   if (size == 1) return;
   assert(2 <= size && size <= 8, "update low bits table");
   assert(is_power_of_2(size), "sanity");
@@ -293,7 +294,7 @@
 
 //------------------------------smear_to_sets----------------------------------
 // Smear out partial bits to aligned adjacent bit sets
-void RegMask::smear_to_sets(int size) {
+void RegMask::smear_to_sets(const int size) {
   if (size == 1) return;
   assert(2 <= size && size <= 8, "update low bits table");
   assert(is_power_of_2(size), "sanity");
@@ -318,7 +319,7 @@
 }
 
 //------------------------------is_aligned_set--------------------------------
-bool RegMask::is_aligned_sets(int size) const {
+bool RegMask::is_aligned_sets(const int size) const {
   if (size == 1) return true;
   assert(2 <= size && size <= 8, "update low bits table");
   assert(is_power_of_2(size), "sanity");
@@ -344,7 +345,7 @@
 //------------------------------is_bound_set-----------------------------------
 // Return TRUE if the mask contains one adjacent set of bits and no other bits.
 // Works also for size 1.
-int RegMask::is_bound_set(int size) const {
+int RegMask::is_bound_set(const int size) const {
   if( is_AllStack() ) return false;
   assert(1 <= size && size <= 8, "update low bits table");
   int bit = -1;                 // Set to hold the one bit allowed
@@ -352,7 +353,7 @@
     if (_A[i] ) {               // Found some bits
       if (bit != -1)
        return false;            // Already had bits, so fail
-      bit = _A[i] & -_A[i];     // Extract 1 bit from mask
+      bit = _A[i] & -_A[i];     // Extract low bit from mask
       int hi_bit = bit << (size-1); // high bit
       if (hi_bit != 0) {        // Bit set stays in same word?
         int set = hi_bit + ((hi_bit-1) & ~(bit-1));
@@ -362,12 +363,12 @@
         if (((-1) & ~(bit-1)) != _A[i])
           return false;         // Found many bits, so fail
         i++;                    // Skip iteration forward and check high part
-        assert(size <= 8, "update next code");
         // The lower 24 bits should be 0 since it is split case and size <= 8.
         int set = bit>>24;
         set = set & -set; // Remove sign extension.
         set = (((set << size) - 1) >> 8);
-        if (_A[i] != set) return false; // Require 1 lo bit in next word
+        if (i >= RM_SIZE || _A[i] != set)
+          return false; // Require expected low bits in next word
       }
     }
   }
--- a/src/share/vm/opto/regmask.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/regmask.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -225,22 +225,22 @@
   // Find the lowest-numbered register set in the mask.  Return the
   // HIGHEST register number in the set, or BAD if no sets.
   // Assert that the mask contains only bit sets.
-  OptoReg::Name find_first_set(int size) const;
+  OptoReg::Name find_first_set(const int size) const;
 
   // Clear out partial bits; leave only aligned adjacent bit sets of size.
-  void clear_to_sets(int size);
+  void clear_to_sets(const int size);
   // Smear out partial bits to aligned adjacent bit sets.
-  void smear_to_sets(int size);
+  void smear_to_sets(const int size);
   // Verify that the mask contains only aligned adjacent bit sets
   void verify_sets(int size) const { assert(is_aligned_sets(size), "mask is not aligned, adjacent sets"); }
   // Test that the mask contains only aligned adjacent bit sets
-  bool is_aligned_sets(int size) const;
+  bool is_aligned_sets(const int size) const;
 
   // mask is a set of misaligned registers
   bool is_misaligned_set(int size) const { return (int)Size()==size && !is_aligned_sets(size);}
 
   // Test for a single adjacent set
-  int is_bound_set(int size) const;
+  int is_bound_set(const int size) const;
 
   static bool is_vector(uint ireg);
   static int num_registers(uint ireg);
--- a/src/share/vm/opto/subnode.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/subnode.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -399,7 +399,10 @@
 // Cosinus of a double
 class CosDNode : public Node {
 public:
-  CosDNode( Node *in1  ) : Node(0, in1) {}
+  CosDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
+    init_flags(Flag_is_expensive);
+    C->add_expensive_node(this);
+  }
   virtual int Opcode() const;
   const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint ideal_reg() const { return Op_RegD; }
@@ -410,7 +413,10 @@
 // Sinus of a double
 class SinDNode : public Node {
 public:
-  SinDNode( Node *in1  ) : Node(0, in1) {}
+  SinDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
+    init_flags(Flag_is_expensive);
+    C->add_expensive_node(this);
+  }
   virtual int Opcode() const;
   const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint ideal_reg() const { return Op_RegD; }
@@ -422,7 +428,10 @@
 // tangens of a double
 class TanDNode : public Node {
 public:
-  TanDNode(Node *in1  ) : Node(0, in1) {}
+  TanDNode(Compile* C, Node *c,Node *in1) : Node(c, in1) {
+    init_flags(Flag_is_expensive);
+    C->add_expensive_node(this);
+  }
   virtual int Opcode() const;
   const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint ideal_reg() const { return Op_RegD; }
@@ -445,7 +454,10 @@
 // square root a double
 class SqrtDNode : public Node {
 public:
-  SqrtDNode(Node *c, Node *in1  ) : Node(c, in1) {}
+  SqrtDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
+    init_flags(Flag_is_expensive);
+    C->add_expensive_node(this);
+  }
   virtual int Opcode() const;
   const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint ideal_reg() const { return Op_RegD; }
@@ -456,7 +468,10 @@
 //  Exponentiate a double
 class ExpDNode : public Node {
 public:
-  ExpDNode( Node *c, Node *in1 ) : Node(c, in1) {}
+  ExpDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
+    init_flags(Flag_is_expensive);
+    C->add_expensive_node(this);
+  }
   virtual int Opcode() const;
   const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint ideal_reg() const { return Op_RegD; }
@@ -467,7 +482,10 @@
 // Log_e of a double
 class LogDNode : public Node {
 public:
-  LogDNode( Node *in1 ) : Node(0, in1) {}
+  LogDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
+    init_flags(Flag_is_expensive);
+    C->add_expensive_node(this);
+  }
   virtual int Opcode() const;
   const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint ideal_reg() const { return Op_RegD; }
@@ -478,7 +496,10 @@
 // Log_10 of a double
 class Log10DNode : public Node {
 public:
-  Log10DNode( Node *in1 ) : Node(0, in1) {}
+  Log10DNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
+    init_flags(Flag_is_expensive);
+    C->add_expensive_node(this);
+  }
   virtual int Opcode() const;
   const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint ideal_reg() const { return Op_RegD; }
@@ -489,7 +510,10 @@
 // Raise a double to a double power
 class PowDNode : public Node {
 public:
-  PowDNode(Node *c, Node *in1, Node *in2  ) : Node(c, in1, in2) {}
+  PowDNode(Compile* C, Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) {
+    init_flags(Flag_is_expensive);
+    C->add_expensive_node(this);
+  }
   virtual int Opcode() const;
   const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint ideal_reg() const { return Op_RegD; }
--- a/src/share/vm/opto/superword.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/superword.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -143,7 +143,8 @@
 
   // Ready the block
 
-  construct_bb();
+  if (!construct_bb())
+    return; // Exit if no interesting nodes or complex graph.
 
   dependence_graph();
 
@@ -615,6 +616,7 @@
     if (n == stop) break;
     preds.push(n);
     prev = n;
+    assert(n->is_Mem(), err_msg_res("unexpected node %s", n->Name()));
     n = n->in(MemNode::Memory);
   }
 }
@@ -1578,7 +1580,7 @@
 
 //------------------------------construct_bb---------------------------
 // Construct reverse postorder list of block members
-void SuperWord::construct_bb() {
+bool SuperWord::construct_bb() {
   Node* entry = bb();
 
   assert(_stk.length() == 0,            "stk is empty");
@@ -1596,6 +1598,12 @@
     Node *n = lpt()->_body.at(i);
     set_bb_idx(n, i); // Create a temporary map
     if (in_bb(n)) {
+      if (n->is_LoadStore() || n->is_MergeMem() ||
+          (n->is_Proj() && !n->as_Proj()->is_CFG())) {
+        // Bailout if the loop has LoadStore, MergeMem or data Proj
+        // nodes. Superword optimization does not work with them.
+        return false;
+      }
       bb_ct++;
       if (!n->is_CFG()) {
         bool found = false;
@@ -1620,6 +1628,10 @@
     if (in_bb(n) && (n->is_Phi() && n->bottom_type() == Type::MEMORY)) {
       Node* n_tail  = n->in(LoopNode::LoopBackControl);
       if (n_tail != n->in(LoopNode::EntryControl)) {
+        if (!n_tail->is_Mem()) {
+          assert(n_tail->is_Mem(), err_msg_res("unexpected node for memory slice: %s", n_tail->Name()));
+          return false; // Bailout
+        }
         _mem_slice_head.push(n);
         _mem_slice_tail.push(n_tail);
       }
@@ -1695,6 +1707,7 @@
   }
 #endif
   assert(rpo_idx == -1 && bb_ct == _block.length(), "all block members found");
+  return (_mem_slice_head.length() > 0) || (_data_entry.length() > 0);
 }
 
 //------------------------------initialize_bb---------------------------
--- a/src/share/vm/opto/superword.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/opto/superword.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -380,7 +380,7 @@
   // Is use->in(u_idx) a vector use?
   bool is_vector_use(Node* use, int u_idx);
   // Construct reverse postorder list of block members
-  void construct_bb();
+  bool construct_bb();
   // Initialize per node info
   void initialize_bb();
   // Insert n into block after pos
--- a/src/share/vm/precompiled/precompiled.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/precompiled/precompiled.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -24,6 +24,7 @@
 
 // Precompiled headers are turned off for Sun Studion,
 // or if the user passes USE_PRECOMPILED_HEADER=0 to the makefiles.
+
 #ifndef DONT_USE_PRECOMPILED_HEADER
 
 # include "asm/assembler.hpp"
@@ -288,7 +289,7 @@
 #ifdef GRAAL
 # include "graal/graalGlobals.hpp"
 #endif // GRAAL
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 # include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
 # include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
 # include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
@@ -317,6 +318,6 @@
 # include "gc_implementation/shared/gcAdaptivePolicyCounters.hpp"
 # include "gc_implementation/shared/gcPolicyCounters.hpp"
 # include "gc_implementation/shared/parGCAllocBuffer.hpp"
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 #endif // !DONT_USE_PRECOMPILED_HEADER
--- a/src/share/vm/prims/jni.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jni.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -32,12 +32,13 @@
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "interpreter/linkResolver.hpp"
+#include "utilities/macros.hpp"
 #ifdef GRAAL
 #include "graal/graalCompiler.hpp"
 #endif
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/gcLocker.inline.hpp"
@@ -1318,7 +1319,6 @@
 }
 
 
-static bool first_time_InvokeMain = true;
 
 static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
   methodHandle method(THREAD, Method::resolve_jmethod_id(method_id));
@@ -1327,8 +1327,6 @@
   // the jni parser
   ResourceMark rm(THREAD);
   int number_of_parameters = method->size_of_parameters();
-
-  // Invoke the method. Result is returned as oop.
   JavaCallArguments java_args(number_of_parameters);
   args->set_java_argument_object(&java_args);
 
@@ -1336,23 +1334,16 @@
 
   // Fill out JavaCallArguments object
   args->iterate( Fingerprinter(method).fingerprint() );
-  // Initialize result type (must be done after args->iterate())
+  // Initialize result type
   result->set_type(args->get_ret_type());
 
+  // Invoke the method. Result is returned as oop.
   JavaCalls::call(result, method, &java_args, CHECK);
 
   // Convert result
   if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) {
     result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject()));
   }
-
-#ifdef HIGH_LEVEL_INTERPRETER
-  if (invoked_main_method) {
-    assert(THREAD->is_Java_thread(), "other threads must not call into java");
-    JavaThread* thread = (JavaThread*)THREAD;
-    thread->set_high_level_interpreter_in_vm(false);
-  }
-#endif
 }
 
 
@@ -2654,7 +2645,7 @@
     o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
   }
   jobject ret = JNIHandles::make_local(env, o->obj_field(offset));
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // If G1 is enabled and we are accessing the value of the referent
   // field in a reference object then we need to register a non-null
   // referent with the SATB barrier.
@@ -2673,7 +2664,7 @@
       G1SATBCardTableModRefBS::enqueue(referent);
     }
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 #ifndef USDT2
   DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret);
 #else /* USDT2 */
--- a/src/share/vm/prims/jniCheck.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jniCheck.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,7 @@
 #ifndef SHARE_VM_PRIMS_JNICHECK_HPP
 #define SHARE_VM_PRIMS_JNICHECK_HPP
 
-#ifndef KERNEL
 #include "runtime/thread.hpp"
-#endif
 
 extern "C" {
   // Report a JNI failure caught by -Xcheck:jni.  Perform a core dump.
--- a/src/share/vm/prims/jvm.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvm.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1575,9 +1575,9 @@
   if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
     Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
     if (k->oop_is_instance()) {
-      Annotations* type_annotations = InstanceKlass::cast(k)->type_annotations();
+      AnnotationArray* type_annotations = InstanceKlass::cast(k)->class_type_annotations();
       if (type_annotations != NULL) {
-        typeArrayOop a = Annotations::make_java_array(type_annotations->class_annotations(), CHECK_NULL);
+        typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL);
         return (jbyteArray) JNIHandles::make_local(env, a);
       }
     }
@@ -1622,7 +1622,7 @@
       // For a 0 index, give a NULL symbol
       Symbol* const sym = 0 != params[i].name_cp_index ?
         mh->constants()->symbol_at(params[i].name_cp_index) : NULL;
-      int flags = build_int_from_shorts(params[i].flags_lo, params[i].flags_hi);
+      int flags = params[i].flags;
       oop param = Reflection::new_parameter(reflected_method, i, sym,
                                             flags, CHECK_NULL);
       result->obj_at_put(i, param);
@@ -2304,6 +2304,15 @@
 JVM_END
 
 
+JVM_QUICK_ENTRY(jboolean, JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cls, int method_index))
+  JVMWrapper("JVM_IsVMGeneratedMethodIx");
+  ResourceMark rm(THREAD);
+  Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
+  k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
+  Method* method = InstanceKlass::cast(k)->methods()->at(method_index);
+  return method->is_overpass();
+JVM_END
+
 JVM_ENTRY(const char*, JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index))
   JVMWrapper("JVM_GetMethodIxIxUTF");
   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
@@ -4521,10 +4530,5 @@
   // consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat
   // counter defined in runtimeService.cpp.
   info->is_attachable = AttachListener::is_attach_supported();
-#ifdef KERNEL
-  info->is_kernel_jvm = 1; // true;
-#else  // KERNEL
-  info->is_kernel_jvm = 0; // false;
-#endif // KERNEL
 }
 JVM_END
--- a/src/share/vm/prims/jvm.h	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvm.h	Thu Mar 21 14:11:13 2013 +0100
@@ -860,6 +860,13 @@
 JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index);
 
 /*
+ * Is the given method generated by the VM.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jboolean JNICALL
+JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cb, int index);
+
+/*
  * Returns the name of a given method in UTF format.
  * The result remains valid until JVM_ReleaseUTF is called.
  *
@@ -1552,8 +1559,7 @@
      * the new bit is also added in the main/baseline.
      */
     unsigned int is_attachable : 1;
-    unsigned int is_kernel_jvm : 1;
-    unsigned int : 30;
+    unsigned int : 31;
     unsigned int : 32;
     unsigned int : 32;
 } jvm_version_info;
--- a/src/share/vm/prims/jvmtiCodeBlobEvents.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiCodeBlobEvents.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,7 @@
 #ifndef SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP
 #define SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP
 
-#ifndef JVMTI_KERNEL
 #include "jvmtifiles/jvmti.h"
-#endif
 
 // forward declaration
 class JvmtiEnv;
--- a/src/share/vm/prims/jvmtiEnv.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiEnv.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -647,8 +647,6 @@
   return JVMTI_ERROR_NONE;
 } /* end GetJLocationFormat */
 
-#ifndef JVMTI_KERNEL
-
   //
   // Thread functions
   //
@@ -3436,5 +3434,3 @@
   }
   return err;
 } /* end SetSystemProperty */
-
-#endif // !JVMTI_KERNEL
--- a/src/share/vm/prims/jvmtiEnvBase.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiEnvBase.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,10 +74,8 @@
 
   JvmtiManageCapabilities::initialize();
 
-#ifndef JVMTI_KERNEL
   // register extension functions and events
   JvmtiExtensions::register_extensions();
-#endif // !JVMTI_KERNEL
 
 #ifdef JVMTI_TRACE
   JvmtiTrace::initialize();
@@ -236,14 +234,12 @@
   // Same situation as with events (see above)
   set_native_method_prefixes(0, NULL);
 
-#ifndef JVMTI_KERNEL
   JvmtiTagMap* tag_map_to_deallocate = _tag_map;
   set_tag_map(NULL);
   // A tag map can be big, deallocate it now
   if (tag_map_to_deallocate != NULL) {
     delete tag_map_to_deallocate;
   }
-#endif // !JVMTI_KERNEL
 
   _needs_clean_up = true;
 }
@@ -255,14 +251,12 @@
   // There is a small window of time during which the tag map of a
   // disposed environment could have been reallocated.
   // Make sure it is gone.
-#ifndef JVMTI_KERNEL
   JvmtiTagMap* tag_map_to_deallocate = _tag_map;
   set_tag_map(NULL);
   // A tag map can be big, deallocate it now
   if (tag_map_to_deallocate != NULL) {
     delete tag_map_to_deallocate;
   }
-#endif // !JVMTI_KERNEL
 
   _magic = BAD_MAGIC;
 }
@@ -593,8 +587,6 @@
   return (jclass)jni_reference(k->java_mirror());
 }
 
-#ifndef JVMTI_KERNEL
-
 //
 // Field Information
 //
@@ -1482,5 +1474,3 @@
     }
   }
 }
-
-#endif // !JVMTI_KERNEL
--- a/src/share/vm/prims/jvmtiEnvBase.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiEnvBase.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -35,6 +35,7 @@
 #include "runtime/thread.hpp"
 #include "runtime/vm_operations.hpp"
 #include "utilities/growableArray.hpp"
+#include "utilities/macros.hpp"
 
 //
 // Forward Declarations
--- a/src/share/vm/prims/jvmtiExport.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiExport.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,9 +50,10 @@
 #include "runtime/vframe.hpp"
 #include "services/attachListener.hpp"
 #include "services/serviceUtil.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 #ifdef JVMTI_TRACE
 #define EVT_TRACE(evt,out) if ((JvmtiTrace::event_trace_flags(evt) & JvmtiTrace::SHOW_EVENT_SENT) != 0) { SafeResourceMark rm; tty->print_cr out; }
@@ -677,7 +678,6 @@
 }
 
 
-#ifndef JVMTI_KERNEL
 static inline Klass* oop_to_klass(oop obj) {
   Klass* k = obj->klass();
 
@@ -2178,7 +2178,6 @@
   typedef jint (JNICALL *OnAttachEntry_t)(JavaVM*, char *, void *);
 }
 
-#ifndef SERVICES_KERNEL
 jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) {
   char ebuf[1024];
   char buffer[JVM_MAXPATHLEN];
@@ -2259,7 +2258,6 @@
   }
   return result;
 }
-#endif // SERVICES_KERNEL
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -2457,4 +2455,3 @@
     JvmtiExport::post_garbage_collection_finish();
   }
 }
-#endif // JVMTI_KERNEL
--- a/src/share/vm/prims/jvmtiExport.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiExport.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -34,6 +34,7 @@
 #include "runtime/handles.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/growableArray.hpp"
+#include "utilities/macros.hpp"
 
 // Must be included after jvmti.h.
 #include "code/jvmticmlr.h"
--- a/src/share/vm/prims/jvmtiExtensions.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiExtensions.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,9 @@
 #ifndef SHARE_VM_PRIMS_JVMTIEXTENSIONS_HPP
 #define SHARE_VM_PRIMS_JVMTIEXTENSIONS_HPP
 
-#ifndef JVMTI_KERNEL
 #include "jvmtifiles/jvmti.h"
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "memory/allocation.hpp"
-#endif
 
 // JvmtiExtensions
 //
--- a/src/share/vm/prims/jvmtiImpl.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiImpl.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -905,8 +905,6 @@
 #endif
 }
 
-#ifndef KERNEL
-
 JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event(
     nmethod* nm) {
   JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD);
@@ -1098,5 +1096,3 @@
     }
   }
 }
-
-#endif // ndef KERNEL
--- a/src/share/vm/prims/jvmtiImpl.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiImpl.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
 #ifndef SHARE_VM_PRIMS_JVMTIIMPL_HPP
 #define SHARE_VM_PRIMS_JVMTIIMPL_HPP
 
-#ifndef JVMTI_KERNEL
-
 #include "classfile/systemDictionary.hpp"
 #include "jvmtifiles/jvmti.h"
 #include "oops/objArrayOop.hpp"
@@ -435,7 +433,6 @@
   static void print();
 };
 
-#endif // !JVMTI_KERNEL
 
 /**
  * When a thread (such as the compiler thread or VM thread) cannot post a
--- a/src/share/vm/prims/jvmtiRawMonitor.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiRawMonitor.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,8 @@
 #ifndef SHARE_VM_PRIMS_JVMTIRAWMONITOR_HPP
 #define SHARE_VM_PRIMS_JVMTIRAWMONITOR_HPP
 
-#ifndef JVMTI_KERNEL
 #include "runtime/objectMonitor.hpp"
 #include "utilities/growableArray.hpp"
-#endif
 
 //
 // class JvmtiRawMonitor
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/metadataOnStackMark.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/verifier.hpp"
 #include "code/codeCache.hpp"
@@ -115,43 +116,6 @@
   return true;
 }
 
-// Keep track of marked on-stack metadata so it can be cleared.
-GrowableArray<Metadata*>* _marked_objects = NULL;
-NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
-
-// Walk metadata on the stack and mark it so that redefinition doesn't delete
-// it.  Class unloading also walks the previous versions and might try to
-// delete it, so this class is used by class unloading also.
-MetadataOnStackMark::MetadataOnStackMark() {
-  assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
-  NOT_PRODUCT(_is_active = true;)
-  if (_marked_objects == NULL) {
-    _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(1000, true);
-  }
-  Threads::metadata_do(Metadata::mark_on_stack);
-  CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
-  CompileBroker::mark_on_stack();
-}
-
-MetadataOnStackMark::~MetadataOnStackMark() {
-  assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
-  // Unmark everything that was marked.   Can't do the same walk because
-  // redefine classes messes up the code cache so the set of methods
-  // might not be the same.
-  for (int i = 0; i< _marked_objects->length(); i++) {
-    _marked_objects->at(i)->set_on_stack(false);
-  }
-  _marked_objects->clear();   // reuse growable array for next time.
-  NOT_PRODUCT(_is_active = false;)
-}
-
-// Record which objects are marked so we can unmark the same objects.
-void MetadataOnStackMark::record(Metadata* m) {
-  assert(_is_active, "metadata on stack marking is active");
-  _marked_objects->push(m);
-}
-
-
 void VM_RedefineClasses::doit() {
   Thread *thread = Thread::current();
 
@@ -190,8 +154,15 @@
   // See jvmtiExport.hpp for detailed explanation.
   JvmtiExport::set_has_redefined_a_class();
 
-#ifdef ASSERT
-  SystemDictionary::classes_do(check_class, thread);
+// check_class() is optionally called for product bits, but is
+// always called for non-product bits.
+#ifdef PRODUCT
+  if (RC_TRACE_ENABLED(0x00004000)) {
+#endif
+    RC_TRACE_WITH_THREAD(0x00004000, thread, ("calling check_class"));
+    SystemDictionary::classes_do(check_class, thread);
+#ifdef PRODUCT
+  }
 #endif
 }
 
@@ -314,76 +285,23 @@
     case JVM_CONSTANT_NameAndType:
     {
       int name_ref_i = scratch_cp->name_ref_index_at(scratch_i);
-      int new_name_ref_i = 0;
-      bool match = (name_ref_i < *merge_cp_length_p) &&
-        scratch_cp->compare_entry_to(name_ref_i, *merge_cp_p, name_ref_i,
-          THREAD);
-      if (!match) {
-        // forward reference in *merge_cp_p or not a direct match
-
-        int found_i = scratch_cp->find_matching_entry(name_ref_i, *merge_cp_p,
-          THREAD);
-        if (found_i != 0) {
-          guarantee(found_i != name_ref_i,
-            "compare_entry_to() and find_matching_entry() do not agree");
-
-          // Found a matching entry somewhere else in *merge_cp_p so
-          // just need a mapping entry.
-          new_name_ref_i = found_i;
-          map_index(scratch_cp, name_ref_i, found_i);
-        } else {
-          // no match found so we have to append this entry to *merge_cp_p
-          append_entry(scratch_cp, name_ref_i, merge_cp_p, merge_cp_length_p,
-            THREAD);
-          // The above call to append_entry() can only append one entry
-          // so the post call query of *merge_cp_length_p is only for
-          // the sake of consistency.
-          new_name_ref_i = *merge_cp_length_p - 1;
-        }
-      }
+      int new_name_ref_i = find_or_append_indirect_entry(scratch_cp, name_ref_i, merge_cp_p,
+                                                         merge_cp_length_p, THREAD);
 
       int signature_ref_i = scratch_cp->signature_ref_index_at(scratch_i);
-      int new_signature_ref_i = 0;
-      match = (signature_ref_i < *merge_cp_length_p) &&
-        scratch_cp->compare_entry_to(signature_ref_i, *merge_cp_p,
-          signature_ref_i, THREAD);
-      if (!match) {
-        // forward reference in *merge_cp_p or not a direct match
-
-        int found_i = scratch_cp->find_matching_entry(signature_ref_i,
-          *merge_cp_p, THREAD);
-        if (found_i != 0) {
-          guarantee(found_i != signature_ref_i,
-            "compare_entry_to() and find_matching_entry() do not agree");
-
-          // Found a matching entry somewhere else in *merge_cp_p so
-          // just need a mapping entry.
-          new_signature_ref_i = found_i;
-          map_index(scratch_cp, signature_ref_i, found_i);
-        } else {
-          // no match found so we have to append this entry to *merge_cp_p
-          append_entry(scratch_cp, signature_ref_i, merge_cp_p,
-            merge_cp_length_p, THREAD);
-          // The above call to append_entry() can only append one entry
-          // so the post call query of *merge_cp_length_p is only for
-          // the sake of consistency.
-          new_signature_ref_i = *merge_cp_length_p - 1;
-        }
-      }
+      int new_signature_ref_i = find_or_append_indirect_entry(scratch_cp, signature_ref_i,
+                                                              merge_cp_p, merge_cp_length_p,
+                                                              THREAD);
 
       // If the referenced entries already exist in *merge_cp_p, then
       // both new_name_ref_i and new_signature_ref_i will both be 0.
       // In that case, all we are appending is the current entry.
-      if (new_name_ref_i == 0) {
-        new_name_ref_i = name_ref_i;
-      } else {
+      if (new_name_ref_i != name_ref_i) {
         RC_TRACE(0x00080000,
           ("NameAndType entry@%d name_ref_index change: %d to %d",
           *merge_cp_length_p, name_ref_i, new_name_ref_i));
       }
-      if (new_signature_ref_i == 0) {
-        new_signature_ref_i = signature_ref_i;
-      } else {
+      if (new_signature_ref_i != signature_ref_i) {
         RC_TRACE(0x00080000,
           ("NameAndType entry@%d signature_ref_index change: %d to %d",
           *merge_cp_length_p, signature_ref_i, new_signature_ref_i));
@@ -405,76 +323,12 @@
     case JVM_CONSTANT_Methodref:
     {
       int klass_ref_i = scratch_cp->uncached_klass_ref_index_at(scratch_i);
-      int new_klass_ref_i = 0;
-      bool match = (klass_ref_i < *merge_cp_length_p) &&
-        scratch_cp->compare_entry_to(klass_ref_i, *merge_cp_p, klass_ref_i,
-          THREAD);
-      if (!match) {
-        // forward reference in *merge_cp_p or not a direct match
-
-        int found_i = scratch_cp->find_matching_entry(klass_ref_i, *merge_cp_p,
-          THREAD);
-        if (found_i != 0) {
-          guarantee(found_i != klass_ref_i,
-            "compare_entry_to() and find_matching_entry() do not agree");
-
-          // Found a matching entry somewhere else in *merge_cp_p so
-          // just need a mapping entry.
-          new_klass_ref_i = found_i;
-          map_index(scratch_cp, klass_ref_i, found_i);
-        } else {
-          // no match found so we have to append this entry to *merge_cp_p
-          append_entry(scratch_cp, klass_ref_i, merge_cp_p, merge_cp_length_p,
-            THREAD);
-          // The above call to append_entry() can only append one entry
-          // so the post call query of *merge_cp_length_p is only for
-          // the sake of consistency. Without the optimization where we
-          // use JVM_CONSTANT_UnresolvedClass, then up to two entries
-          // could be appended.
-          new_klass_ref_i = *merge_cp_length_p - 1;
-        }
-      }
-
-      int name_and_type_ref_i =
-        scratch_cp->uncached_name_and_type_ref_index_at(scratch_i);
-      int new_name_and_type_ref_i = 0;
-      match = (name_and_type_ref_i < *merge_cp_length_p) &&
-        scratch_cp->compare_entry_to(name_and_type_ref_i, *merge_cp_p,
-          name_and_type_ref_i, THREAD);
-      if (!match) {
-        // forward reference in *merge_cp_p or not a direct match
-
-        int found_i = scratch_cp->find_matching_entry(name_and_type_ref_i,
-          *merge_cp_p, THREAD);
-        if (found_i != 0) {
-          guarantee(found_i != name_and_type_ref_i,
-            "compare_entry_to() and find_matching_entry() do not agree");
-
-          // Found a matching entry somewhere else in *merge_cp_p so
-          // just need a mapping entry.
-          new_name_and_type_ref_i = found_i;
-          map_index(scratch_cp, name_and_type_ref_i, found_i);
-        } else {
-          // no match found so we have to append this entry to *merge_cp_p
-          append_entry(scratch_cp, name_and_type_ref_i, merge_cp_p,
-            merge_cp_length_p, THREAD);
-          // The above call to append_entry() can append more than
-          // one entry so the post call query of *merge_cp_length_p
-          // is required in order to get the right index for the
-          // JVM_CONSTANT_NameAndType entry.
-          new_name_and_type_ref_i = *merge_cp_length_p - 1;
-        }
-      }
-
-      // If the referenced entries already exist in *merge_cp_p, then
-      // both new_klass_ref_i and new_name_and_type_ref_i will both be
-      // 0. In that case, all we are appending is the current entry.
-      if (new_klass_ref_i == 0) {
-        new_klass_ref_i = klass_ref_i;
-      }
-      if (new_name_and_type_ref_i == 0) {
-        new_name_and_type_ref_i = name_and_type_ref_i;
-      }
+      int new_klass_ref_i = find_or_append_indirect_entry(scratch_cp, klass_ref_i,
+                                                          merge_cp_p, merge_cp_length_p, THREAD);
+
+      int name_and_type_ref_i = scratch_cp->uncached_name_and_type_ref_index_at(scratch_i);
+      int new_name_and_type_ref_i = find_or_append_indirect_entry(scratch_cp, name_and_type_ref_i,
+                                                          merge_cp_p, merge_cp_length_p, THREAD);
 
       const char *entry_name;
       switch (scratch_cp->tag_at(scratch_i).value()) {
@@ -517,6 +371,72 @@
       (*merge_cp_length_p)++;
     } break;
 
+    // this is an indirect CP entry so it needs special handling
+    case JVM_CONSTANT_MethodType:
+    {
+      int ref_i = scratch_cp->method_type_index_at(scratch_i);
+      int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
+                                                    merge_cp_length_p, THREAD);
+      if (new_ref_i != ref_i) {
+        RC_TRACE(0x00080000,
+                 ("MethodType entry@%d ref_index change: %d to %d",
+                  *merge_cp_length_p, ref_i, new_ref_i));
+      }
+      (*merge_cp_p)->method_type_index_at_put(*merge_cp_length_p, new_ref_i);
+      if (scratch_i != *merge_cp_length_p) {
+        // The new entry in *merge_cp_p is at a different index than
+        // the new entry in scratch_cp so we need to map the index values.
+        map_index(scratch_cp, scratch_i, *merge_cp_length_p);
+      }
+      (*merge_cp_length_p)++;
+    } break;
+
+    // this is an indirect CP entry so it needs special handling
+    case JVM_CONSTANT_MethodHandle:
+    {
+      int ref_kind = scratch_cp->method_handle_ref_kind_at(scratch_i);
+      int ref_i = scratch_cp->method_handle_index_at(scratch_i);
+      int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
+                                                    merge_cp_length_p, THREAD);
+      if (new_ref_i != ref_i) {
+        RC_TRACE(0x00080000,
+                 ("MethodHandle entry@%d ref_index change: %d to %d",
+                  *merge_cp_length_p, ref_i, new_ref_i));
+      }
+      (*merge_cp_p)->method_handle_index_at_put(*merge_cp_length_p, ref_kind, new_ref_i);
+      if (scratch_i != *merge_cp_length_p) {
+        // The new entry in *merge_cp_p is at a different index than
+        // the new entry in scratch_cp so we need to map the index values.
+        map_index(scratch_cp, scratch_i, *merge_cp_length_p);
+      }
+      (*merge_cp_length_p)++;
+    } break;
+
+    // this is an indirect CP entry so it needs special handling
+    case JVM_CONSTANT_InvokeDynamic:
+    {
+      // TBD: cross-checks and possible extra appends into CP and bsm operands
+      // are needed as well. This issue is tracked by a separate bug 8007037.
+      int bss_idx = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i);
+
+      int ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i);
+      int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
+                                                    merge_cp_length_p, THREAD);
+      if (new_ref_i != ref_i) {
+        RC_TRACE(0x00080000,
+                 ("InvokeDynamic entry@%d name_and_type ref_index change: %d to %d",
+                  *merge_cp_length_p, ref_i, new_ref_i));
+      }
+
+      (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, bss_idx, new_ref_i);
+      if (scratch_i != *merge_cp_length_p) {
+        // The new entry in *merge_cp_p is at a different index than
+        // the new entry in scratch_cp so we need to map the index values.
+        map_index(scratch_cp, scratch_i, *merge_cp_length_p);
+      }
+      (*merge_cp_length_p)++;
+    } break;
+
     // At this stage, Class or UnresolvedClass could be here, but not
     // ClassIndex
     case JVM_CONSTANT_ClassIndex: // fall through
@@ -543,24 +463,33 @@
 } // end append_entry()
 
 
-void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS) {
-  AnnotationArray* save;
-
-  Annotations* sca = scratch_class->annotations();
-  if (sca == NULL) return;
-
-  save = sca->get_method_annotations_of(i);
-  sca->set_method_annotations_of(scratch_class, i, sca->get_method_annotations_of(j), CHECK);
-  sca->set_method_annotations_of(scratch_class, j, save, CHECK);
-
-  save = sca->get_method_parameter_annotations_of(i);
-  sca->set_method_parameter_annotations_of(scratch_class, i, sca->get_method_parameter_annotations_of(j), CHECK);
-  sca->set_method_parameter_annotations_of(scratch_class, j, save, CHECK);
-
-  save = sca->get_method_default_annotations_of(i);
-  sca->set_method_default_annotations_of(scratch_class, i, sca->get_method_default_annotations_of(j), CHECK);
-  sca->set_method_default_annotations_of(scratch_class, j, save, CHECK);
-}
+int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch_cp,
+      int ref_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
+
+  int new_ref_i = ref_i;
+  bool match = (ref_i < *merge_cp_length_p) &&
+               scratch_cp->compare_entry_to(ref_i, *merge_cp_p, ref_i, THREAD);
+
+  if (!match) {
+    // forward reference in *merge_cp_p or not a direct match
+    int found_i = scratch_cp->find_matching_entry(ref_i, *merge_cp_p, THREAD);
+    if (found_i != 0) {
+      guarantee(found_i != ref_i, "compare_entry_to() and find_matching_entry() do not agree");
+      // Found a matching entry somewhere else in *merge_cp_p so just need a mapping entry.
+      new_ref_i = found_i;
+      map_index(scratch_cp, ref_i, found_i);
+    } else {
+      // no match found so we have to append this entry to *merge_cp_p
+      append_entry(scratch_cp, ref_i, merge_cp_p, merge_cp_length_p, THREAD);
+      // The above call to append_entry() can only append one entry
+      // so the post call query of *merge_cp_length_p is only for
+      // the sake of consistency.
+      new_ref_i = *merge_cp_length_p - 1;
+    }
+  }
+
+  return new_ref_i;
+} // end find_or_append_indirect_entry()
 
 
 jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
@@ -744,10 +673,9 @@
             idnum_owner->set_method_idnum(new_num);
           }
           k_new_method->set_method_idnum(old_num);
-          swap_all_method_annotations(old_num, new_num, scratch_class, thread);
-           if (thread->has_pending_exception()) {
-             return JVMTI_ERROR_OUT_OF_MEMORY;
-           }
+          if (thread->has_pending_exception()) {
+            return JVMTI_ERROR_OUT_OF_MEMORY;
+          }
         }
       }
       RC_TRACE(0x00008000, ("Method matched: new: %s [%d] == old: %s [%d]",
@@ -780,7 +708,6 @@
           idnum_owner->set_method_idnum(new_num);
         }
         k_new_method->set_method_idnum(num);
-        swap_all_method_annotations(new_num, num, scratch_class, thread);
         if (thread->has_pending_exception()) {
           return JVMTI_ERROR_OUT_OF_MEMORY;
         }
@@ -1158,6 +1085,8 @@
       }
     } // end for each old_cp entry
 
+    ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0);
+
     // We don't need to sanity check that *merge_cp_length_p is within
     // *merge_cp_p bounds since we have the minimum on-entry check above.
     (*merge_cp_length_p) = old_i;
@@ -1341,8 +1270,12 @@
   _index_map_count = 0;
   _index_map_p = new intArray(scratch_cp->length(), -1);
 
+  // reference to the cp holder is needed for copy_operands()
+  merge_cp->set_pool_holder(scratch_class());
   bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp,
                   &merge_cp_length, THREAD);
+  merge_cp->set_pool_holder(NULL);
+
   if (!result) {
     // The merge can fail due to memory allocation failure or due
     // to robustness checks.
@@ -1594,6 +1527,7 @@
       case Bytecodes::_getfield       : // fall through
       case Bytecodes::_getstatic      : // fall through
       case Bytecodes::_instanceof     : // fall through
+      case Bytecodes::_invokedynamic  : // fall through
       case Bytecodes::_invokeinterface: // fall through
       case Bytecodes::_invokespecial  : // fall through
       case Bytecodes::_invokestatic   : // fall through
@@ -1615,15 +1549,27 @@
             bcp, cp_index, new_index));
           // Rewriter::rewrite_method() uses put_native_u2() in this
           // situation because it is reusing the constant pool index
-          // location for a native index into the constantPoolCache.
+          // location for a native index into the ConstantPoolCache.
           // Since we are updating the constant pool index prior to
-          // verification and constantPoolCache initialization, we
+          // verification and ConstantPoolCache initialization, we
           // need to keep the new index in Java byte order.
           Bytes::put_Java_u2(p, new_index);
         }
       } break;
     }
   } // end for each bytecode
+
+  // We also need to rewrite the parameter name indexes, if there is
+  // method parameter data present
+  if(method->has_method_parameters()) {
+    const int len = method->method_parameters_length();
+    MethodParametersElement* elem = method->method_parameters_start();
+
+    for (int i = 0; i < len; i++) {
+      const u2 cp_index = elem[i].name_cp_index;
+      elem[i].name_cp_index = find_new_index(cp_index);
+    }
+  }
 } // end rewrite_cp_refs_in_method()
 
 
@@ -1939,10 +1885,7 @@
 bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
        instanceKlassHandle scratch_class, TRAPS) {
 
-  Annotations* sca = scratch_class->annotations();
-  if (sca == NULL) return true;
-
-  Array<AnnotationArray*>* fields_annotations = sca->fields_annotations();
+  Array<AnnotationArray*>* fields_annotations = scratch_class->fields_annotations();
 
   if (fields_annotations == NULL || fields_annotations->length() == 0) {
     // no fields_annotations so nothing to do
@@ -1977,21 +1920,10 @@
 bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
        instanceKlassHandle scratch_class, TRAPS) {
 
-  Annotations* sca = scratch_class->annotations();
-  if (sca == NULL) return true;
-
-  Array<AnnotationArray*>* methods_annotations = sca->methods_annotations();
-
-  if (methods_annotations == NULL || methods_annotations->length() == 0) {
-    // no methods_annotations so nothing to do
-    return true;
-  }
-
-  RC_TRACE_WITH_THREAD(0x02000000, THREAD,
-    ("methods_annotations length=%d", methods_annotations->length()));
-
-  for (int i = 0; i < methods_annotations->length(); i++) {
-    AnnotationArray* method_annotations = methods_annotations->at(i);
+  for (int i = 0; i < scratch_class->methods()->length(); i++) {
+    Method* m = scratch_class->methods()->at(i);
+    AnnotationArray* method_annotations = m->constMethod()->method_annotations();
+
     if (method_annotations == NULL || method_annotations->length() == 0) {
       // this method does not have any annotations so skip it
       continue;
@@ -2027,24 +1959,9 @@
 bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
        instanceKlassHandle scratch_class, TRAPS) {
 
-  Annotations* sca = scratch_class->annotations();
-  if (sca == NULL) return true;
-
-  Array<AnnotationArray*>* methods_parameter_annotations =
-    sca->methods_parameter_annotations();
-
-  if (methods_parameter_annotations == NULL
-      || methods_parameter_annotations->length() == 0) {
-    // no methods_parameter_annotations so nothing to do
-    return true;
-  }
-
-  RC_TRACE_WITH_THREAD(0x02000000, THREAD,
-    ("methods_parameter_annotations length=%d",
-    methods_parameter_annotations->length()));
-
-  for (int i = 0; i < methods_parameter_annotations->length(); i++) {
-    AnnotationArray* method_parameter_annotations = methods_parameter_annotations->at(i);
+  for (int i = 0; i < scratch_class->methods()->length(); i++) {
+    Method* m = scratch_class->methods()->at(i);
+    AnnotationArray* method_parameter_annotations = m->constMethod()->parameter_annotations();
     if (method_parameter_annotations == NULL
         || method_parameter_annotations->length() == 0) {
       // this method does not have any parameter annotations so skip it
@@ -2094,24 +2011,9 @@
 bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations(
        instanceKlassHandle scratch_class, TRAPS) {
 
-  Annotations* sca = scratch_class->annotations();
-  if (sca == NULL) return true;
-
-  Array<AnnotationArray*>* methods_default_annotations =
-    sca->methods_default_annotations();
-
-  if (methods_default_annotations == NULL
-      || methods_default_annotations->length() == 0) {
-    // no methods_default_annotations so nothing to do
-    return true;
-  }
-
-  RC_TRACE_WITH_THREAD(0x02000000, THREAD,
-    ("methods_default_annotations length=%d",
-    methods_default_annotations->length()));
-
-  for (int i = 0; i < methods_default_annotations->length(); i++) {
-    AnnotationArray* method_default_annotations = methods_default_annotations->at(i);
+  for (int i = 0; i < scratch_class->methods()->length(); i++) {
+    Method* m = scratch_class->methods()->at(i);
+    AnnotationArray* method_default_annotations = m->constMethod()->default_annotations();
     if (method_default_annotations == NULL
         || method_default_annotations->length() == 0) {
       // this method does not have any default annotations so skip it
@@ -2416,13 +2318,14 @@
   assert(version != 0, "sanity check");
   smaller_cp->set_version(version);
 
+  // attach klass to new constant pool
+  // reference to the cp holder is needed for copy_operands()
+  smaller_cp->set_pool_holder(scratch_class());
+
   scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
   scratch_cp = smaller_cp;
 
   // attach new constant pool to klass
-  scratch_cp->set_pool_holder(scratch_class());
-
-  // attach klass to new constant pool
   scratch_class->set_constants(scratch_cp());
 
   int i;  // for portability
@@ -3115,6 +3018,31 @@
 }
 
 
+void VM_RedefineClasses::swap_annotations(instanceKlassHandle the_class,
+                                          instanceKlassHandle scratch_class) {
+  // Since there is currently no rewriting of type annotations indexes
+  // into the CP, we null out type annotations on scratch_class before
+  // we swap annotations with the_class rather than facing the
+  // possibility of shipping annotations with broken indexes to
+  // Java-land.
+  ClassLoaderData* loader_data = scratch_class->class_loader_data();
+  AnnotationArray* new_class_type_annotations = scratch_class->class_type_annotations();
+  if (new_class_type_annotations != NULL) {
+    MetadataFactory::free_array<u1>(loader_data, new_class_type_annotations);
+    scratch_class->annotations()->set_class_type_annotations(NULL);
+  }
+  Array<AnnotationArray*>* new_field_type_annotations = scratch_class->fields_type_annotations();
+  if (new_field_type_annotations != NULL) {
+    Annotations::free_contents(loader_data, new_field_type_annotations);
+    scratch_class->annotations()->set_fields_type_annotations(NULL);
+  }
+
+  // Swap annotation fields values
+  Annotations* old_annotations = the_class->annotations();
+  the_class->set_annotations(scratch_class->annotations());
+  scratch_class->set_annotations(old_annotations);
+}
+
 
 // Install the redefinition of a class:
 //    - house keeping (flushing breakpoints and caches, deoptimizing
@@ -3140,11 +3068,9 @@
   Klass* the_class_oop = java_lang_Class::as_Klass(the_class_mirror);
   instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop);
 
-#ifndef JVMTI_KERNEL
   // Remove all breakpoints in methods of this class
   JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints();
   jvmti_breakpoints.clearall_in_class_at_safepoint(the_class_oop);
-#endif // !JVMTI_KERNEL
 
   if (the_class_oop == Universe::reflect_invoke_cache()->klass()) {
     // We are redefining java.lang.reflect.Method. Method.invoke() is
@@ -3327,23 +3253,7 @@
     the_class->set_access_flags(flags);
   }
 
-  // Since there is currently no rewriting of type annotations indexes
-  // into the CP, we null out type annotations on scratch_class before
-  // we swap annotations with the_class rather than facing the
-  // possibility of shipping annotations with broken indexes to
-  // Java-land.
-  Annotations* new_annotations = scratch_class->annotations();
-  if (new_annotations != NULL) {
-    Annotations* new_type_annotations = new_annotations->type_annotations();
-    if (new_type_annotations != NULL) {
-      MetadataFactory::free_metadata(scratch_class->class_loader_data(), new_type_annotations);
-      new_annotations->set_type_annotations(NULL);
-    }
-  }
-  // Swap annotation fields values
-  Annotations* old_annotations = the_class->annotations();
-  the_class->set_annotations(scratch_class->annotations());
-  scratch_class->set_annotations(old_annotations);
+  swap_annotations(the_class, scratch_class);
 
   // Replace minor version number of class file
   u2 old_minor_version = the_class->minor_version();
@@ -3423,7 +3333,6 @@
   }
 }
 
-#ifndef PRODUCT
 void VM_RedefineClasses::check_class(Klass* k_oop,
                                      ClassLoaderData* initiating_loader,
                                      TRAPS) {
@@ -3431,82 +3340,110 @@
   if (k->oop_is_instance()) {
     HandleMark hm(THREAD);
     InstanceKlass *ik = (InstanceKlass *) k;
-
-    if (ik->vtable_length() > 0) {
-      ResourceMark rm(THREAD);
-      if (!ik->vtable()->check_no_old_entries()) {
-        tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name());
+    bool no_old_methods = true;  // be optimistic
+    ResourceMark rm(THREAD);
+
+    // a vtable should never contain old or obsolete methods
+    if (ik->vtable_length() > 0 &&
+        !ik->vtable()->check_no_old_or_obsolete_entries()) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        RC_TRACE_WITH_THREAD(0x00004000, THREAD,
+          ("klassVtable::check_no_old_or_obsolete_entries failure"
+           " -- OLD or OBSOLETE method found -- class: %s",
+           ik->signature_name()));
         ik->vtable()->dump_vtable();
-        assert(false, "OLD method found");
       }
+      no_old_methods = false;
     }
-    if (ik->itable_length() > 0) {
-      ResourceMark rm(THREAD);
-      if (!ik->itable()->check_no_old_entries()) {
-        tty->print_cr("klassItable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name());
-        assert(false, "OLD method found");
+
+    // an itable should never contain old or obsolete methods
+    if (ik->itable_length() > 0 &&
+        !ik->itable()->check_no_old_or_obsolete_entries()) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        RC_TRACE_WITH_THREAD(0x00004000, THREAD,
+          ("klassItable::check_no_old_or_obsolete_entries failure"
+           " -- OLD or OBSOLETE method found -- class: %s",
+           ik->signature_name()));
+        ik->itable()->dump_itable();
       }
+      no_old_methods = false;
     }
-    // Check that the constant pool cache has no deleted entries.
+
+    // the constant pool cache should never contain old or obsolete methods
     if (ik->constants() != NULL &&
         ik->constants()->cache() != NULL &&
-       !ik->constants()->cache()->check_no_old_entries()) {
-      tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name());
-      assert(false, "OLD method found");
+        !ik->constants()->cache()->check_no_old_or_obsolete_entries()) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        RC_TRACE_WITH_THREAD(0x00004000, THREAD,
+          ("cp-cache::check_no_old_or_obsolete_entries failure"
+           " -- OLD or OBSOLETE method found -- class: %s",
+           ik->signature_name()));
+        ik->constants()->cache()->dump_cache();
+      }
+      no_old_methods = false;
+    }
+
+    if (!no_old_methods) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        dump_methods();
+      } else {
+        tty->print_cr("INFO: use the '-XX:TraceRedefineClasses=16384' option "
+          "to see more info about the following guarantee() failure.");
+      }
+      guarantee(false, "OLD and/or OBSOLETE method(s) found");
     }
   }
 }
 
 void VM_RedefineClasses::dump_methods() {
-        int j;
-        tty->print_cr("_old_methods --");
-        for (j = 0; j < _old_methods->length(); ++j) {
-          Method* m = _old_methods->at(j);
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
-        tty->print_cr("_new_methods --");
-        for (j = 0; j < _new_methods->length(); ++j) {
-          Method* m = _new_methods->at(j);
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
-        tty->print_cr("_matching_(old/new)_methods --");
-        for (j = 0; j < _matching_methods_length; ++j) {
-          Method* m = _matching_old_methods[j];
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-          m = _matching_new_methods[j];
-          tty->print("      (%5d)  ", m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->cr();
-        }
-        tty->print_cr("_deleted_methods --");
-        for (j = 0; j < _deleted_methods_length; ++j) {
-          Method* m = _deleted_methods[j];
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
-        tty->print_cr("_added_methods --");
-        for (j = 0; j < _added_methods_length; ++j) {
-          Method* m = _added_methods[j];
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
+  int j;
+  RC_TRACE(0x00004000, ("_old_methods --"));
+  for (j = 0; j < _old_methods->length(); ++j) {
+    Method* m = _old_methods->at(j);
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_new_methods --"));
+  for (j = 0; j < _new_methods->length(); ++j) {
+    Method* m = _new_methods->at(j);
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_matching_(old/new)_methods --"));
+  for (j = 0; j < _matching_methods_length; ++j) {
+    Method* m = _matching_old_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+    m = _matching_new_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("      (%5d)  ", m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_deleted_methods --"));
+  for (j = 0; j < _deleted_methods_length; ++j) {
+    Method* m = _deleted_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_added_methods --"));
+  for (j = 0; j < _added_methods_length; ++j) {
+    Method* m = _added_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
 }
-#endif
--- a/src/share/vm/prims/jvmtiRedefineClasses.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -384,11 +384,6 @@
   jvmtiError compare_and_normalize_class_versions(
     instanceKlassHandle the_class, instanceKlassHandle scratch_class);
 
-  // Swap annotations[i] with annotations[j]
-  // Used by compare_and_normalize_class_versions() when normalizing
-  // overloaded methods or changing idnum as when adding or deleting methods.
-  void swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS);
-
   // Figure out which new methods match old methods in name and signature,
   // which methods have been added, and which are no longer present
   void compute_added_deleted_matching_methods();
@@ -417,14 +412,18 @@
   void redefine_single_class(jclass the_jclass,
     Klass* scratch_class_oop, TRAPS);
 
+  void swap_annotations(instanceKlassHandle new_class,
+                        instanceKlassHandle scratch_class);
+
   // Increment the classRedefinedCount field in the specific InstanceKlass
   // and in all direct and indirect subclasses.
   void increment_class_counter(InstanceKlass *ik, TRAPS);
 
-  // Support for constant pool merging (these routines are in alpha
-  // order):
+  // Support for constant pool merging (these routines are in alpha order):
   void append_entry(constantPoolHandle scratch_cp, int scratch_i,
     constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
+  int find_or_append_indirect_entry(constantPoolHandle scratch_cp, int scratch_i,
+    constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
   int find_new_index(int old_index);
   bool is_unresolved_class_mismatch(constantPoolHandle cp1, int index1,
     constantPoolHandle cp2, int index2);
@@ -467,9 +466,9 @@
 
   void flush_dependent_code(instanceKlassHandle k_h, TRAPS);
 
-  static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader, TRAPS) PRODUCT_RETURN;
-
-  static void dump_methods()   PRODUCT_RETURN;
+  static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader,
+                TRAPS);
+  static void dump_methods();
 
  public:
   VM_RedefineClasses(jint class_count,
@@ -487,17 +486,4 @@
   // and redefine implementation
   static bool is_modifiable_class(oop klass_mirror);
 };
-
-
-// Helper class to mark and unmark metadata used on the stack as either handles
-// or executing methods, so that it can't be deleted during class redefinition
-// and class unloading.
-class MetadataOnStackMark : public StackObj {
-  NOT_PRODUCT(static bool _is_active;)
- public:
-  MetadataOnStackMark() NOT_JVMTI_RETURN;
-  ~MetadataOnStackMark() NOT_JVMTI_RETURN;
-  static void record(Metadata* m) NOT_JVMTI_RETURN;
-};
-
 #endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES_HPP
--- a/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
 //    0x00000800 |       2048 - previous class breakpoint mgmt
 //    0x00001000 |       4096 - detect calls to obsolete methods
 //    0x00002000 |       8192 - fail a guarantee() in addition to detection
-//    0x00004000 |      16384 - unused
+//    0x00004000 |      16384 - detect old/obsolete methods in metadata
 //    0x00008000 |      32768 - old/new method matching/add/delete
 //    0x00010000 |      65536 - impl details: CP size info
 //    0x00020000 |     131072 - impl details: CP merge pass info
@@ -82,6 +82,13 @@
     tty->print_cr args; \
   } while (0)
 
+#define RC_TRACE_NO_CR(level, args) \
+  if ((TraceRedefineClasses & level) != 0) { \
+    ResourceMark rm; \
+    tty->print("RedefineClasses-0x%x: ", level); \
+    tty->print args; \
+  } while (0)
+
 #define RC_TRACE_WITH_THREAD(level, thread, args) \
   if ((TraceRedefineClasses & level) != 0) { \
     ResourceMark rm(thread); \
--- a/src/share/vm/prims/jvmtiTagMap.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiTagMap.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -45,9 +45,10 @@
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
 #include "services/serviceUtil.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // JvmtiTagHashmapEntry
 //
--- a/src/share/vm/prims/jvmtiTagMap.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/jvmtiTagMap.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,14 +27,12 @@
 #ifndef SHARE_VM_PRIMS_JVMTITAGMAP_HPP
 #define SHARE_VM_PRIMS_JVMTITAGMAP_HPP
 
-#ifndef JVMTI_KERNEL
 #include "gc_interface/collectedHeap.hpp"
 #include "jvmtifiles/jvmti.h"
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "memory/allocation.hpp"
 #include "memory/genCollectedHeap.hpp"
 #include "memory/universe.hpp"
-#endif
 
 // forward references
 class JvmtiTagHashmap;
--- a/src/share/vm/prims/nativeLookup.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/nativeLookup.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -40,6 +40,7 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/signature.hpp"
+#include "utilities/macros.hpp"
 #ifdef TARGET_OS_FAMILY_linux
 # include "os_linux.inline.hpp"
 #endif
--- a/src/share/vm/prims/unsafe.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/unsafe.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -24,9 +24,10 @@
 
 #include "precompiled.hpp"
 #include "classfile/vmSymbols.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 #include "memory/allocation.inline.hpp"
 #include "prims/jni.h"
 #include "prims/jvm.h"
@@ -189,7 +190,7 @@
   if (obj == NULL)  THROW_0(vmSymbols::java_lang_NullPointerException());
   GET_OOP_FIELD(obj, offset, v)
   jobject ret = JNIHandles::make_local(env, v);
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // We could be accessing the referent field in a reference
   // object. If G1 is enabled then we need to register a non-null
   // referent with the SATB barrier.
@@ -212,7 +213,7 @@
       G1SATBCardTableModRefBS::enqueue(referent);
     }
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
   return ret;
 UNSAFE_END
 
@@ -247,7 +248,7 @@
   UnsafeWrapper("Unsafe_GetObject");
   GET_OOP_FIELD(obj, offset, v)
   jobject ret = JNIHandles::make_local(env, v);
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // We could be accessing the referent field in a reference
   // object. If G1 is enabled then we need to register non-null
   // referent with the SATB barrier.
@@ -270,7 +271,7 @@
       G1SATBCardTableModRefBS::enqueue(referent);
     }
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
   return ret;
 UNSAFE_END
 
--- a/src/share/vm/prims/wbtestmethods/parserTests.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/wbtestmethods/parserTests.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -27,6 +27,6 @@
 #include "prims/jni.h"
 #include "prims/whitebox.hpp"
 
-WB_METHOD_DECLARE WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jobjectArray arguments);
+WB_METHOD_DECLARE(jobjectArray) WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jobjectArray arguments);
 
 #endif //SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H
--- a/src/share/vm/prims/whitebox.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/whitebox.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -36,12 +36,19 @@
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/os.hpp"
 #include "utilities/debug.hpp"
+#include "utilities/macros.hpp"
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/concurrentMark.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
+
+#ifdef INCLUDE_NMT
+#include "services/memTracker.hpp"
+#endif // INCLUDE_NMT
+
+#include "compiler/compileBroker.hpp"
 
 bool WhiteBox::_used = false;
 
@@ -85,7 +92,7 @@
   return closure.found();
 WB_END
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
   G1CollectedHeap* g1 = G1CollectedHeap::heap();
   oop result = JNIHandles::resolve(obj);
@@ -108,7 +115,144 @@
 WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
   return (jint)HeapRegion::GrainBytes;
 WB_END
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
+
+#ifdef INCLUDE_NMT
+// Keep track of the 3 allocations in NMTAllocTest so we can free them later
+// on and verify that they're not visible anymore
+static void* nmtMtTest1 = NULL, *nmtMtTest2 = NULL, *nmtMtTest3 = NULL;
+
+// Alloc memory using the test memory type so that we can use that to see if
+// NMT picks it up correctly
+WB_ENTRY(jboolean, WB_NMTAllocTest(JNIEnv* env))
+  void *mem;
+
+  if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
+    return false;
+  }
+
+  // Allocate 2 * 128k + 256k + 1024k and free the 1024k one to make sure we track
+  // everything correctly. Total should be 512k held alive.
+  nmtMtTest1 = os::malloc(128 * 1024, mtTest);
+  mem = os::malloc(1024 * 1024, mtTest);
+  nmtMtTest2 = os::malloc(256 * 1024, mtTest);
+  os::free(mem, mtTest);
+  nmtMtTest3 = os::malloc(128 * 1024, mtTest);
+
+  return true;
+WB_END
+
+// Free the memory allocated by NMTAllocTest
+WB_ENTRY(jboolean, WB_NMTFreeTestMemory(JNIEnv* env))
+
+  if (nmtMtTest1 == NULL || nmtMtTest2 == NULL || nmtMtTest3 == NULL) {
+    return false;
+  }
+
+  os::free(nmtMtTest1, mtTest);
+  nmtMtTest1 = NULL;
+  os::free(nmtMtTest2, mtTest);
+  nmtMtTest2 = NULL;
+  os::free(nmtMtTest3, mtTest);
+  nmtMtTest3 = NULL;
+
+  return true;
+WB_END
+
+// Block until the current generation of NMT data to be merged, used to reliably test the NMT feature
+WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env))
+
+  if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
+    return false;
+  }
+
+  return MemTracker::wbtest_wait_for_data_merge();
+WB_END
+
+#endif // INCLUDE_NMT
+
+static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
+  assert(method != NULL, "method should not be null");
+  ThreadToNativeFromVM ttn(thread);
+  return env->FromReflectedMethod(method);
+}
+
+WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
+  MutexLockerEx mu(Compile_lock);
+  CodeCache::mark_all_nmethods_for_deoptimization();
+  VM_Deoptimize op;
+  VMThread::execute(&op);
+WB_END
+
+WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  MutexLockerEx mu(Compile_lock);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  int result = 0;
+  nmethod* code = mh->code();
+  if (code != NULL) {
+    code->mark_for_deoptimization();
+    ++result;
+  }
+  result += CodeCache::mark_for_deoptimization(mh());
+  if (result > 0) {
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
+  return result;
+WB_END
+
+WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  MutexLockerEx mu(Compile_lock);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  nmethod* code = mh->code();
+  if (code == NULL) {
+    return JNI_FALSE;
+  }
+  return (code->is_alive() && !code->is_marked_for_deoptimization());
+WB_END
+
+WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  MutexLockerEx mu(Compile_lock);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  return !mh->is_not_compilable();
+WB_END
+
+WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  MutexLockerEx mu(Compile_lock);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  return mh->queued_for_compilation();
+WB_END
+
+WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  nmethod* code = mh->code();
+  return (code != NULL ? code->comp_level() : CompLevel_none);
+WB_END
+
+
+WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  mh->set_not_compilable();
+WB_END
+
+WB_ENTRY(jboolean, WB_SetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  bool result = mh->dont_inline();
+  mh->set_dont_inline(value == JNI_TRUE);
+  return result;
+WB_END
+
+WB_ENTRY(jint, WB_GetCompileQueuesSize(JNIEnv* env, jobject o))
+  return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
+         CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
+WB_END
 
 //Some convenience methods to deal with objects from java
 int WhiteBox::offset_for_field(const char* field_name, oop object,
@@ -166,17 +310,39 @@
 static JNINativeMethod methods[] = {
   {CC"getObjectAddress",   CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress  },
   {CC"getHeapOopSize",     CC"()I",                   (void*)&WB_GetHeapOopSize    },
-  {CC"isClassAlive0",       CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive      },
-  {CC "parseCommandLine",
-      CC "(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
+  {CC"isClassAlive0",      CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive      },
+  {CC"parseCommandLine",
+      CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
       (void*) &WB_ParseCommandLine
   },
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
   {CC"g1IsHumongous",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
   {CC"g1NumFreeRegions",   CC"()J",                   (void*)&WB_G1NumFreeRegions  },
   {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
+#ifdef INCLUDE_NMT
+  {CC"NMTAllocTest",       CC"()Z",                   (void*)&WB_NMTAllocTest      },
+  {CC"NMTFreeTestMemory",  CC"()Z",                   (void*)&WB_NMTFreeTestMemory },
+  {CC"NMTWaitForDataMerge",CC"()Z",                   (void*)&WB_NMTWaitForDataMerge},
+#endif // INCLUDE_NMT
+  {CC"deoptimizeAll",      CC"()V",                   (void*)&WB_DeoptimizeAll     },
+  {CC"deoptimizeMethod",   CC"(Ljava/lang/reflect/Method;)I",
+                                                      (void*)&WB_DeoptimizeMethod  },
+  {CC"isMethodCompiled",   CC"(Ljava/lang/reflect/Method;)Z",
+                                                      (void*)&WB_IsMethodCompiled  },
+  {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;)Z",
+                                                      (void*)&WB_IsMethodCompilable},
+  {CC"isMethodQueuedForCompilation",
+      CC"(Ljava/lang/reflect/Method;)Z",              (void*)&WB_IsMethodQueuedForCompilation},
+  {CC"makeMethodNotCompilable",
+      CC"(Ljava/lang/reflect/Method;)V",              (void*)&WB_MakeMethodNotCompilable},
+  {CC"setDontInlineMethod",
+      CC"(Ljava/lang/reflect/Method;Z)Z",             (void*)&WB_SetDontInlineMethod},
+  {CC"getMethodCompilationLevel",
+      CC"(Ljava/lang/reflect/Method;)I",              (void*)&WB_GetMethodCompilationLevel},
+  {CC"getCompileQueuesSize",
+      CC"()I",                                        (void*)&WB_GetCompileQueuesSize},
 };
 
 #undef CC
--- a/src/share/vm/prims/whitebox.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/prims/whitebox.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -34,7 +34,7 @@
 
 #define WB_ENTRY(result_type, header) JNI_ENTRY(result_type, header)
 #define WB_END JNI_END
-#define WB_METHOD_DECLARE extern "C" jobjectArray JNICALL
+#define WB_METHOD_DECLARE(result_type) extern "C" result_type JNICALL
 
 class WhiteBox : public AllStatic {
  private:
--- a/src/share/vm/runtime/arguments.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -38,6 +38,7 @@
 #include "services/management.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/defaultStream.hpp"
+#include "utilities/macros.hpp"
 #include "utilities/taskqueue.hpp"
 #ifdef TARGET_OS_FAMILY_linux
 # include "os_linux.inline.hpp"
@@ -51,9 +52,9 @@
 #ifdef TARGET_OS_FAMILY_bsd
 # include "os_bsd.inline.hpp"
 #endif
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // Note: This is a special bug reporting site for the JVM
 #define DEFAULT_VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/crash.jsp"
@@ -104,9 +105,6 @@
 SystemProperty *Arguments::_java_home = NULL;
 SystemProperty *Arguments::_java_class_path = NULL;
 SystemProperty *Arguments::_sun_boot_class_path = NULL;
-#ifdef GRAAL
-SystemProperty *Arguments::_compiler_class_path = NULL;
-#endif
 
 char* Arguments::_meta_index_path = NULL;
 char* Arguments::_meta_index_dir = NULL;
@@ -168,9 +166,6 @@
   _java_library_path = new SystemProperty("java.library.path", NULL,  true);
   _java_home =  new SystemProperty("java.home", NULL,  true);
   _sun_boot_class_path = new SystemProperty("sun.boot.class.path", NULL,  true);
-#ifdef GRAAL
-  _compiler_class_path = new SystemProperty("compiler.class.path", NULL,  true);
-#endif
 
   _java_class_path = new SystemProperty("java.class.path", "",  true);
 
@@ -182,9 +177,6 @@
   PropertyList_add(&_system_properties, _java_home);
   PropertyList_add(&_system_properties, _java_class_path);
   PropertyList_add(&_system_properties, _sun_boot_class_path);
-#ifdef GRAAL
-  PropertyList_add(&_system_properties, _compiler_class_path);
-#endif
 
   // Set OS specific system properties values
   os::init_system_properties_values();
@@ -845,7 +837,8 @@
     return true;
   }
 
-  const char * const argname = *arg == '+' || *arg == '-' ? arg + 1 : arg;
+  bool has_plus_minus = (*arg == '+' || *arg == '-');
+  const char* const argname = has_plus_minus ? arg + 1 : arg;
   if (is_newly_obsolete(arg, &since)) {
     char version[256];
     since.to_string(version, sizeof(version));
@@ -856,13 +849,29 @@
   // For locked flags, report a custom error message if available.
   // Otherwise, report the standard unrecognized VM option.
 
-  Flag* locked_flag = Flag::find_flag((char*)argname, strlen(argname), true);
-  if (locked_flag != NULL) {
+  size_t arg_len;
+  const char* equal_sign = strchr(argname, '=');
+  if (equal_sign == NULL) {
+    arg_len = strlen(argname);
+  } else {
+    arg_len = equal_sign - argname;
+  }
+
+  Flag* found_flag = Flag::find_flag((char*)argname, arg_len, true);
+  if (found_flag != NULL) {
     char locked_message_buf[BUFLEN];
-    locked_flag->get_locked_message(locked_message_buf, BUFLEN);
+    found_flag->get_locked_message(locked_message_buf, BUFLEN);
     if (strlen(locked_message_buf) == 0) {
-      jio_fprintf(defaultStream::error_stream(),
-        "Unrecognized VM option '%s'\n", argname);
+      if (found_flag->is_bool() && !has_plus_minus) {
+        jio_fprintf(defaultStream::error_stream(),
+          "Missing +/- setting for VM option '%s'\n", argname);
+      } else if (!found_flag->is_bool() && has_plus_minus) {
+        jio_fprintf(defaultStream::error_stream(),
+          "Unexpected +/- setting in VM option '%s'\n", argname);
+      } else {
+        jio_fprintf(defaultStream::error_stream(),
+          "Improperly specified VM option '%s'\n", argname);
+      }
     } else {
       jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf);
     }
@@ -1086,11 +1095,11 @@
   }
   // Increase the code cache size - tiered compiles a lot more.
   if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
-    FLAG_SET_DEFAULT(ReservedCodeCacheSize, ReservedCodeCacheSize * 2);
+    FLAG_SET_DEFAULT(ReservedCodeCacheSize, ReservedCodeCacheSize * 5);
   }
 }
 
-#if INCLUDE_ALTERNATE_GCS
+#if INCLUDE_ALL_GCS
 static void disable_adaptive_size_policy(const char* collector_name) {
   if (UseAdaptiveSizePolicy) {
     if (FLAG_IS_CMDLINE(UseAdaptiveSizePolicy)) {
@@ -1257,7 +1266,7 @@
   // prefer minuscule survivor spaces so as not to waste
   // space for (non-existent) survivors
   if (FLAG_IS_DEFAULT(SurvivorRatio) && MaxTenuringThreshold == 0) {
-    FLAG_SET_ERGO(intx, SurvivorRatio, MAX2((intx)1024, SurvivorRatio));
+    FLAG_SET_ERGO(uintx, SurvivorRatio, MAX2((uintx)1024, SurvivorRatio));
   }
   // If OldPLABSize is set and CMSParPromoteBlocksToClaim is not,
   // set CMSParPromoteBlocksToClaim equal to OldPLABSize.
@@ -1302,7 +1311,7 @@
     tty->print_cr("ConcGCThreads: %u", ConcGCThreads);
   }
 }
-#endif // INCLUDE_ALTERNATE_GCS
+#endif // INCLUDE_ALL_GCS
 
 void set_object_alignment() {
   // Object alignment.
@@ -1319,10 +1328,10 @@
   // Oop encoding heap max
   OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes;
 
-#if INCLUDE_ALTERNATE_GCS
+#if INCLUDE_ALL_GCS
   // Set CMS global values
   CompactibleFreeListSpace::set_cms_values();
-#endif // INCLUDE_ALTERNATE_GCS
+#endif // INCLUDE_ALL_GCS
 }
 
 bool verify_object_alignment() {
@@ -1447,13 +1456,18 @@
     }
     // Set the ClassMetaspaceSize to something that will not need to be
     // expanded, since it cannot be expanded.
-    if (UseCompressedKlassPointers && FLAG_IS_DEFAULT(ClassMetaspaceSize)) {
-      // 100,000 classes seems like a good size, so 100M assumes around 1K
-      // per klass.   The vtable and oopMap is embedded so we don't have a fixed
-      // size per klass.   Eventually, this will be parameterized because it
-      // would also be useful to determine the optimal size of the
-      // systemDictionary.
-      FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M);
+    if (UseCompressedKlassPointers) {
+      if (ClassMetaspaceSize > KlassEncodingMetaspaceMax) {
+        warning("Class metaspace size is too large for UseCompressedKlassPointers");
+        FLAG_SET_DEFAULT(UseCompressedKlassPointers, false);
+      } else if (FLAG_IS_DEFAULT(ClassMetaspaceSize)) {
+        // 100,000 classes seems like a good size, so 100M assumes around 1K
+        // per klass.   The vtable and oopMap is embedded so we don't have a fixed
+        // size per klass.   Eventually, this will be parameterized because it
+        // would also be useful to determine the optimal size of the
+        // systemDictionary.
+        FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M);
+      }
     }
   }
   // Also checks that certain machines are slower with compressed oops
@@ -1733,16 +1747,6 @@
   return false;
 }
 
-static void force_serial_gc() {
-  FLAG_SET_DEFAULT(UseSerialGC, true);
-  FLAG_SET_DEFAULT(UseParNewGC, false);
-  FLAG_SET_DEFAULT(UseConcMarkSweepGC, false);
-  FLAG_SET_DEFAULT(CMSIncrementalMode, false);  // special CMS suboption
-  FLAG_SET_DEFAULT(UseParallelGC, false);
-  FLAG_SET_DEFAULT(UseParallelOldGC, false);
-  FLAG_SET_DEFAULT(UseG1GC, false);
-}
-
 static bool verify_serial_gc_flags() {
   return (UseSerialGC &&
         !(UseParNewGC || (UseConcMarkSweepGC || CMSIncrementalMode) || UseG1GC ||
@@ -1892,6 +1896,24 @@
   // Keeping the heap 100% free is hard ;-) so limit it to 99%.
   MinHeapFreeRatio = MIN2(MinHeapFreeRatio, (uintx) 99);
 
+  // Min/MaxMetaspaceFreeRatio
+  status = status && verify_percentage(MinMetaspaceFreeRatio, "MinMetaspaceFreeRatio");
+  status = status && verify_percentage(MaxMetaspaceFreeRatio, "MaxMetaspaceFreeRatio");
+
+  if (MinMetaspaceFreeRatio > MaxMetaspaceFreeRatio) {
+    jio_fprintf(defaultStream::error_stream(),
+                "MinMetaspaceFreeRatio (%s" UINTX_FORMAT ") must be less than or "
+                "equal to MaxMetaspaceFreeRatio (%s" UINTX_FORMAT ")\n",
+                FLAG_IS_DEFAULT(MinMetaspaceFreeRatio) ? "Default: " : "",
+                MinMetaspaceFreeRatio,
+                FLAG_IS_DEFAULT(MaxMetaspaceFreeRatio) ? "Default: " : "",
+                MaxMetaspaceFreeRatio);
+    status = false;
+  }
+
+  // Trying to keep 100% free is not practical
+  MinMetaspaceFreeRatio = MIN2(MinMetaspaceFreeRatio, (uintx) 99);
+
   if (FullGCALot && FLAG_IS_DEFAULT(MarkSweepAlwaysCompactCount)) {
     MarkSweepAlwaysCompactCount = 1;  // Move objects every gc.
   }
@@ -1899,7 +1921,7 @@
   if (UseParallelOldGC && ParallelOldGCSplitALot) {
     // Settings to encourage splitting.
     if (!FLAG_IS_CMDLINE(NewRatio)) {
-      FLAG_SET_CMDLINE(intx, NewRatio, 2);
+      FLAG_SET_CMDLINE(uintx, NewRatio, 2);
     }
     if (!FLAG_IS_CMDLINE(ScavengeBeforeFullGC)) {
       FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
@@ -1994,7 +2016,7 @@
 
   status = status && verify_min_value(ParGCArrayScanChunk, 1, "ParGCArrayScanChunk");
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   if (UseG1GC) {
     status = status && verify_percentage(InitiatingHeapOccupancyPercent,
                                          "InitiatingHeapOccupancyPercent");
@@ -2003,7 +2025,7 @@
     status = status && verify_min_value((intx)G1ConcMarkStepDurationMillis, 1,
                                         "G1ConcMarkStepDurationMillis");
   }
-#endif
+#endif // INCLUDE_ALL_GCS
 
   status = status && verify_interval(RefDiscoveryPolicy,
                                      ReferenceProcessor::DiscoveryPolicyMin,
@@ -2048,18 +2070,28 @@
   }
 #ifdef GRAAL
   if (UseCompressedOops) {
-    jio_fprintf(defaultStream::error_stream(),
+    if (IgnoreUnrecognizedVMOptions) {
+      warning("UseCompressedOops is disabled, because it is not supported by Graal");
+      FLAG_SET_CMDLINE(bool, UseCompressedOops, false);
+    } else {
+      jio_fprintf(defaultStream::error_stream(),
                     "CompressedOops are not supported in Graal at the moment\n");
-        status = false;
+      status = false;
+    }
   } else {
     // This prevents the flag being set to true by set_ergonomics_flags()
     FLAG_SET_CMDLINE(bool, UseCompressedOops, false);
   }
 
   if (UseCompressedKlassPointers) {
-    jio_fprintf(defaultStream::error_stream(),
+    if (IgnoreUnrecognizedVMOptions) {
+      warning("UseCompressedKlassPointers is disabled, because it is not supported by Graal");
+      FLAG_SET_CMDLINE(bool, UseCompressedKlassPointers, false);
+    } else {
+      jio_fprintf(defaultStream::error_stream(),
                     "UseCompressedKlassPointers are not supported in Graal at the moment\n");
-        status = false;
+      status = false;
+    }
   } else {
     // This prevents the flag being set to true by set_ergonomics_flags()
     FLAG_SET_CMDLINE(bool, UseCompressedKlassPointers, false);
@@ -2150,58 +2182,6 @@
 }
 
 // Parse JavaVMInitArgs structure
-#ifdef GRAAL
-static void prepend_to_graal_classpath(SysClassPath &cp, const char* path) {
-  cp.add_prefix(path);
-}
-
-static void prepend_to_graal_classpath(SysClassPath &cp, const char* graal_dir, const char* project) {
-  const int BUFFER_SIZE = 1024;
-  char path[BUFFER_SIZE];
-
-  const char fileSep = *os::file_separator();
-  sprintf(path, "%s%c%s%cbin", graal_dir, fileSep, project, fileSep);
-  
-  DIR* dir = os::opendir(path);
-  if (dir == NULL) {
-    jio_fprintf(defaultStream::output_stream(), "Error while starting Graal VM: The Graal class directory %s could not be opened.\n", path);
-    vm_exit(1);
-  }
-  os::closedir(dir);
-  prepend_to_graal_classpath(cp, path);
-}
-
-// Walk up the directory hierarchy starting from JAVA_HOME looking
-// for a directory named "graal". If found, then the full path to
-// this directory is returned in graal_dir.
-static bool find_graal_dir(char* graal_dir) {
-  strcpy(graal_dir, Arguments::get_java_home());
-  char* end = graal_dir + strlen(graal_dir);
-  const char fileSep = *os::file_separator();
-  while (end != graal_dir) {
-    if (fileSep == '/') 
-      strcat(graal_dir, "/graal");
-    else {
-      assert(fileSep == '\\', "unexpected separator char");
-      strcat(graal_dir, "\\graal");
-    }
-    DIR* dir = os::opendir(graal_dir);
-    if (dir != NULL) {
-      os::closedir(dir);
-      return true;
-    }
-    *end = 0;
-    while (end != graal_dir) {
-      if (*end == fileSep) {
-        *end = 0;
-        break;
-      }
-      end--;
-    }
-  }
-  return false;
-}
-#endif
 
 jint Arguments::parse_vm_init_args(const JavaVMInitArgs* args) {
   // For components of the system classpath.
@@ -2229,72 +2209,6 @@
     return result;
   }
 
-#ifdef GRAAL
-    if (PrintVMOptions) {
-      tty->print_cr("Running Graal VM... ");
-    }
-
-    SysClassPath scp_compiler("");
-
-    if (GraalClassPath != NULL) {
-      prepend_to_graal_classpath(scp_compiler, GraalClassPath);
-    } else {
-      const int BUFFER_SIZE = 1024;
-      char graal_dir[BUFFER_SIZE];
-      if (!os::getenv("GRAAL", graal_dir, sizeof(graal_dir))) {
-        if (find_graal_dir(graal_dir) == false) {
-          jio_fprintf(defaultStream::output_stream(), "Error while starting Graal VM: The GRAAL environment variable needs to point to the directory containing the Graal projects.\n");
-          vm_exit(0);
-        }
-      }
-      if (PrintVMOptions) tty->print_cr("GRAAL=%s", graal_dir);
-    
-      // this declaration is checked for correctness by 'mx build' - only
-      // modify its entries, not its name or shape
-      const char* graal_projects[] = {
-  #ifdef AMD64
-          "com.oracle.graal.amd64",
-          "com.oracle.graal.asm.amd64",
-          "com.oracle.graal.lir.amd64",
-          "com.oracle.graal.compiler.amd64",
-          "com.oracle.graal.hotspot.amd64",
-  #endif
-          "com.oracle.graal.api.runtime",
-          "com.oracle.graal.api.meta",
-          "com.oracle.graal.api.code",
-          "com.oracle.graal.hotspot",
-          "com.oracle.graal.asm",
-          "com.oracle.graal.alloc",
-          "com.oracle.graal.word",
-          "com.oracle.graal.snippets",
-          "com.oracle.graal.compiler",
-          "com.oracle.graal.loop",
-          "com.oracle.graal.phases",
-          "com.oracle.graal.phases.common",
-          "com.oracle.graal.virtual",
-          "com.oracle.graal.nodes",
-          "com.oracle.graal.printer",
-          "com.oracle.graal.debug",
-          "com.oracle.graal.graph",
-          "com.oracle.graal.lir",
-          "com.oracle.graal.bytecode",
-          "com.oracle.graal.java"
-      };
-            
-      const int len = sizeof(graal_projects) / sizeof(char*);
-      for (int i = 0; i < len; i++) {
-        if (PrintVMOptions) {
-          tty->print_cr("Adding project directory %s to bootclasspath", graal_projects[i]);
-        }
-        prepend_to_graal_classpath(scp_compiler, graal_dir, graal_projects[i]);
-      }
-    }
-
-    scp_compiler.expand_endorsed();
-    Arguments::set_compilerclasspath(scp_compiler.combined_path());
-
-#endif
-
   if (AggressiveOpts) {
     // Insert alt-rt.jar between user-specified bootclasspath
     // prefix and the default bootclasspath.  os::set_boot_path()
@@ -2310,19 +2224,6 @@
     FREE_C_HEAP_ARRAY(char, altclasses_path, mtInternal);
   }
 
-  if (WhiteBoxAPI) {
-    // Append wb.jar to bootclasspath if enabled
-    const char* wb_jar = "wb.jar";
-    size_t wb_path_len = strlen(get_meta_index_dir()) + 1 +
-                         strlen(wb_jar);
-    char* wb_path = NEW_C_HEAP_ARRAY(char, wb_path_len, mtInternal);
-    strcpy(wb_path, get_meta_index_dir());
-    strcat(wb_path, wb_jar);
-    scp.add_suffix(wb_path);
-    scp_assembly_required = true;
-    FREE_C_HEAP_ARRAY(char, wb_path, mtInternal);
-  }
-
   // Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM)
   result = parse_java_options_environment_variable(&scp, &scp_assembly_required);
   if (result != JNI_OK) {
@@ -2617,7 +2518,12 @@
       }
       // Out of the box management support
       if (match_option(option, "-Dcom.sun.management", &tail)) {
+#if INCLUDE_MANAGEMENT
         FLAG_SET_CMDLINE(bool, ManagementServer, true);
+#else
+        vm_exit_during_initialization(
+            "-Dcom.sun.management is not supported in this VM.", NULL);
+#endif
       }
     // -Xint
     } else if (match_option(option, "-Xint", &tail)) {
@@ -2632,10 +2538,7 @@
 
     // -Xshare:dump
     } else if (match_option(option, "-Xshare:dump", &tail)) {
-#if defined(KERNEL)
-      vm_exit_during_initialization(
-          "Dumping a shared archive is not supported on the Kernel JVM.", NULL);
-#elif !INCLUDE_CDS
+#if !INCLUDE_CDS
       vm_exit_during_initialization(
           "Dumping a shared archive is not supported in this VM.", NULL);
 #else
@@ -2966,6 +2869,11 @@
       //       away and will cause VM initialization failures!
       warning("-XX:+UseVMInterruptibleIO is obsolete and will be removed in a future release.");
       FLAG_SET_CMDLINE(bool, UseVMInterruptibleIO, true);
+#if !INCLUDE_MANAGEMENT
+    } else if (match_option(option, "-XX:+ManagementServer", &tail)) {
+      vm_exit_during_initialization(
+        "ManagementServer is not supported in this VM.", NULL);
+#endif // INCLUDE_MANAGEMENT
     } else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx
       // Skip -XX:Flags= since that case has already been handled
       if (strncmp(tail, "Flags=", strlen("Flags=")) != 0) {
@@ -3205,6 +3113,27 @@
   }                                                             \
 } while(0)
 
+
+#define UNSUPPORTED_GC_OPTION(gc)                                     \
+do {                                                                  \
+  if (gc) {                                                           \
+    if (FLAG_IS_CMDLINE(gc)) {                                        \
+      warning(#gc " is not supported in this VM.  Using Serial GC."); \
+    }                                                                 \
+    FLAG_SET_DEFAULT(gc, false);                                      \
+  }                                                                   \
+} while(0)
+
+static void force_serial_gc() {
+  FLAG_SET_DEFAULT(UseSerialGC, true);
+  FLAG_SET_DEFAULT(CMSIncrementalMode, false);  // special CMS suboption
+  UNSUPPORTED_GC_OPTION(UseG1GC);
+  UNSUPPORTED_GC_OPTION(UseParallelGC);
+  UNSUPPORTED_GC_OPTION(UseParallelOldGC);
+  UNSUPPORTED_GC_OPTION(UseConcMarkSweepGC);
+  UNSUPPORTED_GC_OPTION(UseParNewGC);
+}
+
 // Parse entry point called from JNI_CreateJavaVM
 
 jint Arguments::parse(const JavaVMInitArgs* args) {
@@ -3320,28 +3249,15 @@
             hotspotrc, hotspotrc);
   }
 
-#if (defined JAVASE_EMBEDDED || defined ARM)
-  UNSUPPORTED_OPTION(UseG1GC, "G1 GC");
-#endif
-
 #ifdef _ALLBSD_SOURCE  // UseLargePages is not yet supported on BSD.
   UNSUPPORTED_OPTION(UseLargePages, "-XX:+UseLargePages");
 #endif
 
-#if !INCLUDE_ALTERNATE_GCS
-  if (UseParallelGC) {
-    warning("Parallel GC is not supported in this VM.  Using Serial GC.");
-  }
-  if (UseParallelOldGC) {
-    warning("Parallel Old GC is not supported in this VM.  Using Serial GC.");
-  }
-  if (UseConcMarkSweepGC) {
-    warning("Concurrent Mark Sweep GC is not supported in this VM.  Using Serial GC.");
-  }
-  if (UseParNewGC) {
-    warning("Par New GC is not supported in this VM.  Using Serial GC.");
-  }
-#endif // INCLUDE_ALTERNATE_GCS
+#if INCLUDE_ALL_GCS
+  #if (defined JAVASE_EMBEDDED || defined ARM)
+    UNSUPPORTED_OPTION(UseG1GC, "G1 GC");
+  #endif
+#endif
 
 #ifndef PRODUCT
   if (TraceBytecodesAt != 0) {
@@ -3388,9 +3304,9 @@
   // Set object alignment values.
   set_object_alignment();
 
-#ifdef SERIALGC
+#if !INCLUDE_ALL_GCS
   force_serial_gc();
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 #if !INCLUDE_CDS
   no_shared_spaces();
 #endif // INCLUDE_CDS
@@ -3418,7 +3334,7 @@
   // Set heap size based on available physical memory
   set_heap_size();
 
-#if INCLUDE_ALTERNATE_GCS
+#if INCLUDE_ALL_GCS
   // Set per-collector flags
   if (UseParallelGC || UseParallelOldGC) {
     set_parallel_gc_flags();
@@ -3430,11 +3346,9 @@
     set_g1_gc_flags();
   }
   check_deprecated_gcs();
-#endif // INCLUDE_ALTERNATE_GCS
-
-#ifdef SERIALGC
+#else // INCLUDE_ALL_GCS
   assert(verify_serial_gc_flags(), "SerialGC unset");
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // Set bytecode rewriting flags
   set_bytecode_flags();
@@ -3531,7 +3445,7 @@
 }
 
 jint Arguments::adjust_after_os() {
-#if INCLUDE_ALTERNATE_GCS
+#if INCLUDE_ALL_GCS
   if (UseParallelGC || UseParallelOldGC) {
     if (UseNUMA) {
       if (FLAG_IS_DEFAULT(MinHeapDeltaBytes)) {
@@ -3542,7 +3456,7 @@
       UseNUMAInterleaving = true;
     }
   }
-#endif
+#endif // INCLUDE_ALL_GCS
   return JNI_OK;
 }
 
@@ -3637,36 +3551,6 @@
   PropertyList_add(plist, k, v);
 }
 
-#ifdef KERNEL
-char *Arguments::get_kernel_properties() {
-  // Find properties starting with kernel and append them to string
-  // We need to find out how long they are first because the URL's that they
-  // might point to could get long.
-  int length = 0;
-  SystemProperty* prop;
-  for (prop = _system_properties; prop != NULL; prop = prop->next()) {
-    if (strncmp(prop->key(), "kernel.", 7 ) == 0) {
-      length += (strlen(prop->key()) + strlen(prop->value()) + 5);  // "-D ="
-    }
-  }
-  // Add one for null terminator.
-  char *props = AllocateHeap(length + 1, mtInternal);
-  if (length != 0) {
-    int pos = 0;
-    for (prop = _system_properties; prop != NULL; prop = prop->next()) {
-      if (strncmp(prop->key(), "kernel.", 7 ) == 0) {
-        jio_snprintf(&props[pos], length-pos,
-                     "-D%s=%s ", prop->key(), prop->value());
-        pos = strlen(props);
-      }
-    }
-  }
-  // null terminate props in case of null
-  props[length] = '\0';
-  return props;
-}
-#endif // KERNEL
-
 // Copies src into buf, replacing "%%" with "%" and "%p" with pid
 // Returns true if all of the source pointed by src has been copied over to
 // the destination buffer pointed by buf. Otherwise, returns false.
--- a/src/share/vm/runtime/arguments.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/arguments.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -247,9 +247,6 @@
   static SystemProperty *_java_home;
   static SystemProperty *_java_class_path;
   static SystemProperty *_sun_boot_class_path;
-#ifdef GRAAL
-  static SystemProperty *_compiler_class_path;
-#endif
 
   // Meta-index for knowing what packages are in the boot class path
   static char* _meta_index_path;
@@ -537,9 +534,6 @@
   static void set_ext_dirs(char *value) { _java_ext_dirs->set_value(value); }
   static void set_endorsed_dirs(char *value) { _java_endorsed_dirs->set_value(value); }
   static void set_sysclasspath(char *value) { _sun_boot_class_path->set_value(value); }
-#ifdef GRAAL
-  static void set_compilerclasspath(char *value) { _compiler_class_path->set_value(value); }
-#endif
   static void append_sysclasspath(const char *value) { _sun_boot_class_path->append_value(value); }
   static void set_meta_index_path(char* meta_index_path, char* meta_index_dir) {
     _meta_index_path = meta_index_path;
@@ -550,9 +544,6 @@
   static char *get_dll_dir() { return _sun_boot_library_path->value(); }
   static char *get_endorsed_dir() { return _java_endorsed_dirs->value(); }
   static char *get_sysclasspath() { return _sun_boot_class_path->value(); }
-#ifdef GRAAL
-  static char *get_compilerclasspath() { return _compiler_class_path->value(); }
-#endif
   static char* get_meta_index_path() { return _meta_index_path; }
   static char* get_meta_index_dir()  { return _meta_index_dir;  }
 
@@ -561,11 +552,6 @@
 
   // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid.
   static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen);
-
-#ifdef KERNEL
-  // For java kernel vm, return property string for kernel properties.
-  static char *get_kernel_properties();
-#endif // KERNEL
 };
 
 #endif // SHARE_VM_RUNTIME_ARGUMENTS_HPP
--- a/src/share/vm/runtime/atomic.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/atomic.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -29,10 +29,17 @@
 
 class Atomic : AllStatic {
  public:
+  // Atomic operations on jlong types are not available on all 32-bit
+  // platforms. If atomic ops on jlongs are defined here they must only
+  // be used from code that verifies they are available at runtime and
+  // can provide an alternative action if not - see supports_cx8() for
+  // a means to test availability.
+
   // Atomically store to a location
   inline static void store    (jbyte    store_value, jbyte*    dest);
   inline static void store    (jshort   store_value, jshort*   dest);
   inline static void store    (jint     store_value, jint*     dest);
+  // See comment above about using jlong atomics on 32-bit platforms
   inline static void store    (jlong    store_value, jlong*    dest);
   inline static void store_ptr(intptr_t store_value, intptr_t* dest);
   inline static void store_ptr(void*    store_value, void*     dest);
@@ -40,17 +47,19 @@
   inline static void store    (jbyte    store_value, volatile jbyte*    dest);
   inline static void store    (jshort   store_value, volatile jshort*   dest);
   inline static void store    (jint     store_value, volatile jint*     dest);
+  // See comment above about using jlong atomics on 32-bit platforms
   inline static void store    (jlong    store_value, volatile jlong*    dest);
   inline static void store_ptr(intptr_t store_value, volatile intptr_t* dest);
   inline static void store_ptr(void*    store_value, volatile void*     dest);
 
+  // See comment above about using jlong atomics on 32-bit platforms
   inline static jlong load(volatile jlong* src);
 
   // Atomically add to a location, return updated value
   inline static jint     add    (jint     add_value, volatile jint*     dest);
   inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest);
   inline static void*    add_ptr(intptr_t add_value, volatile void*     dest);
-
+  // See comment above about using jlong atomics on 32-bit platforms
          static jlong    add    (jlong    add_value, volatile jlong*    dest);
 
   // Atomically increment location
@@ -75,6 +84,7 @@
   // barrier across the cmpxchg.  I.e., it's really a 'fence_cmpxchg_acquire'.
          static jbyte    cmpxchg    (jbyte    exchange_value, volatile jbyte*    dest, jbyte    compare_value);
   inline static jint     cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value);
+  // See comment above about using jlong atomics on 32-bit platforms
   inline static jlong    cmpxchg    (jlong    exchange_value, volatile jlong*    dest, jlong    compare_value);
 
          static unsigned int cmpxchg(unsigned int exchange_value,
--- a/src/share/vm/runtime/basicLock.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/basicLock.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -63,7 +63,6 @@
  public:
   // Manipulation
   oop      obj() const                                { return _obj;  }
-  oop*     obj_addr()                                 { return &_obj; }
   void set_obj(oop obj)                               { _obj = obj; }
   BasicLock* lock()                                   { return &_lock; }
 
--- a/src/share/vm/runtime/compilationPolicy.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -60,7 +60,7 @@
     break;
 
   case 1:
-#if defined(COMPILER2)
+#ifdef COMPILER2
     CompilationPolicy::set_policy(new StackWalkCompPolicy());
 #else
     Unimplemented();
@@ -81,7 +81,7 @@
 #endif
     break;
   case 4:
-#if defined(GRAALVM)
+#ifdef GRAALVM
     CompilationPolicy::set_policy(new GraalCompPolicy());
 #else
     Unimplemented();
@@ -188,7 +188,6 @@
 #endif
 
 #ifdef COMPILER1
-  GRAALVM_ONLY(ShouldNotReachHere();)
   if (is_c1_compile(comp_level)) {
     return _compiler_count;
   } else {
@@ -212,7 +211,6 @@
 }
 
 void NonTieredCompPolicy::reset_counter_for_back_branch_event(methodHandle m) {
-//  GRAAL_ONLY(assert(false, "unexpected"));
   // Delay next back-branch event but pump up invocation counter to triger
   // whole method compilation.
   InvocationCounter* i = m->invocation_counter();
@@ -510,7 +508,7 @@
 
 // StackWalkCompPolicy - walk up stack to find a suitable method to compile
 
-#if defined(COMPILER2)
+#ifdef COMPILER2
 const char* StackWalkCompPolicy::_msg = NULL;
 
 
--- a/src/share/vm/runtime/compilationPolicy.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/compilationPolicy.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -126,7 +126,7 @@
 
 // StackWalkCompPolicy - existing C2 policy
 
-#if defined(COMPILER2)
+#ifdef COMPILER2
 class StackWalkCompPolicy : public NonTieredCompPolicy {
  public:
   virtual void method_invocation_event(methodHandle m, JavaThread* thread);
--- a/src/share/vm/runtime/deoptimization.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/deoptimization.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1312,24 +1312,14 @@
     
     if (TraceDeoptimization) {
       tty->print_cr("  bci=%d pc=%d, relative_pc=%d, method=%s", trap_scope->bci(), fr.pc(), fr.pc() - nm->code_begin(), trap_scope->method()->name()->as_C_string());
-#ifdef GRAAL
-      if (thread->graal_deopt_info() != NULL) {
-        oop deopt_info = thread->graal_deopt_info();
-        if (java_lang_String::is_instance(deopt_info)) {
-          char buf[O_BUFLEN];
-          java_lang_String::as_utf8_string(deopt_info, buf, O_BUFLEN);
-          tty->print_cr("deopt info: %s", buf);
-        } else {
-          tty->print_cr("deopt info:");
-          deopt_info->print();
-        }
-        thread->set_graal_deopt_info(NULL);
-      }
-#endif
     }
 
     methodHandle    trap_method = trap_scope->method();
     int             trap_bci    = trap_scope->bci();
+    if (trap_bci == SynchronizationEntryBCI) {
+      trap_bci = 0;
+      Thread::current()->set_pending_monitorenter(true);
+    }
     Bytecodes::Code trap_bc     = trap_method->java_code_at(trap_bci);
 
     if (trap_scope->rethrow_exception()) {
@@ -1339,7 +1329,7 @@
       GrowableArray<ScopeValue*>* expressions = trap_scope->expressions();
       guarantee(expressions != NULL, "must have exception to throw");
       ScopeValue* topOfStack = expressions->top();
-      Handle topOfStackObj = cvf->create_stack_value(topOfStack)->get_obj();
+      Handle topOfStackObj = StackValue::create_stack_value(&fr, &reg_map, topOfStack)->get_obj();
       THREAD->set_pending_exception(topOfStackObj(), NULL, 0);
     }
     
@@ -1637,7 +1627,7 @@
         if (trap_method() == nm->method()) {
           make_not_compilable = true;
         } else {
-          trap_method->set_not_compilable(CompLevel_full_optimization);
+          trap_method->set_not_compilable(CompLevel_full_optimization, true, "overflow_recompile_count > PerBytecodeRecompilationCutoff");
           // But give grace to the enclosing nm->method().
         }
       }
--- a/src/share/vm/runtime/deoptimization.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/deoptimization.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -37,7 +37,7 @@
   friend class VMStructs;
 
  public:
-  // What condition caused the deoptimization
+  // What condition caused the deoptimization?
   enum DeoptReason {
     Reason_many = -1,             // indicates presence of several reasons
     Reason_none = 0,              // indicates absence of a relevant deopt.
@@ -85,7 +85,7 @@
     // Note:  Reason_RECORDED_LIMIT should be < 8 to fit into 3 bits of
     // DataLayout::trap_bits.  This dependency is enforced indirectly
     // via asserts, to avoid excessive direct header-to-header dependencies.
-    // See Deoptimization::trap_state_reason and class DataLayout
+    // See Deoptimization::trap_state_reason and class DataLayout.
   };
 
   // What action must be taken by the runtime?
@@ -132,7 +132,7 @@
   // executing in a particular CodeBlob if UseBiasedLocking is enabled
   static void revoke_biases_of_monitors(CodeBlob* cb);
 
-//#ifdef COMPILER2
+#if defined(COMPILER2) || defined(GRAAL)
   // Support for restoring non-escaping objects
   static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS);
   static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);
@@ -140,7 +140,7 @@
   static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects);
   static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread);
   NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects);)
-//#endif // COMPILER2
+#endif // COMPILER2 || GRAAL
 
   public:
   static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk);
@@ -319,12 +319,11 @@
     assert((1 << _reason_bits) >= Reason_LIMIT, "enough bits");
     assert((1 << _action_bits) >= Action_LIMIT, "enough bits");
     int trap_request;
-    if (index != -1) {
+    if (index != -1)
       trap_request = index;
-    } else {
+    else
       trap_request = (~(((reason) << _reason_shift)
                         + ((action) << _action_shift)));
-    }
     assert(reason == trap_request_reason(trap_request), "valid reason");
     assert(action == trap_request_action(trap_request), "valid action");
     assert(index  == trap_request_index(trap_request),  "valid index");
--- a/src/share/vm/runtime/fieldDescriptor.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/fieldDescriptor.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,13 +67,10 @@
 
 AnnotationArray* fieldDescriptor::type_annotations() const {
   InstanceKlass* ik = field_holder();
-  Annotations* type_annos = ik->type_annotations();
+  Array<AnnotationArray*>* type_annos = ik->fields_type_annotations();
   if (type_annos == NULL)
     return NULL;
-  Array<AnnotationArray*>* md = type_annos->fields_annotations();
-  if (md == NULL)
-    return NULL;
-  return md->at(index());
+  return type_annos->at(index());
 }
 
 constantTag fieldDescriptor::initial_value_tag() const {
--- a/src/share/vm/runtime/fieldDescriptor.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/fieldDescriptor.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,10 +25,7 @@
 #ifndef SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP
 #define SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP
 
-#include "oops/annotations.hpp"
 #include "oops/constantPool.hpp"
-#include "oops/fieldInfo.hpp"
-#include "oops/instanceKlass.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/fieldType.hpp"
 #include "utilities/accessFlags.hpp"
--- a/src/share/vm/runtime/fprofiler.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/fprofiler.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_RUNTIME_FPROFILER_HPP
 #define SHARE_VM_RUNTIME_FPROFILER_HPP
 
+#include "utilities/macros.hpp"
 #include "runtime/timer.hpp"
 
 // a simple flat profiler for Java
--- a/src/share/vm/runtime/frame.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/frame.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -597,67 +597,44 @@
 void frame::interpreter_frame_print_on(outputStream* st) const {
 #ifndef PRODUCT
   assert(is_interpreted_frame(), "Not an interpreted frame");
-  assert(interpreter_frame_method() != NULL && interpreter_frame_method()->contains(interpreter_frame_bcp()), "must be");
   jint i;
-  st->print_cr(" - sp                                  = " INTPTR_FORMAT, sp());
-  // expressions
+  for (i = 0; i < interpreter_frame_method()->max_locals(); i++ ) {
+    intptr_t x = *interpreter_frame_local_at(i);
+    st->print(" - local  [" INTPTR_FORMAT "]", x);
+    st->fill_to(23);
+    st->print_cr("; #%d", i);
+  }
   for (i = interpreter_frame_expression_stack_size() - 1; i >= 0; --i ) {
-    intptr_t* x = interpreter_frame_expression_stack_at(i);
-    st->print(" - stack         at " INTPTR_FORMAT " = " INTPTR_FORMAT, x, *x);
-    st->fill_to(70);
+    intptr_t x = *interpreter_frame_expression_stack_at(i);
+    st->print(" - stack  [" INTPTR_FORMAT "]", x);
+    st->fill_to(23);
     st->print_cr("; #%d", i);
   }
   // locks for synchronization
-  st->print_cr(" - monitorend                          = " INTPTR_FORMAT, interpreter_frame_monitor_end());
   for (BasicObjectLock* current = interpreter_frame_monitor_end();
        current < interpreter_frame_monitor_begin();
        current = next_monitor_in_interpreter_frame(current)) {
-    st->print (" - lock          at " INTPTR_FORMAT " = ", current->lock());
+    st->print(" - obj    [");
+    current->obj()->print_value_on(st);
+    st->print_cr("]");
+    st->print(" - lock   [");
     current->lock()->print_on(st);
-    st->cr();
-    st->print (" - obj           at " INTPTR_FORMAT " = " INTPTR_FORMAT " ", current->obj_addr(), *current->obj_addr());
-    current->obj()->print_value_on(st);
-    st->cr();
+    st->print_cr("]");
   }
-  st->print_cr(" - monitorbegin                        = " INTPTR_FORMAT, interpreter_frame_monitor_begin());
-  
-  // bcp/bcx
-  st->print   (" - bcp           at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_bcx_addr(), interpreter_frame_bcp());
-  st->fill_to(70);
-  st->print_cr("; @%d - %s", interpreter_frame_bci(), Bytecodes::name(interpreter_frame_method()->code_at(interpreter_frame_bci())));
+  // monitor
+  st->print_cr(" - monitor[" INTPTR_FORMAT "]", interpreter_frame_monitor_begin());
+  // bcp
+  st->print(" - bcp    [" INTPTR_FORMAT "]", interpreter_frame_bcp());
+  st->fill_to(23);
+  st->print_cr("; @%d", interpreter_frame_bci());
   // locals
-  st->print_cr(" - locals        at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_locals_addr(), *interpreter_frame_locals_addr());
-  // constant pool cache
-  st->print_cr(" - constant pool at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_cache_addr(), *interpreter_frame_cache_addr());
-  // method data
-  st->print_cr(" - method data   at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_mdx_addr(), *interpreter_frame_mdx_addr());
+  st->print_cr(" - locals [" INTPTR_FORMAT "]", interpreter_frame_local_at(0));
   // method
-  st->print   (" - method        at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_method_addr(), *interpreter_frame_method_addr());
-  st->fill_to(70);
+  st->print(" - method [" INTPTR_FORMAT "]", (address)interpreter_frame_method());
+  st->fill_to(23);
   st->print("; ");
   interpreter_frame_method()->print_name(st);
   st->cr();
-#ifdef AMD64
-  // last sp
-  st->print_cr(" - last sp       at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_last_sp_addr(), *interpreter_frame_last_sp_addr());
-#endif
-  // sender sp
-  st->print_cr(" - sender sp     at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_sender_sp_addr(), *interpreter_frame_sender_sp_addr());
-  // old fp
-  st->print_cr(" - old fp        at " INTPTR_FORMAT " = " INTPTR_FORMAT, link_addr(), *link_addr());
-  // return address
-  st->print_cr(" - return pc     at " INTPTR_FORMAT " = " INTPTR_FORMAT, sender_pc_addr(), *sender_pc_addr());
-
-  // locals
-  for (i = interpreter_frame_method()->max_locals() - 1; i >= 0; i--) {
-    intptr_t* x = interpreter_frame_local_at(i);
-    st->print (" - local         at " INTPTR_FORMAT " = " INTPTR_FORMAT, x, *x);
-    st->fill_to(70);
-    st->print_cr("; #%d", i);
-  }
-
-  // fp
-  st->print_cr(" - fp                                  = " INTPTR_FORMAT, fp());
 #endif
 }
 
@@ -735,9 +712,8 @@
     } else if (_cb->is_nmethod()) {
       Method* m = ((nmethod *)_cb)->method();
       if (m != NULL) {
-        address code = _cb->code_begin();
         m->name_and_sig_as_C_string(buf, buflen);
-        st->print("J  %s [" PTR_FORMAT "+%d]", buf, code, pc() - code);
+        st->print("J  %s", buf);
       } else {
         st->print("J  " PTR_FORMAT, pc());
       }
--- a/src/share/vm/runtime/frame.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/frame.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -204,11 +204,9 @@
  public:
   // Link (i.e., the pointer to the previous frame)
   intptr_t* link() const;
-  intptr_t** link_addr() const;
   void set_link(intptr_t* addr);
 
   // Return address
-  address* sender_pc_addr() const;
   address  sender_pc() const;
 
   // Support for deoptimization
@@ -305,7 +303,6 @@
   jint  interpreter_frame_expression_stack_size() const;
 
   intptr_t* interpreter_frame_sender_sp() const;
-  intptr_t** interpreter_frame_sender_sp_addr() const;
 
 #ifndef CC_INTERP
   // template based interpreter deoptimization support
--- a/src/share/vm/runtime/globals.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/globals.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,10 +29,11 @@
 #include "runtime/globals.hpp"
 #include "runtime/globals_extension.hpp"
 #include "utilities/ostream.hpp"
+#include "utilities/macros.hpp"
 #include "utilities/top.hpp"
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1_globals.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
 #endif
@@ -71,7 +72,10 @@
 }
 
 bool Flag::is_unlocked() const {
-  if (strcmp(kind, "{diagnostic}") == 0) {
+  if (strcmp(kind, "{diagnostic}") == 0 ||
+      strcmp(kind, "{C2 diagnostic}") == 0 ||
+      strcmp(kind, "{ARCH diagnostic}") == 0 ||
+      strcmp(kind, "{Shark diagnostic}") == 0) {
     if (strcmp(name, "EnableInvokeDynamic") == 0 && UnlockExperimentalVMOptions && !UnlockDiagnosticVMOptions) {
       // transitional logic to allow tests to run until they are changed
       static int warned;
@@ -80,7 +84,9 @@
     }
     return UnlockDiagnosticVMOptions;
   } else if (strcmp(kind, "{experimental}") == 0 ||
-             strcmp(kind, "{C2 experimental}") == 0) {
+             strcmp(kind, "{C2 experimental}") == 0 ||
+             strcmp(kind, "{ARCH experimental}") == 0 ||
+             strcmp(kind, "{Shark experimental}") == 0) {
     return UnlockExperimentalVMOptions;
   } else {
     return is_unlocked_ext();
@@ -271,9 +277,9 @@
 static Flag flagTable[] = {
  RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT)
  RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT)
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
  G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
  C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT)
 #endif
--- a/src/share/vm/runtime/globals.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/globals.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1218,9 +1218,6 @@
   notproduct(bool, TraceJVMCalls, false,                                    \
           "Trace JVM calls")                                                \
                                                                             \
-  product(bool, TraceSignals, false,                                        \
-          "Trace signals and implicit exception handling")                  \
-                                                                            \
   product(ccstr, TraceJVMTI, NULL,                                          \
           "Trace flags for JVMTI functions and events")                     \
                                                                             \
@@ -1252,7 +1249,7 @@
   develop(bool, TraceClassInitialization, false,                            \
           "Trace class initialization")                                     \
                                                                             \
-  product(bool, TraceExceptions, false,                                     \
+  develop(bool, TraceExceptions, false,                                     \
           "Trace exceptions")                                               \
                                                                             \
   develop(bool, TraceICs, false,                                            \
@@ -1822,7 +1819,7 @@
   product(bool, ParallelRefProcBalancingEnabled, true,                      \
           "Enable balancing of reference processing queues")                \
                                                                             \
-  product(intx, CMSTriggerRatio, 80,                                        \
+  product(uintx, CMSTriggerRatio, 80,                                       \
           "Percentage of MinHeapFreeRatio in CMS generation that is "       \
           "allocated before a CMS collection cycle commences")              \
                                                                             \
@@ -1836,7 +1833,7 @@
                                                                             \
   product(uintx, InitiatingHeapOccupancyPercent, 45,                        \
           "Percentage of the (entire) heap occupancy to start a "           \
-          "concurrent GC cycle. It us used by GCs that trigger a "          \
+          "concurrent GC cycle. It is used by GCs that trigger a "          \
           "concurrent GC cycle based on the occupancy of the entire heap, " \
           "not just one of the generations (e.g., G1). A value of 0 "       \
           "denotes 'do constant GC cycles'.")                               \
@@ -2621,9 +2618,6 @@
   diagnostic(bool, PrintInterpreter, false,                                 \
           "Prints the generated interpreter code")                          \
                                                                             \
-  product(bool, PrintMachineCodeToFile, false,                              \
-          "Prints the generated machine code to a file (int + comp)")       \
-                                                                            \
   product(bool, UseInterpreter, true,                                       \
           "Use interpreter for non-compiled methods")                       \
                                                                             \
@@ -3003,10 +2997,10 @@
   product(uintx, TLABWasteIncrement,    4,                                  \
           "Increment allowed waste at slow allocation")                     \
                                                                             \
-  product(intx, SurvivorRatio, 8,                                           \
+  product(uintx, SurvivorRatio, 8,                                          \
           "Ratio of eden/survivor space size")                              \
                                                                             \
-  product(intx, NewRatio, 2,                                                \
+  product(uintx, NewRatio, 2,                                               \
           "Ratio of new/old generation sizes")                              \
                                                                             \
   product_pd(uintx, NewSizeThreadIncrease,                                  \
@@ -3036,10 +3030,16 @@
           "Min change in heap space due to GC (in bytes)")                  \
                                                                             \
   product(uintx, MinMetaspaceExpansion, ScaleForWordSize(256*K),            \
-          "Min expansion of permanent heap (in bytes)")                     \
+          "Min expansion of Metaspace (in bytes)")                          \
+                                                                            \
+  product(uintx, MinMetaspaceFreeRatio,    40,                              \
+          "Min percentage of Metaspace free after GC to avoid expansion")   \
+                                                                            \
+  product(uintx, MaxMetaspaceFreeRatio,    70,                              \
+          "Max percentage of Metaspace free after GC to avoid shrinking")   \
                                                                             \
   product(uintx, MaxMetaspaceExpansion, ScaleForWordSize(4*M),              \
-          "Max expansion of permanent heap without full GC (in bytes)")     \
+          "Max expansion of Metaspace without full GC (in bytes)")          \
                                                                             \
   product(intx, QueuedAllocationWarningCount, 0,                            \
           "Number of times an allocation that queues behind a GC "          \
@@ -3057,7 +3057,7 @@
   product(uintx, InitialTenuringThreshold,    7,                            \
           "Initial value for tenuring threshold")                           \
                                                                             \
-  product(intx, TargetSurvivorRatio,    50,                                 \
+  product(uintx, TargetSurvivorRatio,    50,                                \
           "Desired percentage of survivor space used after scavenge")       \
                                                                             \
   product(uintx, MarkSweepDeadRatio,     5,                                 \
@@ -3588,7 +3588,7 @@
   product(uintx, SharedDummyBlockSize, 0,                                   \
           "Size of dummy block used to shift heap addresses (in bytes)")    \
                                                                             \
-  diagnostic(bool, EnableInvokeDynamic, false,                              \
+  diagnostic(bool, EnableInvokeDynamic, true,                               \
           "support JSR 292 (method handles, invokedynamic, "                \
           "anonymous classes")                                              \
                                                                             \
--- a/src/share/vm/runtime/globals_extension.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/globals_extension.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -26,6 +26,7 @@
 #define SHARE_VM_RUNTIME_GLOBALS_EXTENSION_HPP
 
 #include "runtime/globals.hpp"
+#include "utilities/macros.hpp"
 #include "utilities/top.hpp"
 
 // Construct enum of Flag_<cmdline-arg> constants.
@@ -106,9 +107,9 @@
 typedef enum {
  RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER, RUNTIME_LP64_PRODUCT_FLAG_MEMBER)
  RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER)
-#if INCLUDE_ALTERNATE_GCS
+#if INCLUDE_ALL_GCS
  G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER)
-#endif // INCLUDE_ALTERNATE_GCS
+#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
  C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, C1_PD_DEVELOP_FLAG_MEMBER, C1_PRODUCT_FLAG_MEMBER, C1_PD_PRODUCT_FLAG_MEMBER, C1_NOTPRODUCT_FLAG_MEMBER)
 #endif
@@ -213,7 +214,7 @@
                   RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
                   RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
                   RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE)
-#if INCLUDE_ALTERNATE_GCS
+#if INCLUDE_ALL_GCS
  G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE,
           RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
           RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE,
@@ -223,7 +224,7 @@
           RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
           RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE,
           RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE)
-#endif // INCLUDE_ALTERNATE_GCS
+#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
  C1_FLAGS(C1_DEVELOP_FLAG_MEMBER_WITH_TYPE,
           C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
--- a/src/share/vm/runtime/init.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/init.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -34,7 +34,7 @@
 #include "runtime/init.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/sharedRuntime.hpp"
-#include "utilities/machineCodePrinter.hpp"
+#include "utilities/macros.hpp"
 
 // Initialization done by VM thread in vm_init_globals()
 void check_ThreadShadow();
@@ -87,10 +87,6 @@
   mutex_init();
   chunkpool_init();
   perfMemory_init();
-
-  if(PrintMachineCodeToFile) {
-    MachineCodePrinter::initialize();
-  }
 }
 
 
--- a/src/share/vm/runtime/java.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/java.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -67,6 +67,7 @@
 #include "utilities/dtrace.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/histogram.hpp"
+#include "utilities/macros.hpp"
 #include "utilities/vmError.hpp"
 #ifdef TARGET_ARCH_x86
 # include "vm_version_x86.hpp"
@@ -83,11 +84,11 @@
 #ifdef TARGET_ARCH_ppc
 # include "vm_version_ppc.hpp"
 #endif
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_Compiler.hpp"
 #include "c1/c1_Runtime1.hpp"
@@ -248,13 +249,10 @@
     Runtime1::print_statistics();
     Deoptimization::print_statistics();
     SharedRuntime::print_statistics();
+    nmethod::print_statistics();
   }
 #endif /* COMPILER1 */
 
-  if(PrintNMethodStatistics) {
-    nmethod::print_statistics();
-  }
-
 #ifdef COMPILER2
   if ((PrintOptoStatistics || LogVMOutput || LogCompilation) && UseCompiler) {
     FlagSetting fs(DisplayVMOutput, DisplayVMOutput && PrintOptoStatistics);
@@ -375,10 +373,6 @@
     CompileBroker::print_times();
   }
 
-  if(PrintNMethodStatistics) {
-    nmethod::print_statistics();
-  }
-
   if (PrintCodeCache) {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     CodeCache::print();
--- a/src/share/vm/runtime/javaCalls.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/javaCalls.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -39,21 +39,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/stubRoutines.hpp"
-#ifdef HIGH_LEVEL_INTERPRETER
-# include "graal/graalVMToInterpreter.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_linux
-# include "thread_linux.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_solaris
-# include "thread_solaris.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_windows
-# include "thread_windows.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_bsd
-# include "thread_bsd.inline.hpp"
-#endif
+#include "runtime/thread.inline.hpp"
 
 // -----------------------------------------------------
 // Implementation of JavaCallWrapper
@@ -335,19 +321,10 @@
   assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls");
   // Need to wrap each and everytime, since there might be native code down the
   // stack that has installed its own exception handlers
-  os::os_exception_wrapper(call_helper, result, &method, NULL, args, THREAD);
+  os::os_exception_wrapper(call_helper, result, &method, args, THREAD);
 }
 
-void JavaCalls::call(JavaValue* result, methodHandle method, nmethod* nm, JavaCallArguments* args, TRAPS) {
-  // Check if we need to wrap a potential OS exception handler around thread
-  // This is used for e.g. Win32 structured exception handlers
-  assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls");
-  // Need to wrap each and everytime, since there might be native code down the
-  // stack that has installed its own exception handlers
-  os::os_exception_wrapper(call_helper, result, &method, nm, args, THREAD);
-}
-
-void JavaCalls::call_helper(JavaValue* result, methodHandle* m, nmethod* nm, JavaCallArguments* args, TRAPS) {
+void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) {
   methodHandle method = *m;
   JavaThread* thread = (JavaThread*)THREAD;
   assert(thread->is_Java_thread(), "must be called by a java thread");
@@ -373,6 +350,7 @@
   }
 #endif
 
+
 #ifdef ASSERT
   { InstanceKlass* holder = method->method_holder();
     // A klass might not be initialized since JavaCall's might be used during the executing of
@@ -427,26 +405,18 @@
     os::bang_stack_shadow_pages();
   }
 
+#ifdef GRAAL
+  nmethod* nm = args->alternative_target();
   if (nm != NULL) {
-#ifdef GRAAL
     if (nm->is_alive()) {
       ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->verified_entry_point());
       entry_point = method->adapter()->get_i2c_entry();
     } else {
       THROW(vmSymbols::MethodInvalidatedException());
     }
-#else
-    ShouldNotReachHere();
+  }
 #endif
-  }
   
-#ifdef HIGH_LEVEL_INTERPRETER
-  if (thread->high_level_interpreter_in_vm() && !method->is_native() && Interpreter::contains(entry_point)) {
-    assert(nm == NULL || !nm->is_alive(), "otherwise nm should be invoked");
-    VMToInterpreter::execute(result, m, args, result->get_type(), thread);
-    oop_result_flag = false; // result already holds the correct value
-  } else
-#endif
   // do call
   { JavaCallWrapper link(method, receiver, result, CHECK);
     { HandleMark hm(thread);  // HandleMark used by HandleMarkCleaner
@@ -482,6 +452,7 @@
   }
 }
 
+
 //--------------------------------------------------------------------------------------
 // Implementation of JavaCallArguments
 
--- a/src/share/vm/runtime/javaCalls.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/javaCalls.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -98,6 +98,9 @@
   int         _size;
   int         _max_size;
   bool        _start_at_zero;      // Support late setting of receiver
+#ifdef GRAAL
+  nmethod*    _alternative_target; // Nmethod that should be called instead of normal target
+#endif
 
   void initialize() {
     // Starts at first element to support set_receiver.
@@ -107,6 +110,7 @@
     _max_size = _default_size;
     _size = 0;
     _start_at_zero = false;
+    GRAAL_ONLY(_alternative_target = NULL;)
   }
 
  public:
@@ -128,11 +132,22 @@
       _max_size = max_size;
       _size = 0;
       _start_at_zero = false;
+      GRAAL_ONLY(_alternative_target = NULL;)
     } else {
       initialize();
     }
   }
 
+#ifdef GRAAL
+  void set_alternative_target(nmethod* target) {
+    _alternative_target = target;
+  }
+
+  nmethod* alternative_target() {
+    return _alternative_target;
+  }
+#endif
+
   inline void push_oop(Handle h)    { _is_oop[_size] = true;
                                JNITypes::put_obj((oop)h.raw_value(), _value, _size); }
 
@@ -148,12 +163,6 @@
   inline void push_float(float f)   { _is_oop[_size] = false;
                                JNITypes::put_float(f, _value, _size); }
 
-  inline oop* get_raw_oop(int& pos)   { return (oop*)JNITypes::get_obj(_value, pos); }
-  inline jint get_int(int& pos)       { return JNITypes::get_int(_value, pos); }
-  inline jdouble get_double(int& pos) { return JNITypes::get_double(_value, pos); }
-  inline jlong get_long(int& pos)     { return JNITypes::get_long(_value, pos); }
-  inline jfloat get_float(int& pos)   { return JNITypes::get_float(_value, pos); }
-
   // receiver
   Handle receiver() {
     assert(_size > 0, "must at least be one argument");
@@ -185,8 +194,8 @@
 //
 
 class JavaCalls: AllStatic {
-  static void call_helper(JavaValue* result, methodHandle* method, nmethod* nm, JavaCallArguments* args, TRAPS);
-public:
+  static void call_helper(JavaValue* result, methodHandle* method, JavaCallArguments* args, TRAPS);
+ public:
   // Optimized Constuctor call
   static void call_default_constructor(JavaThread* thread, methodHandle method, Handle receiver, TRAPS);
 
@@ -225,7 +234,6 @@
 
   // Low-level interface
   static void call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS);
-  static void call(JavaValue* result, methodHandle method, nmethod* nm, JavaCallArguments* args, TRAPS);
 };
 
 #endif // SHARE_VM_RUNTIME_JAVACALLS_HPP
--- a/src/share/vm/runtime/os.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/os.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -985,15 +985,28 @@
 // if C stack is walkable beyond current frame. The check for fp() is not
 // necessary on Sparc, but it's harmless.
 bool os::is_first_C_frame(frame* fr) {
-#ifdef IA64
-  // In order to walk native frames on Itanium, we need to access the unwind
-  // table, which is inside ELF. We don't want to parse ELF after fatal error,
-  // so return true for IA64. If we need to support C stack walking on IA64,
-  // this function needs to be moved to CPU specific files, as fp() on IA64
-  // is register stack, which grows towards higher memory address.
+#if defined(IA64) && !defined(_WIN32)
+  // On IA64 we have to check if the callers bsp is still valid
+  // (i.e. within the register stack bounds).
+  // Notice: this only works for threads created by the VM and only if
+  // we walk the current stack!!! If we want to be able to walk
+  // arbitrary other threads, we'll have to somehow store the thread
+  // object in the frame.
+  Thread *thread = Thread::current();
+  if ((address)fr->fp() <=
+      thread->register_stack_base() HPUX_ONLY(+ 0x0) LINUX_ONLY(+ 0x50)) {
+    // This check is a little hacky, because on Linux the first C
+    // frame's ('start_thread') register stack frame starts at
+    // "register_stack_base + 0x48" while on HPUX, the first C frame's
+    // ('__pthread_bound_body') register stack frame seems to really
+    // start at "register_stack_base".
+    return true;
+  } else {
+    return false;
+  }
+#elif defined(IA64) && defined(_WIN32)
   return true;
-#endif
-
+#else
   // Load up sp, fp, sender sp and sender fp, check for reasonable values.
   // Check usp first, because if that's bad the other accessors may fault
   // on some architectures.  Ditto ufp second, etc.
@@ -1023,6 +1036,7 @@
   if (old_fp - ufp > 64 * K) return true;
 
   return false;
+#endif
 }
 
 #ifdef ASSERT
@@ -1135,6 +1149,9 @@
 #ifdef __APPLE__
         "%/lib/JObjC.jar:"
 #endif
+#ifdef GRAAL
+        "%/lib/graal.jar:"
+#endif
         "%/classes";
     char* sysclasspath = format_boot_path(classpath_format, home, home_len, fileSep, pathSep);
     if (sysclasspath == NULL) return false;
--- a/src/share/vm/runtime/os.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/os.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -79,7 +79,7 @@
 };
 
 // Typedef for structured exception handling support
-typedef void (*java_call_t)(JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread);
+typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
 
 class os: AllStatic {
  public:
@@ -658,7 +658,7 @@
   static void init_random(long initval);   // initialize random sequence
 
   // Structured OS Exception support
-  static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread);
+  static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
 
   // On Windows this will create an actual minidump, on Linux/Solaris it will simply check core dump limits
   static void check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize);
--- a/src/share/vm/runtime/reflectionUtils.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/reflectionUtils.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -26,9 +26,6 @@
 #include "classfile/javaClasses.hpp"
 #include "memory/universe.inline.hpp"
 #include "runtime/reflectionUtils.hpp"
-#ifdef GRAAL
-#include "graal/graalJavaAccess.hpp"
-#endif
 
 KlassStream::KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only) {
   _klass = klass;
--- a/src/share/vm/runtime/safepoint.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/safepoint.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -52,6 +52,7 @@
 #include "services/memTracker.hpp"
 #include "services/runtimeService.hpp"
 #include "utilities/events.hpp"
+#include "utilities/macros.hpp"
 #ifdef TARGET_ARCH_x86
 # include "nativeInst_x86.hpp"
 # include "vmreg_x86.inline.hpp"
@@ -72,16 +73,13 @@
 # include "nativeInst_ppc.hpp"
 # include "vmreg_ppc.inline.hpp"
 #endif
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
 #include "gc_implementation/shared/concurrentGCThread.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
 #endif
-#ifdef GRAAL
-#include "graal/graalGlobals.hpp"
-#endif
 
 // --------------------------------------------------------------------------------------------------
 // Implementation of Safepoint begin/end
@@ -106,7 +104,7 @@
     _ts_of_current_safepoint = tty->time_stamp().seconds();
   }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   if (UseConcMarkSweepGC) {
     // In the future we should investigate whether CMS can use the
     // more-general mechanism below.  DLD (01/05).
@@ -114,7 +112,7 @@
   } else if (UseG1GC) {
     ConcurrentGCThread::safepoint_synchronize();
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // By getting the Threads_lock, we assure that no threads are about to start or
   // exit. It is released again in SafepointSynchronize::end().
@@ -483,14 +481,14 @@
     Threads_lock->unlock();
 
   }
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // If there are any concurrent GC threads resume them.
   if (UseConcMarkSweepGC) {
     ConcurrentMarkSweepThread::desynchronize(false);
   } else if (UseG1GC) {
     ConcurrentGCThread::safepoint_desynchronize();
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
   // record this time so VMThread can keep track how much time has elasped
   // since last safepoint.
   _end_of_last_safepoint = os::javaTimeMillis();
--- a/src/share/vm/runtime/sharedRuntime.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -56,6 +56,7 @@
 #include "utilities/dtrace.hpp"
 #include "utilities/events.hpp"
 #include "utilities/hashtable.inline.hpp"
+#include "utilities/macros.hpp"
 #include "utilities/xmlstream.hpp"
 #ifdef TARGET_ARCH_x86
 # include "nativeInst_x86.hpp"
@@ -212,7 +213,7 @@
 }
 #endif // PRODUCT
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 
 // G1 write-barrier pre: executed before a pointer store.
 JRT_LEAF(void, SharedRuntime::g1_wb_pre(oopDesc* orig, JavaThread *thread))
@@ -230,7 +231,7 @@
   thread->dirty_card_queue().enqueue(card_addr);
 JRT_END
 
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 
 JRT_LEAF(jlong, SharedRuntime::lmul(jlong y, jlong x))
@@ -772,11 +773,8 @@
 #ifdef GRAAL
 address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason) {
   assert(deopt_reason > Deoptimization::Reason_none && deopt_reason < Deoptimization::Reason_LIMIT, "invalid deopt reason");
-  if (TraceSignals) {
-    tty->print_cr(err_msg("Deoptimizing on implicit exception at relative pc=%d in method %s", pc - nm->entry_point(), nm->method()->name()->as_C_string()));
-  }
   thread->_ScratchA = (intptr_t)pc;
-  thread->_ScratchB = Deoptimization::make_trap_request((Deoptimization::DeoptReason)deopt_reason, Deoptimization::Action_reinterpret);
+  thread->set_pending_deoptimization(Deoptimization::make_trap_request((Deoptimization::DeoptReason)deopt_reason, Deoptimization::Action_reinterpret));
   return (SharedRuntime::deopt_blob()->implicit_exception_uncommon_trap());
 }
 #endif
@@ -898,9 +896,6 @@
 #endif
 #ifdef GRAAL
         if (nm->is_compiled_by_graal()) {
-          if (TraceSignals) {
-            tty->print_cr("Graal implicit div0");
-          }
           target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check);
         } else {
 #endif
@@ -2868,10 +2863,6 @@
 
 JRT_LEAF(intptr_t*, SharedRuntime::OSR_migration_begin( JavaThread *thread) )
 
-#ifdef IA64
-  ShouldNotReachHere(); // NYI
-#endif /* IA64 */
-
   //
   // This code is dependent on the memory layout of the interpreter local
   // array and the monitors. On all of our platforms the layout is identical
--- a/src/share/vm/runtime/sharedRuntime.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -32,6 +32,7 @@
 #include "memory/resourceArea.hpp"
 #include "runtime/threadLocalStorage.hpp"
 #include "utilities/hashtable.hpp"
+#include "utilities/macros.hpp"
 
 class AdapterHandlerEntry;
 class AdapterHandlerTable;
@@ -168,11 +169,11 @@
   static address raw_exception_handler_for_return_address(JavaThread* thread, address return_address);
   static address exception_handler_for_return_address(JavaThread* thread, address return_address);
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // G1 write barriers
   static void g1_wb_pre(oopDesc* orig, JavaThread *thread);
   static void g1_wb_post(void* card_addr, JavaThread* thread);
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // exception handling and implicit exceptions
   static address compute_compiled_exc_handler(nmethod* nm, address ret_pc, Handle& exception,
--- a/src/share/vm/runtime/stackValue.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/stackValue.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -118,22 +118,6 @@
          val = (oop)NULL;
       }
 #endif
-#ifndef PRODUCT
-      if (val != NULL && !val->is_oop()) {
-        ResourceMark rm;
-        tty->print_cr("found wrong oop " INTPTR_FORMAT " at location " INTPTR_FORMAT " (%d):", val, value_addr, val->is_oop());
-        if (fr->cb() != NULL) {
-          CodeBlob* cb = fr->cb();
-          if (cb->is_nmethod()) {
-            nmethod* nm = (nmethod*)cb;
-            tty->print_cr("method is %s", nm->method()->name()->as_C_string());
-          }
-        }
-        sv->print();
-        tty->print_cr("");
-        tty->print_cr("one less %d; one more %d", (*(((oop *)value_addr) - 1))->is_oop(), (*(((oop *)value_addr) + 1))->is_oop());
-      }
-#endif
       Handle h(val); // Wrap a handle around the oop
       return new StackValue(h);
     }
--- a/src/share/vm/runtime/synchronizer.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/synchronizer.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -53,7 +53,7 @@
 # include "os_bsd.inline.hpp"
 #endif
 
-#if defined(__GNUC__) && !defined(IA64)
+#if defined(__GNUC__)
   // Need to inhibit inlining for older versions of GCC to avoid build-time failures
   #define ATTR __attribute__((noinline))
 #else
--- a/src/share/vm/runtime/thread.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/thread.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -85,6 +85,7 @@
 #include "utilities/dtrace.hpp"
 #include "utilities/events.hpp"
 #include "utilities/preserveException.hpp"
+#include "utilities/macros.hpp"
 #ifdef TARGET_OS_FAMILY_linux
 # include "os_linux.inline.hpp"
 #endif
@@ -97,11 +98,11 @@
 #ifdef TARGET_OS_FAMILY_bsd
 # include "os_bsd.inline.hpp"
 #endif
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
 #include "gc_implementation/parallelScavenge/pcTasks.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_Compiler.hpp"
 #endif
@@ -1409,7 +1410,6 @@
   // Set the claimed par_id to -1 (ie not claiming any par_ids)
   set_claimed_par_id(-1);
   
-  _env   = NULL;
   _buffer_blob = NULL;
   set_saved_exception_pc(NULL);
   set_threadObj(NULL);
@@ -1439,12 +1439,7 @@
   _doing_unsafe_access = false;
   _stack_guard_state = stack_guard_unused;
 #ifdef GRAAL
-  _graal_deopt_info = NULL;
   _graal_alternate_call_target = NULL;
-  _debug_scope = NULL;
-#endif
-#ifdef HIGH_LEVEL_INTERPRETER
-  _high_level_interpreter_in_vm = false;
 #endif
   _exception_oop = NULL;
   _exception_pc  = 0;
@@ -1496,17 +1491,17 @@
   pd_initialize();
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 SATBMarkQueueSet JavaThread::_satb_mark_queue_set;
 DirtyCardQueueSet JavaThread::_dirty_card_queue_set;
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 JavaThread::JavaThread(bool is_attaching_via_jni) :
   Thread()
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   , _satb_mark_queue(&_satb_mark_queue_set),
   _dirty_card_queue(&_dirty_card_queue_set)
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 {
   initialize();
   if (is_attaching_via_jni) {
@@ -1514,7 +1509,7 @@
   } else {
     _jni_attach_state = _not_attaching_via_jni;
   }
-  assert(_deferred_card_mark.is_empty(), "Default MemRegion ctor");
+  assert(deferred_card_mark().is_empty(), "Default MemRegion ctor");
   _safepoint_visible = false;
 }
 
@@ -1561,10 +1556,10 @@
 
 JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
   Thread()
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   , _satb_mark_queue(&_satb_mark_queue_set),
   _dirty_card_queue(&_dirty_card_queue_set)
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 {
   if (TraceThreadEvents) {
     tty->print_cr("creating thread %p", this);
@@ -1910,19 +1905,26 @@
     JvmtiExport::cleanup_thread(this);
   }
 
-#ifndef SERIALGC
-  // We must flush G1-related buffers before removing a thread from
+  // We must flush any deferred card marks before removing a thread from
   // the list of active threads.
+  Universe::heap()->flush_deferred_store_barrier(this);
+  assert(deferred_card_mark().is_empty(), "Should have been flushed");
+
+#if INCLUDE_ALL_GCS
+  // We must flush the G1-related buffers before removing a thread
+  // from the list of active threads. We must do this after any deferred
+  // card marks have been flushed (above) so that any entries that are
+  // added to the thread's dirty card queue as a result are not lost.
   if (UseG1GC) {
     flush_barrier_queues();
   }
-#endif
+#endif // INCLUDE_ALL_GCS
 
   // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread
   Threads::remove(this);
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 // Flush G1-related queues.
 void JavaThread::flush_barrier_queues() {
   satb_mark_queue().flush();
@@ -1950,7 +1952,7 @@
   // active field set to true.
   assert(dirty_queue.is_active(), "dirty card queue should be active");
 }
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 void JavaThread::cleanup_failed_attach_current_thread() {
   if (get_thread_profiler() != NULL) {
@@ -1978,11 +1980,11 @@
     tlab().make_parsable(true);  // retire TLAB, if any
   }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   if (UseG1GC) {
     flush_barrier_queues();
   }
-#endif
+#endif // INCLUDE_ALL_GCS
 
   Threads::remove(this);
   delete this;
@@ -2187,9 +2189,7 @@
 
   // Do not throw asynchronous exceptions against the compiler thread
   // (the compiler thread should not be a Java thread -- fix in 1.4.2)
-
-  // (thomaswue) May we do this?
-  //if (is_Compiler_thread()) return;
+  if (is_Compiler_thread()) return;
 
   {
     // Actually throw the Throwable against the target Thread - however
@@ -2776,9 +2776,6 @@
   // around using this function
   f->do_oop((oop*) &_threadObj);
   f->do_oop((oop*) &_vm_result);
-#ifdef GRAAL
-  f->do_oop((oop*) &_graal_deopt_info);
-#endif
   f->do_oop((oop*) &_exception_oop);
   f->do_oop((oop*) &_pending_async_exception);
 
@@ -3236,6 +3233,7 @@
 // Create a CompilerThread
 CompilerThread::CompilerThread(CompileQueue* queue, CompilerCounters* counters)
 : JavaThread(&compiler_thread_entry) {
+  _env   = NULL;
   _log   = NULL;
   _task  = NULL;
   _queue = queue;
@@ -3613,7 +3611,7 @@
     vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
   }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // Support for ConcurrentMarkSweep. This should be cleaned up
   // and better encapsulated. The ugly nested if test would go away
   // once things are properly refactored. XXX YSR
@@ -3627,7 +3625,7 @@
       vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
     }
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // Always call even when there are not JVMTI environments yet, since environments
   // may be attached late and JVMTI must track phases of VM execution
@@ -3752,28 +3750,6 @@
                              name)) {
         library = os::dll_load(buffer, ebuf, sizeof ebuf);
       }
-#ifdef KERNEL
-      // Download instrument dll
-      if (library == NULL && strcmp(name, "instrument") == 0) {
-        char *props = Arguments::get_kernel_properties();
-        char *home  = Arguments::get_java_home();
-        const char *fmt   = "%s/bin/java %s -Dkernel.background.download=false"
-                      " sun.jkernel.DownloadManager -download client_jvm";
-        size_t length = strlen(props) + strlen(home) + strlen(fmt) + 1;
-        char *cmd = NEW_C_HEAP_ARRAY(char, length, mtThread);
-        jio_snprintf(cmd, length, fmt, home, props);
-        int status = os::fork_and_exec(cmd);
-        FreeHeap(props);
-        if (status == -1) {
-          warning(cmd);
-          vm_exit_during_initialization("fork_and_exec failed: %s",
-                                         strerror(errno));
-        }
-        FREE_C_HEAP_ARRAY(char, cmd, mtThread);
-        // when this comes back the instrument.dll should be where it belongs.
-        library = os::dll_load(buffer, ebuf, sizeof ebuf);
-      }
-#endif // KERNEL
       if (library == NULL) { // Try the local directory
         char ns[1] = {0};
         if (os::dll_build_name(buffer, sizeof(buffer), ns, name)) {
@@ -4222,7 +4198,7 @@
   }
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 // Used by ParallelScavenge
 void Threads::create_thread_roots_tasks(GCTaskQueue* q) {
   ALL_JAVA_THREADS(p) {
@@ -4238,7 +4214,7 @@
   }
   q->enqueue(new ThreadRootsMarkingTask(VMThread::vm_thread()));
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 void Threads::nmethods_do(CodeBlobClosure* cf) {
   ALL_JAVA_THREADS(p) {
@@ -4346,13 +4322,13 @@
                );
   st->cr();
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // Dump concurrent locks
   ConcurrentLocksDump concurrent_locks;
   if (print_concurrent_locks) {
     concurrent_locks.dump_at_safepoint();
   }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   ALL_JAVA_THREADS(p) {
     ResourceMark rm;
@@ -4365,11 +4341,11 @@
       }
     }
     st->cr();
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     if (print_concurrent_locks) {
       concurrent_locks.print_locks_on(p, st);
     }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
   }
 
   VMThread::vm_thread()->print_on(st);
--- a/src/share/vm/runtime/thread.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/thread.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -41,6 +41,7 @@
 #include "runtime/stubRoutines.hpp"
 #include "runtime/threadLocalStorage.hpp"
 #include "runtime/unhandledOops.hpp"
+#include "utilities/macros.hpp"
 
 #if INCLUDE_NMT
 #include "services/memRecorder.hpp"
@@ -49,10 +50,10 @@
 #include "trace/tracing.hpp"
 #include "utilities/exceptions.hpp"
 #include "utilities/top.hpp"
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/dirtyCardQueue.hpp"
 #include "gc_implementation/g1/satbQueue.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 #ifdef ZERO
 #ifdef TARGET_ARCH_zero
 # include "stack_zero.hpp"
@@ -768,13 +769,10 @@
   JavaThread*    _next;                          // The next thread in the Threads list
   oop            _threadObj;                     // The Java level thread object
 
-  // (thomaswue) Necessary for holding a compilation buffer and ci environment.
+  // (thomaswue) Necessary for holding a compilation buffer.
   // Moved up from CompilerThread to JavaThread in order to enable code
   // installation from Java application code.
   BufferBlob*   _buffer_blob;
-  ciEnv*        _env;
-  bool          _is_compiling;
-
 #ifdef ASSERT
  private:
   int _java_call_counter;
@@ -903,14 +901,8 @@
  private:
 
 #ifdef GRAAL
-  volatile oop _graal_deopt_info;
   address _graal_alternate_call_target;
-  DebugScopedValue* _debug_scope;
 #endif
-#ifdef HIGH_LEVEL_INTERPRETER
-  bool _high_level_interpreter_in_vm;
-#endif
-
   StackGuardState        _stack_guard_state;
 
   nmethod*      _scanned_nmethod;  // nmethod being scanned by the sweeper
@@ -923,6 +915,9 @@
   volatile address _exception_handler_pc;        // PC for handler of exception
   volatile int     _is_method_handle_return;     // true (== 1) if the current exception PC is a MethodHandle call site.
 
+  // support for compilation
+  bool    _is_compiling;                         // is true if a compilation is active inthis thread (one compilation per thread possible)
+
   // support for JNI critical regions
   jint    _jni_active_critical;                  // count of entries into JNI critical region
 
@@ -944,7 +939,7 @@
   }   _jmp_ring[ jump_ring_buffer_size ];
 #endif /* PRODUCT */
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // Support for G1 barriers
 
   ObjPtrQueue _satb_mark_queue;          // Thread-local log for SATB barrier.
@@ -956,7 +951,7 @@
   static DirtyCardQueueSet _dirty_card_queue_set;
 
   void flush_barrier_queues();
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   friend class VMThread;
   friend class ThreadWaitTransition;
@@ -982,13 +977,7 @@
   struct JNINativeInterface_* get_jni_functions() {
     return (struct JNINativeInterface_ *)_jni_environment.functions;
   }
-  
-  bool is_compiling() const                      { return _is_compiling; }
-  void set_compiling(bool b)                     { _is_compiling = b; }
 
-  // Get/set the thread's compilation environment.
-  ciEnv*        env()                            { return _env; }
-  void          set_env(ciEnv* env)              { _env = env; }
 
   BufferBlob*   get_buffer_blob()                { return _buffer_blob; }
   void          set_buffer_blob(BufferBlob* b)   { _buffer_blob = b; };
@@ -1018,6 +1007,10 @@
   // Testers
   virtual bool is_Java_thread() const            { return true;  }
 
+  // compilation
+  void set_is_compiling(bool f)                  { _is_compiling = f; }
+  bool is_compiling() const                      { return _is_compiling; }
+
   // Thread chain operations
   JavaThread* next() const                       { return _next; }
   void set_next(JavaThread* p)                   { _next = p; }
@@ -1282,17 +1275,7 @@
   void set_deferred_card_mark(MemRegion mr)      { _deferred_card_mark = mr;   }
 
 #ifdef GRAAL
-  oop      graal_deopt_info() const              { return _graal_deopt_info; }
-  void set_graal_deopt_info(oop o)               { _graal_deopt_info = o; }
-  
   void set_graal_alternate_call_target(address a) { _graal_alternate_call_target = a; }
-
-  DebugScopedValue* debug_scope() const                { return _debug_scope; }
-  void set_debug_scope(DebugScopedValue* ds)           { _debug_scope = ds; }
-#endif
-#ifdef HIGH_LEVEL_INTERPRETER
-  bool high_level_interpreter_in_vm()            { return _high_level_interpreter_in_vm; }
-  void set_high_level_interpreter_in_vm(bool value) { _high_level_interpreter_in_vm = value; }
 #endif
 
   // Exception handling for compiled methods
@@ -1375,12 +1358,8 @@
   static ByteSize saved_exception_pc_offset()    { return byte_offset_of(JavaThread, _saved_exception_pc  ); }
   static ByteSize osthread_offset()              { return byte_offset_of(JavaThread, _osthread            ); }
 #ifdef GRAAL
-  static ByteSize graal_deopt_info_offset()      { return byte_offset_of(JavaThread, _graal_deopt_info    ); }
   static ByteSize graal_alternate_call_target_offset() { return byte_offset_of(JavaThread, _graal_alternate_call_target); }
 #endif
-#ifdef HIGH_LEVEL_INTERPRETER
-  static ByteSize high_level_interpreter_in_vm_offset() { return byte_offset_of(JavaThread, _high_level_interpreter_in_vm); }
-#endif
   static ByteSize exception_oop_offset()         { return byte_offset_of(JavaThread, _exception_oop       ); }
   static ByteSize exception_pc_offset()          { return byte_offset_of(JavaThread, _exception_pc        ); }
   static ByteSize exception_handler_pc_offset()  { return byte_offset_of(JavaThread, _exception_handler_pc); }
@@ -1393,10 +1372,10 @@
     return byte_offset_of(JavaThread, _should_post_on_exceptions_flag);
   }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   static ByteSize satb_mark_queue_offset()       { return byte_offset_of(JavaThread, _satb_mark_queue); }
   static ByteSize dirty_card_queue_offset()      { return byte_offset_of(JavaThread, _dirty_card_queue); }
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // Returns the jni environment for this thread
   JNIEnv* jni_environment()                      { return &_jni_environment; }
@@ -1685,7 +1664,7 @@
     _stack_size_at_create = value;
   }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   // SATB marking queue support
   ObjPtrQueue& satb_mark_queue() { return _satb_mark_queue; }
   static SATBMarkQueueSet& satb_mark_queue_set() {
@@ -1697,7 +1676,7 @@
   static DirtyCardQueueSet& dirty_card_queue_set() {
     return _dirty_card_queue_set;
   }
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // This method initializes the SATB and dirty card queues before a
   // JavaThread is added to the Java thread list. Right now, we don't
@@ -1716,11 +1695,11 @@
   // might happen between the JavaThread constructor being called and the
   // thread being added to the Java thread list (an example of this is
   // when the structure for the DestroyJavaVM thread is created).
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   void initialize_queues();
-#else // !SERIALGC
+#else  // INCLUDE_ALL_GCS
   void initialize_queues() { }
-#endif // !SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   // Machine dependent stuff
 #ifdef TARGET_OS_ARCH_linux_x86
@@ -1836,6 +1815,7 @@
  private:
   CompilerCounters* _counters;
 
+  ciEnv*        _env;
   CompileLog*   _log;
   CompileTask*  _task;
   CompileQueue* _queue;
@@ -1849,18 +1829,15 @@
 
   bool is_Compiler_thread() const                { return true; }
   // Hide this compiler thread from external view.
-  // (thomaswue) For Graal, the compiler thread should be visible.
-  bool is_hidden_from_external_view() const      {
-#ifdef GRAALVM
-    return !DebugGraal;
-#else
-    return true;
-#endif
-  }
+  bool is_hidden_from_external_view() const      { return true; }
 
   CompileQueue* queue()                          { return _queue; }
   CompilerCounters* counters()                   { return _counters; }
 
+  // Get/set the thread's compilation environment.
+  ciEnv*        env()                            { return _env; }
+  void          set_env(ciEnv* env)              { _env = env; }
+
   // Get/set the thread's logging information
   CompileLog*   log()                            { return _log; }
   void          init_log(CompileLog* log) {
--- a/src/share/vm/runtime/vframe.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/vframe.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -266,8 +266,8 @@
 
   // Get oopmap describing oops and int for current bci
   InterpreterOopMap oop_mask;
-  if (PrintDeoptimizationDetails) {
-    methodHandle m_h(method());
+  if (TraceDeoptimization && Verbose) {
+    methodHandle m_h(thread(), method());
     OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
   } else {
     method()->mask_for(bci(), &oop_mask);
@@ -333,7 +333,7 @@
 
   InterpreterOopMap oop_mask;
   // Get oopmap describing oops and int for current bci
-  if (PrintDeoptimizationDetails) {
+  if (TraceDeoptimization && Verbose) {
     methodHandle m_h(method());
     OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
   } else {
--- a/src/share/vm/runtime/vframeArray.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/vframeArray.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -63,7 +63,7 @@
   _method = vf->method();
   _bci    = vf->raw_bci();
   _reexecute = vf->should_reexecute();
-  
+
   int index;
 
   // Get the monitors off-stack
@@ -233,8 +233,6 @@
       // Force early return from top frame after deoptimization
 #ifndef CC_INTERP
       pc = Interpreter::remove_activation_early_entry(state->earlyret_tos());
-#else
-     // TBD: Need to implement ForceEarlyReturn for CC_INTERP (ia64)
 #endif
     } else {
       // Possibly override the previous pc computation of the top (youngest) frame
@@ -288,7 +286,7 @@
 
   _frame.patch_pc(thread, pc);
 
-  assert (!method()->is_synchronized() || locks > 0, "synchronized methods must have monitors");
+  assert (!method()->is_synchronized() || locks > 0 || raw_bci() == SynchronizationEntryBCI, "synchronized methods must have monitors");
 
   BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin();
   for (int index = 0; index < locks; index++) {
@@ -431,6 +429,11 @@
     RegisterMap map(thread);
     vframe* f = vframe::new_vframe(iframe(), &map, thread);
     f->print();
+
+    tty->print_cr("locals size     %d", locals()->size());
+    tty->print_cr("expression size %d", expressions()->size());
+
+    method()->print_value();
     tty->cr();
     // method()->print_codes();
   } else if (TraceDeoptimization) {
--- a/src/share/vm/runtime/vframe_hp.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/vframe_hp.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -70,12 +70,6 @@
     }
   }
 
-  if (PrintDeoptimizationDetails) {
-    tty->print_cr("bci=%d length=%d", this->bci(), length);
-    tty->print_cr(err_msg("method name = %s", this->method()->name()->as_C_string()));
-    tty->print_cr("relative pc=%d", this->fr().pc() - this->nm()->code_begin());
-  }
-
   for( int i = 0; i < length; i++ ) {
     result->add( create_stack_value(scv_list->at(i)) );
   }
--- a/src/share/vm/runtime/vframe_hp.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/vframe_hp.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -66,7 +66,7 @@
   // Returns SynchronizationEntryBCI or bci() (used for synchronization)
   int raw_bci() const;
 
- //protected:
+ protected:
   ScopeDesc* _scope;
 
 
--- a/src/share/vm/runtime/vmStructs.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -101,6 +101,7 @@
 #include "utilities/array.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/hashtable.hpp"
+#include "utilities/macros.hpp"
 #ifdef TARGET_ARCH_x86
 # include "vmStructs_x86.hpp"
 #endif
@@ -146,7 +147,7 @@
 #ifdef TARGET_OS_ARCH_bsd_zero
 # include "vmStructs_bsd_zero.hpp"
 #endif
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
@@ -161,7 +162,7 @@
 #include "gc_implementation/parallelScavenge/psYoungGen.hpp"
 #include "gc_implementation/parallelScavenge/vmStructs_parallelgc.hpp"
 #include "gc_implementation/g1/vmStructs_g1.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER2
 #include "opto/addnode.hpp"
 #include "opto/block.hpp"
@@ -208,7 +209,7 @@
 // type name, indicating an "opaque" type to the serviceability agent.
 
 // NOTE: there is an interdependency between this file and
-// HotSpotJavaTypeDataBase.java, which parses the type strings.
+// HotSpotTypeDataBase.java, which parses the type strings.
 
 #ifndef REG_COUNT
   #define REG_COUNT 0
@@ -365,11 +366,10 @@
   volatile_nonstatic_field(Method,      _from_compiled_entry,                          address)                               \
   volatile_nonstatic_field(Method,      _from_interpreted_entry,                       address)                               \
   volatile_nonstatic_field(ConstMethod, _fingerprint,                                  uint64_t)                              \
-  nonstatic_field(ConstMethod,          _constants,                                    ConstantPool*)                  \
+  nonstatic_field(ConstMethod,          _constants,                                    ConstantPool*)                         \
   nonstatic_field(ConstMethod,          _stackmap_data,                                Array<u1>*)                            \
   nonstatic_field(ConstMethod,          _constMethod_size,                             int)                                   \
-  nonstatic_field(ConstMethod,          _interpreter_kind,                             jbyte)                                 \
-  nonstatic_field(ConstMethod,          _flags,                                        jbyte)                                 \
+  nonstatic_field(ConstMethod,          _flags,                                        u2)                                    \
   nonstatic_field(ConstMethod,          _code_size,                                    u2)                                    \
   nonstatic_field(ConstMethod,          _name_index,                                   u2)                                    \
   nonstatic_field(ConstMethod,          _signature_index,                              u2)                                    \
@@ -1161,6 +1161,7 @@
   static_field(Abstract_VM_Version,            _vm_major_version,                             int)                                   \
   static_field(Abstract_VM_Version,            _vm_minor_version,                             int)                                   \
   static_field(Abstract_VM_Version,            _vm_build_number,                              int)                                   \
+  static_field(Abstract_VM_Version,            _reserve_for_allocation_prefetch,              int)                                   \
                                                                                                                                      \
   static_field(JDK_Version,                    _current,                                      JDK_Version)                           \
   nonstatic_field(JDK_Version,                 _partially_initialized,                        bool)                                  \
@@ -2087,8 +2088,7 @@
   declare_toplevel_type(FreeBlockDictionary<Metablock>*)                  \
   declare_toplevel_type(FreeList<Metablock>*)                             \
   declare_toplevel_type(FreeList<Metablock>)                              \
-  declare_toplevel_type(MetablockTreeDictionary*)                         \
-           declare_type(MetablockTreeDictionary, FreeBlockDictionary<Metablock>)
+  declare_type(MetablockTreeDictionary, FreeBlockDictionary<Metablock>)
 
 
 //--------------------------------------------------------------------------------
@@ -2109,8 +2109,6 @@
   /* Useful globals */                                                    \
   /******************/                                                    \
                                                                           \
-  declare_constant(UseTLAB)                                               \
-  declare_constant(EnableInvokeDynamic)                                   \
                                                                           \
   /**************/                                                        \
   /* Stack bias */                                                        \
@@ -2260,14 +2258,18 @@
   declare_constant(Klass::_lh_array_tag_obj_value)                        \
                                                                           \
   /********************************/                                      \
-  /* ConstMethod anon-enum */                                      \
+  /* ConstMethod anon-enum */                                             \
   /********************************/                                      \
                                                                           \
-  declare_constant(ConstMethod::_has_linenumber_table)             \
-  declare_constant(ConstMethod::_has_checked_exceptions)           \
-  declare_constant(ConstMethod::_has_localvariable_table)          \
-  declare_constant(ConstMethod::_has_exception_table)              \
-  declare_constant(ConstMethod::_has_generic_signature)            \
+  declare_constant(ConstMethod::_has_linenumber_table)                    \
+  declare_constant(ConstMethod::_has_checked_exceptions)                  \
+  declare_constant(ConstMethod::_has_localvariable_table)                 \
+  declare_constant(ConstMethod::_has_exception_table)                     \
+  declare_constant(ConstMethod::_has_generic_signature)                   \
+  declare_constant(ConstMethod::_has_method_annotations)                  \
+  declare_constant(ConstMethod::_has_parameter_annotations)               \
+  declare_constant(ConstMethod::_has_default_annotations)                 \
+  declare_constant(ConstMethod::_has_type_annotations)                    \
                                                                           \
   /*************************************/                                 \
   /* InstanceKlass enum                */                                 \
@@ -2382,32 +2384,26 @@
   declare_constant(Location::on_stack)                                    \
   declare_constant(Location::in_register)                                 \
                                                                           \
-  /* TODO (chaeubl) those constants should be graal/c1/c2 specific */         \
-  /*declare_constant(Deoptimization::Reason_many)*/                           \
-  /*declare_constant(Deoptimization::Reason_none)*/                           \
-  /*declare_constant(Deoptimization::Reason_null_check)*/                     \
-  /*declare_constant(Deoptimization::Reason_range_check)*/                    \
-  /*declare_constant(Deoptimization::Reason_class_check)*/                    \
-  /*declare_constant(Deoptimization::Reason_array_check)*/                    \
-  /*declare_constant(Deoptimization::Reason_unreached)*/                      \
-  /*declare_constant(Deoptimization::Reason_constraint)*/                     \
-  /*declare_constant(Deoptimization::Reason_div0_check)*/                     \
-  /*declare_constant(Deoptimization::Reason_type_checked_inlining)*/          \
-  /*declare_constant(Deoptimization::Reason_optimized_type_check)*/           \
-  /*declare_constant(Deoptimization::Reason_not_compiled_exception_handler)*/ \
-  /*declare_constant(Deoptimization::Reason_unresolved)*/                     \
-  /*declare_constant(Deoptimization::Reason_jsr_mismatch)*/                   \
-  /*declare_constant(Deoptimization::Reason_LIMIT)*/                          \
-  /*declare_constant(Deoptimization::Reason_RECORDED_LIMIT)*/                 \
-  /*declare_constant(Deoptimization::Reason_null_assert)*/                    \
-  /*declare_constant(Deoptimization::Reason_intrinsic)*/                      \
-  /*declare_constant(Deoptimization::Reason_bimorphic)*/                      \
-  /*declare_constant(Deoptimization::Reason_unloaded)*/                       \
-  /*declare_constant(Deoptimization::Reason_uninitialized) */                 \
-  /*declare_constant(Deoptimization::Reason_unhandled)*/                      \
-  /*declare_constant(Deoptimization::Reason_age)*/                            \
-  /*declare_constant(Deoptimization::Reason_predicate)*/                      \
-  /*declare_constant(Deoptimization::Reason_loop_limit_check)*/               \
+  declare_constant(Deoptimization::Reason_many)                           \
+  declare_constant(Deoptimization::Reason_none)                           \
+  declare_constant(Deoptimization::Reason_null_check)                     \
+  declare_constant(Deoptimization::Reason_null_assert)                    \
+  declare_constant(Deoptimization::Reason_range_check)                    \
+  declare_constant(Deoptimization::Reason_class_check)                    \
+  declare_constant(Deoptimization::Reason_array_check)                    \
+  declare_constant(Deoptimization::Reason_intrinsic)                      \
+  declare_constant(Deoptimization::Reason_bimorphic)                      \
+  declare_constant(Deoptimization::Reason_unloaded)                       \
+  declare_constant(Deoptimization::Reason_uninitialized)                  \
+  declare_constant(Deoptimization::Reason_unreached)                      \
+  declare_constant(Deoptimization::Reason_unhandled)                      \
+  declare_constant(Deoptimization::Reason_constraint)                     \
+  declare_constant(Deoptimization::Reason_div0_check)                     \
+  declare_constant(Deoptimization::Reason_age)                            \
+  declare_constant(Deoptimization::Reason_predicate)                      \
+  declare_constant(Deoptimization::Reason_loop_limit_check)               \
+  declare_constant(Deoptimization::Reason_LIMIT)                          \
+  declare_constant(Deoptimization::Reason_RECORDED_LIMIT)                 \
                                                                           \
   /*********************/                                                 \
   /* Matcher (C2 only) */                                                 \
@@ -2792,7 +2788,7 @@
              GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY,
              GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
                         GENERATE_STATIC_VM_STRUCT_ENTRY)
 
@@ -2802,7 +2798,7 @@
 
   VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
                 GENERATE_STATIC_VM_STRUCT_ENTRY)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
                  GENERATE_STATIC_VM_STRUCT_ENTRY,
@@ -2836,7 +2832,7 @@
            GENERATE_C2_VM_TYPE_ENTRY,
            GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   VM_TYPES_PARALLELGC(GENERATE_VM_TYPE_ENTRY,
                       GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
 
@@ -2847,7 +2843,7 @@
 
   VM_TYPES_G1(GENERATE_VM_TYPE_ENTRY,
               GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   VM_TYPES_CPU(GENERATE_VM_TYPE_ENTRY,
                GENERATE_TOPLEVEL_VM_TYPE_ENTRY,
@@ -2878,11 +2874,11 @@
                    GENERATE_C2_VM_INT_CONSTANT_ENTRY,
                    GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   VM_INT_CONSTANTS_CMS(GENERATE_VM_INT_CONSTANT_ENTRY)
 
   VM_INT_CONSTANTS_PARNEW(GENERATE_VM_INT_CONSTANT_ENTRY)
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   VM_INT_CONSTANTS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY,
                        GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY,
@@ -2936,7 +2932,7 @@
              CHECK_NO_OP,
              CHECK_NO_OP);
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   VM_STRUCTS_PARALLELGC(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
              CHECK_STATIC_VM_STRUCT_ENTRY);
 
@@ -2946,7 +2942,7 @@
 
   VM_STRUCTS_G1(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
                 CHECK_STATIC_VM_STRUCT_ENTRY);
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   VM_STRUCTS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
                  CHECK_STATIC_VM_STRUCT_ENTRY,
@@ -2975,7 +2971,7 @@
            CHECK_C2_VM_TYPE_ENTRY,
            CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY);
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   VM_TYPES_PARALLELGC(CHECK_VM_TYPE_ENTRY,
                       CHECK_SINGLE_ARG_VM_TYPE_NO_OP);
 
@@ -2986,7 +2982,7 @@
 
   VM_TYPES_G1(CHECK_VM_TYPE_ENTRY,
               CHECK_SINGLE_ARG_VM_TYPE_NO_OP);
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
   VM_TYPES_CPU(CHECK_VM_TYPE_ENTRY,
                CHECK_SINGLE_ARG_VM_TYPE_NO_OP,
@@ -3041,7 +3037,7 @@
                         ENSURE_C2_FIELD_TYPE_PRESENT,
                         CHECK_NO_OP,
                         CHECK_NO_OP));
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
   debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT,
                                    ENSURE_FIELD_TYPE_PRESENT));
   debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT,
@@ -3049,7 +3045,7 @@
                             ENSURE_FIELD_TYPE_PRESENT));
   debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT,
                            ENSURE_FIELD_TYPE_PRESENT));
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
   debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT,
                             ENSURE_FIELD_TYPE_PRESENT,
                             CHECK_NO_OP,
--- a/src/share/vm/runtime/vmStructs.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/vmStructs.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,7 @@
 #ifndef SHARE_VM_RUNTIME_VMSTRUCTS_HPP
 #define SHARE_VM_RUNTIME_VMSTRUCTS_HPP
 
-#ifndef VM_STRUCTS_KERNEL
 #include "utilities/debug.hpp"
-#endif
 #ifdef COMPILER1
 #include "c1/c1_Runtime1.hpp"
 #endif
--- a/src/share/vm/runtime/vm_version.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/runtime/vm_version.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -111,9 +111,6 @@
 #endif
 
 #ifndef VMTYPE
-  #ifdef KERNEL
-    #define VMTYPE "Kernel"
-  #else // KERNEL
   #ifdef TIERED
     #define VMTYPE "Server"
   #else // TIERED
@@ -132,7 +129,6 @@
   #endif // GRAAL
   #endif // ZERO
   #endif // TIERED
-  #endif // KERNEL
 #endif
 
 #ifndef HOTSPOT_VM_DISTRO
--- a/src/share/vm/services/attachListener.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/attachListener.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -170,7 +170,6 @@
   return JNI_OK;
 }
 
-#ifndef SERVICES_KERNEL   // Heap dumping not supported
 // Implementation of "dumpheap" command.
 // See also: HeapDumpDCmd class
 //
@@ -212,7 +211,6 @@
   }
   return JNI_OK;
 }
-#endif // SERVICES_KERNEL
 
 // Implementation of "inspectheap" command
 // See also: ClassHistogramDCmd class
@@ -382,9 +380,7 @@
 static AttachOperationFunctionInfo funcs[] = {
   { "agentProperties",  get_agent_properties },
   { "datadump",         data_dump },
-#ifndef SERVICES_KERNEL
   { "dumpheap",         dump_heap },
-#endif  // SERVICES_KERNEL
   { "load",             JvmtiExport::load_agent_library },
   { "properties",       get_system_properties },
   { "threaddump",       thread_dump },
--- a/src/share/vm/services/attachListener.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/attachListener.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 #include "memory/allocation.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/ostream.hpp"
+#include "utilities/macros.hpp"
 
 // The AttachListener thread services a queue of operations that are enqueued
 // by client tools. Each operation is identified by a name and has up to 3
@@ -38,8 +39,6 @@
 // complets the result value and any result data is returned to the client
 // tool.
 
-#ifndef SERVICES_KERNEL
-
 class AttachOperation;
 
 typedef jint (*AttachOperationFunction)(AttachOperation* op, outputStream* out);
@@ -48,7 +47,6 @@
   const char* name;
   AttachOperationFunction func;
 };
-#endif // SERVICES_KERNEL
 
 class AttachListener: AllStatic {
  public:
--- a/src/share/vm/services/classLoadingService.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/classLoadingService.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -31,6 +31,7 @@
 #include "services/classLoadingService.hpp"
 #include "services/memoryService.hpp"
 #include "utilities/dtrace.hpp"
+#include "utilities/macros.hpp"
 
 #ifdef DTRACE_ENABLED
 
--- a/src/share/vm/services/classLoadingService.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/classLoadingService.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -28,6 +28,7 @@
 #include "runtime/handles.hpp"
 #include "runtime/perfData.hpp"
 #include "utilities/growableArray.hpp"
+#include "utilities/macros.hpp"
 
 class InstanceKlass;
 
--- a/src/share/vm/services/diagnosticCommand.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/diagnosticCommand.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
 #include "services/diagnosticFramework.hpp"
 #include "services/heapDumper.hpp"
 #include "services/management.hpp"
+#include "utilities/macros.hpp"
 
 void DCmdRegistrant::register_dcmds(){
   // Registration of the diagnostic commands
@@ -43,12 +44,12 @@
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(true, false));
-#if INCLUDE_SERVICES // Heap dumping supported
+#if INCLUDE_SERVICES // Heap dumping/inspection supported
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(true, false));
 #endif // INCLUDE_SERVICES
-  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(true, false));
-
   //Enhanced JMX Agent Support
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(true,false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(true,false));
@@ -252,7 +253,7 @@
                          vmSymbols::void_method_signature(), CHECK);
 }
 
-#if INCLUDE_SERVICES // Heap dumping supported
+#if INCLUDE_SERVICES // Heap dumping/inspection supported
 HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
                            DCmdWithParser(output, heap),
   _filename("filename","Name of the dump file", "STRING",true),
@@ -292,7 +293,6 @@
     return 0;
   }
 }
-#endif // INCLUDE_SERVICES
 
 ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :
                                        DCmdWithParser(output, heap),
@@ -319,6 +319,65 @@
   }
 }
 
+#define DEFAULT_COLUMNS "InstBytes,KlassBytes,CpAll,annotations,MethodCount,Bytecodes,MethodAll,ROAll,RWAll,Total"
+ClassStatsDCmd::ClassStatsDCmd(outputStream* output, bool heap) :
+                                       DCmdWithParser(output, heap),
+  _csv("-csv", "Print in CSV (comma-separated values) format for spreadsheets",
+       "BOOLEAN", false, "false"),
+  _all("-all", "Show all columns",
+       "BOOLEAN", false, "false"),
+  _help("-help", "Show meaning of all the columns",
+       "BOOLEAN", false, "false"),
+  _columns("columns", "Comma-separated list of all the columns to show. "
+           "If not specified, the following columns are shown: " DEFAULT_COLUMNS,
+           "STRING", false) {
+  _dcmdparser.add_dcmd_option(&_all);
+  _dcmdparser.add_dcmd_option(&_csv);
+  _dcmdparser.add_dcmd_option(&_help);
+  _dcmdparser.add_dcmd_argument(&_columns);
+}
+
+void ClassStatsDCmd::execute(TRAPS) {
+  if (!UnlockDiagnosticVMOptions) {
+    output()->print_cr("GC.class_stats command requires -XX:+UnlockDiagnosticVMOptions");
+    return;
+  }
+
+  VM_GC_HeapInspection heapop(output(),
+                              true, /* request_full_gc */
+                              true /* need_prologue */);
+  heapop.set_csv_format(_csv.value());
+  heapop.set_print_help(_help.value());
+  heapop.set_print_class_stats(true);
+  if (_all.value()) {
+    if (_columns.has_value()) {
+      output()->print_cr("Cannot specify -all and individual columns at the same time");
+      return;
+    } else {
+      heapop.set_columns(NULL);
+    }
+  } else {
+    if (_columns.has_value()) {
+      heapop.set_columns(_columns.value());
+    } else {
+      heapop.set_columns(DEFAULT_COLUMNS);
+    }
+  }
+  VMThread::execute(&heapop);
+}
+
+int ClassStatsDCmd::num_arguments() {
+  ResourceMark rm;
+  ClassStatsDCmd* dcmd = new ClassStatsDCmd(NULL, false);
+  if (dcmd != NULL) {
+    DCmdMark mark(dcmd);
+    return dcmd->_dcmdparser.num_arguments();
+  } else {
+    return 0;
+  }
+}
+#endif // INCLUDE_SERVICES
+
 ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) :
                                DCmdWithParser(output, heap),
   _locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false") {
@@ -406,7 +465,32 @@
 
   _jmxremote_ssl_config_file
   ("jmxremote.ssl.config.file",
-   "set com.sun.management.jmxremote.ssl_config_file", "STRING", false)
+   "set com.sun.management.jmxremote.ssl_config_file", "STRING", false),
+
+// JDP Protocol support
+  _jmxremote_autodiscovery
+  ("jmxremote.autodiscovery",
+   "set com.sun.management.jmxremote.autodiscovery", "STRING", false),
+
+   _jdp_port
+  ("jdp.port",
+   "set com.sun.management.jdp.port", "INT", false),
+
+   _jdp_address
+  ("jdp.address",
+   "set com.sun.management.jdp.address", "STRING", false),
+
+   _jdp_source_addr
+  ("jdp.source_addr",
+   "set com.sun.management.jdp.source_addr", "STRING", false),
+
+   _jdp_ttl
+  ("jdp.ttl",
+   "set com.sun.management.jdp.ttl", "INT", false),
+
+   _jdp_pause
+  ("jdp.pause",
+   "set com.sun.management.jdp.pause", "INT", false)
 
   {
     _dcmdparser.add_dcmd_option(&_config_file);
@@ -422,6 +506,12 @@
     _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols);
     _dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth);
     _dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file);
+    _dcmdparser.add_dcmd_option(&_jmxremote_autodiscovery);
+    _dcmdparser.add_dcmd_option(&_jdp_port);
+    _dcmdparser.add_dcmd_option(&_jdp_address);
+    _dcmdparser.add_dcmd_option(&_jdp_source_addr);
+    _dcmdparser.add_dcmd_option(&_jdp_ttl);
+    _dcmdparser.add_dcmd_option(&_jdp_pause);
 }
 
 
@@ -436,7 +526,6 @@
   }
 }
 
-
 void JMXStartRemoteDCmd::execute(TRAPS) {
     ResourceMark rm(THREAD);
     HandleMark hm(THREAD);
@@ -466,7 +555,9 @@
     // file.
 #define PUT_OPTION(a) \
     if ( (a).is_set() ){ \
-        options.print("%scom.sun.management.%s=%s", comma, (a).name(), (a).value()); \
+        options.print(\
+               ( *((a).type()) == 'I' ) ? "%scom.sun.management.%s=%d" : "%scom.sun.management.%s=%s",\
+                comma, (a).name(), (a).value()); \
         comma[0] = ','; \
     }
 
@@ -483,6 +574,12 @@
     PUT_OPTION(_jmxremote_ssl_enabled_protocols);
     PUT_OPTION(_jmxremote_ssl_need_client_auth);
     PUT_OPTION(_jmxremote_ssl_config_file);
+    PUT_OPTION(_jmxremote_autodiscovery);
+    PUT_OPTION(_jdp_port);
+    PUT_OPTION(_jdp_address);
+    PUT_OPTION(_jdp_source_addr);
+    PUT_OPTION(_jdp_ttl);
+    PUT_OPTION(_jdp_pause);
 
 #undef PUT_OPTION
 
--- a/src/share/vm/services/diagnosticCommand.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/diagnosticCommand.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
 #include "services/diagnosticCommand.hpp"
 #include "services/diagnosticFramework.hpp"
 #include "services/diagnosticCommand_ext.hpp"
+#include "utilities/macros.hpp"
 
 class HelpDCmd : public DCmdWithParser {
 protected:
@@ -178,7 +179,7 @@
 };
 #endif // INCLUDE_SERVICES
 
-// See also: inspeactheap in attachListener.cpp
+// See also: inspectheap in attachListener.cpp
 class ClassHistogramDCmd : public DCmdWithParser {
 protected:
   DCmdArgument<bool> _all;
@@ -197,6 +198,27 @@
   virtual void execute(TRAPS);
 };
 
+class ClassStatsDCmd : public DCmdWithParser {
+protected:
+  DCmdArgument<bool> _all;
+  DCmdArgument<bool> _csv;
+  DCmdArgument<bool> _help;
+  DCmdArgument<char*> _columns;
+public:
+  ClassStatsDCmd(outputStream* output, bool heap);
+  static const char* name() {
+    return "GC.class_stats";
+  }
+  static const char* description() {
+    return "Provide statistics about Java class meta data. Requires -XX:+UnlockDiagnosticVMOptions.";
+  }
+  static const char* impact() {
+    return "High: Depends on Java heap size and content.";
+  }
+  static int num_arguments();
+  virtual void execute(TRAPS);
+};
+
 // See also: thread_dump in attachListener.cpp
 class ThreadDumpDCmd : public DCmdWithParser {
 protected:
@@ -236,6 +258,16 @@
   DCmdArgument<char *> _jmxremote_ssl_need_client_auth;
   DCmdArgument<char *> _jmxremote_ssl_config_file;
 
+  // JDP support
+  // Keep autodiscovery char* not bool to pass true/false
+  // as property value to java level.
+  DCmdArgument<char *> _jmxremote_autodiscovery;
+  DCmdArgument<jlong>  _jdp_port;
+  DCmdArgument<char *> _jdp_address;
+  DCmdArgument<char *> _jdp_source_addr;
+  DCmdArgument<jlong>  _jdp_ttl;
+  DCmdArgument<jlong>  _jdp_pause;
+
 public:
   JMXStartRemoteDCmd(outputStream *output, bool heap_allocated);
 
--- a/src/share/vm/services/g1MemoryPool.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/g1MemoryPool.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,11 +25,12 @@
 #ifndef SHARE_VM_SERVICES_G1MEMORYPOOL_HPP
 #define SHARE_VM_SERVICES_G1MEMORYPOOL_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1MonitoringSupport.hpp"
 #include "services/memoryPool.hpp"
 #include "services/memoryUsage.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // This file contains the three classes that represent the memory
 // pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and
--- a/src/share/vm/services/heapDumper.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/heapDumper.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -40,9 +40,10 @@
 #include "services/heapDumper.hpp"
 #include "services/threadService.hpp"
 #include "utilities/ostream.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 /*
  * HPROF binary format - description copied from:
--- a/src/share/vm/services/management.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/management.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -53,6 +53,7 @@
 #include "services/memoryService.hpp"
 #include "services/runtimeService.hpp"
 #include "services/threadService.hpp"
+#include "utilities/macros.hpp"
 
 PerfVariable* Management::_begin_vm_creation_time = NULL;
 PerfVariable* Management::_end_vm_creation_time = NULL;
--- a/src/share/vm/services/memBaseline.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memBaseline.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -40,6 +40,7 @@
   {mtNMT,        "Memory Tracking"},
   {mtChunk,      "Pooled Free Chunks"},
   {mtClassShared,"Shared spaces for classes"},
+  {mtTest,       "Test"},
   {mtNone,       "Unknown"}  // It can happen when type tagging records are lagging
                              // behind
 };
--- a/src/share/vm/services/memPtr.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memPtr.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -27,8 +27,8 @@
 #include "services/memTracker.hpp"
 
 volatile jint SequenceGenerator::_seq_number = 1;
+volatile unsigned long SequenceGenerator::_generation = 1;
 NOT_PRODUCT(jint SequenceGenerator::_max_seq_number = 1;)
-DEBUG_ONLY(volatile unsigned long SequenceGenerator::_generation = 0;)
 
 jint SequenceGenerator::next() {
   jint seq = Atomic::add(1, &_seq_number);
--- a/src/share/vm/services/memPtr.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memPtr.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -47,16 +47,16 @@
   static void reset() {
     assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required");
     _seq_number = 1;
-    DEBUG_ONLY(_generation ++;)
+    _generation ++;
   };
 
-  DEBUG_ONLY(static unsigned long current_generation() { return (unsigned long)_generation; })
+  static unsigned long current_generation() { return _generation; }
   NOT_PRODUCT(static jint max_seq_num() { return _max_seq_number; })
 
  private:
-  static volatile jint _seq_number;
-  NOT_PRODUCT(static jint _max_seq_number; )
-  DEBUG_ONLY(static volatile unsigned long _generation; )
+  static volatile jint             _seq_number;
+  static volatile unsigned long    _generation;
+  NOT_PRODUCT(static jint          _max_seq_number; )
 };
 
 /*
--- a/src/share/vm/services/memRecorder.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memRecorder.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -55,7 +55,7 @@
 MemRecorder::MemRecorder() {
   assert(MemTracker::is_on(), "Native memory tracking is off");
   Atomic::inc(&_instance_count);
-  debug_only(set_generation();)
+  set_generation();
 
   if (MemTracker::track_callsite()) {
     _pointer_records = new (std::nothrow)FixedSizeMemPointerArray<SeqMemPointerRecordEx,
@@ -151,11 +151,12 @@
 }
 
 
-#ifdef ASSERT
 void MemRecorder::set_generation() {
   _generation = SequenceGenerator::current_generation();
 }
 
+#ifdef ASSERT
+
 void MemRecorder::check_dup_seq(jint seq) const {
   MemPointerArrayIteratorImpl itr(_pointer_records);
   MemPointerRecord* rc = (MemPointerRecord*)itr.current();
--- a/src/share/vm/services/memRecorder.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memRecorder.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -213,7 +213,7 @@
   // used for linked list
   MemRecorder*             _next;
   // active recorder can only record a certain generation data
-  debug_only(unsigned long _generation;)
+  unsigned long            _generation;
 
  protected:
   _NOINLINE_ MemRecorder();
@@ -251,6 +251,8 @@
 
   SequencedRecordIterator pointer_itr();
 
+  // return the generation of this recorder which it belongs to
+  unsigned long get_generation() const { return _generation; }
  protected:
   // number of MemRecorder instance
   static volatile jint _instance_count;
@@ -263,7 +265,7 @@
   static int sort_record_fn(const void* e1, const void* e2);
 
   debug_only(void check_dup_seq(jint seq) const;)
-  debug_only(void set_generation();)
+  void set_generation();
 };
 
 #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP
--- a/src/share/vm/services/memReporter.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memReporter.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -29,6 +29,7 @@
 #include "services/memBaseline.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/ostream.hpp"
+#include "utilities/macros.hpp"
 
 #if INCLUDE_NMT
 
--- a/src/share/vm/services/memSnapshot.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memSnapshot.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -528,7 +528,8 @@
         // an arena record can be followed by a size record, we need to remove both
         if (matched_rec->is_arena_record()) {
           MemPointerRecord* next = (MemPointerRecord*)malloc_snapshot_itr.peek_next();
-          if (next->is_arena_memory_record() && next->is_memory_record_of_arena(matched_rec)) {
+          if (next != NULL && next->is_arena_memory_record() &&
+              next->is_memory_record_of_arena(matched_rec)) {
             malloc_snapshot_itr.remove();
           }
         }
--- a/src/share/vm/services/memTrackWorker.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memTrackWorker.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -91,6 +91,8 @@
   MemSnapshot* snapshot = MemTracker::get_snapshot();
   assert(snapshot != NULL, "Worker should not be started");
   MemRecorder* rec;
+  unsigned long processing_generation = 0;
+  bool          worker_idle = false;
 
   while (!MemTracker::shutdown_in_progress()) {
     NOT_PRODUCT(_last_gen_in_use = generations_in_use();)
@@ -100,6 +102,12 @@
       rec = _gen[_head].next_recorder();
     }
     if (rec != NULL) {
+      if (rec->get_generation() != processing_generation || worker_idle) {
+        processing_generation = rec->get_generation();
+        worker_idle = false;
+        MemTracker::set_current_processing_generation(processing_generation);
+      }
+
       // merge the recorder into staging area
       if (!snapshot->merge(rec)) {
         MemTracker::shutdown(MemTracker::NMT_out_of_memory);
@@ -129,6 +137,9 @@
           MemTracker::shutdown(MemTracker::NMT_out_of_memory);
         }
       } else {
+        // worker thread is idle
+        worker_idle = true;
+        MemTracker::report_worker_idle();
         snapshot->wait(1000);
         ThreadCritical tc;
         // check if more data arrived
--- a/src/share/vm/services/memTrackWorker.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memTrackWorker.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -107,6 +107,7 @@
   NOT_PRODUCT(int _merge_count;)
   NOT_PRODUCT(int _last_gen_in_use;)
 
+  // how many generations are queued
   inline int generations_in_use() const {
     return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1));
   }
--- a/src/share/vm/services/memTracker.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memTracker.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -29,6 +29,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/threadCritical.hpp"
+#include "runtime/vm_operations.hpp"
 #include "services/memPtr.hpp"
 #include "services/memReporter.hpp"
 #include "services/memTracker.hpp"
@@ -65,6 +66,8 @@
 MemTracker::ShutdownReason      MemTracker::_reason = NMT_shutdown_none;
 int                             MemTracker::_thread_count = 255;
 volatile jint                   MemTracker::_pooled_recorder_count = 0;
+volatile unsigned long          MemTracker::_processing_generation = 0;
+volatile bool                   MemTracker::_worker_thread_idle = false;
 debug_only(intx                 MemTracker::_main_thread_tid = 0;)
 NOT_PRODUCT(volatile jint       MemTracker::_pending_recorder_count = 0;)
 
@@ -279,7 +282,7 @@
      }
      cur_head->set_next(NULL);
      Atomic::dec(&_pooled_recorder_count);
-     debug_only(cur_head->set_generation();)
+     cur_head->set_generation();
      return cur_head;
   }
 }
@@ -570,6 +573,51 @@
   return false;
 }
 
+// Whitebox API for blocking until the current generation of NMT data has been merged
+bool MemTracker::wbtest_wait_for_data_merge() {
+  // NMT can't be shutdown while we're holding _query_lock
+  MutexLockerEx lock(_query_lock, true);
+  assert(_worker_thread != NULL, "Invalid query");
+  // the generation at query time, so NMT will spin till this generation is processed
+  unsigned long generation_at_query_time = SequenceGenerator::current_generation();
+  unsigned long current_processing_generation = _processing_generation;
+  // if generation counter overflown
+  bool generation_overflown = (generation_at_query_time < current_processing_generation);
+  long generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation;
+  // spin
+  while (!shutdown_in_progress()) {
+    if (!generation_overflown) {
+      if (current_processing_generation > generation_at_query_time) {
+        return true;
+      }
+    } else {
+      assert(generations_to_wrap >= 0, "Sanity check");
+      long current_generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation;
+      assert(current_generations_to_wrap >= 0, "Sanity check");
+      // to overflow an unsigned long should take long time, so to_wrap check should be sufficient
+      if (current_generations_to_wrap > generations_to_wrap &&
+          current_processing_generation > generation_at_query_time) {
+        return true;
+      }
+    }
+
+    // if worker thread is idle, but generation is not advancing, that means
+    // there is not safepoint to let NMT advance generation, force one.
+    if (_worker_thread_idle) {
+      VM_ForceSafepoint vfs;
+      VMThread::execute(&vfs);
+    }
+    MemSnapshot* snapshot = get_snapshot();
+    if (snapshot == NULL) {
+      return false;
+    }
+    snapshot->wait(1000);
+    current_processing_generation = _processing_generation;
+  }
+  // We end up here if NMT is shutting down before our data has been merged
+  return false;
+}
+
 // compare memory usage between current snapshot and baseline
 bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) {
   MutexLockerEx lock(_query_lock, true);
--- a/src/share/vm/services/memTracker.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memTracker.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -91,9 +91,10 @@
    static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
             bool summary_only = true) { }
 
+   static bool wbtest_wait_for_data_merge() { }
+
    static inline void sync() { }
    static inline void thread_exiting(JavaThread* thread) { }
-
 };
 
 
@@ -111,6 +112,10 @@
 
 extern bool NMT_track_callsite;
 
+#ifndef MAX_UNSIGNED_LONG
+#define MAX_UNSIGNED_LONG    (unsigned long)(-1)
+#endif
+
 #ifdef ASSERT
   #define DEBUG_CALLER_PC  (NMT_track_callsite ? os::get_caller_pc(2) : 0)
 #else
@@ -380,6 +385,11 @@
   static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
            bool summary_only = true);
 
+  // the version for whitebox testing support, it ensures that all memory
+  // activities before this method call, are reflected in the snapshot
+  // database.
+  static bool wbtest_wait_for_data_merge();
+
   // sync is called within global safepoint to synchronize nmt data
   static void sync();
 
@@ -432,6 +442,15 @@
   static void create_record_in_recorder(address addr, MEMFLAGS type,
                    size_t size, address pc, JavaThread* thread);
 
+  static void set_current_processing_generation(unsigned long generation) {
+    _worker_thread_idle = false;
+    _processing_generation = generation;
+  }
+
+  static void report_worker_idle() {
+    _worker_thread_idle = true;
+  }
+
  private:
   // global memory snapshot
   static MemSnapshot*     _snapshot;
@@ -483,6 +502,11 @@
   static volatile enum NMTStates   _state;
   // the reason for shutting down nmt
   static enum ShutdownReason       _reason;
+  // the generation that NMT is processing
+  static volatile unsigned long    _processing_generation;
+  // although NMT is still procesing current generation, but
+  // there is not more recorder to process, set idle state
+  static volatile bool             _worker_thread_idle;
 };
 
 #endif // !INCLUDE_NMT
--- a/src/share/vm/services/memoryPool.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memoryPool.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -32,6 +32,7 @@
 #include "services/management.hpp"
 #include "services/memoryManager.hpp"
 #include "services/memoryPool.hpp"
+#include "utilities/macros.hpp"
 
 MemoryPool::MemoryPool(const char* name,
                        PoolType type,
@@ -208,7 +209,7 @@
   return MemoryUsage(initial_size(), used, committed, maxSize);
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 CompactibleFreeListSpacePool::CompactibleFreeListSpacePool(CompactibleFreeListSpace* space,
                                                            const char* name,
                                                            PoolType type,
@@ -225,7 +226,7 @@
 
   return MemoryUsage(initial_size(), used, committed, maxSize);
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 GenerationPool::GenerationPool(Generation* gen,
                                const char* name,
--- a/src/share/vm/services/memoryPool.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memoryPool.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -30,9 +30,10 @@
 #include "memory/heap.hpp"
 #include "memory/space.hpp"
 #include "services/memoryUsage.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 // A memory pool represents the memory area that the VM manages.
 // The Java virtual machine has at least one memory pool
@@ -185,7 +186,7 @@
   }
 };
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 class CompactibleFreeListSpacePool : public CollectedMemoryPool {
 private:
   CompactibleFreeListSpace* _space;
@@ -199,7 +200,7 @@
   MemoryUsage get_memory_usage();
   size_t used_in_bytes()            { return _space->used(); }
 };
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 
 class GenerationPool : public CollectedMemoryPool {
--- a/src/share/vm/services/memoryService.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/memoryService.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -43,7 +43,8 @@
 #include "services/memoryPool.hpp"
 #include "services/memoryService.hpp"
 #include "utilities/growableArray.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/parNew/parNewGeneration.hpp"
@@ -52,7 +53,7 @@
 #include "gc_implementation/parallelScavenge/psYoungGen.hpp"
 #include "services/g1MemoryPool.hpp"
 #include "services/psMemoryPool.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 GrowableArray<MemoryPool*>* MemoryService::_pools_list =
   new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryPool*>(init_pools_list_size, true);
@@ -83,7 +84,7 @@
       add_gen_collected_heap_info(GenCollectedHeap::heap());
       break;
     }
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case CollectedHeap::ParallelScavengeHeap : {
       add_parallel_scavenge_heap_info(ParallelScavengeHeap::heap());
       break;
@@ -92,7 +93,7 @@
       add_g1_heap_info(G1CollectedHeap::heap());
       break;
     }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
     default: {
       guarantee(false, "Unrecognized kind of heap");
     }
@@ -130,22 +131,22 @@
       case Generation::DefNew:
         _minor_gc_manager = MemoryManager::get_copy_memory_manager();
         break;
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
       case Generation::ParNew:
       case Generation::ASParNew:
         _minor_gc_manager = MemoryManager::get_parnew_memory_manager();
         break;
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
       default:
         guarantee(false, "Unrecognized generation spec");
         break;
     }
     if (policy->is_mark_sweep_policy()) {
       _major_gc_manager = MemoryManager::get_msc_memory_manager();
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     } else if (policy->is_concurrent_mark_sweep_policy()) {
       _major_gc_manager = MemoryManager::get_cms_memory_manager();
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
     } else {
       guarantee(false, "Unknown two-gen policy");
     }
@@ -159,7 +160,7 @@
   add_generation_memory_pool(heap->get_gen(major), _major_gc_manager);
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 // Add memory pools for ParallelScavengeHeap
 // This function currently only supports two generations collected heap.
 // The collector for ParallelScavengeHeap will have two memory managers.
@@ -185,7 +186,7 @@
   add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);
   add_g1OldGen_memory_pool(g1h, _major_gc_manager);
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 MemoryPool* MemoryService::add_gen(Generation* gen,
                                    const char* name,
@@ -222,7 +223,7 @@
   return (MemoryPool*) pool;
 }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space,
                                          const char* name,
                                          bool is_heap,
@@ -233,7 +234,7 @@
   _pools_list->append(pool);
   return (MemoryPool*) pool;
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 // Add memory pool(s) for one generation
 void MemoryService::add_generation_memory_pool(Generation* gen,
@@ -261,7 +262,7 @@
       break;
     }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case Generation::ParNew:
     case Generation::ASParNew:
     {
@@ -282,7 +283,7 @@
 
       break;
     }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
     case Generation::MarkSweepCompact: {
       assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager");
@@ -293,7 +294,7 @@
       break;
     }
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case Generation::ConcurrentMarkSweep:
     case Generation::ASConcurrentMarkSweep:
     {
@@ -306,7 +307,7 @@
                                        true  /* support_usage_threshold */);
       break;
     }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
     default:
       assert(false, "should not reach here");
@@ -326,7 +327,7 @@
 }
 
 
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) {
   assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");
 
@@ -384,7 +385,7 @@
   mgr->add_pool(old_gen);
   _pools_list->append(old_gen);
 }
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
 
 void MemoryService::add_code_heap_memory_pool(CodeHeap* heap) {
   _code_heap_pool = new CodeHeapPool(heap,
@@ -534,17 +535,17 @@
 TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause) {
   switch (kind) {
     case Generation::DefNew:
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case Generation::ParNew:
     case Generation::ASParNew:
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
       _fullGC=false;
       break;
     case Generation::MarkSweepCompact:
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
     case Generation::ConcurrentMarkSweep:
     case Generation::ASConcurrentMarkSweep:
-#endif // SERIALGC
+#endif // INCLUDE_ALL_GCS
       _fullGC=true;
       break;
     default:
--- a/src/share/vm/services/psMemoryPool.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/psMemoryPool.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,7 +25,8 @@
 #ifndef SHARE_VM_SERVICES_PSMEMORYPOOL_HPP
 #define SHARE_VM_SERVICES_PSMEMORYPOOL_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/parallelScavenge/psOldGen.hpp"
 #include "gc_implementation/parallelScavenge/psYoungGen.hpp"
 #include "gc_implementation/shared/mutableSpace.hpp"
@@ -34,7 +35,7 @@
 #include "memory/space.hpp"
 #include "services/memoryPool.hpp"
 #include "services/memoryUsage.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 class PSGenerationPool : public CollectedMemoryPool {
 private:
--- a/src/share/vm/services/runtimeService.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/services/runtimeService.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -29,6 +29,7 @@
 #include "services/runtimeService.hpp"
 #include "utilities/dtrace.hpp"
 #include "utilities/exceptions.hpp"
+#include "utilities/macros.hpp"
 
 #ifndef USDT2
 HS_DTRACE_PROBE_DECL(hs_private, safepoint__begin);
--- a/src/share/vm/utilities/accessFlags.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/accessFlags.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,7 @@
   } while(f != old_flags);
 }
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || INCLUDE_JVMTI
 
 void AccessFlags::print_on(outputStream* st) const {
   if (is_public      ()) st->print("public "      );
@@ -80,7 +80,7 @@
   if (on_stack       ()) st->print("{on_stack} "  );
 }
 
-#endif
+#endif // !PRODUCT || INCLUDE_JVMTI
 
 void accessFlags_init() {
   assert(sizeof(AccessFlags) == sizeof(jint), "just checking size of flags");
--- a/src/share/vm/utilities/accessFlags.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/accessFlags.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -239,7 +239,11 @@
   inline friend AccessFlags accessFlags_from(jint flags);
 
   // Printing/debugging
+#if INCLUDE_JVMTI
+  void print_on(outputStream* st) const;
+#else
   void print_on(outputStream* st) const PRODUCT_RETURN;
+#endif
 };
 
 inline AccessFlags accessFlags_from(jint flags) {
--- a/src/share/vm/utilities/constantTag.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/constantTag.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,6 @@
     case JVM_CONSTANT_StringIndex :
     case JVM_CONSTANT_MethodHandle :
     case JVM_CONSTANT_MethodType :
-    case JVM_CONSTANT_Object :
       return T_OBJECT;
     default:
       ShouldNotReachHere();
@@ -96,8 +95,6 @@
       return "MethodType Error";
     case JVM_CONSTANT_InvokeDynamic :
       return "InvokeDynamic";
-    case JVM_CONSTANT_Object :
-      return "Object";
     case JVM_CONSTANT_Utf8 :
       return "Utf8";
     case JVM_CONSTANT_UnresolvedClass :
--- a/src/share/vm/utilities/constantTag.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/constantTag.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,8 +43,7 @@
   JVM_CONSTANT_UnresolvedClassInError   = 103,  // Error tag due to resolution error
   JVM_CONSTANT_MethodHandleInError      = 104,  // Error tag due to resolution error
   JVM_CONSTANT_MethodTypeInError        = 105,  // Error tag due to resolution error
-  JVM_CONSTANT_Object                   = 106,  // Required for BoundMethodHandle arguments.
-  JVM_CONSTANT_InternalMax              = 106   // Last implementation tag
+  JVM_CONSTANT_InternalMax              = 105   // Last implementation tag
 };
 
 
@@ -84,8 +83,6 @@
   bool is_klass_index() const       { return _tag == JVM_CONSTANT_ClassIndex; }
   bool is_string_index() const      { return _tag == JVM_CONSTANT_StringIndex; }
 
-  bool is_object() const            { return _tag == JVM_CONSTANT_Object; }
-
   bool is_klass_reference() const   { return is_klass_index() || is_unresolved_klass(); }
   bool is_klass_or_reference() const{ return is_klass() || is_klass_reference(); }
   bool is_field_or_method() const   { return is_field() || is_method() || is_interface_method(); }
@@ -98,7 +95,7 @@
   bool is_loadable_constant() const {
     return ((_tag >= JVM_CONSTANT_Integer && _tag <= JVM_CONSTANT_String) ||
             is_method_type() || is_method_handle() ||
-            is_unresolved_klass() || is_object());
+            is_unresolved_klass());
   }
 
   constantTag() {
--- a/src/share/vm/utilities/debug.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/debug.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -228,28 +228,16 @@
   report_vm_error(file, line, "fatal error", message);
 }
 
-// Used by report_vm_out_of_memory to detect recursion.
-static jint _exiting_out_of_mem = 0;
-
 void report_vm_out_of_memory(const char* file, int line, size_t size,
                              const char* message) {
   if (Debugging) return;
 
-  // We try to gather additional information for the first out of memory
-  // error only; gathering additional data might cause an allocation and a
-  // recursive out_of_memory condition.
-
-  const jint exiting = 1;
-  // If we succeed in changing the value, we're the first one in.
-  bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting;
+  Thread* thread = ThreadLocalStorage::get_thread_slow();
+  VMError(thread, file, line, size, message).report_and_die();
 
-  if (first_time_here) {
-    Thread* thread = ThreadLocalStorage::get_thread_slow();
-    VMError(thread, file, line, size, message).report_and_die();
-  }
-
-  // Dump core and abort
-  vm_abort(true);
+  // The UseOSErrorReporting option in report_and_die() may allow a return
+  // to here. If so then we'll have to figure out how to handle it.
+  guarantee(false, "report_and_die() should not return here");
 }
 
 void report_should_not_call(const char* file, int line) {
@@ -842,37 +830,3 @@
 #endif
 
 #endif // !PRODUCT
-
-#ifdef GRAAL
-
-DebugScopedValue::DebugScopedValue(const char* file, int line) {
-  _file = file;
-  _line = line;
-  Thread* thread = Thread::current();
-  if (thread != NULL && thread->is_Java_thread()) {
-    JavaThread* javaThread = (JavaThread*) thread;
-    _parent = javaThread->debug_scope();
-    javaThread->set_debug_scope(this);
-  } else {
-    _parent = NULL;
-  }
-}
-
-DebugScopedValue::~DebugScopedValue() {
-  Thread* thread = Thread::current();
-  if (thread != NULL && thread->is_Java_thread()) {
-    JavaThread* javaThread = (JavaThread*) thread;
-    javaThread->set_debug_scope(_parent);
-    _parent = NULL;
-  }
-}
-
-void DebugScopedValue::print(outputStream* st) {
-  st->print("%s:%d: ", _file, _line);
-  print_on(st);
-}
-
-void DebugScopedScalar::print_on(outputStream* st) {
-  st->print("int: %d, char: %c, long: %ld, hex: %p", _value, _value, _value, _value);
-}
-#endif
--- a/src/share/vm/utilities/debug.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/debug.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -30,35 +30,6 @@
 
 #include <stdarg.h>
 
-#ifdef GRAAL
-// Scopes a value that may be of interest in a crash log.
-class DebugScopedValue {
-protected:
-  DebugScopedValue *_parent;
-  const char* _file;
-  int _line;
-public:
-  DebugScopedValue(const char* file, int line);
-  ~DebugScopedValue();
-  void print(outputStream* st);
-  virtual void print_on(outputStream* st) = 0;
-  DebugScopedValue* parent() { return _parent; }
-};
-
-class DebugScopedScalar : DebugScopedValue {
-private:
-  void* _value;
-public:
-  DebugScopedScalar(const char* file, int line, void* v) : DebugScopedValue(file, line), _value(v) {}
-  void print_on(outputStream* st);
-};
-#define DS_SCALAR(val) DebugScopedScalar __dss__(__FILE__, __LINE__, (void*) val)
-#define DS_SCALAR1(name, val) DebugScopedScalar name(__FILE__, __LINE__, (void*) val)
-#else
-#define DS_SCALAR(name) do {} while (0)
-#define DS_SCALAR1(name, val) do {} while (0)
-#endif
-
 // Simple class to format the ctor arguments into a fixed-sized buffer.
 class FormatBufferBase {
  protected:
--- a/src/share/vm/utilities/exceptions.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/exceptions.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -61,6 +61,8 @@
   friend class VMStructs;
 
  protected:
+  int _pending_deoptimization;
+  bool _pending_monitorenter;
   oop  _pending_exception;                       // Thread has gc actions.
   const char* _exception_file;                   // file information for exception (debugging only)
   int         _exception_line;                   // line information for exception (debugging only)
@@ -76,12 +78,19 @@
 
  public:
   oop  pending_exception() const                 { return _pending_exception; }
+  int  pending_deoptimization() const            { return _pending_deoptimization; }
   bool has_pending_exception() const             { return _pending_exception != NULL; }
   const char* exception_file() const             { return _exception_file; }
   int  exception_line() const                    { return _exception_line; }
+  bool has_pending_monitorenter() const          { return _pending_monitorenter; }
 
   // Code generation support
+  static ByteSize pending_deoptimization_offset() { return byte_offset_of(ThreadShadow, _pending_deoptimization); }
   static ByteSize pending_exception_offset()     { return byte_offset_of(ThreadShadow, _pending_exception); }
+  static ByteSize pending_monitorenter_offset()  { return byte_offset_of(ThreadShadow, _pending_monitorenter); }
+
+  void set_pending_monitorenter(bool b)          { _pending_monitorenter = b; }
+  void set_pending_deoptimization(int reason)    { _pending_deoptimization = reason; }
 
   // use THROW whenever possible!
   void set_pending_exception(oop exception, const char* file, int line);
@@ -90,7 +99,7 @@
   void clear_pending_exception();
 
   ThreadShadow() : _pending_exception(NULL),
-                   _exception_file(NULL), _exception_line(0) {}
+                   _exception_file(NULL), _exception_line(0), _pending_monitorenter(false), _pending_deoptimization(-1) {}
 };
 
 
--- a/src/share/vm/utilities/machineCodePrinter.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "code/stubs.hpp"
-#include "compiler/disassembler.hpp"
-#include "runtime/thread.hpp"
-#include "utilities/machineCodePrinter.hpp"
-#include "utilities/ostream.hpp"
-
-fileStream* MachineCodePrinter::_st = NULL;
-volatile int MachineCodePrinter::_write_lock = 0;
-
-void MachineCodePrinter::initialize() {
-  _st = new (ResourceObj::C_HEAP, mtInternal) fileStream("machineCode.txt");
-}
-
-void MachineCodePrinter::print(nmethod* nm) {
-  lock();
-  Disassembler::decode(nm, _st);
-  unlock();
-}
-
-void MachineCodePrinter::print(CodeBlob* cb) {
-  lock();
-  Disassembler::decode(cb, _st);
-  unlock();
-}
-
-void MachineCodePrinter::print(StubQueue* stub_queue) {
-  lock();
-  stub_queue->print_on(_st);
-  unlock();
-}
-
-void MachineCodePrinter::flush() {
-  _st->flush();
-}
-
-void MachineCodePrinter::lock() {
-  Thread::SpinAcquire(&_write_lock, "Put");
-}
-
-void MachineCodePrinter::unlock() {
-  Thread::SpinRelease(&_write_lock);
-}
--- a/src/share/vm/utilities/machineCodePrinter.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef SHARE_VM_UTILITIES_MACHINE_CODE_PRINTER_HPP
-#define SHARE_VM_UTILITIES_MACHINE_CODE_PRINTER_HPP
-
-#include "memory/allocation.hpp"
-#include "utilities/ostream.hpp"
-
-class MachineCodePrinter : public AllStatic {
-private:
-  static fileStream* _st;
-  static volatile int _write_lock;
-
-public:
-  static void initialize();
-  static void print(nmethod* nm);
-  static void print(CodeBlob* cb);
-  static void print(StubQueue* stub_queue);
-  static void flush();
-
-private:
-  static void lock();
-  static void unlock();
-};
-
-#endif // SHARE_VM_UTILITIES_MACHINE_CODE_PRINTER_HPP
--- a/src/share/vm/utilities/macros.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/macros.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -130,23 +130,23 @@
 #endif // INCLUDE_MANAGEMENT
 
 /*
- * When INCLUDE_ALTERNATE_GCS is false the only garbage collectors
+ * When INCLUDE_ALL_GCS is false the only garbage collectors
  * included in the JVM are defaultNewGeneration and markCompact.
  *
- * When INCLUDE_ALTERNATE_GCS is true all garbage collectors are
+ * When INCLUDE_ALL_GCS is true all garbage collectors are
  * included in the JVM.
  */
-#ifndef INCLUDE_ALTERNATE_GCS
-#define INCLUDE_ALTERNATE_GCS 1
-#endif // INCLUDE_ALTERNATE_GCS
+#ifndef INCLUDE_ALL_GCS
+#define INCLUDE_ALL_GCS 1
+#endif // INCLUDE_ALL_GCS
 
-#if INCLUDE_ALTERNATE_GCS
-#define NOT_ALTERNATE_GCS_RETURN        /* next token must be ; */
-#define NOT_ALTERNATE_GCS_RETURN_(code) /* next token must be ; */
+#if INCLUDE_ALL_GCS
+#define NOT_ALL_GCS_RETURN        /* next token must be ; */
+#define NOT_ALL_GCS_RETURN_(code) /* next token must be ; */
 #else
-#define NOT_ALTERNATE_GCS_RETURN        {}
-#define NOT_ALTERNATE_GCS_RETURN_(code) { return code; }
-#endif // INCLUDE_ALTERNATE_GCS
+#define NOT_ALL_GCS_RETURN        {}
+#define NOT_ALL_GCS_RETURN_(code) { return code; }
+#endif // INCLUDE_ALL_GCS
 
 #ifndef INCLUDE_NMT
 #define INCLUDE_NMT 1
@@ -201,14 +201,6 @@
 #define NOT_GRAALVM(code) code
 #endif // GRAAL
 
-#ifdef HIGH_LEVEL_INTERPRETER
-#define HIGH_LEVEL_INTERPRETER_ONLY(code) code
-#define NOT_HIGH_LEVEL_INTERPRETER(code)
-#else
-#define HIGH_LEVEL_INTERPRETER_ONLY(code)
-#define NOT_HIGH_LEVEL_INTERPRETER(code) code
-#endif // HIGH_LEVEL_INTERPRETER
-
 #ifdef TIERED
 #define TIERED_ONLY(code) code
 #define NOT_TIERED(code)
--- a/src/share/vm/utilities/ostream.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/ostream.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -102,7 +102,6 @@
     result_len = strlen(result);
   } else {
     DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
-
     result = buffer;
     result_len = buflen - 1;
     buffer[result_len] = 0;
@@ -432,7 +431,7 @@
 
 rotatingFileStream::rotatingFileStream(const char* file_name) {
   _cur_file_num = 0;
-  _bytes_writen = 0L;
+  _bytes_written = 0L;
   _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal);
   jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num);
   _file = fopen(_file_name, "w");
@@ -441,7 +440,7 @@
 
 rotatingFileStream::rotatingFileStream(const char* file_name, const char* opentype) {
   _cur_file_num = 0;
-  _bytes_writen = 0L;
+  _bytes_written = 0L;
   _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal);
   jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num);
   _file = fopen(_file_name, opentype);
@@ -449,10 +448,9 @@
 }
 
 void rotatingFileStream::write(const char* s, size_t len) {
-  if (_file != NULL)  {
-    // Make an unused local variable to avoid warning from gcc 4.x compiler.
+  if (_file != NULL) {
     size_t count = fwrite(s, 1, len, _file);
-    Atomic::add((jlong)count, &_bytes_writen);
+    _bytes_written += count;
   }
   update_position(s, len);
 }
@@ -466,7 +464,10 @@
 // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
 // must be synchronized.
 void rotatingFileStream::rotate_log() {
-  if (_bytes_writen < (jlong)GCLogFileSize) return;
+  if (_bytes_written < (jlong)GCLogFileSize) {
+    return;
+  }
+
 #ifdef ASSERT
   Thread *thread = Thread::current();
   assert(thread == NULL ||
@@ -476,7 +477,7 @@
   if (NumberOfGCLogFiles == 1) {
     // rotate in same file
     rewind();
-    _bytes_writen = 0L;
+    _bytes_written = 0L;
     return;
   }
 
@@ -492,7 +493,7 @@
   }
   _file = fopen(_file_name, "w");
   if (_file != NULL) {
-    _bytes_writen = 0L;
+    _bytes_written = 0L;
     _need_close = true;
   } else {
     tty->print_cr("failed to open rotation log file %s due to %s\n",
@@ -656,9 +657,7 @@
       // Print it as a java-style property list.
       // System properties don't generally contain newlines, so don't bother with unparsing.
       for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
-        xs->text()->print(p->key() ? p->key() : "");
-        xs->text()->print("=");
-        xs->text()->print_cr(p->value() ? p->value() : "");
+        xs->text()->print_cr("%s=%s", p->key(), p->value());
       }
       xs->tail("properties");
     }
--- a/src/share/vm/utilities/ostream.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/ostream.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -231,7 +231,7 @@
 class rotatingFileStream : public fileStream {
  protected:
   char*  _file_name;
-  jlong  _bytes_writen;
+  jlong  _bytes_written;
   uintx  _cur_file_num;             // current logfile rotation number, from 0 to MaxGCLogFileNumbers-1
  public:
   rotatingFileStream(const char* file_name);
--- a/src/share/vm/utilities/top.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/top.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -33,18 +33,18 @@
 #include "utilities/macros.hpp"
 #include "utilities/ostream.hpp"
 #include "utilities/sizes.hpp"
-#ifndef SERIALGC
+#if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1_globals.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
 #endif
+#ifdef COMPILER2
+#include "opto/c2_globals.hpp"
+#endif
 #ifdef GRAAL
 #include "graal/graalGlobals.hpp"
 #endif
-#ifdef COMPILER2
-#include "opto/c2_globals.hpp"
-#endif
 
 // THIS FILE IS INTESIONALLY LEFT EMPTY
 // IT IS USED TO MINIMIZE THE NUMBER OF DEPENDENCIES IN includeDB
--- a/src/share/vm/utilities/vmError.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/vmError.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -491,30 +491,6 @@
        print_bug_submit_message(st, _thread);
      }
 
-#ifdef GRAAL
-  STEP(67, "(printing debug scope)" )
-
-     if (_verbose) {
-       if (_thread != NULL && _thread->is_Java_thread()) {
-         JavaThread* javaThread = (JavaThread*) _thread;
-         DebugScopedValue* ds = javaThread->debug_scope();
-         int level = 0;
-         while (ds != NULL) {
-           if (level == 0) {
-             st->cr();
-             st->print_cr("---------------  D E B U G  S C O P E ---------------");
-             st->cr();
-           }
-           st->print("%d: ", level);
-           ds->print(st);
-           st->cr();
-           ds = ds->parent();
-           level++;
-         }
-       }
-     }
-#endif
-
   STEP(70, "(printing thread)" )
 
      if (_verbose) {
--- a/src/share/vm/utilities/yieldingWorkgroup.cpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/yieldingWorkgroup.cpp	Thu Mar 21 14:11:13 2013 +0100
@@ -23,9 +23,8 @@
  */
 
 #include "precompiled.hpp"
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
 #include "utilities/yieldingWorkgroup.hpp"
-#endif
 
 // Forward declaration of classes declared here.
 
--- a/src/share/vm/utilities/yieldingWorkgroup.hpp	Thu Mar 21 11:30:38 2013 +0100
+++ b/src/share/vm/utilities/yieldingWorkgroup.hpp	Thu Mar 21 14:11:13 2013 +0100
@@ -25,9 +25,10 @@
 #ifndef SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP
 #define SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP
 
-#ifndef SERIALGC
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
 #include "utilities/workgroup.hpp"
-#endif
+#endif // INCLUDE_ALL_GCS
 
 
 // Forward declarations
--- a/test/TEST.ROOT	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/TEST.ROOT	Thu Mar 21 14:11:13 2013 +0100
@@ -28,4 +28,4 @@
 # DO NOT EDIT without first contacting hotspot-regtest@sun.com
 
 # The list of keywords supported in this test suite
-keys=cte_test
+keys=cte_test jcmd nmt regression gc
--- a/test/compiler/5091921/Test6850611.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/compiler/5091921/Test6850611.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @bug 6850611
  * @summary int / long arithmetic seems to be broken in 1.6.0_14 HotSpot Server VM (Win XP)
  *
- * @run main Test6850611
+ * @run main/timeout=480 Test6850611
  */
 
 public class Test6850611 {
--- a/test/compiler/5091921/Test6890943.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/compiler/5091921/Test6890943.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @bug 6890943
  * @summary JVM mysteriously gives wrong result on 64-bit 1.6 VMs in hotspot mode.
  *
- * @run shell Test6890943.sh
+ * @run shell/timeout=240 Test6890943.sh
  */
 import java.util.*;
 import java.io.*;
--- a/test/compiler/5091921/Test6890943.sh	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/compiler/5091921/Test6890943.sh	Thu Mar 21 14:11:13 2013 +0100
@@ -1,6 +1,6 @@
 #!/bin/sh
 # 
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 # 
 # This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,10 @@
 
 ${TESTJAVA}/bin/javac -d . Test6890943.java
 
-${TESTJAVA}/bin/java -XX:-PrintVMOptions ${TESTVMOPTS} Test6890943 < input6890943.txt > test.out 2>&1
+${TESTJAVA}/bin/java -XX:-PrintVMOptions -XX:+IgnoreUnrecognizedVMOptions ${TESTVMOPTS} Test6890943 < input6890943.txt > pretest.out 2>&1
+
+# This test sometimes tickles an unrelated performance warning that interferes with diff.
+grep -v 'warning: Performance bug: SystemDictionary' pretest.out > test.out
 
 diff output6890943.txt test.out
 
--- a/test/compiler/5091921/Test6905845.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/compiler/5091921/Test6905845.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @bug 6905845
  * @summary Server VM improperly optimizing away loop.
  *
- * @run main Test6905845
+ * @run main/timeout=480 Test6905845
  */
 
 public class Test6905845 {
--- a/test/compiler/5091921/Test6992759.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/compiler/5091921/Test6992759.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @bug 6992759
  * @summary Bad code generated for integer <= comparison, fails for Integer.MAX_VALUE
  *
- * @run main Test6992759
+ * @run main/timeout=240 Test6992759
  */
 
 public class Test6992759 {
--- a/test/compiler/6852078/Test6852078.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/compiler/6852078/Test6852078.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @bug 6852078
  * @summary Disable SuperWord optimization for unsafe read/write
  *
- * @run main/othervm Test6852078
+ * @run main Test6852078
  */
 
 import java.util.*;
@@ -50,7 +50,11 @@
     }
 
     public static void main(String [] args) {
+        long start = System.currentTimeMillis();
         for (int i=0; i<2000; i++) {
+            // To protect slow systems from test-too-long timeouts
+            if ((i > 100) && ((System.currentTimeMillis() - start) > 100000))
+               break;
             Test6852078 t = new Test6852078(args);
         }
     }
--- a/test/compiler/7009359/Test7009359.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/compiler/7009359/Test7009359.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,13 +27,13 @@
  * @bug 7009359
  * @summary HS with -XX:+AggressiveOpts optimize new StringBuffer(null) so it does not throw NPE as expected
  *
- * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+OptimizeStringConcat -XX:CompileCommand=exclude,Test7009359,main Test7009359
+ * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+OptimizeStringConcat -XX:CompileCommand=dontinline,Test7009359,stringmakerBUG Test7009359
  *
  */
 
 public class Test7009359 {
     public static void main (String[] args) {
-        for(int i = 0; i < 1000000; i++) {
+        for(int i = 0; i < 100000; i++) {
             if(!stringmakerBUG(null).equals("NPE")) {
                 System.out.println("StringBuffer(null) does not throw NPE");
                 System.exit(97);
--- a/test/compiler/8004741/Test8004741.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/compiler/8004741/Test8004741.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,70 +25,160 @@
  * @test Test8004741.java
  * @bug 8004741
  * @summary Missing compiled exception handle table entry for multidimensional array allocation
+ * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers -XX:+SafepointALot -XX:GuaranteedSafepointInterval=100 Test8004741
  * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers Test8004741
- *
  */
 
 import java.util.*;
 
 public class Test8004741 extends Thread {
 
+  static int passed = 0;
+
+  /**
+   * Loop forever allocating 2-d arrays.
+   * Catches and rethrows all exceptions; in the case of ThreadDeath, increments passed.
+   * Note that passed is incremented here because this is the exception handler with
+   * the smallest scope; we only want to declare success in the case where it is highly
+   * likely that the test condition
+   * (exception in 2-d array alloc interrupted by ThreadDeath)
+   * actually occurs.
+   */
   static int[][] test(int a, int b) throws Exception {
-    int[][] ar = null;
+    int[][] ar;
     try {
       ar = new int[a][b];
-    } catch (Error e) {
-      System.out.println("test got Error");
-      passed = true;
-      throw(e);
-    } catch (Exception e) {
-      System.out.println("test got Exception");
+    } catch (ThreadDeath e) {
+      System.out.println("test got ThreadDeath");
+      passed++;
       throw(e);
     }
     return ar;
   }
 
-  static boolean passed = false;
+  /* Cookbook wait-notify to track progress of test thread. */
+  Object progressLock = new Object();
+  private static final int NOT_STARTED = 0;
+  private static final int RUNNING = 1;
+  private static final int STOPPING = 2;
+
+  int progressState = NOT_STARTED;
 
-  public void run() {
-      System.out.println("test started");
-      try {
-        while(true) {
-          test(2,20000);
+  void toState(int state) {
+    synchronized (progressLock) {
+      progressState = state;
+      progressLock.notify();
+    }
+  }
+
+  void waitFor(int state) {
+    synchronized (progressLock) {
+      while (progressState < state) {
+        try {
+          progressLock.wait();
+        } catch (InterruptedException e) {
+          e.printStackTrace();
+          System.out.println("unexpected InterruptedException");
+          fail();
         }
-      } catch (ThreadDeath e) {
-        System.out.println("test got ThreadDeath");
-        passed = true;
-      } catch (Error e) {
-        e.printStackTrace();
-        System.out.println("test got Error");
-      } catch (Exception e) {
-        e.printStackTrace();
-        System.out.println("test got Exception");
+      }
+      if (progressState > state) {
+        System.out.println("unexpected test state change, expected " +
+                            state + " but saw " + progressState);
+        fail();
+      }
+    }
+  }
+
+  /**
+   * Loops running test until some sort of an exception or error,
+   * expects to see ThreadDeath.
+   */
+  public void run() {
+    try {
+      // Print before state change, so that other thread is most likely
+      // to see this thread executing calls to test() in a loop.
+      System.out.println("thread running");
+      toState(RUNNING);
+      while (true) {
+        // (2,2) (2,10) (2,100) were observed to tickle the bug;
+        test(2, 100);
       }
+    } catch (ThreadDeath e) {
+      // nothing to say, passing was incremented by the test.
+    } catch (Throwable e) {
+      e.printStackTrace();
+      System.out.println("unexpected Throwable " + e);
+      fail();
+    }
+    toState(STOPPING);
+  }
+
+  /**
+   * Runs a single trial of the test in a thread.
+   * No single trial is definitive, since the ThreadDeath
+   * exception might not land in the tested region of code.
+   */
+  public static void threadTest() throws InterruptedException {
+    Test8004741 t = new Test8004741();
+    t.start();
+    t.waitFor(RUNNING);
+    Thread.sleep(100);
+    System.out.println("stopping thread");
+    t.stop();
+    t.waitFor(STOPPING);
+    t.join();
   }
 
   public static void main(String[] args) throws Exception {
+    // Warm up "test"
+    // t will never be started.
     for (int n = 0; n < 11000; n++) {
-      test(2, 20);
+      test(2, 100);
+    }
+
+    // Will this sleep help ensure that the compiler is run?
+    Thread.sleep(500);
+    passed = 0;
+
+    try {
+      test(-1, 100);
+      System.out.println("Missing NegativeArraySizeException #1");
+      fail();
+    } catch ( java.lang.NegativeArraySizeException e ) {
+      System.out.println("Saw expected NegativeArraySizeException #1");
     }
 
-    // First test exception catch
-    Test8004741 t = new Test8004741();
+    try {
+      test(100, -1);
+      fail();
+      System.out.println("Missing NegativeArraySizeException #2");
+      fail();
+    } catch ( java.lang.NegativeArraySizeException e ) {
+      System.out.println("Saw expected NegativeArraySizeException #2");
+    }
 
-    passed = false;
-    t.start();
-    Thread.sleep(1000);
-    t.stop();
+    /* Test repetitions.  If the test succeeds-mostly, it succeeds,
+     * as long as it does not crash (the outcome if the exception range
+     * table entry for the array allocation is missing).
+     */
+    int N = 12;
+    for (int n = 0; n < N; n++) {
+      threadTest();
+    }
 
-    Thread.sleep(5000);
-    t.join();
-    if (passed) {
+    if (passed > N/2) {
+      System.out.println("Saw " + passed + " out of " + N + " possible ThreadDeath hits");
       System.out.println("PASSED");
     } else {
-      System.out.println("FAILED");
-      System.exit(97);
+      System.out.println("Too few ThreadDeath hits; expected at least " + N/2 +
+                         " but saw only " + passed);
+      fail();
     }
   }
 
+  static void fail() {
+    System.out.println("FAILED");
+    System.exit(97);
+  }
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8004867/TestIntAtomicCAS.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,969 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8004867
+ * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob"
+ *
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntAtomicCAS
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntAtomicCAS
+ */
+
+import java.util.concurrent.atomic.AtomicIntegerArray;
+
+public class TestIntAtomicCAS {
+  private static final int ARRLEN = 97;
+  private static final int ITERS  = 11000;
+  private static final int OFFSET = 3;
+  private static final int SCALE = 2;
+  private static final int ALIGN_OFF = 8;
+  private static final int UNALIGN_OFF = 5;
+
+  public static void main(String args[]) {
+    System.out.println("Testing Integer array atomic CAS operations");
+    int errn = test(false);
+    if (errn > 0) {
+      System.err.println("FAILED: " + errn + " errors");
+      System.exit(97);
+    }
+    System.out.println("PASSED");
+  }
+
+  static int test(boolean test_only) {
+    AtomicIntegerArray a1 = new AtomicIntegerArray(ARRLEN);
+    AtomicIntegerArray a2 = new AtomicIntegerArray(ARRLEN);
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1.set(i, -1);
+      a2.set(i, -1);
+    }
+    System.out.println("Warmup");
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+      test_vi(a2, 123, -1);
+      test_cp(a1, a2);
+      test_2ci(a1, a2);
+      test_2vi(a1, a2, 123, 103);
+      test_ci_neg(a1, 123);
+      test_vi_neg(a2, 123, 103);
+      test_cp_neg(a1, a2);
+      test_2ci_neg(a1, a2);
+      test_2vi_neg(a1, a2, 123, 103);
+      test_ci_oppos(a1, 123);
+      test_vi_oppos(a2, 123, 103);
+      test_cp_oppos(a1, a2);
+      test_2ci_oppos(a1, a2);
+      test_2vi_oppos(a1, a2, 123, 103);
+      test_ci_off(a1, 123);
+      test_vi_off(a2, 123, 103);
+      test_cp_off(a1, a2);
+      test_2ci_off(a1, a2);
+      test_2vi_off(a1, a2, 123, 103);
+      test_ci_inv(a1, OFFSET, 123);
+      test_vi_inv(a2, 123, OFFSET, 103);
+      test_cp_inv(a1, a2, OFFSET);
+      test_2ci_inv(a1, a2, OFFSET);
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      test_ci_scl(a1, 123);
+      test_vi_scl(a2, 123, 103);
+      test_cp_scl(a1, a2);
+      test_2ci_scl(a1, a2);
+      test_2vi_scl(a1, a2, 123, 103);
+      test_cp_alndst(a1, a2);
+      test_cp_alnsrc(a1, a2);
+      test_2ci_aln(a1, a2);
+      test_2vi_aln(a1, a2, 123, 103);
+      test_cp_unalndst(a1, a2);
+      test_cp_unalnsrc(a1, a2);
+      test_2ci_unaln(a1, a2);
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1.set(i, -1);
+      a2.set(i, -1);
+    }
+    // Test and verify results
+    System.out.println("Verification");
+    int errn = 0;
+    {
+      test_ci(a1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci: a1", i, a1.get(i), -123);
+      }
+      test_vi(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi: a2", i, a2.get(i), 123);
+      }
+      test_cp(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp: a1", i, a1.get(i), 123);
+      }
+      test_2ci(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci: a2", i, a2.get(i), -103);
+      }
+      test_2vi(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi: a2", i, a2.get(i), 103);
+      }
+      // Reset for negative stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_ci_neg(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_neg: a1", i, a1.get(i), -123);
+      }
+      test_vi_neg(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_neg: a2", i, a2.get(i), 123);
+      }
+      test_cp_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_neg: a1", i, a1.get(i), 123);
+      }
+      test_2ci_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_neg: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_neg: a2", i, a2.get(i), -103);
+      }
+      test_2vi_neg(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_neg: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_neg: a2", i, a2.get(i), 103);
+      }
+      // Reset for opposite stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_ci_oppos(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_oppos: a1", i, a1.get(i), -123);
+      }
+      test_vi_oppos(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_oppos: a2", i, a2.get(i), 123);
+      }
+      test_cp_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_oppos: a1", i, a1.get(i), 123);
+      }
+      test_2ci_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_oppos: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_oppos: a2", i, a2.get(i), -103);
+      }
+      test_2vi_oppos(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_oppos: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_oppos: a2", i, a2.get(i), 103);
+      }
+      // Reset for indexing with offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_ci_off(a1, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_off: a1", i, a1.get(i), -123);
+      }
+      test_vi_off(a2, 123, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_off: a2", i, a2.get(i), 123);
+      }
+      test_cp_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_off: a1", i, a1.get(i), 123);
+      }
+      test_2ci_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_off: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_off: a2", i, a2.get(i), -103);
+      }
+      test_2vi_off(a1, a2, 123, 103);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_off: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_off: a2", i, a2.get(i), 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_off: a1", i, a1.get(i), -1);
+        errn += verify("test_2vi_off: a2", i, a2.get(i), -1);
+      }
+      // Reset for indexing with invariant offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_ci_inv(a1, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_inv: a1", i, a1.get(i), -123);
+      }
+      test_vi_inv(a2, 123, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_inv: a2", i, a2.get(i), 123);
+      }
+      test_cp_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_inv: a1", i, a1.get(i), 123);
+      }
+      test_2ci_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_inv: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_inv: a2", i, a2.get(i), -103);
+      }
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_inv: a2", i, a2.get(i), 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1.get(i), -1);
+        errn += verify("test_2vi_inv: a2", i, a2.get(i), -1);
+      }
+      // Reset for indexing with scale
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_ci_scl(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : -123;
+        errn += verify("test_ci_scl: a1", i, a1.get(i), val);
+      }
+      test_vi_scl(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_vi_scl: a2", i, a2.get(i), val);
+      }
+      test_cp_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_cp_scl: a1", i, a1.get(i), val);
+      }
+      test_2ci_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a1", i, a1.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a1", i*SCALE, a1.get(i*SCALE), -123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a2", i, a2.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a2", i*SCALE, a2.get(i*SCALE), -103);
+        }
+      }
+      test_2vi_scl(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a1", i, a1.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a1", i*SCALE, a1.get(i*SCALE), 123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a2", i, a2.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a2", i*SCALE, a2.get(i*SCALE), 103);
+        }
+      }
+      // Reset for 2 arrays with relative aligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_vi(a2, 123, -1);
+      test_cp_alndst(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1.get(i), 123);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1.set(i, 123);
+      }
+      test_vi(a2, -123, 123);
+      test_cp_alnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1.get(i), -123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1.get(i), 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_2ci_aln(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2.get(i), -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2.get(i), -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_2vi_aln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1.get(i), -1);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2.get(i), 103);
+      }
+
+      // Reset for 2 arrays with relative unaligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_vi(a2, 123, -1);
+      test_cp_unalndst(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1.get(i), 123);
+      }
+      test_vi(a2, -123, 123);
+      test_cp_unalnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), -123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_2ci_unaln(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2.get(i), -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2.get(i), -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_2vi_unaln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1.get(i), -1);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2.get(i), 103);
+      }
+
+      // Reset for aligned overlap initialization
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1.set(i, i);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_cp_alndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alndst_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1.set((i+ALIGN_OFF), -1);
+      }
+      test_cp_alnsrc(a1, a1);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_2ci_aln(a1, a1);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_2vi_aln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 103);
+      }
+
+      // Reset for unaligned overlap initialization
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1.set(i, i);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_cp_unalndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalndst_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1.set((i+UNALIGN_OFF), -1);
+      }
+      test_cp_unalnsrc(a1, a1);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_2ci_unaln(a1, a1);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_2vi_unaln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 103);
+      }
+
+    }
+
+    if (errn > 0 || test_only)
+      return errn;
+
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1.set(i, -1);
+      a2.set(i, -1);
+    }
+    System.out.println("Time");
+    long start, end;
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi(a2, 123, -1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_neg(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_neg(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_neg(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_neg: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_oppos(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_oppos(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_oppos(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_oppos: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_off(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_off(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_off(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_off: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_inv(a1, OFFSET, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_inv(a2, 123, OFFSET, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_inv: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_scl(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_scl(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_scl(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_scl: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_aln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_aln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_aln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_aln: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_unaln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_unaln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_unaln: " + (end - start));
+
+    return errn;
+  }
+
+  static void test_ci(AtomicIntegerArray a) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.compareAndSet(i, -1, -123);
+    }
+  }
+  static void test_vi(AtomicIntegerArray a, int b, int old) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.compareAndSet(i, old, b);
+    }
+  }
+  static void test_cp(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.compareAndSet(i, -123, b.get(i));
+    }
+  }
+  static void test_2ci(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.compareAndSet(i, 123, -123);
+      b.compareAndSet(i, 123, -103);
+    }
+  }
+  static void test_2vi(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.compareAndSet(i, -123, c);
+      b.compareAndSet(i, -103, d);
+    }
+  }
+  static void test_ci_neg(AtomicIntegerArray a, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.compareAndSet(i, old, -123);
+    }
+  }
+  static void test_vi_neg(AtomicIntegerArray a, int b, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.compareAndSet(i, old, b);
+    }
+  }
+  static void test_cp_neg(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.compareAndSet(i, -123, b.get(i));
+    }
+  }
+  static void test_2ci_neg(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.compareAndSet(i, 123, -123);
+      b.compareAndSet(i, 123, -103);
+    }
+  }
+  static void test_2vi_neg(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.compareAndSet(i, -123, c);
+      b.compareAndSet(i, -103, d);
+    }
+  }
+  static void test_ci_oppos(AtomicIntegerArray a, int old) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.compareAndSet((limit-i), old, -123);
+    }
+  }
+  static void test_vi_oppos(AtomicIntegerArray a, int b, int old) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      a.compareAndSet((limit-i), old, b);
+    }
+  }
+  static void test_cp_oppos(AtomicIntegerArray a, AtomicIntegerArray b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.compareAndSet(i, -123, b.get(limit-i));
+    }
+  }
+  static void test_2ci_oppos(AtomicIntegerArray a, AtomicIntegerArray b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.compareAndSet((limit-i), 123, -123);
+      b.compareAndSet(i, 123, -103);
+    }
+  }
+  static void test_2vi_oppos(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      a.compareAndSet(i, -123, c);
+      b.compareAndSet((limit-i), -103, d);
+    }
+  }
+  static void test_ci_off(AtomicIntegerArray a, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.compareAndSet((i+OFFSET), old, -123);
+    }
+  }
+  static void test_vi_off(AtomicIntegerArray a, int b, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.compareAndSet((i+OFFSET), old, b);
+    }
+  }
+  static void test_cp_off(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.compareAndSet((i+OFFSET), -123, b.get(i+OFFSET));
+    }
+  }
+  static void test_2ci_off(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.compareAndSet((i+OFFSET), 123, -123);
+      b.compareAndSet((i+OFFSET), 123, -103);
+    }
+  }
+  static void test_2vi_off(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.compareAndSet((i+OFFSET), -123, c);
+      b.compareAndSet((i+OFFSET), -103, d);
+    }
+  }
+  static void test_ci_inv(AtomicIntegerArray a, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.compareAndSet((i+k), old, -123);
+    }
+  }
+  static void test_vi_inv(AtomicIntegerArray a, int b, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.compareAndSet((i+k), old, b);
+    }
+  }
+  static void test_cp_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.compareAndSet((i+k), -123, b.get(i+k));
+    }
+  }
+  static void test_2ci_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.compareAndSet((i+k), 123, -123);
+      b.compareAndSet((i+k), 123, -103);
+    }
+  }
+  static void test_2vi_inv(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.compareAndSet((i+k), -123, c);
+      b.compareAndSet((i+k), -103, d);
+    }
+  }
+  static void test_ci_scl(AtomicIntegerArray a, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.compareAndSet((i*SCALE), old, -123);
+    }
+  }
+  static void test_vi_scl(AtomicIntegerArray a, int b, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.compareAndSet((i*SCALE), old, b);
+    }
+  }
+  static void test_cp_scl(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.compareAndSet((i*SCALE), -123, b.get(i*SCALE));
+    }
+  }
+  static void test_2ci_scl(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.compareAndSet((i*SCALE), 123, -123);
+      b.compareAndSet((i*SCALE), 123, -103);
+    }
+  }
+  static void test_2vi_scl(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.compareAndSet((i*SCALE), -123, c);
+      b.compareAndSet((i*SCALE), -103, d);
+    }
+  }
+  static void test_cp_alndst(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.compareAndSet((i+ALIGN_OFF), -1, b.get(i));
+    }
+  }
+  static void test_cp_alnsrc(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.getAndSet(i, b.get(i+ALIGN_OFF));
+    }
+  }
+  static void test_2ci_aln(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.compareAndSet((i+ALIGN_OFF), -1, -123);
+      b.getAndSet(i, -103);
+    }
+  }
+  static void test_2vi_aln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.getAndSet(i, c);
+      b.getAndSet((i+ALIGN_OFF), d);
+    }
+  }
+  static void test_cp_unalndst(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.compareAndSet((i+UNALIGN_OFF), -1, b.get(i));
+    }
+  }
+  static void test_cp_unalnsrc(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.getAndSet(i, b.get(i+UNALIGN_OFF));
+    }
+  }
+  static void test_2ci_unaln(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.compareAndSet((i+UNALIGN_OFF), -1, -123);
+      b.getAndSet(i, -103);
+    }
+  }
+  static void test_2vi_unaln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.getAndSet(i, c);
+      b.getAndSet((i+UNALIGN_OFF), d);
+    }
+  }
+
+  static int verify(String text, int i, int elem, int val) {
+    if (elem != val) {
+      System.err.println(text + "[" + i + "] = " + elem + " != " + val);
+      return 1;
+    }
+    return 0;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8004867/TestIntAtomicOrdered.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,969 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8004867
+ * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob"
+ *
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntAtomicOrdered
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntAtomicOrdered
+ */
+
+import java.util.concurrent.atomic.AtomicIntegerArray;
+
+public class TestIntAtomicOrdered {
+  private static final int ARRLEN = 97;
+  private static final int ITERS  = 11000;
+  private static final int OFFSET = 3;
+  private static final int SCALE = 2;
+  private static final int ALIGN_OFF = 8;
+  private static final int UNALIGN_OFF = 5;
+
+  public static void main(String args[]) {
+    System.out.println("Testing Integer array atomic ordered operations");
+    int errn = test(false);
+    if (errn > 0) {
+      System.err.println("FAILED: " + errn + " errors");
+      System.exit(97);
+    }
+    System.out.println("PASSED");
+  }
+
+  static int test(boolean test_only) {
+    AtomicIntegerArray a1 = new AtomicIntegerArray(ARRLEN);
+    AtomicIntegerArray a2 = new AtomicIntegerArray(ARRLEN);
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1.lazySet(i, -1);
+      a2.lazySet(i, -1);
+    }
+    System.out.println("Warmup");
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+      test_vi(a2, 123, -1);
+      test_cp(a1, a2);
+      test_2ci(a1, a2);
+      test_2vi(a1, a2, 123, 103);
+      test_ci_neg(a1, 123);
+      test_vi_neg(a2, 123, 103);
+      test_cp_neg(a1, a2);
+      test_2ci_neg(a1, a2);
+      test_2vi_neg(a1, a2, 123, 103);
+      test_ci_oppos(a1, 123);
+      test_vi_oppos(a2, 123, 103);
+      test_cp_oppos(a1, a2);
+      test_2ci_oppos(a1, a2);
+      test_2vi_oppos(a1, a2, 123, 103);
+      test_ci_off(a1, 123);
+      test_vi_off(a2, 123, 103);
+      test_cp_off(a1, a2);
+      test_2ci_off(a1, a2);
+      test_2vi_off(a1, a2, 123, 103);
+      test_ci_inv(a1, OFFSET, 123);
+      test_vi_inv(a2, 123, OFFSET, 103);
+      test_cp_inv(a1, a2, OFFSET);
+      test_2ci_inv(a1, a2, OFFSET);
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      test_ci_scl(a1, 123);
+      test_vi_scl(a2, 123, 103);
+      test_cp_scl(a1, a2);
+      test_2ci_scl(a1, a2);
+      test_2vi_scl(a1, a2, 123, 103);
+      test_cp_alndst(a1, a2);
+      test_cp_alnsrc(a1, a2);
+      test_2ci_aln(a1, a2);
+      test_2vi_aln(a1, a2, 123, 103);
+      test_cp_unalndst(a1, a2);
+      test_cp_unalnsrc(a1, a2);
+      test_2ci_unaln(a1, a2);
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1.lazySet(i, -1);
+      a2.lazySet(i, -1);
+    }
+    // Test and verify results
+    System.out.println("Verification");
+    int errn = 0;
+    {
+      test_ci(a1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci: a1", i, a1.get(i), -123);
+      }
+      test_vi(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi: a2", i, a2.get(i), 123);
+      }
+      test_cp(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp: a1", i, a1.get(i), 123);
+      }
+      test_2ci(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci: a2", i, a2.get(i), -103);
+      }
+      test_2vi(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi: a2", i, a2.get(i), 103);
+      }
+      // Reset for negative stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_ci_neg(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_neg: a1", i, a1.get(i), -123);
+      }
+      test_vi_neg(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_neg: a2", i, a2.get(i), 123);
+      }
+      test_cp_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_neg: a1", i, a1.get(i), 123);
+      }
+      test_2ci_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_neg: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_neg: a2", i, a2.get(i), -103);
+      }
+      test_2vi_neg(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_neg: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_neg: a2", i, a2.get(i), 103);
+      }
+      // Reset for opposite stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_ci_oppos(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_oppos: a1", i, a1.get(i), -123);
+      }
+      test_vi_oppos(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_oppos: a2", i, a2.get(i), 123);
+      }
+      test_cp_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_oppos: a1", i, a1.get(i), 123);
+      }
+      test_2ci_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_oppos: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_oppos: a2", i, a2.get(i), -103);
+      }
+      test_2vi_oppos(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_oppos: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_oppos: a2", i, a2.get(i), 103);
+      }
+      // Reset for indexing with offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_ci_off(a1, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_off: a1", i, a1.get(i), -123);
+      }
+      test_vi_off(a2, 123, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_off: a2", i, a2.get(i), 123);
+      }
+      test_cp_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_off: a1", i, a1.get(i), 123);
+      }
+      test_2ci_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_off: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_off: a2", i, a2.get(i), -103);
+      }
+      test_2vi_off(a1, a2, 123, 103);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_off: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_off: a2", i, a2.get(i), 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_off: a1", i, a1.get(i), -1);
+        errn += verify("test_2vi_off: a2", i, a2.get(i), -1);
+      }
+      // Reset for indexing with invariant offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_ci_inv(a1, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_inv: a1", i, a1.get(i), -123);
+      }
+      test_vi_inv(a2, 123, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_inv: a2", i, a2.get(i), 123);
+      }
+      test_cp_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_inv: a1", i, a1.get(i), 123);
+      }
+      test_2ci_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_inv: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_inv: a2", i, a2.get(i), -103);
+      }
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_inv: a2", i, a2.get(i), 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1.get(i), -1);
+        errn += verify("test_2vi_inv: a2", i, a2.get(i), -1);
+      }
+      // Reset for indexing with scale
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_ci_scl(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : -123;
+        errn += verify("test_ci_scl: a1", i, a1.get(i), val);
+      }
+      test_vi_scl(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_vi_scl: a2", i, a2.get(i), val);
+      }
+      test_cp_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_cp_scl: a1", i, a1.get(i), val);
+      }
+      test_2ci_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a1", i, a1.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a1", i*SCALE, a1.get(i*SCALE), -123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a2", i, a2.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a2", i*SCALE, a2.get(i*SCALE), -103);
+        }
+      }
+      test_2vi_scl(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a1", i, a1.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a1", i*SCALE, a1.get(i*SCALE), 123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a2", i, a2.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a2", i*SCALE, a2.get(i*SCALE), 103);
+        }
+      }
+      // Reset for 2 arrays with relative aligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_vi(a2, 123, -1);
+      test_cp_alndst(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1.get(i), 123);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1.lazySet(i, 123);
+      }
+      test_vi(a2, -123, 123);
+      test_cp_alnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1.get(i), -123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1.get(i), 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_2ci_aln(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2.get(i), -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2.get(i), -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_2vi_aln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1.get(i), -1);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2.get(i), 103);
+      }
+
+      // Reset for 2 arrays with relative unaligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_vi(a2, 123, -1);
+      test_cp_unalndst(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1.get(i), 123);
+      }
+      test_vi(a2, -123, 123);
+      test_cp_unalnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), -123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_2ci_unaln(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2.get(i), -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2.get(i), -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+        a2.lazySet(i, -1);
+      }
+      test_2vi_unaln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1.get(i), -1);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2.get(i), 103);
+      }
+
+      // Reset for aligned overlap initialization
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1.lazySet(i, i);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+      }
+      test_cp_alndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alndst_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1.lazySet((i+ALIGN_OFF), -1);
+      }
+      test_cp_alnsrc(a1, a1);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+      }
+      test_2ci_aln(a1, a1);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+      }
+      test_2vi_aln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 103);
+      }
+
+      // Reset for unaligned overlap initialization
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1.lazySet(i, i);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+      }
+      test_cp_unalndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalndst_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1.lazySet((i+UNALIGN_OFF), -1);
+      }
+      test_cp_unalnsrc(a1, a1);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+      }
+      test_2ci_unaln(a1, a1);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.lazySet(i, -1);
+      }
+      test_2vi_unaln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 103);
+      }
+
+    }
+
+    if (errn > 0 || test_only)
+      return errn;
+
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1.lazySet(i, -1);
+      a2.lazySet(i, -1);
+    }
+    System.out.println("Time");
+    long start, end;
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi(a2, 123, -1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_neg(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_neg(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_neg(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_neg: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_oppos(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_oppos(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_oppos(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_oppos: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_off(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_off(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_off(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_off: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_inv(a1, OFFSET, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_inv(a2, 123, OFFSET, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_inv: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_scl(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_scl(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_scl(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_scl: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_aln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_aln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_aln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_aln: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_unaln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_unaln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_unaln: " + (end - start));
+
+    return errn;
+  }
+
+  static void test_ci(AtomicIntegerArray a) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.lazySet(i, -123);
+    }
+  }
+  static void test_vi(AtomicIntegerArray a, int b, int old) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.lazySet(i, b);
+    }
+  }
+  static void test_cp(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.lazySet(i, b.get(i));
+    }
+  }
+  static void test_2ci(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.lazySet(i, -123);
+      b.lazySet(i, -103);
+    }
+  }
+  static void test_2vi(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.lazySet(i, c);
+      b.lazySet(i, d);
+    }
+  }
+  static void test_ci_neg(AtomicIntegerArray a, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.lazySet(i,-123);
+    }
+  }
+  static void test_vi_neg(AtomicIntegerArray a, int b, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.lazySet(i, b);
+    }
+  }
+  static void test_cp_neg(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.lazySet(i, b.get(i));
+    }
+  }
+  static void test_2ci_neg(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.lazySet(i, -123);
+      b.lazySet(i, -103);
+    }
+  }
+  static void test_2vi_neg(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.lazySet(i, c);
+      b.lazySet(i, d);
+    }
+  }
+  static void test_ci_oppos(AtomicIntegerArray a, int old) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.lazySet((limit-i), -123);
+    }
+  }
+  static void test_vi_oppos(AtomicIntegerArray a, int b, int old) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      a.lazySet((limit-i), b);
+    }
+  }
+  static void test_cp_oppos(AtomicIntegerArray a, AtomicIntegerArray b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.lazySet(i, b.get(limit-i));
+    }
+  }
+  static void test_2ci_oppos(AtomicIntegerArray a, AtomicIntegerArray b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.lazySet((limit-i), -123);
+      b.lazySet(i, -103);
+    }
+  }
+  static void test_2vi_oppos(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      a.lazySet(i, c);
+      b.lazySet((limit-i), d);
+    }
+  }
+  static void test_ci_off(AtomicIntegerArray a, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.lazySet((i+OFFSET), -123);
+    }
+  }
+  static void test_vi_off(AtomicIntegerArray a, int b, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.lazySet((i+OFFSET), b);
+    }
+  }
+  static void test_cp_off(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.lazySet((i+OFFSET), b.get(i+OFFSET));
+    }
+  }
+  static void test_2ci_off(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.lazySet((i+OFFSET), -123);
+      b.lazySet((i+OFFSET), -103);
+    }
+  }
+  static void test_2vi_off(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.lazySet((i+OFFSET), c);
+      b.lazySet((i+OFFSET), d);
+    }
+  }
+  static void test_ci_inv(AtomicIntegerArray a, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.lazySet((i+k),-123);
+    }
+  }
+  static void test_vi_inv(AtomicIntegerArray a, int b, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.lazySet((i+k), b);
+    }
+  }
+  static void test_cp_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.lazySet((i+k), b.get(i+k));
+    }
+  }
+  static void test_2ci_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.lazySet((i+k), -123);
+      b.lazySet((i+k), -103);
+    }
+  }
+  static void test_2vi_inv(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.lazySet((i+k), c);
+      b.lazySet((i+k), d);
+    }
+  }
+  static void test_ci_scl(AtomicIntegerArray a, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.lazySet((i*SCALE), -123);
+    }
+  }
+  static void test_vi_scl(AtomicIntegerArray a, int b, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.lazySet((i*SCALE), b);
+    }
+  }
+  static void test_cp_scl(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.lazySet((i*SCALE), b.get(i*SCALE));
+    }
+  }
+  static void test_2ci_scl(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.lazySet((i*SCALE), -123);
+      b.lazySet((i*SCALE), -103);
+    }
+  }
+  static void test_2vi_scl(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.lazySet((i*SCALE), c);
+      b.lazySet((i*SCALE), d);
+    }
+  }
+  static void test_cp_alndst(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.lazySet((i+ALIGN_OFF), b.get(i));
+    }
+  }
+  static void test_cp_alnsrc(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.lazySet(i, b.get(i+ALIGN_OFF));
+    }
+  }
+  static void test_2ci_aln(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.lazySet((i+ALIGN_OFF), -123);
+      b.lazySet(i, -103);
+    }
+  }
+  static void test_2vi_aln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.lazySet(i, c);
+      b.lazySet((i+ALIGN_OFF), d);
+    }
+  }
+  static void test_cp_unalndst(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.lazySet((i+UNALIGN_OFF), b.get(i));
+    }
+  }
+  static void test_cp_unalnsrc(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.lazySet(i, b.get(i+UNALIGN_OFF));
+    }
+  }
+  static void test_2ci_unaln(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.lazySet((i+UNALIGN_OFF), -123);
+      b.lazySet(i, -103);
+    }
+  }
+  static void test_2vi_unaln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.lazySet(i, c);
+      b.lazySet((i+UNALIGN_OFF), d);
+    }
+  }
+
+  static int verify(String text, int i, int elem, int val) {
+    if (elem != val) {
+      System.err.println(text + "[" + i + "] = " + elem + " != " + val);
+      return 1;
+    }
+    return 0;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8004867/TestIntAtomicVolatile.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,969 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8004867
+ * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob"
+ *
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntAtomicVolatile
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntAtomicVolatile
+ */
+
+import java.util.concurrent.atomic.AtomicIntegerArray;
+
+public class TestIntAtomicVolatile {
+  private static final int ARRLEN = 97;
+  private static final int ITERS  = 11000;
+  private static final int OFFSET = 3;
+  private static final int SCALE = 2;
+  private static final int ALIGN_OFF = 8;
+  private static final int UNALIGN_OFF = 5;
+
+  public static void main(String args[]) {
+    System.out.println("Testing Integer array atomic volatile operations");
+    int errn = test(false);
+    if (errn > 0) {
+      System.err.println("FAILED: " + errn + " errors");
+      System.exit(97);
+    }
+    System.out.println("PASSED");
+  }
+
+  static int test(boolean test_only) {
+    AtomicIntegerArray a1 = new AtomicIntegerArray(ARRLEN);
+    AtomicIntegerArray a2 = new AtomicIntegerArray(ARRLEN);
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1.set(i, -1);
+      a2.set(i, -1);
+    }
+    System.out.println("Warmup");
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+      test_vi(a2, 123, -1);
+      test_cp(a1, a2);
+      test_2ci(a1, a2);
+      test_2vi(a1, a2, 123, 103);
+      test_ci_neg(a1, 123);
+      test_vi_neg(a2, 123, 103);
+      test_cp_neg(a1, a2);
+      test_2ci_neg(a1, a2);
+      test_2vi_neg(a1, a2, 123, 103);
+      test_ci_oppos(a1, 123);
+      test_vi_oppos(a2, 123, 103);
+      test_cp_oppos(a1, a2);
+      test_2ci_oppos(a1, a2);
+      test_2vi_oppos(a1, a2, 123, 103);
+      test_ci_off(a1, 123);
+      test_vi_off(a2, 123, 103);
+      test_cp_off(a1, a2);
+      test_2ci_off(a1, a2);
+      test_2vi_off(a1, a2, 123, 103);
+      test_ci_inv(a1, OFFSET, 123);
+      test_vi_inv(a2, 123, OFFSET, 103);
+      test_cp_inv(a1, a2, OFFSET);
+      test_2ci_inv(a1, a2, OFFSET);
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      test_ci_scl(a1, 123);
+      test_vi_scl(a2, 123, 103);
+      test_cp_scl(a1, a2);
+      test_2ci_scl(a1, a2);
+      test_2vi_scl(a1, a2, 123, 103);
+      test_cp_alndst(a1, a2);
+      test_cp_alnsrc(a1, a2);
+      test_2ci_aln(a1, a2);
+      test_2vi_aln(a1, a2, 123, 103);
+      test_cp_unalndst(a1, a2);
+      test_cp_unalnsrc(a1, a2);
+      test_2ci_unaln(a1, a2);
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1.set(i, -1);
+      a2.set(i, -1);
+    }
+    // Test and verify results
+    System.out.println("Verification");
+    int errn = 0;
+    {
+      test_ci(a1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci: a1", i, a1.get(i), -123);
+      }
+      test_vi(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi: a2", i, a2.get(i), 123);
+      }
+      test_cp(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp: a1", i, a1.get(i), 123);
+      }
+      test_2ci(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci: a2", i, a2.get(i), -103);
+      }
+      test_2vi(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi: a2", i, a2.get(i), 103);
+      }
+      // Reset for negative stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_ci_neg(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_neg: a1", i, a1.get(i), -123);
+      }
+      test_vi_neg(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_neg: a2", i, a2.get(i), 123);
+      }
+      test_cp_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_neg: a1", i, a1.get(i), 123);
+      }
+      test_2ci_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_neg: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_neg: a2", i, a2.get(i), -103);
+      }
+      test_2vi_neg(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_neg: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_neg: a2", i, a2.get(i), 103);
+      }
+      // Reset for opposite stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_ci_oppos(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_oppos: a1", i, a1.get(i), -123);
+      }
+      test_vi_oppos(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_oppos: a2", i, a2.get(i), 123);
+      }
+      test_cp_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_oppos: a1", i, a1.get(i), 123);
+      }
+      test_2ci_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_oppos: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_oppos: a2", i, a2.get(i), -103);
+      }
+      test_2vi_oppos(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_oppos: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_oppos: a2", i, a2.get(i), 103);
+      }
+      // Reset for indexing with offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_ci_off(a1, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_off: a1", i, a1.get(i), -123);
+      }
+      test_vi_off(a2, 123, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_off: a2", i, a2.get(i), 123);
+      }
+      test_cp_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_off: a1", i, a1.get(i), 123);
+      }
+      test_2ci_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_off: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_off: a2", i, a2.get(i), -103);
+      }
+      test_2vi_off(a1, a2, 123, 103);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_off: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_off: a2", i, a2.get(i), 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_off: a1", i, a1.get(i), -1);
+        errn += verify("test_2vi_off: a2", i, a2.get(i), -1);
+      }
+      // Reset for indexing with invariant offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_ci_inv(a1, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_inv: a1", i, a1.get(i), -123);
+      }
+      test_vi_inv(a2, 123, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_inv: a2", i, a2.get(i), 123);
+      }
+      test_cp_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_inv: a1", i, a1.get(i), 123);
+      }
+      test_2ci_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_inv: a1", i, a1.get(i), -123);
+        errn += verify("test_2ci_inv: a2", i, a2.get(i), -103);
+      }
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1.get(i), 123);
+        errn += verify("test_2vi_inv: a2", i, a2.get(i), 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1.get(i), -1);
+        errn += verify("test_2vi_inv: a2", i, a2.get(i), -1);
+      }
+      // Reset for indexing with scale
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_ci_scl(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : -123;
+        errn += verify("test_ci_scl: a1", i, a1.get(i), val);
+      }
+      test_vi_scl(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_vi_scl: a2", i, a2.get(i), val);
+      }
+      test_cp_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_cp_scl: a1", i, a1.get(i), val);
+      }
+      test_2ci_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a1", i, a1.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a1", i*SCALE, a1.get(i*SCALE), -123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a2", i, a2.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a2", i*SCALE, a2.get(i*SCALE), -103);
+        }
+      }
+      test_2vi_scl(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a1", i, a1.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a1", i*SCALE, a1.get(i*SCALE), 123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a2", i, a2.get(i), -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a2", i*SCALE, a2.get(i*SCALE), 103);
+        }
+      }
+      // Reset for 2 arrays with relative aligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_vi(a2, 123, -1);
+      test_cp_alndst(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1.get(i), 123);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1.set(i, 123);
+      }
+      test_vi(a2, -123, 123);
+      test_cp_alnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1.get(i), -123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1.get(i), 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_2ci_aln(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2.get(i), -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2.get(i), -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_2vi_aln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1.get(i), -1);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2.get(i), 103);
+      }
+
+      // Reset for 2 arrays with relative unaligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_vi(a2, 123, -1);
+      test_cp_unalndst(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1.get(i), 123);
+      }
+      test_vi(a2, -123, 123);
+      test_cp_unalnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), -123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_2ci_unaln(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2.get(i), -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2.get(i), -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+        a2.set(i, -1);
+      }
+      test_2vi_unaln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1.get(i), -1);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2.get(i), 103);
+      }
+
+      // Reset for aligned overlap initialization
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1.set(i, i);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_cp_alndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alndst_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1.set((i+ALIGN_OFF), -1);
+      }
+      test_cp_alnsrc(a1, a1);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_2ci_aln(a1, a1);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_2vi_aln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 103);
+      }
+
+      // Reset for unaligned overlap initialization
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1.set(i, i);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_cp_unalndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalndst_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1.set((i+UNALIGN_OFF), -1);
+      }
+      test_cp_unalnsrc(a1, a1);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_2ci_unaln(a1, a1);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1.set(i, -1);
+      }
+      test_2vi_unaln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 103);
+      }
+
+    }
+
+    if (errn > 0 || test_only)
+      return errn;
+
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1.set(i, -1);
+      a2.set(i, -1);
+    }
+    System.out.println("Time");
+    long start, end;
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi(a2, 123, -1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_neg(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_neg(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_neg(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_neg: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_oppos(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_oppos(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_oppos(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_oppos: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_off(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_off(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_off(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_off: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_inv(a1, OFFSET, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_inv(a2, 123, OFFSET, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_inv: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_scl(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_scl(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_scl(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_scl: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_aln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_aln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_aln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_aln: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_unaln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_unaln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_unaln: " + (end - start));
+
+    return errn;
+  }
+
+  static void test_ci(AtomicIntegerArray a) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.set(i, -123);
+    }
+  }
+  static void test_vi(AtomicIntegerArray a, int b, int old) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.set(i, b);
+    }
+  }
+  static void test_cp(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.set(i, b.get(i));
+    }
+  }
+  static void test_2ci(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.set(i, -123);
+      b.set(i, -103);
+    }
+  }
+  static void test_2vi(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.set(i, c);
+      b.set(i, d);
+    }
+  }
+  static void test_ci_neg(AtomicIntegerArray a, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.set(i,-123);
+    }
+  }
+  static void test_vi_neg(AtomicIntegerArray a, int b, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.set(i, b);
+    }
+  }
+  static void test_cp_neg(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.set(i, b.get(i));
+    }
+  }
+  static void test_2ci_neg(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.set(i, -123);
+      b.set(i, -103);
+    }
+  }
+  static void test_2vi_neg(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      a.set(i, c);
+      b.set(i, d);
+    }
+  }
+  static void test_ci_oppos(AtomicIntegerArray a, int old) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.set((limit-i), -123);
+    }
+  }
+  static void test_vi_oppos(AtomicIntegerArray a, int b, int old) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      a.set((limit-i), b);
+    }
+  }
+  static void test_cp_oppos(AtomicIntegerArray a, AtomicIntegerArray b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.set(i, b.get(limit-i));
+    }
+  }
+  static void test_2ci_oppos(AtomicIntegerArray a, AtomicIntegerArray b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      a.set((limit-i), -123);
+      b.set(i, -103);
+    }
+  }
+  static void test_2vi_oppos(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      a.set(i, c);
+      b.set((limit-i), d);
+    }
+  }
+  static void test_ci_off(AtomicIntegerArray a, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.set((i+OFFSET), -123);
+    }
+  }
+  static void test_vi_off(AtomicIntegerArray a, int b, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.set((i+OFFSET), b);
+    }
+  }
+  static void test_cp_off(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.set((i+OFFSET), b.get(i+OFFSET));
+    }
+  }
+  static void test_2ci_off(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.set((i+OFFSET), -123);
+      b.set((i+OFFSET), -103);
+    }
+  }
+  static void test_2vi_off(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      a.set((i+OFFSET), c);
+      b.set((i+OFFSET), d);
+    }
+  }
+  static void test_ci_inv(AtomicIntegerArray a, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.set((i+k),-123);
+    }
+  }
+  static void test_vi_inv(AtomicIntegerArray a, int b, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.set((i+k), b);
+    }
+  }
+  static void test_cp_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.set((i+k), b.get(i+k));
+    }
+  }
+  static void test_2ci_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.set((i+k), -123);
+      b.set((i+k), -103);
+    }
+  }
+  static void test_2vi_inv(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      a.set((i+k), c);
+      b.set((i+k), d);
+    }
+  }
+  static void test_ci_scl(AtomicIntegerArray a, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.set((i*SCALE), -123);
+    }
+  }
+  static void test_vi_scl(AtomicIntegerArray a, int b, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.set((i*SCALE), b);
+    }
+  }
+  static void test_cp_scl(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.set((i*SCALE), b.get(i*SCALE));
+    }
+  }
+  static void test_2ci_scl(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.set((i*SCALE), -123);
+      b.set((i*SCALE), -103);
+    }
+  }
+  static void test_2vi_scl(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      a.set((i*SCALE), c);
+      b.set((i*SCALE), d);
+    }
+  }
+  static void test_cp_alndst(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.set((i+ALIGN_OFF), b.get(i));
+    }
+  }
+  static void test_cp_alnsrc(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.set(i, b.get(i+ALIGN_OFF));
+    }
+  }
+  static void test_2ci_aln(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.set((i+ALIGN_OFF), -123);
+      b.set(i, -103);
+    }
+  }
+  static void test_2vi_aln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      a.set(i, c);
+      b.set((i+ALIGN_OFF), d);
+    }
+  }
+  static void test_cp_unalndst(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.set((i+UNALIGN_OFF), b.get(i));
+    }
+  }
+  static void test_cp_unalnsrc(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.set(i, b.get(i+UNALIGN_OFF));
+    }
+  }
+  static void test_2ci_unaln(AtomicIntegerArray a, AtomicIntegerArray b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.set((i+UNALIGN_OFF), -123);
+      b.set(i, -103);
+    }
+  }
+  static void test_2vi_unaln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      a.set(i, c);
+      b.set((i+UNALIGN_OFF), d);
+    }
+  }
+
+  static int verify(String text, int i, int elem, int val) {
+    if (elem != val) {
+      System.err.println(text + "[" + i + "] = " + elem + " != " + val);
+      return 1;
+    }
+    return 0;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8004867/TestIntUnsafeCAS.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,998 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8004867
+ * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob"
+ *
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntUnsafeCAS
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntUnsafeCAS
+ */
+
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+public class TestIntUnsafeCAS {
+  private static final int ARRLEN = 97;
+  private static final int ITERS  = 11000;
+  private static final int OFFSET = 3;
+  private static final int SCALE = 2;
+  private static final int ALIGN_OFF = 8;
+  private static final int UNALIGN_OFF = 5;
+
+  private static final Unsafe unsafe;
+  private static final int BASE;
+  static {
+    try {
+      Class c = TestIntUnsafeCAS.class.getClassLoader().loadClass("sun.misc.Unsafe");
+      Field f = c.getDeclaredField("theUnsafe");
+      f.setAccessible(true);
+      unsafe = (Unsafe)f.get(c);
+      BASE = unsafe.arrayBaseOffset(int[].class);
+    } catch (Exception e) {
+      InternalError err = new InternalError();
+      err.initCause(e);
+      throw err;
+    }
+  }
+
+  public static void main(String args[]) {
+    System.out.println("Testing Integer array unsafe CAS operations");
+    int errn = test(false);
+    if (errn > 0) {
+      System.err.println("FAILED: " + errn + " errors");
+      System.exit(97);
+    }
+    System.out.println("PASSED");
+  }
+
+  static int test(boolean test_only) {
+    int[] a1 = new int[ARRLEN];
+    int[] a2 = new int[ARRLEN];
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1[i] = -1;
+      a2[i] = -1;
+    }
+    System.out.println("Warmup");
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+      test_vi(a2, 123, -1);
+      test_cp(a1, a2);
+      test_2ci(a1, a2);
+      test_2vi(a1, a2, 123, 103);
+      test_ci_neg(a1, 123);
+      test_vi_neg(a2, 123, 103);
+      test_cp_neg(a1, a2);
+      test_2ci_neg(a1, a2);
+      test_2vi_neg(a1, a2, 123, 103);
+      test_ci_oppos(a1, 123);
+      test_vi_oppos(a2, 123, 103);
+      test_cp_oppos(a1, a2);
+      test_2ci_oppos(a1, a2);
+      test_2vi_oppos(a1, a2, 123, 103);
+      test_ci_off(a1, 123);
+      test_vi_off(a2, 123, 103);
+      test_cp_off(a1, a2);
+      test_2ci_off(a1, a2);
+      test_2vi_off(a1, a2, 123, 103);
+      test_ci_inv(a1, OFFSET, 123);
+      test_vi_inv(a2, 123, OFFSET, 103);
+      test_cp_inv(a1, a2, OFFSET);
+      test_2ci_inv(a1, a2, OFFSET);
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      test_ci_scl(a1, 123);
+      test_vi_scl(a2, 123, 103);
+      test_cp_scl(a1, a2);
+      test_2ci_scl(a1, a2);
+      test_2vi_scl(a1, a2, 123, 103);
+      test_cp_alndst(a1, a2);
+      test_cp_alnsrc(a1, a2);
+      test_2ci_aln(a1, a2);
+      test_2vi_aln(a1, a2, 123, 103);
+      test_cp_unalndst(a1, a2);
+      test_cp_unalnsrc(a1, a2);
+      test_2ci_unaln(a1, a2);
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1[i] = -1;
+      a2[i] = -1;
+    }
+    // Test and verify results
+    System.out.println("Verification");
+    int errn = 0;
+    {
+      test_ci(a1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci: a1", i, a1[i], -123);
+      }
+      test_vi(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi: a2", i, a2[i], 123);
+      }
+      test_cp(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp: a1", i, a1[i], 123);
+      }
+      test_2ci(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci: a1", i, a1[i], -123);
+        errn += verify("test_2ci: a2", i, a2[i], -103);
+      }
+      test_2vi(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi: a1", i, a1[i], 123);
+        errn += verify("test_2vi: a2", i, a2[i], 103);
+      }
+      // Reset for negative stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_neg(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_neg: a1", i, a1[i], -123);
+      }
+      test_vi_neg(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_neg: a2", i, a2[i], 123);
+      }
+      test_cp_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_neg: a1", i, a1[i], 123);
+      }
+      test_2ci_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_neg: a1", i, a1[i], -123);
+        errn += verify("test_2ci_neg: a2", i, a2[i], -103);
+      }
+      test_2vi_neg(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_neg: a1", i, a1[i], 123);
+        errn += verify("test_2vi_neg: a2", i, a2[i], 103);
+      }
+      // Reset for opposite stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_oppos(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_oppos: a1", i, a1[i], -123);
+      }
+      test_vi_oppos(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_oppos: a2", i, a2[i], 123);
+      }
+      test_cp_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_oppos: a1", i, a1[i], 123);
+      }
+      test_2ci_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_oppos: a1", i, a1[i], -123);
+        errn += verify("test_2ci_oppos: a2", i, a2[i], -103);
+      }
+      test_2vi_oppos(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_oppos: a1", i, a1[i], 123);
+        errn += verify("test_2vi_oppos: a2", i, a2[i], 103);
+      }
+      // Reset for indexing with offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_off(a1, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_off: a1", i, a1[i], -123);
+      }
+      test_vi_off(a2, 123, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_off: a2", i, a2[i], 123);
+      }
+      test_cp_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_off: a1", i, a1[i], 123);
+      }
+      test_2ci_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_off: a1", i, a1[i], -123);
+        errn += verify("test_2ci_off: a2", i, a2[i], -103);
+      }
+      test_2vi_off(a1, a2, 123, 103);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_off: a1", i, a1[i], 123);
+        errn += verify("test_2vi_off: a2", i, a2[i], 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_off: a1", i, a1[i], -1);
+        errn += verify("test_2vi_off: a2", i, a2[i], -1);
+      }
+      // Reset for indexing with invariant offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_inv(a1, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_inv: a1", i, a1[i], -123);
+      }
+      test_vi_inv(a2, 123, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_inv: a2", i, a2[i], 123);
+      }
+      test_cp_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_inv: a1", i, a1[i], 123);
+      }
+      test_2ci_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_inv: a1", i, a1[i], -123);
+        errn += verify("test_2ci_inv: a2", i, a2[i], -103);
+      }
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1[i], 123);
+        errn += verify("test_2vi_inv: a2", i, a2[i], 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1[i], -1);
+        errn += verify("test_2vi_inv: a2", i, a2[i], -1);
+      }
+      // Reset for indexing with scale
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_scl(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : -123;
+        errn += verify("test_ci_scl: a1", i, a1[i], val);
+      }
+      test_vi_scl(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_vi_scl: a2", i, a2[i], val);
+      }
+      test_cp_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_cp_scl: a1", i, a1[i], val);
+      }
+      test_2ci_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a1", i, a1[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a1", i*SCALE, a1[i*SCALE], -123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a2", i, a2[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a2", i*SCALE, a2[i*SCALE], -103);
+        }
+      }
+      test_2vi_scl(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a1", i, a1[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a1", i*SCALE, a1[i*SCALE], 123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a2", i, a2[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a2", i*SCALE, a2[i*SCALE], 103);
+        }
+      }
+      // Reset for 2 arrays with relative aligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_vi(a2, 123, -1);
+      test_cp_alndst(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1[i], 123);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1[i] = 123;
+      }
+      test_vi(a2, -123, 123);
+      test_cp_alnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1[i], -123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1[i], 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2ci_aln(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2[i], -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2[i], -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2vi_aln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1[i], -1);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2[i], 103);
+      }
+
+      // Reset for 2 arrays with relative unaligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_vi(a2, 123, -1);
+      test_cp_unalndst(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1[i], 123);
+      }
+      test_vi(a2, -123, 123);
+      test_cp_unalnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1[i], -123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1[i], 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2ci_unaln(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2[i], -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2[i], -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2vi_unaln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1[i], -1);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2[i], 103);
+      }
+
+      // Reset for aligned overlap initialization
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1[i] = i;
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_cp_alndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alndst_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1[i+ALIGN_OFF] = -1;
+      }
+      test_cp_alnsrc(a1, a1);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2ci_aln(a1, a1);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2vi_aln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 103);
+      }
+
+      // Reset for unaligned overlap initialization
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1[i] = i;
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_cp_unalndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalndst_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1[i+UNALIGN_OFF] = -1;
+      }
+      test_cp_unalnsrc(a1, a1);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2ci_unaln(a1, a1);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2vi_unaln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 103);
+      }
+
+    }
+
+    if (errn > 0 || test_only)
+      return errn;
+
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1[i] = -1;
+      a2[i] = -1;
+    }
+    System.out.println("Time");
+    long start, end;
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi(a2, 123, -1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_neg(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_neg(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_neg(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_neg: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_oppos(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_oppos(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_oppos(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_oppos: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_off(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_off(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_off(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_off: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_inv(a1, OFFSET, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_inv(a2, 123, OFFSET, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_inv: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_scl(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_scl(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_scl(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_scl: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_aln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_aln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_aln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_aln: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_unaln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_unaln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_unaln: " + (end - start));
+
+    return errn;
+  }
+
+  private final static long byte_offset(int i) {
+    return ((long)i << 2) + BASE;
+  }
+
+  static void test_ci(int[] a) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), -1, -123);
+    }
+  }
+  static void test_vi(int[] a, int b, int old) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), old, b);
+    }
+  }
+  static void test_cp(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), -123, b[i]);
+    }
+  }
+  static void test_2ci(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), 123, -123);
+      unsafe.compareAndSwapInt(b, byte_offset(i), 123, -103);
+    }
+  }
+  static void test_2vi(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), -123, c);
+      unsafe.compareAndSwapInt(b, byte_offset(i), -103, d);
+    }
+  }
+  static void test_ci_neg(int[] a, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), old, -123);
+    }
+  }
+  static void test_vi_neg(int[] a, int b, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), old, b);
+    }
+  }
+  static void test_cp_neg(int[] a, int[] b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), -123, b[i]);
+    }
+  }
+  static void test_2ci_neg(int[] a, int[] b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), 123, -123);
+      unsafe.compareAndSwapInt(b, byte_offset(i), 123, -103);
+    }
+  }
+  static void test_2vi_neg(int[] a, int[] b, int c, int d) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), -123, c);
+      unsafe.compareAndSwapInt(b, byte_offset(i), -103, d);
+    }
+  }
+  static void test_ci_oppos(int[] a, int old) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(limit-i), old, -123);
+    }
+  }
+  static void test_vi_oppos(int[] a, int b, int old) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(limit-i), old, b);
+    }
+  }
+  static void test_cp_oppos(int[] a, int[] b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), -123, b[limit-i]);
+    }
+  }
+  static void test_2ci_oppos(int[] a, int[] b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(limit-i), 123, -123);
+      unsafe.compareAndSwapInt(b, byte_offset(i), 123, -103);
+    }
+  }
+  static void test_2vi_oppos(int[] a, int[] b, int c, int d) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i), -123, c);
+      unsafe.compareAndSwapInt(b, byte_offset(limit-i), -103, d);
+    }
+  }
+  static void test_ci_off(int[] a, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), old, -123);
+    }
+  }
+  static void test_vi_off(int[] a, int b, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), old, b);
+    }
+  }
+  static void test_cp_off(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), -123, b[i+OFFSET]);
+    }
+  }
+  static void test_2ci_off(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), 123, -123);
+      unsafe.compareAndSwapInt(b, byte_offset(i+OFFSET), 123, -103);
+    }
+  }
+  static void test_2vi_off(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), -123, c);
+      unsafe.compareAndSwapInt(b, byte_offset(i+OFFSET), -103, d);
+    }
+  }
+  static void test_ci_inv(int[] a, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+k), old, -123);
+    }
+  }
+  static void test_vi_inv(int[] a, int b, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+k), old, b);
+    }
+  }
+  static void test_cp_inv(int[] a, int[] b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+k), -123, b[i+k]);
+    }
+  }
+  static void test_2ci_inv(int[] a, int[] b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+k), 123, -123);
+      unsafe.compareAndSwapInt(b, byte_offset(i+k), 123, -103);
+    }
+  }
+  static void test_2vi_inv(int[] a, int[] b, int c, int d, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+k), -123, c);
+      unsafe.compareAndSwapInt(b, byte_offset(i+k), -103, d);
+    }
+  }
+  static void test_ci_scl(int[] a, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), old, -123);
+    }
+  }
+  static void test_vi_scl(int[] a, int b, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), old, b);
+    }
+  }
+  static void test_cp_scl(int[] a, int[] b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), -123, b[i*SCALE]);
+    }
+  }
+  static void test_2ci_scl(int[] a, int[] b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), 123, -123);
+      unsafe.compareAndSwapInt(b, byte_offset(i*SCALE), 123, -103);
+    }
+  }
+  static void test_2vi_scl(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), -123, c);
+      unsafe.compareAndSwapInt(b, byte_offset(i*SCALE), -103, d);
+    }
+  }
+  static void test_cp_alndst(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+ALIGN_OFF), -1, b[i]);
+    }
+  }
+  static void test_cp_alnsrc(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      int old = unsafe.getIntVolatile(a, byte_offset(i));
+      unsafe.compareAndSwapInt(a, byte_offset(i), old, b[i+ALIGN_OFF]);
+    }
+  }
+  static void test_2ci_aln(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+ALIGN_OFF), -1, -123);
+      int old = unsafe.getIntVolatile(b, byte_offset(i));
+      unsafe.compareAndSwapInt(b, byte_offset(i), old, -103);
+    }
+  }
+  static void test_2vi_aln(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      int old = unsafe.getIntVolatile(a, byte_offset(i));
+      unsafe.compareAndSwapInt(a, byte_offset(i), old, c);
+      old = unsafe.getIntVolatile(b, byte_offset(i+ALIGN_OFF));
+      unsafe.compareAndSwapInt(b, byte_offset(i+ALIGN_OFF), old, d);
+    }
+  }
+  static void test_cp_unalndst(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+UNALIGN_OFF), -1, b[i]);
+    }
+  }
+  static void test_cp_unalnsrc(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      int old = unsafe.getIntVolatile(a, byte_offset(i));
+      unsafe.compareAndSwapInt(a, byte_offset(i), old, b[i+UNALIGN_OFF]);
+    }
+  }
+  static void test_2ci_unaln(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      unsafe.compareAndSwapInt(a, byte_offset(i+UNALIGN_OFF), -1, -123);
+      int old = unsafe.getIntVolatile(b, byte_offset(i));
+      unsafe.compareAndSwapInt(b, byte_offset(i), old, -103);
+    }
+  }
+  static void test_2vi_unaln(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      int old = unsafe.getIntVolatile(a, byte_offset(i));
+      unsafe.compareAndSwapInt(a, byte_offset(i), old, c);
+      old = unsafe.getIntVolatile(b, byte_offset(i+UNALIGN_OFF));
+      unsafe.compareAndSwapInt(b, byte_offset(i+UNALIGN_OFF), old, d);
+    }
+  }
+
+  static int verify(String text, int i, int elem, int val) {
+    if (elem != val) {
+      System.err.println(text + "[" + i + "] = " + elem + " != " + val);
+      return 1;
+    }
+    return 0;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8004867/TestIntUnsafeOrdered.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,990 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8004867
+ * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob"
+ *
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntUnsafeOrdered
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntUnsafeOrdered
+ */
+
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+public class TestIntUnsafeOrdered {
+  private static final int ARRLEN = 97;
+  private static final int ITERS  = 11000;
+  private static final int OFFSET = 3;
+  private static final int SCALE = 2;
+  private static final int ALIGN_OFF = 8;
+  private static final int UNALIGN_OFF = 5;
+
+  private static final Unsafe unsafe;
+  private static final int BASE;
+  static {
+    try {
+      Class c = TestIntUnsafeOrdered.class.getClassLoader().loadClass("sun.misc.Unsafe");
+      Field f = c.getDeclaredField("theUnsafe");
+      f.setAccessible(true);
+      unsafe = (Unsafe)f.get(c);
+      BASE = unsafe.arrayBaseOffset(int[].class);
+    } catch (Exception e) {
+      InternalError err = new InternalError();
+      err.initCause(e);
+      throw err;
+    }
+  }
+
+  public static void main(String args[]) {
+    System.out.println("Testing Integer array unsafe ordered operations");
+    int errn = test(false);
+    if (errn > 0) {
+      System.err.println("FAILED: " + errn + " errors");
+      System.exit(97);
+    }
+    System.out.println("PASSED");
+  }
+
+  static int test(boolean test_only) {
+    int[] a1 = new int[ARRLEN];
+    int[] a2 = new int[ARRLEN];
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1[i] = -1;
+      a2[i] = -1;
+    }
+    System.out.println("Warmup");
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+      test_vi(a2, 123, -1);
+      test_cp(a1, a2);
+      test_2ci(a1, a2);
+      test_2vi(a1, a2, 123, 103);
+      test_ci_neg(a1, 123);
+      test_vi_neg(a2, 123, 103);
+      test_cp_neg(a1, a2);
+      test_2ci_neg(a1, a2);
+      test_2vi_neg(a1, a2, 123, 103);
+      test_ci_oppos(a1, 123);
+      test_vi_oppos(a2, 123, 103);
+      test_cp_oppos(a1, a2);
+      test_2ci_oppos(a1, a2);
+      test_2vi_oppos(a1, a2, 123, 103);
+      test_ci_off(a1, 123);
+      test_vi_off(a2, 123, 103);
+      test_cp_off(a1, a2);
+      test_2ci_off(a1, a2);
+      test_2vi_off(a1, a2, 123, 103);
+      test_ci_inv(a1, OFFSET, 123);
+      test_vi_inv(a2, 123, OFFSET, 103);
+      test_cp_inv(a1, a2, OFFSET);
+      test_2ci_inv(a1, a2, OFFSET);
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      test_ci_scl(a1, 123);
+      test_vi_scl(a2, 123, 103);
+      test_cp_scl(a1, a2);
+      test_2ci_scl(a1, a2);
+      test_2vi_scl(a1, a2, 123, 103);
+      test_cp_alndst(a1, a2);
+      test_cp_alnsrc(a1, a2);
+      test_2ci_aln(a1, a2);
+      test_2vi_aln(a1, a2, 123, 103);
+      test_cp_unalndst(a1, a2);
+      test_cp_unalnsrc(a1, a2);
+      test_2ci_unaln(a1, a2);
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1[i] = -1;
+      a2[i] = -1;
+    }
+    // Test and verify results
+    System.out.println("Verification");
+    int errn = 0;
+    {
+      test_ci(a1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci: a1", i, a1[i], -123);
+      }
+      test_vi(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi: a2", i, a2[i], 123);
+      }
+      test_cp(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp: a1", i, a1[i], 123);
+      }
+      test_2ci(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci: a1", i, a1[i], -123);
+        errn += verify("test_2ci: a2", i, a2[i], -103);
+      }
+      test_2vi(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi: a1", i, a1[i], 123);
+        errn += verify("test_2vi: a2", i, a2[i], 103);
+      }
+      // Reset for negative stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_neg(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_neg: a1", i, a1[i], -123);
+      }
+      test_vi_neg(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_neg: a2", i, a2[i], 123);
+      }
+      test_cp_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_neg: a1", i, a1[i], 123);
+      }
+      test_2ci_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_neg: a1", i, a1[i], -123);
+        errn += verify("test_2ci_neg: a2", i, a2[i], -103);
+      }
+      test_2vi_neg(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_neg: a1", i, a1[i], 123);
+        errn += verify("test_2vi_neg: a2", i, a2[i], 103);
+      }
+      // Reset for opposite stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_oppos(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_oppos: a1", i, a1[i], -123);
+      }
+      test_vi_oppos(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_oppos: a2", i, a2[i], 123);
+      }
+      test_cp_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_oppos: a1", i, a1[i], 123);
+      }
+      test_2ci_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_oppos: a1", i, a1[i], -123);
+        errn += verify("test_2ci_oppos: a2", i, a2[i], -103);
+      }
+      test_2vi_oppos(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_oppos: a1", i, a1[i], 123);
+        errn += verify("test_2vi_oppos: a2", i, a2[i], 103);
+      }
+      // Reset for indexing with offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_off(a1, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_off: a1", i, a1[i], -123);
+      }
+      test_vi_off(a2, 123, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_off: a2", i, a2[i], 123);
+      }
+      test_cp_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_off: a1", i, a1[i], 123);
+      }
+      test_2ci_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_off: a1", i, a1[i], -123);
+        errn += verify("test_2ci_off: a2", i, a2[i], -103);
+      }
+      test_2vi_off(a1, a2, 123, 103);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_off: a1", i, a1[i], 123);
+        errn += verify("test_2vi_off: a2", i, a2[i], 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_off: a1", i, a1[i], -1);
+        errn += verify("test_2vi_off: a2", i, a2[i], -1);
+      }
+      // Reset for indexing with invariant offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_inv(a1, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_inv: a1", i, a1[i], -123);
+      }
+      test_vi_inv(a2, 123, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_inv: a2", i, a2[i], 123);
+      }
+      test_cp_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_inv: a1", i, a1[i], 123);
+      }
+      test_2ci_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_inv: a1", i, a1[i], -123);
+        errn += verify("test_2ci_inv: a2", i, a2[i], -103);
+      }
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1[i], 123);
+        errn += verify("test_2vi_inv: a2", i, a2[i], 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1[i], -1);
+        errn += verify("test_2vi_inv: a2", i, a2[i], -1);
+      }
+      // Reset for indexing with scale
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_scl(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : -123;
+        errn += verify("test_ci_scl: a1", i, a1[i], val);
+      }
+      test_vi_scl(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_vi_scl: a2", i, a2[i], val);
+      }
+      test_cp_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_cp_scl: a1", i, a1[i], val);
+      }
+      test_2ci_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a1", i, a1[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a1", i*SCALE, a1[i*SCALE], -123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a2", i, a2[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a2", i*SCALE, a2[i*SCALE], -103);
+        }
+      }
+      test_2vi_scl(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a1", i, a1[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a1", i*SCALE, a1[i*SCALE], 123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a2", i, a2[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a2", i*SCALE, a2[i*SCALE], 103);
+        }
+      }
+      // Reset for 2 arrays with relative aligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_vi(a2, 123, -1);
+      test_cp_alndst(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1[i], 123);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1[i] = 123;
+      }
+      test_vi(a2, -123, 123);
+      test_cp_alnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1[i], -123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1[i], 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2ci_aln(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2[i], -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2[i], -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2vi_aln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1[i], -1);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2[i], 103);
+      }
+
+      // Reset for 2 arrays with relative unaligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_vi(a2, 123, -1);
+      test_cp_unalndst(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1[i], 123);
+      }
+      test_vi(a2, -123, 123);
+      test_cp_unalnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1[i], -123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1[i], 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2ci_unaln(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2[i], -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2[i], -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2vi_unaln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1[i], -1);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2[i], 103);
+      }
+
+      // Reset for aligned overlap initialization
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1[i] = i;
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_cp_alndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alndst_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1[i+ALIGN_OFF] = -1;
+      }
+      test_cp_alnsrc(a1, a1);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2ci_aln(a1, a1);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2vi_aln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 103);
+      }
+
+      // Reset for unaligned overlap initialization
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1[i] = i;
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_cp_unalndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalndst_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1[i+UNALIGN_OFF] = -1;
+      }
+      test_cp_unalnsrc(a1, a1);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2ci_unaln(a1, a1);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2vi_unaln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 103);
+      }
+
+    }
+
+    if (errn > 0 || test_only)
+      return errn;
+
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1[i] = -1;
+      a2[i] = -1;
+    }
+    System.out.println("Time");
+    long start, end;
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi(a2, 123, -1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_neg(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_neg(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_neg(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_neg: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_oppos(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_oppos(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_oppos(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_oppos: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_off(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_off(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_off(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_off: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_inv(a1, OFFSET, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_inv(a2, 123, OFFSET, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_inv: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_scl(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_scl(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_scl(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_scl: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_aln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_aln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_aln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_aln: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_unaln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_unaln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_unaln: " + (end - start));
+
+    return errn;
+  }
+
+  private final static long byte_offset(int i) {
+    return ((long)i << 2) + BASE;
+  }
+
+  static void test_ci(int[] a) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), -123);
+    }
+  }
+  static void test_vi(int[] a, int b, int old) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), b);
+    }
+  }
+  static void test_cp(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), b[i]);
+    }
+  }
+  static void test_2ci(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), -123);
+      unsafe.putOrderedInt(b, byte_offset(i), -103);
+    }
+  }
+  static void test_2vi(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), c);
+      unsafe.putOrderedInt(b, byte_offset(i), d);
+    }
+  }
+  static void test_ci_neg(int[] a, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), -123);
+    }
+  }
+  static void test_vi_neg(int[] a, int b, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), b);
+    }
+  }
+  static void test_cp_neg(int[] a, int[] b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), b[i]);
+    }
+  }
+  static void test_2ci_neg(int[] a, int[] b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), -123);
+      unsafe.putOrderedInt(b, byte_offset(i), -103);
+    }
+  }
+  static void test_2vi_neg(int[] a, int[] b, int c, int d) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), c);
+      unsafe.putOrderedInt(b, byte_offset(i), d);
+    }
+  }
+  static void test_ci_oppos(int[] a, int old) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(limit-i), -123);
+    }
+  }
+  static void test_vi_oppos(int[] a, int b, int old) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      unsafe.putOrderedInt(a, byte_offset(limit-i), b);
+    }
+  }
+  static void test_cp_oppos(int[] a, int[] b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), b[limit-i]);
+    }
+  }
+  static void test_2ci_oppos(int[] a, int[] b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(limit-i), -123);
+      unsafe.putOrderedInt(b, byte_offset(i), -103);
+    }
+  }
+  static void test_2vi_oppos(int[] a, int[] b, int c, int d) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), c);
+      unsafe.putOrderedInt(b, byte_offset(limit-i), d);
+    }
+  }
+  static void test_ci_off(int[] a, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+OFFSET), -123);
+    }
+  }
+  static void test_vi_off(int[] a, int b, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+OFFSET), b);
+    }
+  }
+  static void test_cp_off(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+OFFSET), b[i+OFFSET]);
+    }
+  }
+  static void test_2ci_off(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+OFFSET), -123);
+      unsafe.putOrderedInt(b, byte_offset(i+OFFSET), -103);
+    }
+  }
+  static void test_2vi_off(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+OFFSET), c);
+      unsafe.putOrderedInt(b, byte_offset(i+OFFSET), d);
+    }
+  }
+  static void test_ci_inv(int[] a, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+k), -123);
+    }
+  }
+  static void test_vi_inv(int[] a, int b, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+k), b);
+    }
+  }
+  static void test_cp_inv(int[] a, int[] b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+k), b[i+k]);
+    }
+  }
+  static void test_2ci_inv(int[] a, int[] b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+k), -123);
+      unsafe.putOrderedInt(b, byte_offset(i+k), -103);
+    }
+  }
+  static void test_2vi_inv(int[] a, int[] b, int c, int d, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+k), c);
+      unsafe.putOrderedInt(b, byte_offset(i+k), d);
+    }
+  }
+  static void test_ci_scl(int[] a, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i*SCALE), -123);
+    }
+  }
+  static void test_vi_scl(int[] a, int b, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i*SCALE), b);
+    }
+  }
+  static void test_cp_scl(int[] a, int[] b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i*SCALE), b[i*SCALE]);
+    }
+  }
+  static void test_2ci_scl(int[] a, int[] b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i*SCALE), -123);
+      unsafe.putOrderedInt(b, byte_offset(i*SCALE), -103);
+    }
+  }
+  static void test_2vi_scl(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i*SCALE), c);
+      unsafe.putOrderedInt(b, byte_offset(i*SCALE), d);
+    }
+  }
+  static void test_cp_alndst(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+ALIGN_OFF), b[i]);
+    }
+  }
+  static void test_cp_alnsrc(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), b[i+ALIGN_OFF]);
+    }
+  }
+  static void test_2ci_aln(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+ALIGN_OFF), -123);
+      unsafe.putOrderedInt(b, byte_offset(i), -103);
+    }
+  }
+  static void test_2vi_aln(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), c);
+      unsafe.putOrderedInt(b, byte_offset(i+ALIGN_OFF), d);
+    }
+  }
+  static void test_cp_unalndst(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+UNALIGN_OFF), b[i]);
+    }
+  }
+  static void test_cp_unalnsrc(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), b[i+UNALIGN_OFF]);
+    }
+  }
+  static void test_2ci_unaln(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i+UNALIGN_OFF), -123);
+      unsafe.putOrderedInt(b, byte_offset(i), -103);
+    }
+  }
+  static void test_2vi_unaln(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      unsafe.putOrderedInt(a, byte_offset(i), c);
+      unsafe.putOrderedInt(b, byte_offset(i+UNALIGN_OFF), d);
+    }
+  }
+
+  static int verify(String text, int i, int elem, int val) {
+    if (elem != val) {
+      System.err.println(text + "[" + i + "] = " + elem + " != " + val);
+      return 1;
+    }
+    return 0;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8004867/TestIntUnsafeVolatile.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,990 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8004867
+ * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob"
+ *
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntUnsafeVolatile
+ * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntUnsafeVolatile
+ */
+
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+public class TestIntUnsafeVolatile {
+  private static final int ARRLEN = 97;
+  private static final int ITERS  = 11000;
+  private static final int OFFSET = 3;
+  private static final int SCALE = 2;
+  private static final int ALIGN_OFF = 8;
+  private static final int UNALIGN_OFF = 5;
+
+  private static final Unsafe unsafe;
+  private static final int BASE;
+  static {
+    try {
+      Class c = TestIntUnsafeVolatile.class.getClassLoader().loadClass("sun.misc.Unsafe");
+      Field f = c.getDeclaredField("theUnsafe");
+      f.setAccessible(true);
+      unsafe = (Unsafe)f.get(c);
+      BASE = unsafe.arrayBaseOffset(int[].class);
+    } catch (Exception e) {
+      InternalError err = new InternalError();
+      err.initCause(e);
+      throw err;
+    }
+  }
+
+  public static void main(String args[]) {
+    System.out.println("Testing Integer array unsafe volatile operations");
+    int errn = test(false);
+    if (errn > 0) {
+      System.err.println("FAILED: " + errn + " errors");
+      System.exit(97);
+    }
+    System.out.println("PASSED");
+  }
+
+  static int test(boolean test_only) {
+    int[] a1 = new int[ARRLEN];
+    int[] a2 = new int[ARRLEN];
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1[i] = -1;
+      a2[i] = -1;
+    }
+    System.out.println("Warmup");
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+      test_vi(a2, 123, -1);
+      test_cp(a1, a2);
+      test_2ci(a1, a2);
+      test_2vi(a1, a2, 123, 103);
+      test_ci_neg(a1, 123);
+      test_vi_neg(a2, 123, 103);
+      test_cp_neg(a1, a2);
+      test_2ci_neg(a1, a2);
+      test_2vi_neg(a1, a2, 123, 103);
+      test_ci_oppos(a1, 123);
+      test_vi_oppos(a2, 123, 103);
+      test_cp_oppos(a1, a2);
+      test_2ci_oppos(a1, a2);
+      test_2vi_oppos(a1, a2, 123, 103);
+      test_ci_off(a1, 123);
+      test_vi_off(a2, 123, 103);
+      test_cp_off(a1, a2);
+      test_2ci_off(a1, a2);
+      test_2vi_off(a1, a2, 123, 103);
+      test_ci_inv(a1, OFFSET, 123);
+      test_vi_inv(a2, 123, OFFSET, 103);
+      test_cp_inv(a1, a2, OFFSET);
+      test_2ci_inv(a1, a2, OFFSET);
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      test_ci_scl(a1, 123);
+      test_vi_scl(a2, 123, 103);
+      test_cp_scl(a1, a2);
+      test_2ci_scl(a1, a2);
+      test_2vi_scl(a1, a2, 123, 103);
+      test_cp_alndst(a1, a2);
+      test_cp_alnsrc(a1, a2);
+      test_2ci_aln(a1, a2);
+      test_2vi_aln(a1, a2, 123, 103);
+      test_cp_unalndst(a1, a2);
+      test_cp_unalnsrc(a1, a2);
+      test_2ci_unaln(a1, a2);
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1[i] = -1;
+      a2[i] = -1;
+    }
+    // Test and verify results
+    System.out.println("Verification");
+    int errn = 0;
+    {
+      test_ci(a1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci: a1", i, a1[i], -123);
+      }
+      test_vi(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi: a2", i, a2[i], 123);
+      }
+      test_cp(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp: a1", i, a1[i], 123);
+      }
+      test_2ci(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci: a1", i, a1[i], -123);
+        errn += verify("test_2ci: a2", i, a2[i], -103);
+      }
+      test_2vi(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi: a1", i, a1[i], 123);
+        errn += verify("test_2vi: a2", i, a2[i], 103);
+      }
+      // Reset for negative stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_neg(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_neg: a1", i, a1[i], -123);
+      }
+      test_vi_neg(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_neg: a2", i, a2[i], 123);
+      }
+      test_cp_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_neg: a1", i, a1[i], 123);
+      }
+      test_2ci_neg(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_neg: a1", i, a1[i], -123);
+        errn += verify("test_2ci_neg: a2", i, a2[i], -103);
+      }
+      test_2vi_neg(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_neg: a1", i, a1[i], 123);
+        errn += verify("test_2vi_neg: a2", i, a2[i], 103);
+      }
+      // Reset for opposite stride
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_oppos(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_ci_oppos: a1", i, a1[i], -123);
+      }
+      test_vi_oppos(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_vi_oppos: a2", i, a2[i], 123);
+      }
+      test_cp_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_cp_oppos: a1", i, a1[i], 123);
+      }
+      test_2ci_oppos(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2ci_oppos: a1", i, a1[i], -123);
+        errn += verify("test_2ci_oppos: a2", i, a2[i], -103);
+      }
+      test_2vi_oppos(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        errn += verify("test_2vi_oppos: a1", i, a1[i], 123);
+        errn += verify("test_2vi_oppos: a2", i, a2[i], 103);
+      }
+      // Reset for indexing with offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_off(a1, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_off: a1", i, a1[i], -123);
+      }
+      test_vi_off(a2, 123, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_off: a2", i, a2[i], 123);
+      }
+      test_cp_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_off: a1", i, a1[i], 123);
+      }
+      test_2ci_off(a1, a2);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_off: a1", i, a1[i], -123);
+        errn += verify("test_2ci_off: a2", i, a2[i], -103);
+      }
+      test_2vi_off(a1, a2, 123, 103);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_off: a1", i, a1[i], 123);
+        errn += verify("test_2vi_off: a2", i, a2[i], 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_off: a1", i, a1[i], -1);
+        errn += verify("test_2vi_off: a2", i, a2[i], -1);
+      }
+      // Reset for indexing with invariant offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_inv(a1, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_ci_inv: a1", i, a1[i], -123);
+      }
+      test_vi_inv(a2, 123, OFFSET, -1);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_vi_inv: a2", i, a2[i], 123);
+      }
+      test_cp_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_cp_inv: a1", i, a1[i], 123);
+      }
+      test_2ci_inv(a1, a2, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2ci_inv: a1", i, a1[i], -123);
+        errn += verify("test_2ci_inv: a2", i, a2[i], -103);
+      }
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+      for (int i=OFFSET; i<ARRLEN; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1[i], 123);
+        errn += verify("test_2vi_inv: a2", i, a2[i], 103);
+      }
+      for (int i=0; i<OFFSET; i++) {
+        errn += verify("test_2vi_inv: a1", i, a1[i], -1);
+        errn += verify("test_2vi_inv: a2", i, a2[i], -1);
+      }
+      // Reset for indexing with scale
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_ci_scl(a1, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : -123;
+        errn += verify("test_ci_scl: a1", i, a1[i], val);
+      }
+      test_vi_scl(a2, 123, -1);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_vi_scl: a2", i, a2[i], val);
+      }
+      test_cp_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        int val = (i%SCALE != 0) ? -1 : 123;
+        errn += verify("test_cp_scl: a1", i, a1[i], val);
+      }
+      test_2ci_scl(a1, a2);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a1", i, a1[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a1", i*SCALE, a1[i*SCALE], -123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2ci_scl: a2", i, a2[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2ci_scl: a2", i*SCALE, a2[i*SCALE], -103);
+        }
+      }
+      test_2vi_scl(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN; i++) {
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a1", i, a1[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a1", i*SCALE, a1[i*SCALE], 123);
+        }
+        if (i%SCALE != 0) {
+          errn += verify("test_2vi_scl: a2", i, a2[i], -1);
+        } else if (i*SCALE < ARRLEN) {
+          errn += verify("test_2vi_scl: a2", i*SCALE, a2[i*SCALE], 103);
+        }
+      }
+      // Reset for 2 arrays with relative aligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_vi(a2, 123, -1);
+      test_cp_alndst(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alndst: a1", i, a1[i], 123);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1[i] = 123;
+      }
+      test_vi(a2, -123, 123);
+      test_cp_alnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1[i], -123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_alnsrc: a1", i, a1[i], 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2ci_aln(a1, a2);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2[i], -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln: a2", i, a2[i], -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2vi_aln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a1", i, a1[i], -1);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln: a2", i, a2[i], 103);
+      }
+
+      // Reset for 2 arrays with relative unaligned offset
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_vi(a2, 123, -1);
+      test_cp_unalndst(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalndst: a1", i, a1[i], 123);
+      }
+      test_vi(a2, -123, 123);
+      test_cp_unalnsrc(a1, a2);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1[i], -123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_cp_unalnsrc: a1", i, a1[i], 123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2ci_unaln(a1, a2);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2[i], -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln: a2", i, a2[i], -1);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+        a2[i] = -1;
+      }
+      test_2vi_unaln(a1, a2, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a1", i, a1[i], -1);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln: a2", i, a2[i], 103);
+      }
+
+      // Reset for aligned overlap initialization
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1[i] = i;
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_cp_alndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alndst_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<ALIGN_OFF; i++) {
+        a1[i+ALIGN_OFF] = -1;
+      }
+      test_cp_alnsrc(a1, a1);
+      for (int i=0; i<ALIGN_OFF; i++) {
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], -1);
+      }
+      for (int i=ALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%ALIGN_OFF;
+        errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2ci_aln(a1, a1);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -103);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2vi_aln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-ALIGN_OFF; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 103);
+      }
+
+      // Reset for unaligned overlap initialization
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1[i] = i;
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_cp_unalndst(a1, a1);
+      for (int i=0; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalndst_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        a1[i+UNALIGN_OFF] = -1;
+      }
+      test_cp_unalnsrc(a1, a1);
+      for (int i=0; i<UNALIGN_OFF; i++) {
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], -1);
+      }
+      for (int i=UNALIGN_OFF; i<ARRLEN; i++) {
+        int v = i%UNALIGN_OFF;
+        errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], v);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2ci_unaln(a1, a1);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -103);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -123);
+      }
+      for (int i=0; i<ARRLEN; i++) {
+        a1[i] = -1;
+      }
+      test_2vi_unaln(a1, a1, 123, 103);
+      for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 123);
+      }
+      for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) {
+        errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 103);
+      }
+
+    }
+
+    if (errn > 0 || test_only)
+      return errn;
+
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      a1[i] = -1;
+      a2[i] = -1;
+    }
+    System.out.println("Time");
+    long start, end;
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci(a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi(a2, 123, -1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_neg(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_neg(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_neg(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_neg: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_neg(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_neg: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_oppos(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_oppos(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_oppos(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_oppos: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_oppos(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_oppos: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_off(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_off(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_off(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_off: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_off(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_off: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_inv(a1, OFFSET, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_inv(a2, 123, OFFSET, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_inv(a1, a2, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_inv: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_inv(a1, a2, 123, 103, OFFSET);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_inv: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_ci_scl(a1, 123);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_vi_scl(a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_vi_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_scl(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_scl: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_scl(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_scl: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_alnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_alnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_aln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_aln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_aln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_aln: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalndst(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalndst: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_cp_unalnsrc(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_cp_unalnsrc: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2ci_unaln(a1, a2);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2ci_unaln: " + (end - start));
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_2vi_unaln(a1, a2, 123, 103);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_2vi_unaln: " + (end - start));
+
+    return errn;
+  }
+
+  private final static long byte_offset(int i) {
+    return ((long)i << 2) + BASE;
+  }
+
+  static void test_ci(int[] a) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), -123);
+    }
+  }
+  static void test_vi(int[] a, int b, int old) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), b);
+    }
+  }
+  static void test_cp(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), b[i]);
+    }
+  }
+  static void test_2ci(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), -123);
+      unsafe.putIntVolatile(b, byte_offset(i), -103);
+    }
+  }
+  static void test_2vi(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), c);
+      unsafe.putIntVolatile(b, byte_offset(i), d);
+    }
+  }
+  static void test_ci_neg(int[] a, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), -123);
+    }
+  }
+  static void test_vi_neg(int[] a, int b, int old) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), b);
+    }
+  }
+  static void test_cp_neg(int[] a, int[] b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), b[i]);
+    }
+  }
+  static void test_2ci_neg(int[] a, int[] b) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), -123);
+      unsafe.putIntVolatile(b, byte_offset(i), -103);
+    }
+  }
+  static void test_2vi_neg(int[] a, int[] b, int c, int d) {
+    for (int i = ARRLEN-1; i >= 0; i-=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), c);
+      unsafe.putIntVolatile(b, byte_offset(i), d);
+    }
+  }
+  static void test_ci_oppos(int[] a, int old) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(limit-i), -123);
+    }
+  }
+  static void test_vi_oppos(int[] a, int b, int old) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      unsafe.putIntVolatile(a, byte_offset(limit-i), b);
+    }
+  }
+  static void test_cp_oppos(int[] a, int[] b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), b[limit-i]);
+    }
+  }
+  static void test_2ci_oppos(int[] a, int[] b) {
+    int limit = ARRLEN-1;
+    for (int i = 0; i < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(limit-i), -123);
+      unsafe.putIntVolatile(b, byte_offset(i), -103);
+    }
+  }
+  static void test_2vi_oppos(int[] a, int[] b, int c, int d) {
+    int limit = ARRLEN-1;
+    for (int i = limit; i >= 0; i-=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), c);
+      unsafe.putIntVolatile(b, byte_offset(limit-i), d);
+    }
+  }
+  static void test_ci_off(int[] a, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+OFFSET), -123);
+    }
+  }
+  static void test_vi_off(int[] a, int b, int old) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+OFFSET), b);
+    }
+  }
+  static void test_cp_off(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+OFFSET), b[i+OFFSET]);
+    }
+  }
+  static void test_2ci_off(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+OFFSET), -123);
+      unsafe.putIntVolatile(b, byte_offset(i+OFFSET), -103);
+    }
+  }
+  static void test_2vi_off(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+OFFSET), c);
+      unsafe.putIntVolatile(b, byte_offset(i+OFFSET), d);
+    }
+  }
+  static void test_ci_inv(int[] a, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+k), -123);
+    }
+  }
+  static void test_vi_inv(int[] a, int b, int k, int old) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+k), b);
+    }
+  }
+  static void test_cp_inv(int[] a, int[] b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+k), b[i+k]);
+    }
+  }
+  static void test_2ci_inv(int[] a, int[] b, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+k), -123);
+      unsafe.putIntVolatile(b, byte_offset(i+k), -103);
+    }
+  }
+  static void test_2vi_inv(int[] a, int[] b, int c, int d, int k) {
+    for (int i = 0; i < ARRLEN-k; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+k), c);
+      unsafe.putIntVolatile(b, byte_offset(i+k), d);
+    }
+  }
+  static void test_ci_scl(int[] a, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i*SCALE), -123);
+    }
+  }
+  static void test_vi_scl(int[] a, int b, int old) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i*SCALE), b);
+    }
+  }
+  static void test_cp_scl(int[] a, int[] b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i*SCALE), b[i*SCALE]);
+    }
+  }
+  static void test_2ci_scl(int[] a, int[] b) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i*SCALE), -123);
+      unsafe.putIntVolatile(b, byte_offset(i*SCALE), -103);
+    }
+  }
+  static void test_2vi_scl(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i*SCALE < ARRLEN; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i*SCALE), c);
+      unsafe.putIntVolatile(b, byte_offset(i*SCALE), d);
+    }
+  }
+  static void test_cp_alndst(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+ALIGN_OFF), b[i]);
+    }
+  }
+  static void test_cp_alnsrc(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), b[i+ALIGN_OFF]);
+    }
+  }
+  static void test_2ci_aln(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+ALIGN_OFF), -123);
+      unsafe.putIntVolatile(b, byte_offset(i), -103);
+    }
+  }
+  static void test_2vi_aln(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), c);
+      unsafe.putIntVolatile(b, byte_offset(i+ALIGN_OFF), d);
+    }
+  }
+  static void test_cp_unalndst(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+UNALIGN_OFF), b[i]);
+    }
+  }
+  static void test_cp_unalnsrc(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), b[i+UNALIGN_OFF]);
+    }
+  }
+  static void test_2ci_unaln(int[] a, int[] b) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i+UNALIGN_OFF), -123);
+      unsafe.putIntVolatile(b, byte_offset(i), -103);
+    }
+  }
+  static void test_2vi_unaln(int[] a, int[] b, int c, int d) {
+    for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
+      unsafe.putIntVolatile(a, byte_offset(i), c);
+      unsafe.putIntVolatile(b, byte_offset(i+UNALIGN_OFF), d);
+    }
+  }
+
+  static int verify(String text, int i, int elem, int val) {
+    if (elem != val) {
+      System.err.println(text + "[" + i + "] = " + elem + " != " + val);
+      return 1;
+    }
+    return 0;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8007294/Test8007294.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8007294
+ * @summary ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+AlwaysIncrementalInline -XX:-UseOnStackReplacement -XX:-BackgroundCompilation Test8007294
+ *
+ */
+
+public class Test8007294 {
+
+    int i1;
+    int i2;
+
+    Test8007294(int i1, int i2) {
+        this.i1 = i1;
+        this.i2 = i2;
+    }
+
+    static int m(int v) {
+        return v;
+    }
+
+    static Test8007294 test1() {
+        Test8007294 obj = new Test8007294(10, 100);
+        int v1 = obj.i1;
+
+        int v3 = m(v1);
+        int v2 = obj.i2;
+        obj.i2 = v3;
+        obj.i1 = v2;
+
+        return obj;
+    }
+
+    static int test2(int i) {
+        int j = 0;
+        if (i > 0) {
+            j = 1;
+        }
+
+        int[] arr = new int[10];
+        arr[0] = 1;
+        arr[1] = 2;
+        int v1 = arr[j];
+        arr[0] = 3;
+        arr[1] = 4;
+
+        return v1;
+    }
+
+    static public void main(String[] args) {
+        boolean failed = false;
+        for (int i = 0; i < 20000; i++) {
+            Test8007294 obj = test1();
+            if (obj.i1 != 100 || obj.i2 != 10) {
+                System.out.println("FAILED test1 obj.i1 = " + obj.i1 +", obj.i2 = " + obj.i2);
+                failed = true;
+                break;
+            }
+        }
+        for (int i = 0; i < 20000; i++) {
+            int res = test2(1);
+            if (res != 2) {
+                System.out.println("FAILED test2 = " + res);
+                failed = true;
+                break;
+            }
+        }
+        if (failed) {
+            System.exit(97);
+        } else {
+            System.out.println("PASSED");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/8007722/Test8007722.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8007722
+ * @summary GetAndSetP's MachNode should capture bottom type
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation Test8007722
+ *
+ */
+
+import java.util.concurrent.atomic.*;
+
+public class Test8007722 {
+
+    int i;
+    static AtomicReference<Test8007722> ref;
+
+    static int test(Test8007722 new_obj) {
+        Test8007722 o = ref.getAndSet(new_obj);
+        int ret = o.i;
+        o.i = 5;
+        return ret;
+    }
+
+    static public void main(String[] args) {
+        Test8007722 obj = new Test8007722();
+        ref = new AtomicReference<Test8007722>(obj);
+
+        for (int i = 0; i < 20000; i++) {
+            test(obj);
+        }
+
+        System.out.println("PASSED");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sun.hotspot.WhiteBox;
+import sun.management.ManagementFactoryHelper;
+import com.sun.management.HotSpotDiagnosticMXBean;
+
+import java.lang.reflect.Method;
+
+/*
+ * @author igor.ignatyev@oracle.com
+ */
+public abstract class CompilerWhiteBoxTest {
+    protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+    protected static final Method METHOD = getMethod("method");
+    protected static final int COMPILE_THRESHOLD
+            = Integer.parseInt(getVMOption("CompileThreshold", "10000"));
+
+    protected static Method getMethod(String name) {
+        try {
+            return CompilerWhiteBoxTest.class.getDeclaredMethod(name);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new RuntimeException(
+                    "exception on getting method " + name, e);
+        }
+    }
+
+    protected static String getVMOption(String name, String defaultValue) {
+        String result;
+        HotSpotDiagnosticMXBean diagnostic
+                = ManagementFactoryHelper.getDiagnosticMXBean();
+        result = diagnostic.getVMOption(name).getValue();
+        return result == null ? defaultValue : result;
+    }
+
+    protected final void runTest() throws RuntimeException {
+        if (ManagementFactoryHelper.getCompilationMXBean() == null) {
+            System.err.println(
+                    "Warning: test is not applicable in interpreted mode");
+            return;
+        }
+        System.out.println("at test's start:");
+        printInfo(METHOD);
+        try {
+            test();
+        } catch (Exception e) {
+            System.out.printf("on exception '%s':", e.getMessage());
+            printInfo(METHOD);
+            throw new RuntimeException(e);
+        }
+        System.out.println("at test's end:");
+        printInfo(METHOD);
+    }
+
+    protected static void checkNotCompiled(Method method) {
+        if (WHITE_BOX.isMethodCompiled(method)) {
+            throw new RuntimeException(method + " must be not compiled");
+        }
+        if (WHITE_BOX.getMethodCompilationLevel(method) != 0) {
+            throw new RuntimeException(method + " comp_level must be == 0");
+        }
+    }
+
+    protected static void checkCompiled(Method method)
+            throws InterruptedException {
+        final long start = System.currentTimeMillis();
+        waitBackgroundCompilation(method);
+        if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
+            System.err.printf("Warning: %s is still in queue after %dms%n",
+                    method, System.currentTimeMillis() - start);
+            return;
+        }
+        if (!WHITE_BOX.isMethodCompiled(method)) {
+            throw new RuntimeException(method + " must be compiled");
+        }
+        if (WHITE_BOX.getMethodCompilationLevel(method) == 0) {
+            throw new RuntimeException(method + " comp_level must be != 0");
+        }
+    }
+
+    protected static void waitBackgroundCompilation(Method method)
+            throws InterruptedException {
+        final Object obj = new Object();
+        synchronized (obj) {
+            for (int i = 0; i < 10; ++i) {
+                if (!WHITE_BOX.isMethodQueuedForCompilation(method)) {
+                    break;
+                }
+                obj.wait(1000);
+            }
+        }
+    }
+
+    protected static void printInfo(Method method) {
+        System.out.printf("%n%s:%n", method);
+        System.out.printf("\tcompilable:\t%b%n",
+                WHITE_BOX.isMethodCompilable(method));
+        System.out.printf("\tcompiled:\t%b%n",
+                WHITE_BOX.isMethodCompiled(method));
+        System.out.printf("\tcomp_level:\t%d%n",
+                WHITE_BOX.getMethodCompilationLevel(method));
+        System.out.printf("\tin_queue:\t%b%n",
+                WHITE_BOX.isMethodQueuedForCompilation(method));
+        System.out.printf("compile_queues_size:\t%d%n%n",
+                WHITE_BOX.getCompileQueuesSize());
+    }
+
+    protected abstract void test() throws Exception;
+
+    protected final int compile() {
+        int result = 0;
+        for (int i = 0; i < COMPILE_THRESHOLD; ++i) {
+            result += method();
+        }
+        return result;
+    }
+
+
+    protected int method() {
+        return 42;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/DeoptimizeAllTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test DeoptimizeAllTest
+ * @library /testlibrary /testlibrary/whitebox
+ * @build DeoptimizeAllTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DeoptimizeAllTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class DeoptimizeAllTest extends CompilerWhiteBoxTest {
+
+    public static void main(String[] args) throws Exception {
+        new DeoptimizeAllTest().runTest();
+    }
+
+    protected void test() throws Exception {
+        // to prevent inlining #method into #compile()
+        WHITE_BOX.setDontInlineMethod(METHOD, true);
+        compile();
+        checkCompiled(METHOD);
+        WHITE_BOX.deoptimizeAll();
+        checkNotCompiled(METHOD);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/DeoptimizeMethodTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test DeoptimizeMethodTest
+ * @library /testlibrary /testlibrary/whitebox
+ * @build DeoptimizeMethodTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DeoptimizeMethodTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class DeoptimizeMethodTest extends CompilerWhiteBoxTest {
+
+    public static void main(String[] args) throws Exception {
+        new DeoptimizeMethodTest().runTest();
+    }
+
+    protected void test() throws Exception {
+        // to prevent inlining #method into #compile()
+        WHITE_BOX.setDontInlineMethod(METHOD, true);
+        compile();
+        checkCompiled(METHOD);
+        WHITE_BOX.deoptimizeMethod(METHOD);
+        checkNotCompiled(METHOD);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/IsMethodCompilableTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test IsMethodCompilableTest
+ * @bug 8007270
+ * @library /testlibrary /testlibrary/whitebox
+ * @build IsMethodCompilableTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI IsMethodCompilableTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class IsMethodCompilableTest extends CompilerWhiteBoxTest {
+    protected static final long PER_METHOD_RECOMPILATION_CUTOFF;
+
+    static {
+        long tmp = Long.parseLong(
+                getVMOption("PerMethodRecompilationCutoff", "400"));
+        if (tmp == -1) {
+            PER_METHOD_RECOMPILATION_CUTOFF = -1 /* Inf */;
+        } else {
+            PER_METHOD_RECOMPILATION_CUTOFF = 1 + (0xFFFFFFFFL & tmp);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        new IsMethodCompilableTest().runTest();
+    }
+
+    protected void test() throws Exception {
+        if (!WHITE_BOX.isMethodCompilable(METHOD)) {
+            throw new RuntimeException(METHOD + " must be compilable");
+        }
+        System.out.println("PerMethodRecompilationCutoff = "
+                + PER_METHOD_RECOMPILATION_CUTOFF);
+        if (PER_METHOD_RECOMPILATION_CUTOFF == -1) {
+            System.err.println(
+                    "Warning: test is not applicable if PerMethodRecompilationCutoff == Inf");
+            return;
+        }
+        // to prevent inlining #method into #compile()
+        WHITE_BOX.setDontInlineMethod(METHOD, true);
+        boolean madeNotCompilable = false;
+
+        for (long i = 0; i < PER_METHOD_RECOMPILATION_CUTOFF; ++i) {
+            compile();
+            waitBackgroundCompilation(METHOD);
+            WHITE_BOX.deoptimizeMethod(METHOD);
+            if (!WHITE_BOX.isMethodCompilable(METHOD)) {
+                madeNotCompilable = true;
+                break;
+            }
+        }
+        if (!madeNotCompilable) {
+            throw new RuntimeException(METHOD + " is still compilable after "
+                    + PER_METHOD_RECOMPILATION_CUTOFF + " iterations");
+        }
+        compile();
+        if (WHITE_BOX.isMethodCompiled(METHOD)) {
+            printInfo(METHOD);
+            throw new RuntimeException(
+                    METHOD + " is not compilable but compiled");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test MakeMethodNotCompilableTest
+ * @library /testlibrary /testlibrary/whitebox
+ * @build MakeMethodNotCompilableTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI MakeMethodNotCompilableTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest {
+
+    public static void main(String[] args) throws Exception {
+        new MakeMethodNotCompilableTest().runTest();
+    }
+
+    protected void test() throws Exception  {
+        if (!WHITE_BOX.isMethodCompilable(METHOD)) {
+            throw new RuntimeException(METHOD + " must be compilable");
+        }
+        WHITE_BOX.makeMethodNotCompilable(METHOD);
+        if (WHITE_BOX.isMethodCompilable(METHOD)) {
+            throw new RuntimeException(METHOD + " must be not compilable");
+        }
+        compile();
+        if (WHITE_BOX.isMethodQueuedForCompilation(METHOD)) {
+            throw new RuntimeException(METHOD + " must not be in queue");
+        }
+        checkNotCompiled(METHOD);
+        if (WHITE_BOX.isMethodCompilable(METHOD)) {
+            throw new RuntimeException(METHOD + " must be not compilable");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/whitebox/SetDontInlineMethodTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test SetDontInlineMethodTest
+ * @library /testlibrary /testlibrary/whitebox
+ * @build SetDontInlineMethodTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetDontInlineMethodTest
+ * @author igor.ignatyev@oracle.com
+ */
+public class SetDontInlineMethodTest extends CompilerWhiteBoxTest {
+
+    public static void main(String[] args) throws Exception {
+        new SetDontInlineMethodTest().runTest();
+    }
+
+    protected void test() throws Exception {
+        if (WHITE_BOX.setDontInlineMethod(METHOD, true)) {
+            throw new RuntimeException("on start " + METHOD
+                    + " must be inlineable");
+        }
+        if (!WHITE_BOX.setDontInlineMethod(METHOD, true)) {
+            throw new RuntimeException("after first change to true " + METHOD
+                    + " must be not inlineable");
+        }
+        if (!WHITE_BOX.setDontInlineMethod(METHOD, false)) {
+            throw new RuntimeException("after second change to true " + METHOD
+                    + " must be still not inlineable");
+        }
+        if (WHITE_BOX.setDontInlineMethod(METHOD, false)) {
+            throw new RuntimeException("after first change to false" + METHOD
+                    + " must be inlineable");
+        }
+        if (WHITE_BOX.setDontInlineMethod(METHOD, false)) {
+            throw new RuntimeException("after second change to false " + METHOD
+                    + " must be inlineable");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/8000311/Test8000311.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test Test8000311
+ * @key gc
+ * @bug 8000311
+ * @summary G1: ParallelGCThreads==0 broken
+ * @run main/othervm -XX:+UseG1GC -XX:ParallelGCThreads=0 -XX:+ResizePLAB -XX:+ExplicitGCInvokesConcurrent Test8000311
+ * @author filipp.zhinkin@oracle.com
+ */
+
+import java.util.*;
+
+public class Test8000311 {
+  public static void main(String args[]) {
+    for(int i = 0; i<100; i++) {
+      byte[] garbage = new byte[1000];
+      System.gc();
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/TestG1ZeroPGCTJcmdThreadPrint.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test TestG1ZeroPGCTJcmdThreadPrint
+ * @key gc
+ * @bug 8005875
+ * @summary Use jcmd to generate a thread dump of a Java program being run with PGCT=0 to verify 8005875
+ * @library /testlibrary
+ * @run main/othervm -XX:+UseG1GC -XX:ParallelGCThreads=0 -XX:+IgnoreUnrecognizedVMOptions TestG1ZeroPGCTJcmdThreadPrint
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class TestG1ZeroPGCTJcmdThreadPrint {
+  public static void main(String args[]) throws Exception {
+
+    // Grab the pid from the current java process
+    String pid = Integer.toString(ProcessTools.getProcessId());
+
+    // Create a ProcessBuilder
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Run jcmd <pid> Thread.print
+    pb.command(JDKToolFinder.getJDKTool("jcmd"), pid, "Thread.print");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    // There shouldn't be a work gang for concurrent marking.
+    output.shouldNotContain("G1 Parallel Marking Threads");
+
+    // Make sure we didn't crash
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test ClassMetaspaceSizeInJmapHeap
+ * @bug 8004924
+ * @summary Checks that jmap -heap contains the flag ClassMetaspaceSize
+ * @library /testlibrary
+ * @run main/othervm -XX:ClassMetaspaceSize=50m ClassMetaspaceSizeInJmapHeap
+ */
+
+import com.oracle.java.testlibrary.*;
+import java.nio.file.*;
+import java.io.File;
+import java.nio.charset.Charset;
+import java.util.List;
+
+public class ClassMetaspaceSizeInJmapHeap {
+    public static void main(String[] args) throws Exception {
+        String pid = Integer.toString(ProcessTools.getProcessId());
+
+        ProcessBuilder pb = new ProcessBuilder();
+        pb.command(JDKToolFinder.getJDKTool("jmap"), "-heap",  pid);
+
+        File out = new File("ClassMetaspaceSizeInJmapHeap.stdout.txt");
+        pb.redirectOutput(out);
+
+        File err = new File("ClassMetaspaceSizeInJmapHeap.stderr.txt");
+        pb.redirectError(err);
+
+        run(pb);
+
+        OutputAnalyzer output = new OutputAnalyzer(read(out));
+        output.shouldContain("ClassMetaspaceSize = 52428800 (50.0MB)");
+        out.delete();
+    }
+
+    private static void run(ProcessBuilder pb) throws Exception {
+        Process p = pb.start();
+        p.waitFor();
+        int exitValue = p.exitValue();
+        if (exitValue != 0) {
+            throw new Exception("jmap -heap exited with error code: " + exitValue);
+        }
+    }
+
+    private static String read(File f) throws Exception {
+        Path p = f.toPath();
+        List<String> lines = Files.readAllLines(p, Charset.defaultCharset());
+
+        StringBuilder sb = new StringBuilder();
+        for (String line : lines) {
+            sb.append(line).append('\n');
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestCMS.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestCMS
+* @key gc
+* @bug 8006398
+* @summary Test that CMS does not print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+
+public class TestCMS {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseConcMarkSweepGC", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("warning");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestCMSIncrementalMode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestCMSIncrementalMode
+* @key gc
+* @bug 8006398
+* @summary Test that the deprecated CMSIncrementalMode print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+public class TestCMSIncrementalMode {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("warning: Using incremental CMS is deprecated and will likely be removed in a future release");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestCMSNoIncrementalMode.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestCMSNoIncrementalMode
+* @key gc
+* @bug 8006398
+* @summary Test that CMS with incremental mode turned off does not print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+public class TestCMSNoIncrementalMode {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseConcMarkSweepGC", "-XX:-CMSIncrementalMode", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("warning");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestDefNewCMS.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestDefNewCMS
+* @key gc
+* @bug 8006398
+* @summary Test that the deprecated DefNew+CMS combination print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+public class TestDefNewCMS {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:-UseParNewGC", "-XX:+UseConcMarkSweepGC", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("warning: Using the DefNew young collector with the CMS collector is deprecated and will likely be removed in a future release");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestG1.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestG1
+* @key gc
+* @bug 8006398
+* @summary Test that the G1 collector does not print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+public class TestG1 {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("warning");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestIncGC.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestIncGC
+* @key gc
+* @bug 8006398
+* @summary Test that the deprecated -Xincgc print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+
+public class TestIncGC {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xincgc", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("warning: Using incremental CMS is deprecated and will likely be removed in a future release");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestParNewCMS.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestParNewCMS
+* @key gc
+* @bug 8006398
+* @summary Test that the combination ParNew+CMS does not print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+
+public class TestParNewCMS {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseParNewGC", "-XX:+UseConcMarkSweepGC", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("warning");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestParNewSerialOld.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestParNewSerialOld
+* @key gc
+* @bug 8006398
+* @summary Test that the deprecated ParNew+SerialOld combination print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+
+public class TestParNewSerialOld {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseParNewGC", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestParallelGC.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestParallelGC
+* @key gc
+* @bug 8006398
+* @summary Test that ParallelGC does not print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+
+public class TestParallelGC {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseParallelGC", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("warning");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestParallelScavengeSerialOld.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestParallelScavengeSerialOld
+* @key gc
+* @bug 8006398
+* @summary Test that the ParallelScavenge+SerialOld combination does not print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+
+public class TestParallelScavengeSerialOld {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseParallelGC", "-XX:-UseParallelOldGC", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("warning");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/startup_warnings/TestSerialGC.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+* @test TestSerialGC
+* @key gc
+* @bug 8006398
+* @summary Test that SerialGC does not print a warning message
+* @library /testlibrary
+*/
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+
+public class TestSerialGC {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseSerialGC", "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("warning");
+    output.shouldNotContain("error");
+    output.shouldHaveExitValue(0);
+  }
+
+}
--- a/test/runtime/7158988/FieldMonitor.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/runtime/7158988/FieldMonitor.java	Thu Mar 21 14:11:13 2013 +0100
@@ -24,8 +24,10 @@
 /*
  * @test FieldMonitor.java
  * @bug 7158988
+ * @key regression
  * @summary verify jvm does not crash while debugging
- * @run shell TestFieldMonitor.sh
+ * @run compile TestPostFieldModification.java
+ * @run main/othervm FieldMonitor
  * @author axel.siebenborn@sap.com
  */
 import java.io.BufferedReader;
--- a/test/runtime/7158988/TestFieldMonitor.sh	Thu Mar 21 11:30:38 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-#!/bin/sh
-
-if [ "${TESTSRC}" = "" ]
-then TESTSRC=.
-fi
-
-if [ "${TESTJAVA}" = "" ]
-then
-  PARENT=`dirname \`which java\``
-  TESTJAVA=`dirname ${PARENT}`
-  echo "TESTJAVA not set, selecting " ${TESTJAVA}
-  echo "If this is incorrect, try setting the variable manually."
-fi
-
-if [ "${TESTCLASSES}" = "" ]
-then
-  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux | Darwin)
-    NULL=/dev/null
-    PS=":"
-    FS="/"
-    ;;
-  Windows_95 | Windows_98 | Windows_ME )
-    NULL=NUL
-    PS=";"
-    FS="\\"
-    echo "Test skipped, only for WinNT"
-    exit 0
-    ;;
-  Windows_NT )
-    NULL=NUL
-    PS=";"
-    FS="\\"
-    ;;
-  CYGWIN_NT* )
-    NULL=/dev/null
-    PS=";"
-    FS="/"
-    ;;
-  CYGWIN_* )
-    NULL=/dev/null
-    PS=";"
-    FS="/"
-    echo "Test skipped, only for WinNT"
-    exit 0
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-#CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH
-
-cp ${TESTSRC}${FS}*.java .
-
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion
-
-${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java
-
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out
-
-grep "A fatal error has been detected" test.out > ${NULL}
-if [ $? = 0 ]; then
-    cat test.out
-    STATUS=1
-fi
-
-exit $STATUS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/8000968/Test8000968.sh	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,99 @@
+#
+#  Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+#  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+#  This code is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License version 2 only, as
+#  published by the Free Software Foundation.
+#
+#  This code is distributed in the hope that it will be useful, but WITHOUT
+#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+#  version 2 for more details (a copy is included in the LICENSE file that
+#  accompanied this code).
+#
+#  You should have received a copy of the GNU General Public License version
+#  2 along with this work; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+#  Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+#  or visit www.oracle.com if you need additional information or have any
+#  questions.
+#
+
+
+# @test Test8000968.sh
+# @bug 8000968
+# @summary NPG: UseCompressedKlassPointers asserts with ObjectAlignmentInBytes=32
+# @run shell Test8000968.sh
+#
+
+if [ "${TESTJAVA}" = "" ]
+then
+  PARENT=`dirname \`which java\``
+  TESTJAVA=`dirname ${PARENT}`
+  printf "TESTJAVA not set, selecting " ${TESTJAVA}
+  printf "  If this is incorrect, try setting the variable manually.\n"
+fi
+
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+  Windows_* )
+    FS="\\"
+    NULL=NUL
+    ;;
+  * )
+    FS="/"
+    NULL=/dev/null
+    ;;
+esac
+
+JAVA=${TESTJAVA}${FS}bin${FS}java
+
+#
+# See if platform has 64 bit java.
+#
+${JAVA} ${TESTVMOPTS} -d64 -version 2>&1 | grep -i "does not support" > ${NULL}
+if [ "$?" != "1" ]
+then
+  printf "Platform is 32 bit, does not support -XX:ObjectAlignmentInBytes= option.\n"
+  printf "Passed.\n"
+  exit 0
+fi
+
+#
+# Test -XX:ObjectAlignmentInBytes with -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops.
+#
+${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=16 -version 2>&1 > ${NULL}
+if [ "$?" != "0" ]
+then
+  printf "FAILED: -XX:ObjectAlignmentInBytes=16 option did not work.\n"
+  exit 1
+fi
+
+${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=32 -version 2>&1 > ${NULL}
+if [ "$?" != "0" ]
+then
+  printf "FAILED: -XX:ObjectAlignmentInBytes=32 option did not work.\n"
+  exit 1
+fi
+
+${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=64 -version 2>&1 > ${NULL}
+if [ "$?" != "0" ]
+then
+  printf "FAILED: -XX:ObjectAlignmentInBytes=64 option did not work.\n"
+  exit 1
+fi
+
+${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=128 -version 2>&1 > ${NULL}
+if [ "$?" != "0" ]
+then
+  printf "FAILED: -XX:ObjectAlignmentInBytes=128 option did not work.\n"
+  exit 1
+fi
+
+
+printf "Passed.\n"
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/8007320/ConstMethodTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8007320
+ * @summary Test all optional fields in ConstMethod
+ * @compile -g -parameters ConstMethodTest.java
+ * @run main ConstMethodTest
+ */
+
+import java.util.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.io.Serializable;
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface MyAnnotation {
+    public String name();
+    public String value();
+    public String date() default "today";
+}
+
+@Target(ElementType.TYPE_USE)
+@Retention(RetentionPolicy.RUNTIME)
+@interface TypeAnno {
+    String value();
+}
+
+@Target(ElementType.TYPE_USE)
+@Retention(RetentionPolicy.RUNTIME)
+@interface TypeAnno2 {
+    String value();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+@interface Named {
+  String value();
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface ScalarTypesWithDefault {
+    byte     b()    default 11;
+    short    s()    default 12;
+    int      i()    default 13;
+    long     l()    default 14;
+    char     c()    default 'V';
+}
+
+// Some exception class
+class OkException extends RuntimeException {};
+
+
+@MyAnnotation(name="someName", value = "Hello World")
+public class ConstMethodTest {
+
+    private static void check(boolean b) {
+        if (!b)
+            throw new RuntimeException();
+    }
+    private static void fail(String msg) {
+       System.err.println(msg);
+       throw new RuntimeException();
+    }
+    private static void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) {
+        } else {
+            fail(x + " not equal to " + y);
+        }
+    }
+    private static final String[] parameter_names = {
+        "parameter", "parameter2", "x"
+    };
+
+    // Declare a function with everything in it.
+    @MyAnnotation(name="someName", value="Hello World")
+    static <T> void kitchenSinkFunc(@Named(value="aName") String parameter,
+              @Named("bName") String parameter2,
+              @ScalarTypesWithDefault T x)
+            throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException,
+                NullPointerException,
+                @TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException {
+      int i, j, k;
+      try {
+        System.out.println("calling kitchenSinkFunc " + parameter);
+        throw new OkException();  // to see stack trace with line numbers
+      } catch (Exception e) {
+       e.printStackTrace();
+      }
+    }
+
+    private static void test1() throws Throwable {
+        for (Method m : ConstMethodTest.class.getDeclaredMethods()) {
+            if (m.getName().equals("kitchenSinkFunc")) {
+                Annotation[][] ann = m.getParameterAnnotations();
+                equal(ann.length, 3);
+                Annotation foo = ann[0][0];
+                Annotation bar = ann[1][0];
+                equal(foo.toString(), "@Named(value=aName)");
+                equal(bar.toString(), "@Named(value=bName)");
+                check(foo.equals(foo));
+                check(bar.equals(bar));
+                check(! foo.equals(bar));
+                // method annotations
+                Annotation[] ann2 = m.getAnnotations();
+                equal(ann2.length, 1);
+                Annotation mann = ann2[0];
+                equal(mann.toString(), "@MyAnnotation(date=today, name=someName, value=Hello World)");
+                // Test Method parameter names
+                Parameter[] parameters = m.getParameters();
+                if(parameters == null)
+                    throw new Exception("getParameters should never be null");
+                for(int i = 0; i < parameters.length; i++) {
+                    Parameter p = parameters[i];
+                    equal(parameters[i].getName(), parameter_names[i]);
+                }
+            }
+        }
+    }
+
+    public static void main(java.lang.String[] unused) throws Throwable {
+        // pass 5 so kitchenSinkFunc is instantiated with an int
+        kitchenSinkFunc("parameter", "param2", 5);
+        test1();
+    }
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/8007475/StackMapFrameTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8007475
+ * @summary Test memory stomp in stack map test
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseMallocOnly StackMapFrameTest
+ */
+public class StackMapFrameTest {
+
+  public static void foo() {
+    Object o = new Object();
+  }
+
+  public static void main(String args[]) {
+    for (int i = 0; i < 25000; i++) {
+      foo();
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/8007736/TestStaticIF.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8007736
+ * @summary Test static interface method.
+ * @run main/othervm -Xverify:all TestStaticIF
+ */
+
+public class TestStaticIF implements StaticMethodInInterface {
+
+    public static void main(String[] args) {
+        System.out.printf("main: %s%n", StaticMethodInInterface.get());
+    }
+}
+
+interface StaticMethodInInterface {
+
+    public static String get() {
+        return "Hello from StaticMethodInInterface.get()";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/CommandLine/BooleanFlagWithInvalidValue.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8006298
+ * @summary Setting an invalid value for a bool argument should result in a useful error message
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class BooleanFlagWithInvalidValue {
+  public static void main(String[] args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:+UseLargePages=8", "-version");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Improperly specified VM option 'UseLargePages=8'");
+    output.shouldHaveExitValue(1);
+
+    pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:-UseLargePages=8", "-version");
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Improperly specified VM option 'UseLargePages=8'");
+    output.shouldHaveExitValue(1);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/CommandLine/FlagWithInvalidValue.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8006298
+ * @summary Setting a flag to an invalid value should print a useful error message
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class FlagWithInvalidValue {
+  public static void main(String[] args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:ObjectAlignmentInBytes=v", "-version");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Improperly specified VM option 'ObjectAlignmentInBytes=v'");
+    output.shouldHaveExitValue(1);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/CommandLine/NonBooleanFlagWithInvalidBooleanPrefix.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8006298
+ * @summary Using a bool (+/-) prefix on non-bool flag should result in a useful error message
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class NonBooleanFlagWithInvalidBooleanPrefix {
+  public static void main(String[] args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:-ObjectAlignmentInBytes=16", "-version");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'");
+    output.shouldHaveExitValue(1);
+
+    pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:+ObjectAlignmentInBytes=16", "-version");
+
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'");
+    output.shouldHaveExitValue(1);
+
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/CommandLine/UnrecognizedVMOption.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8006298
+ * @summary Using an unrecognized VM option should print the name of the option
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class UnrecognizedVMOption {
+  public static void main(String[] args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:bogus_option", "-version");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Unrecognized VM option 'bogus_option'");
+    output.shouldHaveExitValue(1);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/AllocTestType.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd
+ * @key nmt jcmd
+ * @library /testlibrary /testlibrary/whitebox
+ * @build AllocTestType
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class AllocTestType {
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Use WB API to alloc with the mtTest type
+    if (!WhiteBox.getWhiteBox().NMTAllocTest()) {
+      throw new Exception("Call to WB API NMTAllocTest() failed");
+    }
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+
+    // Run 'jcmd <pid> VM.native_memory summary'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Test (reserved=512KB, committed=512KB)");
+
+    // Free the memory allocated by NMTAllocTest
+    if (!WhiteBox.getWhiteBox().NMTFreeTestMemory()) {
+      throw new Exception("Call to WB API NMTFreeTestMemory() failed");
+    }
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+    output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("Test (reserved=");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/BaselineWithParameter.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8004802
+ * @key nmt jcmd regression
+ * @summary Regression test for invoking a jcmd with baseline=false, result was that the target VM crashed
+ * @library /testlibrary
+ * @run main/othervm -XX:NativeMemoryTracking=detail BaselineWithParameter
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class BaselineWithParameter {
+
+  public static void main(String args[]) throws Exception {
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    OutputAnalyzer output;
+
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Run 'jcmd <pid> VM.native_memory baseline=false'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=false"});
+    pb.start();
+
+    // Run 'jcmd <pid> VM.native_memory summary=false'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary=false"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("No command to execute");
+
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/CommandLineDetail.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @key nmt
+ * @summary Running with NMT detail should not result in an error or warning
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class CommandLineDetail {
+
+  public static void main(String args[]) throws Exception {
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-XX:NativeMemoryTracking=detail",
+      "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("error");
+    output.shouldNotContain("warning");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/CommandLineEmptyArgument.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @key nmt
+ * @summary Empty argument to NMT should result in an informative error message
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class CommandLineEmptyArgument {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking=");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]");
+    output.shouldHaveExitValue(1);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/CommandLineInvalidArgument.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @key nmt
+ * @summary Invalid argument to NMT should result in an informative error message
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class CommandLineInvalidArgument {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking=apa");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]");
+    output.shouldHaveExitValue(1);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/CommandLineSummary.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @key nmt
+ * @summary Running with NMT summary should not result in an error or warning
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class CommandLineSummary {
+
+  public static void main(String args[]) throws Exception {
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-XX:NativeMemoryTracking=summary",
+      "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("error");
+    output.shouldNotContain("warning");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/CommandLineTurnOffNMT.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @key nmt
+ * @summary Turning off NMT should not result in an error or warning
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class CommandLineTurnOffNMT {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+              "-XX:NativeMemoryTracking=off",
+              "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldNotContain("error");
+    output.shouldNotContain("warning");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/JcmdScale.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @key nmt jcmd
+ * @summary Test the NMT scale parameter
+ * @library /testlibrary
+ * @run main/othervm -XX:NativeMemoryTracking=summary JcmdScale
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class JcmdScale {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = new ProcessBuilder();
+    OutputAnalyzer output;
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("KB,  committed=");
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=MB"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("MB,  committed=");
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=GB"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("GB,  committed=");
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=apa"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Incorrect scale value: apa");
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("GB,  committed=");
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=apa"});
+    output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Incorrect scale value: apa");
+
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/JcmdWithNMTDisabled.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @key nmt jcmd
+ * @summary Verify that jcmd correctly reports that NMT is not enabled
+ * @library /testlibrary
+ * First run without enabling NMT
+ * @run main/othervm JcmdWithNMTDisabled
+ * Then run with explicitly disabling NMT, should not be any difference
+ * @run main/othervm -XX:NativeMemoryTracking=off JcmdWithNMTDisabled
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class JcmdWithNMTDisabled {
+  static ProcessBuilder pb = new ProcessBuilder();
+  static String pid;
+
+  public static void main(String args[]) throws Exception {
+    // Grab my own PID
+    pid = Integer.toString(ProcessTools.getProcessId());
+
+    jcmdCommand("summary");
+    jcmdCommand("detail");
+    jcmdCommand("baseline");
+    jcmdCommand("summary.diff");
+    jcmdCommand("detail.diff");
+    jcmdCommand("scale=GB");
+    jcmdCommand("shutdown");
+  }
+
+  // Helper method for invoking different jcmd calls, all should fail with the same message saying NMT is not enabled
+  public static void jcmdCommand(String command) throws Exception {
+
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", command});
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    // Verify that jcmd reports that NMT is not enabled
+    output.shouldContain("Native memory tracking is not enabled");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/PrintNMTStatistics.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @key nmt regression
+ * @bug 8005936
+ * @summary Make sure PrintNMTStatistics works on normal JVM exit
+ * @library /testlibrary /testlibrary/whitebox
+ * @run compile PrintNMTStatistics.java
+ */
+
+import com.oracle.java.testlibrary.*;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import sun.hotspot.WhiteBox;
+
+public class PrintNMTStatistics {
+
+  public static void main(String args[]) throws Exception {
+
+    // We start a new java process running with an argument and use WB API to ensure
+    // we have data for NMT on VM exit
+    if (args.length > 0) {
+      // Use WB API to ensure that all data has been merged before we continue
+      if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
+        throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+      }
+      return;
+    }
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:+UnlockDiagnosticVMOptions",
+        "-XX:NativeMemoryTracking=summary",
+        "+XX:+PrintNMTStatistics",
+        "PrintNMTStatistics",
+        "test");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("Java Heap  (reserved=");
+    output.shouldNotContain("error");
+    output.shouldNotContain("warning");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @key nmt
+ * @summary Trying to enable PrintNMTStatistics should result in a warning
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class PrintNMTStatisticsWithNMTDisabled {
+
+  public static void main(String args[]) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-XX:+UnlockDiagnosticVMOptions",
+      "-XX:+PrintNMTStatistics",
+      "-version");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("warning: PrintNMTStatistics is disabled, because native memory tracking is not enabled");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/ShutdownTwice.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @key nmt jcmd
+ * @summary Run shutdown twice
+ * @library /testlibrary
+ * @run main/othervm -XX:NativeMemoryTracking=detail ShutdownTwice
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class ShutdownTwice {
+
+  public static void main(String args[]) throws Exception {
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    OutputAnalyzer output;
+
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Run 'jcmd <pid> VM.native_memory shutdown'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"});
+    output = new OutputAnalyzer(pb.start());
+
+    // Verify that jcmd reports that NMT is shutting down
+    output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown");
+
+    // Run shutdown again
+    output = new OutputAnalyzer(pb.start());
+
+    // Verify that jcmd reports that NMT has been shutdown already
+    output.shouldContain("Native memory tracking has been shutdown by user");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/SummaryAfterShutdown.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @key nmt jcmd
+ * @summary Verify that jcmd correctly reports that NMT is not enabled after a shutdown
+ * @library /testlibrary
+ * @run main/othervm -XX:NativeMemoryTracking=detail SummaryAfterShutdown
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class SummaryAfterShutdown {
+
+  public static void main(String args[]) throws Exception {
+    OutputAnalyzer output;
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Run 'jcmd <pid> VM.native_memory shutdown'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"});
+    output = new OutputAnalyzer(pb.start());
+
+    // Verify that jcmd reports that NMT is shutting down
+    output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown");
+
+    // Run 'jcmd <pid> VM.native_memory summary'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
+    output = new OutputAnalyzer(pb.start());
+
+    // Verify that jcmd reports that NMT has been shutdown
+    output.shouldContain("Native memory tracking has been shutdown by user");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/NMT/SummarySanityCheck.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @key nmt jcmd
+ * @summary Sanity check the output of NMT
+ * @library /testlibrary /testlibrary/whitebox
+ * @build SummarySanityCheck
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck
+ */
+
+import com.oracle.java.testlibrary.*;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import sun.hotspot.WhiteBox;
+
+public class SummarySanityCheck {
+
+  private static String jcmdout;
+  public static void main(String args[]) throws Exception {
+    // Grab my own PID
+    String pid = Integer.toString(ProcessTools.getProcessId());
+
+    // Use WB API to ensure that all data has been merged before we continue
+    if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
+      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
+    }
+
+    ProcessBuilder pb = new ProcessBuilder();
+
+    // Run  'jcmd <pid> VM.native_memory summary scale=KB'
+    pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=KB"});
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    jcmdout = output.getOutput();
+    // Split by '-' to get the 'groups'
+    String[] lines = jcmdout.split("\n");
+
+    if (lines.length == 0) {
+      throwTestException("Failed to parse jcmd output");
+    }
+
+    int totalCommitted = 0, totalReserved = 0;
+    int totalCommittedSum = 0, totalReservedSum = 0;
+
+    // Match '- <mtType> (reserved=<reserved>KB, committed=<committed>KB)
+    Pattern mtTypePattern = Pattern.compile("-\\s+(?<typename>[\\w\\s]+)\\(reserved=(?<reserved>\\d+)KB,\\scommitted=(?<committed>\\d+)KB\\)");
+    // Match 'Total: reserved=<reserved>KB, committed=<committed>KB'
+    Pattern totalMemoryPattern = Pattern.compile("Total\\:\\s\\sreserved=(?<reserved>\\d+)KB,\\s\\scommitted=(?<committed>\\d+)KB");
+
+    for (int i = 0; i < lines.length; i++) {
+      if (lines[i].startsWith("Total")) {
+        Matcher totalMemoryMatcher = totalMemoryPattern.matcher(lines[i]);
+
+        if (totalMemoryMatcher.matches() && totalMemoryMatcher.groupCount() == 2) {
+          totalCommitted = Integer.parseInt(totalMemoryMatcher.group("committed"));
+          totalReserved = Integer.parseInt(totalMemoryMatcher.group("reserved"));
+        } else {
+          throwTestException("Failed to match the expected groups in 'Total' memory part");
+        }
+      } else if (lines[i].startsWith("-")) {
+        Matcher typeMatcher = mtTypePattern.matcher(lines[i]);
+        if (typeMatcher.matches()) {
+          int typeCommitted = Integer.parseInt(typeMatcher.group("committed"));
+          int typeReserved = Integer.parseInt(typeMatcher.group("reserved"));
+
+          // Make sure reserved is always less or equals
+          if (typeCommitted > typeReserved) {
+            throwTestException("Committed (" + typeCommitted + ") was more than Reserved ("
+                + typeReserved + ") for mtType: " + typeMatcher.group("typename"));
+          }
+
+          // Add to total and compare them in the end
+          totalCommittedSum += typeCommitted;
+          totalReservedSum += typeReserved;
+        } else {
+          throwTestException("Failed to match the group on line " + i);
+        }
+      }
+    }
+
+    // See if they add up correctly, rounding is a problem so make sure we're within +/- 8KB
+    int committedDiff = totalCommitted - totalCommittedSum;
+    if (committedDiff > 8 || committedDiff < -8) {
+      throwTestException("Total committed (" + totalCommitted + ") did not match the summarized committed (" + totalCommittedSum + ")" );
+    }
+
+    int reservedDiff = totalReserved - totalReservedSum;
+    if (reservedDiff > 8 || reservedDiff < -8) {
+      throwTestException("Total reserved (" + totalReserved + ") did not match the summarized reserved (" + totalReservedSum + ")" );
+    }
+  }
+
+  private static void throwTestException(String reason) throws Exception {
+      throw new Exception(reason + " . Stdout is :\n" + jcmdout);
+  }
+}
--- a/test/sanity/WBApi.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/sanity/WBApi.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,8 +1,33 @@
+/*
+ * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
 /*
  * @test WBApi
  * @summary verify that whitebox functions can be linked and executed
- * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI WBApi.java
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI WBApi
+ * @library /testlibrary /testlibrary/whitebox
+ * @build WBApi
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI WBApi
  */
 
 import sun.hotspot.WhiteBox;
--- a/test/serviceability/ParserTest.java	Thu Mar 21 11:30:38 2013 +0100
+++ b/test/serviceability/ParserTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -1,8 +1,33 @@
+/*
+ * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
 /*
  * @test ParserTest
- * @summary verify that whitebox functions can be linked and executed
- * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI ParserTest.java
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest
+ * @summary Test that the diagnostic command arguemnt parser works
+ * @library /testlibrary /testlibrary/whitebox
+ * @build ParserTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest
  */
 
 import java.math.BigInteger;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/ClassFileInstaller.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+
+/**
+ * Dump a class file for a class on the class path in the current directory
+ */
+public class ClassFileInstaller {
+    /**
+     * @param args The names of the classes to dump
+     * @throws Exception
+     */
+    public static void main(String... args) throws Exception {
+        for (String arg : args) {
+            ClassLoader cl = ClassFileInstaller.class.getClassLoader();
+
+            // Convert dotted class name to a path to a class file
+            String pathName = arg.replace('.', '/').concat(".class");
+            InputStream is = cl.getResourceAsStream(pathName);
+
+            // Create the class file's package directory
+            Path p = Paths.get(pathName);
+            Files.createDirectories(p.getParent());
+            // Create the class file
+            Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/OutputAnalyzerTest.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test the OutputAnalyzer utility class
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public class OutputAnalyzerTest {
+
+  public static void main(String args[]) throws Exception {
+
+    String stdout = "aaaaaa";
+    String stderr = "bbbbbb";
+
+    OutputAnalyzer output = new OutputAnalyzer(stdout, stderr);
+
+    if (!stdout.equals(output.getStdout())) {
+      throw new Exception("getStdout() returned '" + output.getStdout() + "', expected '" + stdout + "'");
+    }
+
+    if (!stderr.equals(output.getStderr())) {
+      throw new Exception("getStderr() returned '" + output.getStderr() + "', expected '" + stderr + "'");
+    }
+
+    try {
+      output.shouldContain(stdout);
+      output.stdoutShouldContain(stdout);
+      output.shouldContain(stderr);
+      output.stderrShouldContain(stderr);
+    } catch (RuntimeException e) {
+      throw new Exception("shouldContain() failed", e);
+    }
+
+    try {
+      output.shouldContain("cccc");
+      throw new Exception("shouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+
+    try {
+      output.stdoutShouldContain(stderr);
+      throw new Exception("stdoutShouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+
+    try {
+      output.stderrShouldContain(stdout);
+      throw new Exception("stdoutShouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+
+    try {
+      output.shouldNotContain("cccc");
+      output.stdoutShouldNotContain("cccc");
+      output.stderrShouldNotContain("cccc");
+    } catch (RuntimeException e) {
+      throw new Exception("shouldNotContain() failed", e);
+    }
+
+    try {
+      output.shouldNotContain(stdout);
+      throw new Exception("shouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+
+    try {
+      output.stdoutShouldNotContain(stdout);
+      throw new Exception("shouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+
+    try {
+      output.stderrShouldNotContain(stderr);
+      throw new Exception("shouldContain() failed to throw exception");
+    } catch (RuntimeException e) {
+      // expected
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.java.testlibrary;
+
+import java.io.File;
+
+public final class JDKToolFinder {
+
+  private JDKToolFinder() {
+  }
+
+  /**
+   * Returns the full path to an executable in jdk/bin based on System property
+   * test.jdk (set by jtreg test suite)
+   *
+   * @return Full path to an executable in jdk/bin
+   */
+  public static String getJDKTool(String tool) {
+    String binPath = System.getProperty("test.jdk");
+    if (binPath == null) {
+      throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. "
+          + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'.");
+    }
+
+    binPath += File.separatorChar + "bin" + File.separatorChar + tool;
+
+    return binPath;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.java.testlibrary;
+
+import java.io.IOException;
+
+public final class OutputAnalyzer {
+
+  private final String stdout;
+  private final String stderr;
+  private final int exitValue;
+
+  /**
+   * Create an OutputAnalyzer, a utility class for verifying output and exit
+   * value from a Process
+   *
+   * @param process Process to analyze
+   * @throws IOException If an I/O error occurs.
+   */
+  public OutputAnalyzer(Process process) throws IOException {
+    OutputBuffer output = ProcessTools.getOutput(process);
+    exitValue = process.exitValue();
+    this.stdout = output.getStdout();
+    this.stderr = output.getStderr();
+  }
+
+  /**
+   * Create an OutputAnalyzer, a utility class for verifying output
+   *
+   * @param buf String buffer to analyze
+   */
+  public OutputAnalyzer(String buf) {
+    this(buf, buf);
+  }
+
+  /**
+   * Create an OutputAnalyzer, a utility class for verifying output
+   *
+   * @param stdout stdout buffer to analyze
+   * @param stderr stderr buffer to analyze
+   */
+  public OutputAnalyzer(String stdout, String stderr) {
+    this.stdout = stdout;
+    this.stderr = stderr;
+    exitValue = -1;
+  }
+
+  /**
+   * Verify that the stdout and stderr contents of output buffer contains the string
+   *
+   * @param expectedString String that buffer should contain
+   * @throws RuntimeException If the string was not found
+   */
+  public void shouldContain(String expectedString) {
+    if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
+      throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr: [" + stdout + stderr + "]\n");
+    }
+  }
+
+  /**
+   * Verify that the stdout contents of output buffer contains the string
+   *
+   * @param expectedString String that buffer should contain
+   * @throws RuntimeException If the string was not found
+   */
+  public void stdoutShouldContain(String expectedString) {
+    if (!stdout.contains(expectedString)) {
+      throw new RuntimeException("'" + expectedString + "' missing from stdout: [" + stdout + "]\n");
+    }
+  }
+
+  /**
+   * Verify that the stderr contents of output buffer contains the string
+   *
+   * @param expectedString String that buffer should contain
+   * @throws RuntimeException If the string was not found
+   */
+  public void stderrShouldContain(String expectedString) {
+    if (!stderr.contains(expectedString)) {
+      throw new RuntimeException("'" + expectedString + "' missing from stderr: [" + stderr + "]\n");
+    }
+  }
+
+  /**
+   * Verify that the stdout and stderr contents of output buffer does not contain the string
+   *
+   * @param expectedString String that the buffer should not contain
+   * @throws RuntimeException If the string was found
+   */
+  public void shouldNotContain(String notExpectedString) {
+    if (stdout.contains(notExpectedString)) {
+      throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n");
+    }
+    if (stderr.contains(notExpectedString)) {
+      throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n");
+    }
+  }
+
+  /**
+   * Verify that the stdout contents of output buffer does not contain the string
+   *
+   * @param expectedString String that the buffer should not contain
+   * @throws RuntimeException If the string was found
+   */
+  public void stdoutShouldNotContain(String notExpectedString) {
+    if (stdout.contains(notExpectedString)) {
+      throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n");
+    }
+  }
+
+  /**
+   * Verify that the stderr contents of output buffer does not contain the string
+   *
+   * @param expectedString String that the buffer should not contain
+   * @throws RuntimeException If the string was found
+   */
+  public void stderrShouldNotContain(String notExpectedString) {
+    if (stderr.contains(notExpectedString)) {
+      throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n");
+    }
+  }
+
+  /**
+   * Verifiy the exit value of the process
+   *
+   * @param expectedExitValue Expected exit value from process
+   * @throws RuntimeException If the exit value from the process did not match the expected value
+   */
+  public void shouldHaveExitValue(int expectedExitValue) {
+    if (getExitValue() != expectedExitValue) {
+      throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue);
+    }
+  }
+
+  /**
+   * Get the contents of the output buffer (stdout and stderr)
+   *
+   * @return Content of the output buffer
+   */
+  public String getOutput() {
+    return stdout + stderr;
+  }
+
+  /**
+   * Get the contents of the stdout buffer
+   *
+   * @return Content of the stdout buffer
+   */
+  public String getStdout() {
+    return stdout;
+  }
+
+  /**
+   * Get the contents of the stderr buffer
+   *
+   * @return Content of the stderr buffer
+   */
+  public String getStderr() {
+    return stderr;
+  }
+
+  /**
+   * Get the process exit value
+   *
+   * @return Process exit value
+   */
+  public int getExitValue() {
+    return exitValue;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.java.testlibrary;
+
+public class OutputBuffer {
+  private final String stdout;
+  private final String stderr;
+
+  /**
+   * Create an OutputBuffer, a class for storing and managing stdout and stderr
+   * results separately
+   *
+   * @param stdout stdout result
+   * @param stderr stderr result
+   */
+  public OutputBuffer(String stdout, String stderr) {
+    this.stdout = stdout;
+    this.stderr = stderr;
+  }
+
+  /**
+   * Returns the stdout result
+   *
+   * @return stdout result
+   */
+  public String getStdout() {
+    return stdout;
+  }
+
+  /**
+   * Returns the stderr result
+   *
+   * @return stderr result
+   */
+  public String getStderr() {
+    return stderr;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.java.testlibrary;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+
+import sun.management.VMManagement;
+
+public final class ProcessTools {
+
+  private ProcessTools() {
+  }
+
+  /**
+   * Pumps stdout and stderr from running the process into a String.
+   *
+   * @param processHandler ProcessHandler to run.
+   * @return Output from process.
+   * @throws IOException If an I/O error occurs.
+   */
+  public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException {
+    return getOutput(processBuilder.start());
+  }
+
+  /**
+   * Pumps stdout and stderr the running process into a String.
+   *
+   * @param process Process to pump.
+   * @return Output from process.
+   * @throws IOException If an I/O error occurs.
+   */
+  public static OutputBuffer getOutput(Process process) throws IOException {
+    ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream();
+    ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream();
+    StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer);
+    StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer);
+    Thread outPumperThread = new Thread(outPumper);
+    Thread errPumperThread = new Thread(errPumper);
+
+    outPumperThread.setDaemon(true);
+    errPumperThread.setDaemon(true);
+
+    outPumperThread.start();
+    errPumperThread.start();
+
+    try {
+      process.waitFor();
+      outPumperThread.join();
+      errPumperThread.join();
+    } catch (InterruptedException e) {
+      Thread.currentThread().interrupt();
+      return null;
+    }
+
+    return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString());
+  }
+
+  /**
+   * Get the process id of the current running Java process
+   *
+   * @return Process id
+   */
+  public static int getProcessId() throws Exception {
+
+    // Get the current process id using a reflection hack
+    RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+    Field jvm = runtime.getClass().getDeclaredField("jvm");
+
+    jvm.setAccessible(true);
+    VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
+
+    Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
+
+    pid_method.setAccessible(true);
+
+    int pid = (Integer) pid_method.invoke(mgmt);
+
+    return pid;
+  }
+
+  /**
+   * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris)
+   *
+   * @return String[] with platform specific arguments, empty if there are none
+   */
+  public static String[] getPlatformSpecificVMArgs() {
+    String osName = System.getProperty("os.name");
+    String dataModel = System.getProperty("sun.arch.data.model");
+
+    if (osName.equals("SunOS") && dataModel.equals("64")) {
+      return new String[] { "-d64" };
+    }
+
+    return new String[] {};
+  }
+
+  /**
+   * Create ProcessBuilder using the java launcher from the jdk to be tested and
+   * with any platform specific arguments prepended
+   */
+  public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception {
+    String javapath = JDKToolFinder.getJDKTool("java");
+
+    ArrayList<String> args = new ArrayList<>();
+    args.add(javapath);
+    Collections.addAll(args, getPlatformSpecificVMArgs());
+    Collections.addAll(args, command);
+
+    return new ProcessBuilder(args.toArray(new String[args.size()]));
+
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.java.testlibrary;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+public final class StreamPumper implements Runnable {
+
+  private static final int BUF_SIZE = 256;
+
+  private final OutputStream out;
+  private final InputStream in;
+
+  /**
+   * Create a StreamPumper that reads from in and writes to out.
+   *
+   * @param in The stream to read from.
+   * @param out The stream to write to.
+   */
+  public StreamPumper(InputStream in, OutputStream out) {
+    this.in = in;
+    this.out = out;
+  }
+
+  /**
+   * Implements Thread.run(). Continuously read from <code>in</code> and write
+   * to <code>out</code> until <code>in</code> has reached end of stream. Abort
+   * on interruption. Abort on IOExceptions.
+   */
+  @Override
+  public void run() {
+    int length;
+    InputStream localIn = in;
+    OutputStream localOut = out;
+    byte[] buffer = new byte[BUF_SIZE];
+
+    try {
+      while (!Thread.interrupted() && (length = localIn.read(buffer)) > 0) {
+        localOut.write(buffer, 0, length);
+      }
+    } catch (IOException e) {
+      // Just abort if something like this happens.
+      e.printStackTrace();
+    } finally {
+      try {
+        localOut.flush();
+        in.close();
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.hotspot;
+
+import java.lang.reflect.Method;
+import java.security.BasicPermission;
+import sun.hotspot.parser.DiagnosticCommand;
+
+public class WhiteBox {
+
+  @SuppressWarnings("serial")
+  public static class WhiteBoxPermission extends BasicPermission {
+    public WhiteBoxPermission(String s) {
+      super(s);
+    }
+  }
+
+  private WhiteBox() {}
+  private static final WhiteBox instance = new WhiteBox();
+  private static native void registerNatives();
+
+  /**
+   * Returns the singleton WhiteBox instance.
+   *
+   * The returned WhiteBox object should be carefully guarded
+   * by the caller, since it can be used to read and write data
+   * at arbitrary memory addresses. It must never be passed to
+   * untrusted code.
+   */
+  public synchronized static WhiteBox getWhiteBox() {
+    SecurityManager sm = System.getSecurityManager();
+    if (sm != null) {
+      sm.checkPermission(new WhiteBoxPermission("getInstance"));
+    }
+    return instance;
+  }
+
+  static {
+    registerNatives();
+  }
+
+  // Memory
+  public native long getObjectAddress(Object o);
+  public native int  getHeapOopSize();
+
+  // Runtime
+  // Make sure class name is in the correct format
+  public boolean isClassAlive(String name) {
+    return isClassAlive0(name.replace('.', '/'));
+  }
+  private native boolean isClassAlive0(String name);
+
+  // G1
+  public native boolean g1InConcurrentMark();
+  public native boolean g1IsHumongous(Object o);
+  public native long    g1NumFreeRegions();
+  public native int     g1RegionSize();
+  public native Object[]    parseCommandLine(String commandline, DiagnosticCommand[] args);
+
+  // NMT
+  public native boolean NMTAllocTest();
+  public native boolean NMTFreeTestMemory();
+  public native boolean NMTWaitForDataMerge();
+
+  // Compiler
+  public native void    deoptimizeAll();
+  public native boolean isMethodCompiled(Method method);
+  public native boolean isMethodCompilable(Method method);
+  public native boolean isMethodQueuedForCompilation(Method method);
+  public native int     deoptimizeMethod(Method method);
+  public native void    makeMethodNotCompilable(Method method);
+  public native int     getMethodCompilationLevel(Method method);
+  public native boolean setDontInlineMethod(Method method, boolean value);
+  public native int     getCompileQueuesSize();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java	Thu Mar 21 14:11:13 2013 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.hotspot.parser;
+
+public class DiagnosticCommand {
+
+    public enum DiagnosticArgumentType {
+        JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE
+    }
+
+    private String name;
+    private String desc;
+    private DiagnosticArgumentType type;
+    private boolean mandatory;
+    private String defaultValue;
+
+    public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type,
+            boolean mandatory, String defaultValue) {
+        this.name = name;
+        this.desc = desc;
+        this.type = type;
+        this.mandatory = mandatory;
+        this.defaultValue = defaultValue;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public DiagnosticArgumentType getType() {
+        return type;
+    }
+
+    public boolean isMandatory() {
+        return mandatory;
+    }
+
+    public String getDefaultValue() {
+        return defaultValue;
+    }
+}